From bfa1c8ea8d95f60c3176b488d9c4ea40c806408a Mon Sep 17 00:00:00 2001 From: JarWarren <43893126+JarWarren@users.noreply.github.com> Date: Sun, 6 Oct 2024 18:34:57 -0600 Subject: [PATCH] 0.30.0 (#13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove performance logs (#6709) We have found the root cause of the issue: - when using a datasource (including the cached ones), we are fetching ObjectMetadataCollection from cache (700kB). Datasource usage is happening any time we are using twentyORM, which is everywhere in the jobs and in some resolvers (including the GetCurrentUser one). This is leading to a high load on redis and leading to the performance issues we are seeing. - we actually don't need to fetch this objectMetadataCollection while using a cached datasource, only when we instantiate a new one * Fix webhook issue (#6711) Fix [#web](https://github.com/orgs/twentyhq/projects/1/views/3?pane=issue&itemId=75329194) This PR does 2 things: - migrate webhooks to TwentyORM - Fix inversion between objectNameSingular and operation in webhook eventName. It is stored as {objectNameSingular}.{operation} and we were querying {operation}.{objectNameSingular} * Bump version to 0.23.2 * corrected targetableobject being undefined when clicked on create task in command menu (#6635) Issue #6630 It seems this bug is caused by `targetableObjects` being assigned an empty array, which then leads to an error due to it being undefined. I've made some changes that should address the issue, but I would appreciate any feedback or suggestions on alternative solutions. Please let me know if there is a better approach to resolving this. Thank you! https://github.com/user-attachments/assets/d6409798-3320-49b3-834f-2b6888847ed8 * Trigger workflow run manually (#6696) Fix https://github.com/twentyhq/twenty/issues/6669 - create a commun function `startWorkflowRun` that both create the run object and the job for executing the workflow - use it in both the `workflowEventJob` and the `runWorkflowVersion` endpoint Bonus: - use filtering for exceptions instead of a util. It avoids doing a try catch in all endpoint * Check workflow version is valid before publishing (#6702) Fix https://github.com/twentyhq/twenty/issues/6670 * Fix logging error in webhook system * Make workspaceMemberId optional in JWT for workspaces that are not ACTIVE (#6714) WorkspaceMemberId is mandatory in the jwt token generated for a given user on a given workspace. However, when a user signs up, it does not have a workspaceMemberId yet. * TWNTY-6135 - Improve Data Importer Select Matching (#6338) ### Description: - we move all logic about the unmatchedOptions to a new component called UnmatchColumn, because as it will be a full line in the table, it was better to update where the component will be rendered - In the latest changes to keep the columns when we change the step to step 3 and go back to step 2, we added a fallback state initialComputedColumnsState that saves the columns and only reverts the updates when we go back to step 1 or close by clicking the X button ### Refs: #6135 ``` It was necessary to add references and floating styles to the generic component to fix the bug when the last option was open and the dropdown was being hidden in the next row of the spreadsheet table. We fixed the same problem that occurs in the companies table as well ``` we used this approach mentioned on this documentation to be able to use the hook without calling it on each component, we are calling only once, on the shared component \ before: ![](https://assets-service.gitstart.com/25493/2c994e0f-6548-4a9e-8b22-2c6eccb73b2e.png) now: ![](https://assets-service.gitstart.com/25493/f56fd516-7e95-4616-b1ed-c9ea5195a8ae.png)### Demo: Fixes #6135 NOTES: the enter key are not working on main branch too --------- Co-authored-by: gitstart-twenty Co-authored-by: Lucas Bordeau * 6687 change messaging import cron job to run every minute (#6704) Closes #6687 * Update workflow version struct (#6716) We want to avoid the nested structure of active pieces. Steps to execute will now be separated from the trigger. It will be an array executed sequentially. For now a step can only be an action. But at some point it will also be a branch or a loop * Created a specific scroll wrapper context per scroll wrapper and made ScrollTop and ScrollLeft componentStates (#6645) @lucasbordeau @charlesBochet Issue #4826 Could u review this changes. Let me know what do you think. --------- Co-authored-by: Lucas Bordeau * 6686 Add try catch on every cron job, and send exception to exceptionHandler (#6705) Closes #6686 --------- Co-authored-by: Charles Bochet * Add isInactive to FieldMetadata decorator (#6623) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-4145](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-4145). This ticket was imported from: [TWNTY-4145](https://github.com/twentyhq/twenty/issues/4145) --- ### Description This PR introduces the @isInActive() decorator to the standard field metadata. \ - This gives the ability to allow workspaces to be able to be created with standard fields as inactive *Helps prevent polluting existing workspaces - A new standard field can be added to* eg company-workspace-entity.ts and the @WorkspaceIsInActive() decorator can be added to create it in deactivated mode sync-metadata command: `yarn command:prod workspace:sync-metadata -f` ### Refs #4145 ### Demo \ \ Fixes: #4145 --------- Co-authored-by: gitstart-twenty Co-authored-by: Charles Bochet * 6654 serverless functions add a deploy button disable deploy when autosave (#6715) - improvements on serverless function behavior (autosave performances, deploy on execution only) - add versioning to serverless functions - add a publish endpoint to create a new version of a serverless function - add deploy and reset to lastVersion button in the settings section: image * chore: upgrade aws-sdk v2 to v3 (#6643) (#6693) Fixes (#6643) - According to `aws-sdk` v3, each service is packaged as a separate module, and the codebase uses all of the required AWS services accordingly. Therefore, removing the direct dependency on `aws-sdk:v2` to resolve the warning shown in (#6643) Co-authored-by: Charles Bochet * Fix addition of new option in select field if there are no existing options (#6718) Fixes [sentry](https://twenty-v7.sentry.io/issues/5745628875/?alert_rule_id=15135099&alert_type=issue¬ification_uuid=95108411-b431-4abd-bdd6-687c96a7353e&project=4507072563183616&referrer=discord) * [Fix] Prevent fields name conflicts with composite subfields names (#6713) At field creation we are checking the availability of the name by comparing it to the other fields' names' on the object; but for composite fields the fields' names' as indicated in the repository do not exactly match the column names' on the tables (e.g "createdBy" field is actually represented by columns createdByName, createdBySource etc.). In this PR we prevent the conflict with the standard composite fields' names. There is still room for errors with the custom composite fields: for example a custom composite field "address" of type address on a custom object "listing" will introduce the columns addressAddressStreet1, addressAddressStreet2 etc. while we won't prevent the user from later creating a custom field named "addressAddressStreet1". For now I decided not to tackle this as this seem extremely edgy + would impact performance on creation of all fields while never actually useful (I think). * Fix sentry issue (#6719) https://twenty-v7.sentry.io/issues/5677123076/?environment=prod&project=4507072499810304&query=is%3Aunresolved+issue.priority%3A%5Bhigh%2C+medium%5D&referrer=issue-stream&statsPeriod=7d&stream_index=12 Removes billing section when is_free_access_enabled * Added hotkeyScopes to serverless functions in settings (#6710) Fixes #6656 Is this the right way to implement keyboard listeners? Please let me know, I'll make the changes accordingly. :) https://github.com/user-attachments/assets/af71d340-ead9-4659-81e6-a440522a194f --------- Co-authored-by: Lucas Bordeau * Fix serverless save when name empty (#6720) - fix serverless function error on save when name empty - remove useless unique constraint on serverless function names * Visualize Workflows (#6697) ## Features - Fetch a workflow and display it in a tree with the React Flow library - The nodes are positioned by an algorithm - The feature is put behind a feature flag. The `/workflow/:id` route is disabled if the flag is off. - I started implementing a right drawer. That's a big WIP and it will be finished in another PR. ## How to test this feature 1. Create a workflow instance in the database through a GraphQL query. See below for instructions. 2. After enabling the feature flag, you should be able to see the workflow you created in the workflows list. To visualize the workflow, go to the `/workflow/:id` page where the id is the id of the workflow. See the video for a quick way to do so. ```gql // First mutation createWorkflow($data: WorkflowCreateInput!) { createWorkflow(data: $data) { id } } // Result { "data": { "name": "test" } } // Second mutation createWorkflowVersion($data: WorkflowVersionCreateInput!) { createWorkflowVersion (data: $data) { id } } // Result { "data": { "name": "v1", "trigger": { "name": "trigger", "displayName": "New or Updated Row", "type": "DATABASE_EVENT", "settings": { "eventName": "company.created", "triggerName": "Company Created" }, "nextAction": { "name": "step_1", "displayName": "Code", "type": "CODE", "valid": true, "settings": { "serverlessFunctionId": "function_id", "errorHandlingOptions": { "retryOnFailure": { "value": false }, "continueOnFailure": { "value": false } } } } }, "workflowId": "workflow_id" } } ``` https://github.com/user-attachments/assets/42bbd98c-5e13-447c-9307-461a18ac2195 * Fix table re-renders on update field (#6722) The update of all fields was caused by `useContextSelector` not being properly implemented. As it is a memoization library the `useRecordFieldValue` hook wasn't giving to the library the required things to allow memoization. I just added recordId + fieldName to the memoization function so that `useContextSelector` doesn't recompute itself whenever any record changes. * Fix currency field edition form (#6723) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-6692](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6692). This ticket was imported from: [TWNTY-6692](https://github.com/twentyhq/twenty/issues/6692) --- ### Description The problem is not related to the API, what was happening was a failure in the form validation, because in the changed file, the `currencyCode` value, which should be a string with single quotes around it, was receiving single quotes again, unnecessarily, and this affected field validation in `packages/twenty-front/src/modules/object-record/record-field/validation-schemas/currencyFieldDefaultValueSchema.ts` please, make this change below before testing the PR(to fix a bug, the slice is not updated yet):\ ### Demo ### Refs #6692 Fixes #6692 --------- Co-authored-by: gitstart-twenty Co-authored-by: Marie Stoppa * Fix twenty-front performances (#6744) I have investigated the performance of our frontend vite build: `npx nx run twenty:start` of `npx nx run twenty:build` RAM usage: - 160Mb: vite serve - background typescript checker: 2.5GB - background eslint checker: 3.5GB I'm introducing two environment variables in FE .env to disable these checkers on lower configuration (and to disable them from CD build): ``` # VITE_DISABLE_TYPESCRIPT_CHECKER=true # VITE_DISABLE_ESLINT_CHECKER=true ``` * Increase front build max memory usage for sourcemaps build * [Fix] Move save button to top on field edit (#6739) Before image After Capture d’écran 2024-08-26 à 12 17 29 * E2E tests (#6717) Continuation of #6644 Now chromium browser is used in workspaces tests instead of firefox and screenshots after each test are properly saved in one folder when run from IDE and from terminal using `yarn test:e2e` command * View becomes blank after deleting select (#6703) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-6027](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6027). This ticket was imported from: [TWNTY-6027](https://github.com/twentyhq/twenty/issues/6027) --- ### Description - Delete corresponding view simultaneously once select field is deactivated instead of deleted because the bug happens on the deactivation (one step before deleting), confirmation: - Is still possible to create Kanban views with deactivated Select fields, but this is not related to the PR. - The changes on the frontend are for refreshing the data after the view deletion ### Refs #6027 ### Demo Fixes #6027 --------- Co-authored-by: gitstart-twenty Co-authored-by: Lucas Bordeau * Added sync status on the FE (#6730) Issue #6685 How do we make sure we get the latest syncStatus on the frontend? For now we dont get it unless refreshed. useInterval() on fetching account details? * Increase front build max memory usage for sourcemaps build * Fix Website build CD (#6751) Website CD has been broken by the recent addition of typeorm patch in root package.json Our current vision is to add npm package to each twenty-package package.json directly * [POC] add graphql query runner (#6747) ## Context The goal is to replace pg_graphql with our own ORM wrapper (TwentyORM). This PR tries to add some parsing logic to convert graphql requests to send to the ORM to replace pg_graphql implementation. --------- Co-authored-by: Charles Bochet * Fix twenty-front build (#6752) * 6256 refactor messaging module to remove all provider specific code and put it inside the drivers folders (#6721) Closes #6256 Closes #6257 + Create custom exceptions --------- Co-authored-by: Charles Bochet * Add function execution throttler (#6742) Add throttler service to limit the number of function execution * Improve record table scroll look (#6753) We had a regression on the record table as our inView hook was not able to find the right div to compute its margin. This is because we are identify this div by a hacky css selector as we don't have a direct control on it (it's provided by our scrolling library) * 6655 remove field direction in message and add it in mcma (#6743) Closes #6655 - Remove direction from message - Add direction do mcma - Create migration command - Create upgrade 0.24 * 5617 Create CalendarOngoingStaleCron Job (#6748) Closes #5617 --------- Co-authored-by: Charles Bochet * Fix post merge conflicts on messaging services * Fix post merge conflicts on messaging services * Fix message direction seeds (#6760) Direction is now on mcma and no longer on message * Add workflow statuses (#6765) Following figma updates https://www.figma.com/design/PNBfTgOVraw557OXChYagk/Explo?node-id=21872-7929&t=DOUzd6rzwr6lprcs-0 - No activity targets for workflow entities for now - Adding a direct relation between workflow run et workflow - Adding a status on the version (draft, active, deactivated) - Adding a list of statuses on workflow - publishedVersionId => lastPublishedVersionId Also adding: - the endpoint to deactivate a version * Added "Add record" button in kanban view column headers dropdown (#6649) Closes #4629 Refactored `RecordBoardColumnNewOpportunityButton` and `RecordBoardColumnNewButton` to use the same logic in dropdown. I kept those hooks inside `record-board-column` where these buttons are. Let me know if it should be placed somewhere else. Also Added navigation state preservation when clicked on `edit from settings` Thanks :) --------- Co-authored-by: Lucas Bordeau * Fix participant listeners (#6767) Fixes a bug where all the messagesParticipants and the calendarEventParticipants were linked to a contact after its restoration. * added "reply in gmail" button (#6754) Issue https://github.com/twentyhq/twenty/issues/4217 * fix: defaultHomePagePath to be last visited page or alphatically first active object with the name (#6629) ### ISSUE - Closes #6612 - Closes #6125 - Closes #5949 - Closes #6652 ### Description - [x] need to check changes in jest test. - [x] fallback to alphabetically firstActiveObject with the name if no last visited exist https://github.com/user-attachments/assets/dd11480b-c47f-4393-9857-8a55467061e3 - [x] fallback to last visited page with the last visited view by default if no views would have toggled with subNav or viewChangeDropdown it will fallback to INDEX or if no INDEX view then zero position view, works with both subNavViewBar and viewChangeDropdown. https://github.com/user-attachments/assets/33e97e55-2aa2-4c45-a3ab-fc8e43f4964c https://github.com/user-attachments/assets/d1db76a2-da59-4cd2-81bf-d6119408fbbf - [x] lastVisited view across the objects have been persisted so now navigating back from x object to y or z to x will open always last visited view and defaults to index or zero position view. https://github.com/user-attachments/assets/70a01a11-a7ef-4031-926e-02923551466c - [x] lastVisited Page with view has been persisted across the workspace, scope is per workspace so jumping between workspace will also work to have lastvisited object of particular workspace. https://github.com/user-attachments/assets/25107339-8ec1-4421-9f6e-1da43b8f4816 - [x] when lastVisitedObject has been deactivated and going back from settings should have a fallback Object that is alphabetically First activeObject. https://github.com/user-attachments/assets/6b24a933-b139-49ac-82b2-eac5e4848516 - [x] Creation of new View of **anyType** should also get persist and that should get lastVisitedObject with View in case the user leaves from there right away. https://github.com/user-attachments/assets/80ff7114-051d-4e9b-ab58-0e1e3a7d328c - [x] Similarly deleted view also works. https://github.com/user-attachments/assets/cb0b8043-fba4-4a66-941d-b3fa0a57eb22 - [x] fixed active subnav background when opening object directly with root path **/** , it wasn't showing active subNav background. Before: https://github.com/user-attachments/assets/db341c4a-f1f9-43c4-9838-37d1a1f5ab8e Fixed: https://github.com/user-attachments/assets/0f0fd492-bc5d-4efe-b695-bee4e3f41d4e --------- Co-authored-by: Lucas Bordeau * Removed drag grip and accent is now tertiary in hidden fields (#6650) Closes #6115 This change successfully addresses the issue as described. However, it also causes the primary non-draggable field, `Name`, to render without a draggable handle and with a secondary accent. Is this an acceptable outcome? https://github.com/user-attachments/assets/4bc15e00-6c73-41d4-8342-4e36487d0981 --------- Co-authored-by: Lucas Bordeau * Improve Data Importer Select Matching - Post Merge Updates (#6750) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-6135-1](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6135-1). --- ### Description This [PR](https://github.com/twentyhq/twenty/pull/6338) was merged, but the reviewr asked for some changes in another PR https://github.com/twentyhq/twenty/pull/6338#pullrequestreview-2255006727 ### Refs https://github.com/twentyhq/twenty/pull/6338 ### Demo Co-authored-by: gitstart-twenty * refactor graphql query runner connection mapper (#6771) * Add composite Emails field and forbid creation of Email field type (#6689) ### Description 1. - We are introducing new field type(Emails) - We are Forbiding creation of Email field - We Added support for filtering and sorting on Emails field - We are using the same display mode as used on the Links field type (chips), check the Domain field of the Company object - We are also using the same logic of the link when editing the field \ How To Test\ Follow the below steps for testing locally:\ 1. Checkout to TWENTY-6261\ 2. Reset database using "npx nx database:reset twenty-server" command\ 3. Run both the backend and frontend app\ 4. Go to Settings/Data model and choose one of the standard objects like people\ 5. Click on Add Field button and choose Emails as the field type \ ### Refs #6261\ \ ### Demo \ Co-authored-by: gitstart-twenty * fix: relation and record chip height (#6758) # ISSUE - Closes #6756 After Changes: https://github.com/user-attachments/assets/1885be11-b50a-4b05-afae-d2f02a403ad6 https://github.com/user-attachments/assets/edc6a913-95a6-4c75-8ec2-83e2c27fddb0 * fix/6759: reduce icon size in note grip menu to 16px and adjust conta… (#6780) ### Summary This pull request addresses issue #6759 by adjusting the icon size and container padding in the note grip menu. The 6-dot icon's size has been reduced from 20px to 16px, while the container size has been kept at 20px to maintain the proper alignment and spacing. ### Changes Made - **Icon Size**: Reduced the SVG icon size to 16x16px. - **Container Size**: Ensured the container remains 20x20px to accommodate the icon and maintain visual consistency. ### Screenshots Screenshot 2024-08-29 at 3 26 41 AM ### Related Issue - [Issue #6759] ### Testing - Verified that the icon and container sizes are correctly displayed in the note grip menu. - Ensured no other UI elements were affected by these changes. Please review the changes and let me know if any additional modifications are required. Thank you! Co-authored-by: Rishi Kant * Added ability to search objects and fields (#6775) Closes #6770 https://github.com/user-attachments/assets/e3134389-30d2-48c8-bbca-34209d5ae66d * chore(*): remove unused code (#6781) The code removed in the PR was flagged as unused by the JetBrains inspector. I did a QA on the dev environment but other checks are highly recommended. There is one commit by scope to make the review easier. --------- Co-authored-by: Charles Bochet * Fixed record table fetch more scroll bug (#6790) Fetch more on the record table was causing a strange bug where it was auto scrolling to the bottom of the newly loaded chunk of rows. This was confusing because we lost our previous position in the record table. With this fix the table doesn't scroll when more rows are loaded. The fetch more row has been moved in the same tbody as the rest of the rows. We now only hide it when there is no more record to fetch. --------- Co-authored-by: Charles Bochet * 0.24 changelog (#6787) * Bump version to 0.24 (#6789) As title * Update wording on soft deletes * Add instructions to migrate to 0.24 version * Created a breadcrumb for left nav menu sub items (#6762) Closes https://github.com/twentyhq/twenty/issues/6484 image * Create new steps in workflow editor (#6764) This PR adds the possibility of creating new steps. For now, only actions are available. The steps are stored on the server, and the visualizer is reloaded to include them. Selecting a step opens the right drawer and shows its details. For now, it's only the id of the step, but in the future, it will be the parameters of the step. In the future we'll want to let users add steps at any point in the diagram. As a consequence, it's crucial to be able to walk in the tree that make the steps to find the correct place where to put the new step. I wrote a function that returns where the new step should be inserted. This function will become recursive once we get branching implemented. Things to mention: - Reactflow needs every node and edge to have a unique identifier. In this PR, I chose to use steps' id as nodes' id. That way, it's easy to move from a node to a step, which helps make operations on a step without resolving the step's id from the node's id. * Set statuses on workflows (#6792) Add listener to keep status on workflows up to date: - version draft => statuses should contain draft - version active => statuses should contain active - version deactivated => if no version active, statuses should contain deactivated Renaming also the endpoints because it was not reflecting the full behaviour. Finally, adding a new status Archived for versions. Will be used when a version is deactivated, but is not the last published version anymore. It means this version cannot be re-activated. * Fix CI errored tasks for front (#6806) In this PR: - revert de-optimization of icons bundle for storybook. This was forcing the browser to load ~3k files while running stories - adding lazy loading on Settings route to improve developer experience (some files will be loaded later) - fix FE tests: unit, modules stories, pages stories --------- Co-authored-by: Charles Bochet * Increase storybook pages code coverage * fix: EmailThreads and Calendar making one extra graphql requests even total records are fetched (#6814) ## ISSUE (BUG) - Closes #5282 ## Description - [x] Email Threads Tab was making two graphql requests **[GetTimelineThreadsFromCompanyId]** when navigating after a first render of record page, once only, later it was making only one. - [x] Similarly Calendar Tab **[GetTimelineCalendarEventsFromCompanyId]** ### Before https://github.com/user-attachments/assets/c234b7b4-fe7d-4655-92d6-0a6817fda6b5 ### After https://github.com/user-attachments/assets/80af33c7-b801-4377-a59a-47c43e0fecdd Co-authored-by: Charles Bochet * fix: Updated Button states for pages and minor UI fix (#6812) ## Description #6811 - Deleted button lacked `accent danger` on options menu - Customize fields `onhover` lacked width to cover entire div tag - Deactivate button lacked variant ## After Screenshot 2024-08-31 at 1 43 29 AM Screenshot 2024-08-31 at 1 09 31 AM Screenshot 2024-08-31 at 1 07 49 AM --------- Co-authored-by: Charles Bochet * 6657 Refactor and fix blocklist (#6803) Closes #6657 - Fix listeners - Refactor jobs to take array of events - Fix calendar events and messages deletion --------- Co-authored-by: Charles Bochet * fix: Deactivate & Activate icons should be swapped UI improvements (#6796) ## Fix This fixes the minor UI issue #6795 in which it addressed the following two problems- 1. Fixed the Icon switch 2. Updated the Delete Modal ## Screenshots Screenshot 2024-08-30 at 1 38 31 AM Screenshot 2024-08-30 at 1 39 13 AM Screenshot 2024-08-30 at 1 39 23 AM * Add set custom object is soft deletable command (#6788) ## Context Custom object were not automatically created as softDeletable, this has been fixed in a recent PR. This PR adds a command to backfill existing custom objects. We also introduce a baseCommandRunner and ActiveWorkspacesCommandRunner to put some boilerplate and simplify future commands. ## Test ```bash yarn command:prod upgrade-0-24:set-custom-object-is-soft-deletable [Nest] 75852 - 08/29/2024, 5:16:41 PM LOG [SetCustomObjectIsSoftDeletableCommand] Running command on 2 workspaces query: UPDATE "metadata"."objectMetadata" SET "isSoftDeletable" = $1, "updatedAt" = CURRENT_TIMESTAMP WHERE ("workspaceId" IN ($2, $3) AND "isCustom" = $4 AND "isSoftDeletable" = $5) -- PARAMETERS: [true,"3b8e6458-5fc1-4e63-8563-008ccddaa6db","20202020-1c25-4d02-bf25-6aeccf7ea419",true,false] [Nest] 75852 - 08/29/2024, 5:16:41 PM LOG [SetCustomObjectIsSoftDeletableCommand] Updated 1 entities [Nest] 75852 - 08/29/2024, 5:16:41 PM LOG [SetCustomObjectIsSoftDeletableCommand] Command completed! ``` ```bash yarn command:prod upgrade-0-24:set-custom-object-is-soft-deletable -d [Nest] 75424 - 08/29/2024, 5:16:14 PM LOG [SetCustomObjectIsSoftDeletableCommand] Running command on 2 workspaces [Nest] 75424 - 08/29/2024, 5:16:14 PM LOG [SetCustomObjectIsSoftDeletableCommand] Dry run mode: No changes will be applied query: SELECT "ObjectMetadataEntity"."id" AS "ObjectMetadataEntity_id" FROM "metadata"."objectMetadata" "ObjectMetadataEntity" WHERE (("ObjectMetadataEntity"."workspaceId" IN ($1, $2)) AND ("ObjectMetadataEntity"."isCustom" = $3) AND ("ObjectMetadataEntity"."isSoftDeletable" = $4)) -- PARAMETERS: ["3b8e6458-5fc1-4e63-8563-008ccddaa6db","20202020-1c25-4d02-bf25-6aeccf7ea419",true,false] [Nest] 75424 - 08/29/2024, 5:16:14 PM LOG [SetCustomObjectIsSoftDeletableCommand] Dry run: 1 entities would be updated [Nest] 75424 - 08/29/2024, 5:16:14 PM LOG [SetCustomObjectIsSoftDeletableCommand] Command completed! ``` ```bash yarn command:prod upgrade-0-24:set-custom-object-is-soft-deletable -w 20202020-1c25-4d02-bf25-6aeccf7ea419 -w 20202020-1c25-4d02-bf25-6aeccf7ea419 query: UPDATE "metadata"."objectMetadata" SET "isSoftDeletable" = $1, "updatedAt" = CURRENT_TIMESTAMP WHERE ("workspaceId" IN ($2, $3) AND "isCustom" = $4) -- PARAMETERS: [true,"20202020-1c25-4d02-bf25-6aeccf7ea419","20202020-1c25-4d02-bf25-6aeccf7ea419",true] [Nest] 70588 - 08/29/2024, 5:11:31 PM LOG [SetCustomObjectIsSoftDeletableCommand] Updated 2 entities [Nest] 70588 - 08/29/2024, 5:11:31 PM LOG [SetCustomObjectIsSoftDeletableCommand] Command completed! ``` --------- Co-authored-by: Charles Bochet * Make custom objects soft deletable by default (#6768) Fixes #6766 * fix: Fixed API typo and webhook checkerror (#6779) ## Issue 1.There was an Api typo with API under Developers section #6778 2. Webhook lacked an check method for the `TextInput` #6774 ## After- Screenshot 2024-08-29 at 2 13 21 AM https://github.com/user-attachments/assets/8e2b06bc-308a-48ad-8ecb-9d0a130877bc --------- Co-authored-by: Charles Bochet * Serverless function improvements (#6769) - add layer for lambda execution - add layer for local execution - add package resolve for the monaco editor - add route to get installed package for serverless functions - add layer versioning * Prevent workflow version from bad update (#6848) Closes https://github.com/twentyhq/twenty/issues/6840 - Add query-hooks folder in common. Will be followed by hooks for workflows and runs - When updating a version, ensure the status is draft and that the status is not manually updated * chore: improve the softdelete style (#6846) ## This PR - Fix #6836 Screenshot 2024-09-02 at 17 54 31 * Updated MultiItemFieldInput to display current value properly (#6857) * fix: securing tasks and notes all view (#6869) ISSUE - Closes #6863 * Ability to filter on DATE fields (#6299) (#6824) This was surprisingly quick, it was already built, just not enabled. Let's double check it together still on Monday @FelixMalfait! * Field name is oddly displayed when long (#6755) ### Description - we added a new styled component to handle the label styles - we added the title prop, and this will be applied for all fields, track the styles and only adding the title if the label is hidden would add unnecessary complexity to this issue, let us know if It's fine - On our internal QA review, we noticed this extra error in the name:\ when we have spaces between the characters on names the name is displayed in a weird way ![](https://assets-service.gitstart.com/28455/b3933bec-f5ec-48b9-a627-744507bc9fad.png) when we don't have spaces we use the space on the right to fit the full name\ like this: ![](https://assets-service.gitstart.com/28455/77aec9d1-7875-4164-b2ce-97ccee7fb25e.png)Do you want us to fix this problem too? when testing the new changes since we changed one component that is used on the main pages we created objects with a big name, to test the header on the table view, and we noticed that the object name has exactly the same issue as the field name on the settings page. !\[image\]() we added a fix for new field creation if the object name is long ![](https://assets-service.gitstart.com/28455/99faef48-99b4-480e-ae6d-71aa40030434.png)### Refs #6738 ### Demo Fixes #6738 --------- Co-authored-by: gitstart-twenty Co-authored-by: Marie Stoppa * update refresh token expires in (#6879) Fixes https://github.com/twentyhq/twenty/issues/6598 Updating the refresh token default value to a much more common threshold, this can still be overridden with env variables when needed. Example of the refresh token mechanism from the fronted side Screenshot 2024-09-03 at 16 05 12 Screenshot 2024-09-03 at 16 05 22 * Add workflow query hooks (#6876) Workflow version : - prevent status to be update manually - prevent creation / deletion in another status than draft - prevent creation if a draft already exists Workflow: - prevent statuses to set manually WorkflowRun: - prevent all manual operations * Enable payload without status update (#6881) As title * fix: Updated Menu item font size (#6884) ## Description This PR solves the issue #6878. Updated the font size from 12 px to 13 px. ## Before Screenshot 2024-09-03 at 11 46 58 PM ## After Screenshot 2024-09-03 at 11 47 33 PM * Fix bug bypassing verification in confirmation modal when pressing Enter (#6889) # Description Fix bug bypassing verification in the confirmation modal when pressing Enter # Demo Tested for webhook case (similar to other cases): 1. Press Enter when invalid verification => not delete webhook 2. Press Enter when valid verification => delete webhook https://github.com/user-attachments/assets/81aa0aaa-7361-4584-b7ae-b29525f33664 # Ref Fixes #6663 * fix(6423): add username and password for redis connection (#6745) Co-authored-by: pbb * Check if user wants to run make postgres-on-linux (#6819) Fix #6319 Now script checks if user wants to run the script, the default is no, so user has explicitly type `y` or `Y` in order to run it. * Fix unauthorized error handling (#6835) from @BOHEUS comments in #6640 - fix bad 500 error when authentication invalid - remove "id", "createdAt", "updatedAt", etc from creation and update paths schema - improve error message - remove "id" from test body - improve secondaryLink schema description - improve depth parameter description - remove required from response body - improve examples - improve error message formatting - fix filter by position - answered to negative float position @BOHEUS comment Also: - fix secondary field openapi field description - remove schema display in playground Screenshots ![image](https://github.com/user-attachments/assets/a5d52afd-ab10-49f3-8806-ee41b04bc775) ![image](https://github.com/user-attachments/assets/33f985bb-ff75-42f6-a0bb-741bd32a1d08) * Update workflow nodes configuration (#6861) - Improve the design of the right drawer - Allow to update the trigger of the workflow: the object and the event listened to - Allow to update the selected serverless function that a code action should execute - Change how we determine which workflow version to display in the visualizer. We fetch the selected workflow's data, including whether it has a draft or a published version. If the workflow has a draft version, it gets displayed; otherwise, we display the last published version. - I used the type `WorkflowWithCurrentVersion` to forward the currently edited workflow with its _current_ version embedded across the app. - I created single-responsibility hooks like `useFindWorkflowWithCurrentVersion`, `useFindShowPageWorkflow`, `useUpdateWorkflowVersionTrigger` or `useUpdateWorkflowVersionStep`. - I updated the types for workflow related objects, like `Workflow` and `WorkflowVersion`. See `packages/twenty-front/src/modules/workflow/types/Workflow.ts`. - This introduced the possibility to have `null` values for triggers and steps. I made the according changes in the codebase and in the tests. - I created a utility function to extract both parts of object-event format (`company.created`): `packages/twenty-front/src/modules/workflow/utils/splitWorkflowTriggerEventName.ts` * Fixed view reset on view change (#6897) Fixes #6833 The view states for unsaved changes were not reseted on view change. The fix was to just add a call to the existing resetCurrentView when the viewId changes in the related effect. * Fix restore event sent to webhooks (#6905) We were sending the wrong event when restoring a record (delete instead of create) * Add workspace favorites behind feature flag (#6904) - make member nullable on favorites - add potential relation with view entity - add a new type of favorite list in front : workspace favorite - build a new component for retrieving workspace favorite to display + refacto the existing one Bonus: - removing activities seed since this is deprecated * Display workflow visualizer on show page (#6894) - Removed the route I previously used to visualize workflows - Created another tab in the `` component in which we display the visualizer Questions: - Should I use a feature flag to hide the feature? Closes #6858 * fix: Api text typo in ApiKeyInput.tsx (#6916) (#6918) ## Issue Closes (#6916) There was an `Api` typo with API under Developer section while copying the API Key to clipboard in the status popup which is now corrected to `API`. * fix: Minor UI fixes in Settings page (#6915) ## Description This PR fixes the issue #6887. ## Current Behaviour - https://github.com/user-attachments/assets/6e53f7f5-7fed-4482-9c67-fb33969429ab - Screenshot 2024-09-04 at 10 25 14 AM ## Expected behavior - https://github.com/user-attachments/assets/63e92a6a-6be5-4d0a-b42f-d4310492b8b4 - Screenshot 2024-09-04 at 10 36 49 AM * Fixed open table cell triggering (#6910) Open table cell was triggered by a click on a field input. This is a temporary solution. I fixed it for DoubleTextInput but it might be problematic for other field types as well, we should implement a kind of bubbling shield to make sure that no click event can bubble up to trigger things like open table cell in the above components that shouldn't listen. See https://github.com/twentyhq/twenty/issues/6909 * added scroll wrapper for ShowPageActivityContainer (#6903) fixes #6902 * Enables creating an opportunityCard instantly if company field is disabled (#6316) (#6911) fixes #6316 --------- Co-authored-by: martmull * Fix lint (#6922) * multiselect for onetomany relations (#6892) Issue #4345 used `useUpdateRelationFromManyFieldInput` hook from `FieldInput` to `updateRelation`. Creating a seperate hook didnt made sense when it basically does the same thing. However renaming the hook to something generic would make sense so that its not tied to `FieldInput` according to naming convention followup issue to tackle - #6890 https://github.com/user-attachments/assets/452372ea-2699-45fd-9edf-ded36abdbca2 --------- Co-authored-by: Weiko * fix: settings search field bottom padding (#6920) ## ISSUE - Closes #6919 * Adds KeyBoard Navigation to ObjectFilterDropDownFilterSelect ( #4365 ) (#6613) fixes #4365 --------- Co-authored-by: Lucas Bordeau * Added new view to select types for objects (#6700) Issue #6496 Hi team, Is this the right approach for handling type selection with states and conditional rendering, or should these be managed on separate pages altogether? Please let me know Ill make changes accordingly :) I’m also working on styling the buttons according to the Figma design and will be moving constants like categoryDescriptions and categories to the constants folder. Thanks for your guidance! https://github.com/user-attachments/assets/452bea9f-4d0a-4472-9941-421b54cda47f --------- Co-authored-by: Lucas Bordeau Co-authored-by: Charles Bochet * Adds secondary color and styles to code snippets in block note editor ( #6029 ) (#6928) fixes https://github.com/twentyhq/twenty/issues/6929 --------- Co-authored-by: Lucas Bordeau * added timeout to avoid appending of blocks (#6725) @FelixMalfait fixes #6724 Thanks :) --------- Co-authored-by: Lucas Bordeau * fix: Minor bugs in notes pages (#6914) ## Descripion This PR fixed the issue #6913 ## Currently behavior Screenshot 2024-09-06 at 1 12 33 AM Screenshot 2024-09-06 at 1 13 31 AM ## Expected behaviour Screenshot 2024-09-06 at 1 15 07 AM Screenshot 2024-09-06 at 1 15 20 AM Co-authored-by: Lucas Bordeau * Fixed page inputs style layout bugs (#6899) ## Description This PR resolves the issue #6870 - Adjusted width for all textInput - `240px` - Added responsiveness to Address field - [ ] To add Blur to background text component ## Before Screenshot 2024-09-05 at 11 57 40 AM Screenshot 2024-09-05 at 11 57 54 AM ## After Screenshot 2024-09-05 at 11 51 37 AM Screenshot 2024-09-05 at 11 52 26 AM Screenshot 2024-09-05 at 11 52 50 AM --------- Co-authored-by: Lucas Bordeau * Update SettingsDevelopersApiKeyDetail.tsx typo (#6937) Corrected typo error of Expiration description in which it was "diasbled" to "disabled". * fix: Notes not visible in Timeline activities (#6936) ## Description - This PR solves #6935 #6934 - fixed the notes color in timeline activities which was not visible in dark mode - fixed spelling typo ## Before Screenshot 2024-09-08 at 12 28 03 PM Screenshot 2024-09-08 at 12 20 27 PM ## After Screenshot 2024-09-08 at 12 27 53 PM Screenshot 2024-09-08 at 12 19 17 PM * Prevent fullWidth from being passed to Link ie (#6893) fixes #6825 * sort task groups reverse alphabetically by their status (#6886) This PR Solves #6830 ## Issue Summary The tasks are grouped by their respective statuses and displayed on the ui. The grouping is performed by `lodash.groupBy` which doesn't maintain explicit ordering of the keys. ## Fix Sort the tasks groups array by their status on the basis of reverse-alphabetical order before generating task component for each task data. #### Why reverse alphabetical? It implicitly sorts the statuses as per the order `TODO` -> `IN_PROGRESS` -> `DONE` Caveats: 1. Changing the name of one or more status might result in a different unwanted order. 2. `null` is unhandled, although the original code doesn't allow for nulls as status while displaying ### Alternative Fix Maintain an explicit ordering of the statuses and sort the tasks accordingly. --------- Co-authored-by: Lucas Bordeau * fix: ability to create empty kanban (#6951) ## ISSUE - Closes #6946 * minor fix - removed scrollwrapper stylings for SettingsPageContainer (#6949) @Bonapara fixes https://github.com/twentyhq/twenty/pull/6700#issuecomment-2322817298 * Bump version to 0.24.2 (#6955) * Fix/object detail recordcell tooltip (#6908) Fixes for https://github.com/twentyhq/twenty/issues/6596 ![image](https://github.com/user-attachments/assets/69014a93-a61c-4b6a-bffa-33fdb31a8511) --------- Co-authored-by: martmull * Fixes multi-select search not working ( #6800 ) (#6964) fixes #6800 * Fixed the overflow height of the Developers page's table (#6963) Ref: https://github.com/twentyhq/twenty/issues/6962 As of now, if user has more than 20 API keys or webhooks, whole page has scroll, when for the end user (UX) it'd be better if each table had it's own scroll. * added button in nav bar for kanban view (#6829) @Bonapara Addressing issue #6783. I tried to achieve the exact behavior you were looking for, but I couldn't get the dropdown to render correctly in that specific column. I'd love some help to make sure it's working as expected! 😊 Most of the logic is shared with the `useHandleOpportunity` and `useAddNewCard` hooks, which could be refactored to reduce code debt. Also, please go harsh with the review because I know there's a lot of code cleaning required. I also agree with Charles's point in [this comment](https://github.com/twentyhq/twenty/issues/6783#issuecomment-2323299840). Thanks :) https://github.com/user-attachments/assets/bccdb3f1-3946-4e22-b9a4-b7496ef134c9 * Adds secondary color and styling to code blocks using theme varibales ( #6029 ) (#6931) Follow-up of #6929, this PR just changes the hard coded values to theme values. * Fix note linked text in timeline view (in dark mode) (#6944) This PR Fixes https://github.com/twentyhq/twenty/issues/6942 Other improvements : - Fetch activities (note and task) title only when loading timeline, so we don't always have a clickable title. - Fixed IconButton width regression. --------- Co-authored-by: Lucas Bordeau * Support for multiple values in the Phone field (#6882) ### Description - This is the first PR on Phones field; - We are introducing new field type(Phones) - We are Forbidding creation of Phone field - We Added support for filtering and sorting on Phones field - We are using the same display mode as used on the Links field type (chips), check the Domain field of the Company object - We are also using the same logic of the link when editing the field **How to Test** 1. Checkout to TWNTY-6260 branch 2. Reset database using "npx nx database:reset twenty-server" command 3. Add custom field of type Phones in settings/data-model **Loom Video:**\ ### Refs #6260 Co-authored-by: gitstart-twenty * Fix not possible to edit options (#6979) We have recently merged: https://github.com/twentyhq/twenty/pull/6700 However, this introduced a regression on field edition as we have removed the type dropdown from the field edition page. This dropdown was wrapped into a controller setting the type on the form. Without this type, the form is considered as invalid and cannot be saved. I'm setting the form values through useForm. I'm unhappy with this PR for too reasons: - usage of activeMetadataField?.icon ?? '' format because I cannot call useForm conditionnally. This would imply splitting the component into several components to avoid this issue - usage of react hook form which is very hard to debug, we should remove it from the project * [Flexible-schema] Add findOne and fix findMany pagination + soft-delete for graphql-query-runner (#6978) * Fixed CI (#6982) Fixed CI : - Unit test for useTimelineActivities - Story for field creation with new 2-step process * Refactor graphql query runner + fix nested or (#6986) * Add relations to notes/tasks list view (#6971) Screenshot 2024-09-10 at 17 00 11 --------- Co-authored-by: Lucas Bordeau * 6658 workflows add a first twenty piece email sender (#6965) * add contibuting_example.md (#6998) add a contributing_example.md on folder .github --------- Co-authored-by: Félix Malfait * Set all standard objects soft deletable (#7006) * Refactor metadata caching (#7011) This PR introduces the following changes: - add the metadataVersion to all our metadata cache keys to ease troubleshooting: image - introduce a cache recompute lock to avoid overloading the database to recompute the cache many time * Scaffold empty workflow (#6926) - Create a workflow version when the user visits an empty workflow. - If the trigger is not defined yet and the user selects either the standard object type or the event type first, we automatically select the first option of the other value. Indeed, every state update is automatically saved on the backend and we need both standard object and event types to save the event name. - Introduces a change in the backend. I removed the assertions that throw when a workflow version is not complete, that is, when it doesn't have a defined trigger, which is the case when scaffolding a new workflow with a first empty workflow version. - We should keep validating the workflow versions, at least when we publish them. That should be done in a second step. * Handle migration of Email to Emails fields (#6885) This is the second PR on TWNTY-6261 which handlesdata migration of Email field to Emails field.\ \ How to Test?\ Firstly make sure that you have completed the testing steps on first PR then follow the below steps: - Checkout to TWNTY-6261-emails-migrations branch - Rebuild typescript using "npx nx build twenty-server" - Run command "yarn command:prod upgrade-0.25" to do migration\ \ Loom Video:\ **Testing Messaging Sync functionality:** Please watch the below video to see that the synchronization of contacts is working fine after migrating Email field to Emails field:\ **Question to the client** should we rename email to emails here? in the DomainName PR, the name did not change. ```typescript @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.email, type: FieldMetadataType.EMAILS, label: 'Email', description: 'Contact’s Email', icon: 'IconMail', }) email: EmailsMetadata; ``` **Test Messaging Sync** This pr will update messaging sync files so the changes shouldn't break existing functionality of importing people and companies in the app.\ To test messaging sync you should follow the below steps:\ 1. you need to connect a google account to see the importing functionality. For this purpose you have to create a project inside Google Cloud. But to make things easier you can use the below credentials of an already created project. Put them in .env of twenty-server package: ```properties MESSAGING_PROVIDER_GMAIL_ENABLED=true CALENDAR_PROVIDER_GOOGLE_ENABLED=true AUTH_GOOGLE_ENABLED=true AUTH_GOOGLE_CLIENT_ID=951231465939-h61tg6nkpkv1821qi899fjbj9looquto.apps.googleusercontent.com AUTH_GOOGLE_CLIENT_SECRET=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 AUTH_GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/redirect AUTH_GOOGLE_APIS_CALLBACK_URL=http://localhost:3000/auth/google-apis/get-access-token MESSAGE_QUEUE_TYPE=bull-mq ``` Alternative env ```properties MESSAGING_PROVIDER_GMAIL_ENABLED=true CALENDAR_PROVIDER_GOOGLE_ENABLED=true AUTH_GOOGLE_ENABLED=true AUTH_GOOGLE_CLIENT_ID=622006708006-dc4n3vrtf3cs2h6k7hgbborudme7ku9l.apps.googleusercontent.com AUTH_GOOGLE_CLIENT_SECRET=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 AUTH_GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/redirect AUTH_GOOGLE_APIS_CALLBACK_URL=http://localhost:3000/auth/google-apis/get-access-token MESSAGE_QUEUE_TYPE=bull-mq ``` 1. Launch your worker with `npx nx run twenty-server:worker` 2. npx nx run twenty-server:command cron:messaging:messages-import 3. npx nx run twenty-server:command cron:messaging:message-list-fetch 4. npx nx run twenty-server:command cron:calendar:calendar-event-list-fetch 5. Run the app and navigate to Settings/Accounts then connect your Google account --------- Co-authored-by: gitstart-twenty Co-authored-by: Marie Stoppa Co-authored-by: Weiko * Display tag for workflow version status (#6972) - Move where we fetch workflow data. We now fetch them in the `Workflow` component directly. That's useful to access it in the `WorkflowShowPageEffect` and `WorkflowDiagramCanvas` components. ![CleanShot 2024-09-10 at 16 27 53@2x](https://github.com/user-attachments/assets/7d30f407-31ab-472c-a096-c525042c0f35) * [metadata] fix soft delete for standard objects missing deletedAt fieldMetadata (#7017) This https://github.com/twentyhq/twenty/pull/7006 introduced a regression. The goal was to set "isSoftDeletable" to all standard objects but it was done at the wrong level, meaning it was setting the boolean correctly but not creating the corresponding fieldMetadata. I took the occasion to update the new graphql query runner to use that boolean and automatically add a filter on soft delete in case it's true. Also adding **IsQueryRunnerTwentyORMEnabled** by default in the seeds * add field config new icons (#6996) https://github.com/twentyhq/twenty/issues/6950 Add new icons to Object Fields Data types. Before: ![image](https://github.com/user-attachments/assets/55697e31-841d-435e-8c70-13ff1c59268d) After: ![image](https://github.com/user-attachments/assets/bd43f0ec-d3f7-4ecf-a95f-87a030f68e24) ![image](https://github.com/user-attachments/assets/369893a9-35be-43f8-bfcb-55149effa78a) * Optimize metadata queries (#7013) In this PR: 1. Refactor guards to avoid duplicated queries: WorkspaceAuthGuard and UserAuthGuard only check for existence of workspace and user in the request without querying the database * Fix billing services not accepting new subscriptions * Fix emailThread not loading and rest batch api forbidden * feat: improve self hosting documentation (#7024) This PR aims to resolve common misunderstanding while deploying Twenty with Docker compose. I've made the documentation clearer, and more detailed. This should solve https://github.com/twentyhq/twenty/issues/5184, #6140 and similar issues * feat: replace ts-node with tsx and pre-install it globaly in docker (#7027) Implement https://github.com/twentyhq/twenty/issues/5976 suggestion. It leads to faster boot time since we don't have to install dependencies. It should also solve https://github.com/twentyhq/twenty/issues/4772 as we don't need to run ressource-heavy `npm install` (the mentioned migration step does not seem to exist anymore anyway. * fix(one-liner): update SERVER_URL when not using default port (#7026) Small fix that should resolve #6341 by replacing the port of SERVER_URL in the generated .env file * Add data-testid to MultiWorkspaceDropdownButton container (#7028) PR for #6895 * removed @chakra-ui dependencies (#7004) Issue #6976 @FelixMalfait I could not do ``` import { Banner } from 'twenty-ui'; const StyledBanner = styled(Banner) display: flex; align-items: center; padding: ${({ theme }) => theme.spacing(8)}; position: absolute; border-radius: 8px; &:hover { background-color: ${({ theme }) => theme.accent.primary}; } ; ``` The styles wont get overridden for Banner, so for now I styled a new banner in `UnmatchColumnBanner` which is inconsistent. I couldnt figure out why css properties are not being overridden, need help! @Bonapara Question - Should the click work on entire banner or just cheveron? For now it just on cheveron click. https://github.com/user-attachments/assets/0f409e78-a341-4f26-af74-117e4b2775a9 --------- Co-authored-by: Charles Bochet * Optimize sync, reset, seed commands to flush cache and to use less memory (#7034) In this PR: - removing ugprade-0.24 commands as we are releasing 0.30 - introducing cache:flush command - refactoring upgrade command and sync-metadata command to use the ActiveWorkspacesCommand so they consistently run on all workspaces or selected workspaces Fixes: - clear localStorage on sign out - fix missing workspaceMember in verify resolver - do not throw on datasource already destroyed exception which can happen with race condition when several resolvers are resolving in parallel * Optimize migrate-email-fields-command (#7035) Quick follow up to prepare for 0.30 release * Fix contributor script (#7040) We had an issue affecting twenty.com/contributors ; this should probably fix it * [flexible-schema] Add createOne/createMany with upsert to graphql query runner (#7041) ## Context This PR introduces createOne/createMany through the new graphql query runner. Trying to use twentyOrm wrapper as much as possible, in this case here the args are already converted from "metadata-like" structure (including composite fields) as graphql input to typeorm / raw columns (I had to introduce a little fix there). Keep in mind that I'm not using the new graphql query runner parsing classes here, especially the selected-fields part, because typeorm already returns all the record columns in the InsertResult object (including default values such as id, createdAt, ...). That also means relation objects will be returned as NULL in the gql response but we don't handle nested creation for the moment so it should be fine. Note: also removing the feature flag from findOne/findMany * Remove objectMetadata isSoftDeletable * 0-30-set-custom-object-is-soft-deletable.command (#7045) This command was supposed to set all custom objects as softDeletable. After some discussion we realised this bool was not used as intended so we are removing it all together until we find a better usage (remote objects for example). This PR removes the command which won't be needed anymore * Introduce ARRAY field type (#6862) This PR was created by \[GitStart\]() to address the requirements from this ticket: \[TWNTY-6447\](). This ticket was imported from: ### Description \- We added a new field type ### Refs #6447 ### Demo Fixes #6447 --------- Co-authored-by: gitstart-twenty Co-authored-by: Charles Bochet * Create command to set stale message sync back to pending (#7048) Some message channels are stuck in an ongoing `syncStage` because `syncStartedAt` was not set correctly at the beginning of the sync. This command resets message channels with an ongoing `syncStage` and `syncStartedAt` set to null. * Fix: Set sync stage started at when starting sync (#7046) Fix:`syncStageStartedAt` was not set correctly after refactoring * Re-enable displaying one-to-many in table and kanban (#7053) As per title * fix: Company picker opening when it shouldn't (#7023) ### The Company Picker opens when it shouldn't. Fixes #6989 ### Video https://github.com/user-attachments/assets/a1e56418-8409-46e8-879a-d8335593ea28 * fix: page header accessible when deleting webhook (#6985) ## Description This PR resolves the issue #6817 - while deleting webhook, page header is still accessible for both mobile viewport and large devices - When creating a webhook, save or cancel state is not accessible due to page header being overflowed. - Setting state breaks spaces resulting due to `max-width` ## Current Behaviour https://github.com/user-attachments/assets/991b29ac-df1b-4250-8c83-444a36148a7f Screenshot 2024-09-11 at 4 23 51 PM Screenshot 2024-09-11 at 4 24 12 PM ## Expected behavior https://github.com/user-attachments/assets/cbac0b56-578f-49d5-a092-84f936016ca6 Screenshot 2024-09-11 at 4 24 26 PM --------- Co-authored-by: bosiraphael * [Emails migration] Fix email field migration (#7065) Fix email field migration - Remove deprecated field of type Email - Add standard emails field on person to person views in position 4 * relations header button to appear at all times for mobile devices (#7044) fixes #7036 * Fix search on email (#7094) following email (text field type) -> emails (emails field type - composite) migration! closes https://github.com/twentyhq/twenty/issues/7080 * New Settings Layout (#6867) #### \ Description - **Added "Exit Settings" Back Button**: Introduced a new back button labeled "Exit Settings" for easy navigation back to the app content. - **Implemented Settings Navbar Breadcrumb**: A breadcrumb navigation bar for each settings page has been added to improve navigation within the settings. This ensures users can easily trace their location within the settings. - **Persistent CTA Zone**: The Call-to-Action (CTA) zone at the top of the page now remains visible even when the user scrolls down, preventing unresponsive behavior and improving accessibility. - **Page Title**: The page title has been added to each settings page and separated from the breadcrumb, following the app's layout standards. - we could not reproduce the Billing and CMR Migrations settings on the app, but we updated the files according, please let's us know if is there any way to log in with access to these pages, or if is everything ok. - Some breadcrumbs are not following the Figma, are following the current app sections isntead, because we would need to change the sidebar structure, and we should not do it on this PR ### Demo ### Refs: #6144 Fixes #6144 --------- Co-authored-by: gitstart-twenty Co-authored-by: Lucas Bordeau * 7092 destroy connected account instead of soft deleting it (#7099) - Create `destroyOne` endpoint - Call `destroyOne` when removing a `connectedAccount` * Add logs to troubleshoot performances issues * Feat(frontend): improve the soft delete empty state (#6877) # This PR - Fix #6834 ## Demo https://www.loom.com/share/235c4425f3264f429e2064a9d1604a90?sid=02a815c9-3b1a-45e6-b5ce-d5eb3b40e10e ## Notes - There is a missing icon in Figma corresponding to the `noDeletedRecordFound` in the dark mode, thus I used the same icon (different background because we have the correct background image) for both dark / light modes Screenshot 2024-09-03 at 15 04 57 cc: @Bonapara --------- Co-authored-by: Lucas Bordeau * Fixes resetting of scroll position in RecordShowPage due to opening of some dropdowns (#6890) (#6906) fixes #6890 --------- Co-authored-by: Lucas Bordeau * Verification popup can be activated multiple times (#6938) Fixes https://github.com/twentyhq/twenty/issues/6912 By clicking Enter key over and over, user can repeat action Expected: When 'yes' is typed in popup and user clicks Enter key once, popup should disappear and correlated action should be performed only once Implementation: - Added loading state for buttons onClick and onEnter to disable the button when the "Delete Api Key" and "Regenerate Api Key" function is called. - Added a new function to handle modal close and logic handling on clicking enter key. --------- Co-authored-by: Lucas Bordeau * Twnty-#6797 view/edit inactive feature (#6953) This PR resolves the issue raised under #6797. Earlier no view/edit option were present for inActive objects in data-model inside settings. To resolve that following changes were done: 1. `SettingsObjectFieldItemTableRow` was not passing the onEdit with url to `SettingsObjectFieldActiveActionDropdown` to redirect on clicking it. So passed onEdit there. 2. `SettingsObjectFieldActiveActionDropdown` was not implementing the onEdit functionality, so implemented that by creating `handleEdit()` function. 3. `SettingsObjectFieldEdit` was assuming only `activeObjectMetadata `will be coming to render on page. So, when inactive object was accessed the path not found error message was thrown. Thus did changes to manage both active and inactive objects by generalizing the `activeObjectMetadata ` -> `objectMetadata` `activeMetadataField `-> `metadataField`. 4. `findObjectMetadataItemBySlug `function was written inside `useFilteredObjectMetadataItems` for fetching active/inactive object. 5. Updated `SettingsObjectFieldEdit` button to show and change the active to inactive state and vice versa. 6. Test was written for `findObjectMetadataItemBySlug`. --------- Co-authored-by: Lucas Bordeau * fix: Tasks page overflows with large title and body (#6970) ## Description This PR solves the issue #6968. ## Before https://github.com/user-attachments/assets/7a18498e-1185-423e-922f-585d0f93eafb - For responsive behaviour Screenshot 2024-09-11 at 2 49 46 AM ## Expected behavior https://github.com/user-attachments/assets/3f64e246-6431-4eea-9acf-5bf124aadc22 - Screenshot 2024-09-11 at 2 48 39 AM ## Edge cases Edge cases handled - - when date is added or removed, it doesn't effect the body or title - Relations with long names don't affect the task body - Short title and long description and long description and short title are handled --------- Co-authored-by: Lucas Bordeau * Fix race condition with datasource creation (#7106) ## Context We currently have a race condition when dealing with datasource creation. This happen when multiple queries arrive at the same time (for example graphql dataloaders) and the datasource is not created yet. Since the datasource is stored in memory this can happen more often as well and they were all triggering the datasource creation at the same time. I'm trying to fix the issue with promise memoization. Now, instead of caching the datasource only, we also want to cache the promise of the datasource creation and make the creation itself synchronous. More info about promise memoization in this article for example: https://www.jonmellman.com/posts/promise-memoization Co-authored-by: Charles Bochet * 7059 Fix email loading in the timeline (#7116) Fixes #7059 * Modify messaging settings description (#7089) Modify messaging settings description * enhance picture uploader, change justify content (#6974) Fixes https://github.com/twentyhq/twenty/issues/6966 to put label in the place and change remove button to gray. sorry you dont assign this to me but I want to help, hope that if 6 hours pass u could check it --------- Co-authored-by: Lucas Bordeau * Add fail on metadata cache miss (#7118) - avoid failing when missing cache (used for command) - remove unused load cache function. Cache will be always re-created when trying to fetch if not existing * Fixed scroll wrapper for settings page container (#7124) Padding was set on global page component while it is needed only for settings page container component. * Improve demo seed (#7125) We have a few issues on demo seeding: - redis metdata cache was not flushed - server ram graphql schema cache was not cleared on metadata version increment * Backfill workspace favorites (#7122) - command to backfill workspace favorites - create workspace favorites on workspace activation - create workspace favorites on demo seed --------- Co-authored-by: Charles Bochet * Add SettingsCard for Config Data Type and Accounts Settings (#7093) https://github.com/twentyhq/twenty/issues/6950 Add new Settings Card for Config Data Type and accounts Settings Before: Screenshot 2024-09-11 at 17 43 16 After: Screenshot 2024-09-17 at 14 15 18 Screenshot 2024-09-17 at 14 15 38 * 0.30 changelog (#7126) * Fix graphql query createMany resolver with nested relations (#7061) Looks like insert() does not return foreign keys. We could eventually call findMany after but it seems that's what save() is doing so I'm replacing insert with save. ```typescript /** * Flag to determine whether the entity that is being persisted * should be reloaded during the persistence operation. * * It will work only on databases which does not support RETURNING / OUTPUT statement. * Enabled by default. */ reload?: boolean; ``` Note: save() also does an upsert by default with no way to configure that so if we want to keep that behaviour we will need to add a check before ```typescript if (args.upsert) { const existingRecords = await repository.findBy({ id: Any(args.data.map((record) => record.id)), }); ... ``` --------- Co-authored-by: Charles Bochet * Fix sync statuses on the fe (#7117) Follows #6685 * Fix nested relations with large dataset in find queries (#7127) ## Before before ## After after * Fix performance (#7131) * Improve perf during repository creation in nested relations (#7132) * feat(invitation): Improve invitation flow - Milestone 2 (#6804) From PR: #6626 Resolves #6763 Resolves #6055 Resolves #6782 ## GTK I retain the 'Invite by link' feature to prevent any breaking changes. We could make the invitation by link optional through an admin setting, allowing users to rely solely on personal invitations. ## Todo - [x] Add an expiration date to an invitation - [x] Allow to renew an invitation to postpone the expiration date - [x] Refresh the UI - [x] Add the new personal token in the link sent to new user - [x] Display an error if a user tries to use an expired invitation - [x] Display an error if a user uses another mail than the one in the invitation --------- Co-authored-by: Charles Bochet * Improved note cards design (#7129) Fixes #7120 - Removed margin according to design - Increased card content padding from 8px to 16px ![image](https://github.com/user-attachments/assets/bf1b2be4-7176-4af1-bad0-7e7f159b57c2) * Add deletedAt to foreignKey indexes (#7133) We had to remove soft-deletion on default filters due to the missing indexes. We now generate composite indexes with the foreign key containing the deletedAt column as well which should improve performances * [Bug] Select options names can't start with a number (#7079) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-6980](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6980). This ticket was imported from: [TWNTY-6980](https://github.com/twentyhq/twenty/issues/6980) --- ### Description - **fix**: added a transformation step that prefixes the newly added option with an underscore before the Graphql enum is generated so it saves successfully and passes the default GraphQL validation. ### Demo - ### Refs #6980 Fixes #6980 Co-authored-by: gitstart-twenty Co-authored-by: Weiko * Upgrade sentry (#7145) Upgrave Sentry to v8 and add Sentry Cron monitoring --------- Co-authored-by: Charles Bochet * Clean views without object metadata (#7153) Add command for cleaning + clean on object deletion * 7142 make messaging full message list fetch idempotent (#7148) - Add message deletion and thread cleaning during full message list fetch - Add thread cleaning during partial message list fetch - Delete provider from cache key * Fix nested relations (#7158) Co-authored-by: Charles Bochet * Fix CSV export missing last page (#7167) * feat: add integration tests (#6923) ### Summary This PR introduces several integration tests, a mix of manually written tests and those generated using the `generate-integration-tests` Python script located in the `scripts` folder. ### Tests Added: - **Authentication tests**: Validating login, registration, and token handling. - **FindMany queries**: Fetching multiple records for all existing entities that do not require input arguments. ### How the Integration Tests Work: - A `setupTest` function is called during the Jest test run. This function initializes a test instance of the application and exposes it on a dedicated port. - Since tests are executed in isolated workers, they do not have direct access to the in-memory app instance. Instead, the tests query the application through the exposed port. - A static accessToken is used, this one as a big expiration time so it will never expire (365 years) - The queries are executed, and the results are validated against expected outcomes. ### Current State and Next Steps: - These tests currently run using the existing development seed data. We plan to introduce more comprehensive test data using `faker` to improve coverage. - At the moment, the only mutation tests implemented are for authentication. Future updates should include broader mutation testing for other entities. --------- Co-authored-by: Charles Bochet * fix: Cropped company logos on the Companies Kanban (#7166) > [!Note] > This PR addresses the issue #7161 > Removed margin right which made images crop. ## Before Screenshot 2024-09-20 at 1 35 55 AM ## After Screenshot 2024-09-20 at 1 35 34 AM * fix: Update theme card width (#7147) > [!Note] > This PR solves the issue #7119 > Updated the width of Style Color card from ` 120px `to ` 160px` for better UI * Update System Data Type Names to Display 'System' #7136 (#7170) Changes made in twenty/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx fixes #7136 Co-authored-by: subham sharma * Fixed bug with record without activity target (#7175) Fixed bug that was appearing with records without any activity target The problem may come from the new TwentyORM that doesn't understand the filter like before. * Change demo account email (#7177) Change the demo account's email to be able to set SIGN_IN_PREFIL = true on demo.twenty.com * Add indexes to custom relations (#7156) TODO: command to retro-actively create indexes to existing custom objects * View module refactor with atomic recoil component instance states (#6810) This PR refactors the view module to implement utils that avoid having to create hooks to inject the scope id in the states, like `useViewStates`, each componentState will know its unique related InstanceContext (which holds the instanceId), and thus will be able to retrieve it itself. We keep the naming componentState as it reflects the fact that those states are tied to instances of a component (or its children). We introduce the instance word where it is needed, in place of scopeId for example, to precise the fact that we handle instances of component state, one for each instance of a component. For example, the currentViewId is a state that is tied to an instance of the ViewBar, but as we can switch between views, we want currentViewId to be a componentState tied to an instance of the ViewBar component. This PR also refactors view filter and sort states to fix this issue : https://github.com/twentyhq/twenty/issues/6837 and other problems involving resetting those states between page navigation. Fixes https://github.com/twentyhq/twenty/issues/6837 --------- Co-authored-by: Charles Bochet * Safely parse phone numbers before display (#7186) Timeline activity properties are stored as string rather than array. Adding a safe parsing in front. Would be better to also update in backend but doing this as a quick fix * fix: Input fields to have expected behaviour in case of empty / only whitespaces string (#6736) # ISSUE - Closes #6734 - Closes #6633 - Closes #6733 - Closes #6816 # Description - [x] Don't allow Empty (whitespaces) Objects to Create, all the keyboard shortcuts are also handled for this. https://github.com/user-attachments/assets/1c9add4e-f13f-458b-8f76-63bd868413a2 https://github.com/user-attachments/assets/e72b6ee3-74e4-4517-a230-3eb10db80dc7 Note: we do have one other issue with FullName field #6740 Inorder to test use **shift**. - [x] Api Keys Input Name Field -> New and Detail View Name field shouldn't be empty or string with whitespaces, we won't able to have whitespaces in both. **Try Entering just spaces** https://github.com/user-attachments/assets/b521b49f-648c-4585-9d15-8ff4faed3c3a - [x] Similar to above, Empty webhook endpoint url under **/settings/developers/webhooks/new** won't be created. **Try Entering just spaces** - [x] New Functions or Updating Functions will not able to have whitespaces, empty string as Name. **Try Entering just spaces** https://github.com/user-attachments/assets/09fcf394-c6d9-4080-8efd-462b054a22d0 - [x] under **settings/workspace-members** changes will lead and solve that user won't be able to enter Invite by email as just whitespaces + button is now getting disabled when there is no correct email. **Try Entering just spaces** https://github.com/user-attachments/assets/b352edfa-113b-4645-80fd-db6f120ab5db - [x] Text Input Field, will not allow to start entering with whitespaces and won't take just whitespaces as value spaces between words will work. https://github.com/user-attachments/assets/8c1a0812-45be-4ed2-bd3d-bb4f92147976 - [x] Similarly Number works as per above including shortcuts. https://github.com/user-attachments/assets/9f69cc87-5c3c-43ee-93c4-fa887bc0d7ee - [x] Similarly FullName field works as per above including shortcuts https://github.com/user-attachments/assets/7bb006b2-abf7-44cd-a214-7a2fc68df169 - [x] Pasting fullName is been Improved. - Case 1 (Two Words): If there are exactly two words, return them as is. - Case 2 (More than Two Words): If there are more than two words, return the first two words only. - Case 3 (One Word): If there is only one word, return it as the first name, with an empty string as the last name. - WhiteSpaces have been handled. ``` console.log(splitFullName("John Doe")); // ["John", "Doe"] console.log(splitFullName(" ")); // ["", ""] console.log(splitFullName("John")); // ["John", ""] console.log(splitFullName(" John Doe ")); // ["John", "Doe"] console.log(splitFullName("John Michael Andrew Doe")); // ["John", "Michael"] ``` --------- Co-authored-by: Lucas Bordeau * 7182 person avatar is not the same color in emails and calendar (#7185) Fixes #7182 and displayName in calendar * Improve snackbar and fix sentry (#7181) - Improve snackbar to enable displaying multi-line message (so far we only displayed the first few words which was very frustrating) - Followup on previous issue to enable tim@apple.dev on the demo workspace (prefilled automatically) - Fix sentry tracing which had been broken when migrating from v7 to v8 * Set a unique constraint on email table in users #7180 (#7184) Link to issue - https://github.com/twentyhq/twenty/issues/7180 File changed - twenty/packages/twenty-server/src/engine/core-modules/user/user.entity.ts --------- Co-authored-by: subham sharma Co-authored-by: Félix Malfait * Fix linter (#7191) Fix linter * minor fix - email thread reply button stylings/corrections (#7168) fixes #7155 * Fix paginated order by with composite fields (#7187) ## Context Cursor is modifying the where object but does not handle properly composite fields. I'm introducing field metadata as a source of truth to fix this issue. RAW_JSON for example (as a sub-field type) should be ignored in a lt/gt, probably other field types as well. ## Before ```typescript [ { emails: { lt: { primaryEmail: "brenda.brown@example.com", additionalEmails: null, }, }, }, { emails: { eq: { primaryEmail: "brenda.brown@example.com", additionalEmails: null, }, }, position: { gt: 877, }, }, { emails: { eq: { primaryEmail: "brenda.brown@example.com", additionalEmails: null, }, }, position: { eq: 877, }, id: { gt: "fe43c45d-7560-4eb1-8fd3-c48fd0a4dcd4", }, }, ] ``` ## After ```typescript [ { emails: { primaryEmail: { lt: "brenda.brown@example.com", }, }, }, { emails: { primaryEmail: { eq: "brenda.brown@example.com", }, }, position: { gt: 877, }, }, { emails: { primaryEmail: { eq: "brenda.brown@example.com", }, }, position: { eq: 877, }, id: { gt: "fe43c45d-7560-4eb1-8fd3-c48fd0a4dcd4", }, }, ] ``` * Fix lambda creation (#7201) As title * Fix IN filter with empty array (#7202) ## Context The api currently allows empty array in the IN filter but the expected behaviour is not very clear. Typeorm seems to return all records when it is empty which could lead to undesired result. Instead we decided to throw an error. I've updated the FE accordingly to skip calls when array is empty. Screenshot 2024-09-23 at 14 20 28 * Fix demo seeds (#7204) * Introduced Specific Icons image identifier for Notes and Tasks (#6997) Fixes #6486 * fix: Appearance Settings Cropped Card (#7232) ## Description - This PR fixes the issue #7198 ## Before Screenshot 2024-09-24 at 10 58 13 AM ## After Screenshot 2024-09-24 at 10 57 31 AM * fix: #7226 - Improve photo uploader design (#7234) ## Description ### Changes Made - **Icon Size and Style**: Resized the icon**. - **Icon Update**: Changed to **photo-up**. - **Background Color**: Set to **transparent light**. - **Hover Background Color**: Set to **transparent medium**. - **Border**: Set to **Border/medium**. - **Icon Color on Hover**: Set to **light** and **tertiary**. ## Preview of the changes made - https://github.com/user-attachments/assets/72219531-7ffe-47b5-bae9-216764df68ee * Remove shouldUseEmailsField (#7208) Remove shouldUseEmailsField. This boolean was used to ensure retro-compatibility with the old email field. It is no longer needed. * Add try catch around messaging monitoring cron and fix decorators (#7207) Add try catch around messaging monitoring cron and fix decorators:`@Process` and `@SentryCronMonitor` were inverted. * Handle migration of Phone field to Phones field (#7128) This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-6260](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-6260). This ticket was imported from: [TWNTY-6260](https://github.com/twentyhq/twenty/issues/6260) --- ### Description This is the second PR on TWNTY-6260 which handles data migration of Phone field to Phones field.\ \ How to Test?\ Follow the below steps: - On the main branch, - go to `packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts` and change any person's phone number to a string with characters for example: "test invalid phone", and then reset the DB. - reset database using `npx nx database:reset twenty-server` - This is to make sure that invalid numbers will be handled properly. We should use the invalid value itself to avoid removing data and see how the behavior is on the front end. should be the same as in the main, the display shows the invalid value, but the input is empty when you click, and then you can update. - Checkout to `TWNTY-6260-phone-migration` branch - Rebuild typescript using `npx nx build twenty-server` - Run command `yarn command:prod upgrade-0.32` to do migration - Run both backend and frontend to see the migrated field ### Demo - **Loom Video:**\ ### Refs #6260 --------- Co-authored-by: gitstart-twenty Co-authored-by: Marie Stoppa Co-authored-by: Weiko * fix: onEnter creating new function page in settings (#7236) ## Description - This PR solves the issue #7235 - On pressing enter, it automatically redirected to New function page in settings * fix issue (#7152 : Improve relation empty states on record page) (#7157) - "No xxx" removed for empty relations - All(0) removed --------- Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com> * [fix][Phone field migration] Use "Phones" in new field label (#7239) * fix: Phone dropdown field has extra width (#6866) ## Description This PR solves the issue #6865 ## Current Behaviour Screenshot 2024-09-03 at 2 04 55 AM ## Expected behavior Screenshot 2024-09-03 at 2 05 46 AM * [Phones migration][Fix] Remove field from view after creation (#7243) * 'Display as relative date' field formatting option for dateTime and date fields #5398 (#6945) Implements #5398. --------- Co-authored-by: Lucas Bordeau Co-authored-by: Félix Malfait * Add index key to tasks and notes views (#7241) Missing INDEX key for some tasks and notes views. We need it to backfill favorites. * [Phone field migration][fix] Update field label (#7247) * [Phones migration](fix) update label of standard field by using raw query (#7255) * Fix calendar page without account (#7256) More details in this PR https://github.com/twentyhq/twenty/pull/7202 We(I) forgot to fix on the calendar page. * 7242 error when displaying message threads with a large number of participants (#7251) Closes #7242 * fix: Values field card lacks width in mobile viewports (#7248) ## Description - This PR fixes the issue #7230 ## Current Behaviour Screenshot 2024-09-24 at 9 51 42 AM ## After Screenshot 2024-09-25 at 10 38 40 AM Screenshot 2024-09-25 at 10 38 52 AM * Activate/Deactivate workflow and Discard Draft (#7022) ## Setup This PR can be tested only if some feature flags have specific values: - `IsWorkflowEnabled` equals `true` - `IsQueryRunnerTwentyORMEnabled` equals `false` These feature flags weren't committed to don't break other branches. ## What this PR brings - Display buttons to activate and deactivate a workflow version and a button to discard the current draft version. I also scaffolded a "Test" button, which doesn't do anything for now. - Wired the activate, deactivate and discard draft buttons to the backend. - Made it possible to "edit" active and deactivated versions by automatically creating a new draft version when the user tries to edit the version. - Hide the "Discard Draft", button if the current version is not a draft or is the first version ever created. - On the backend, don't consider discarded drafts when checking if a new draft version can be created. - On the backend, disallow deleting the first created workflow version. Otherwise, we will end up with a blank canvas in the front end, and it will be impossible to recover from it. - On the backend, disallow running deactivation steps if the workflow version is not currently active. Previously, we were throwing, which is unnecessary as it's a valid case. ## Spotted bugs that we must dive into ### Duplicate workflow versions in Apollo cache https://github.com/user-attachments/assets/7cfffd06-11e0-417a-8da0-f9a5f43b84e2 --------- Co-authored-by: Charles Bochet * Fixing last column width in table-view (#7258) fixes: #7160 `table-layout: fixed` requires a width, added that. Screenshots: image image Small screen:
image image
--------- Co-authored-by: sid0-0 * Kanban card creation revamp (#7169) fixes #6957 * Fix LinkedIn URL special character formatting (#7249) Before: link-formatting-before After: linkedin-formatting-after Co-authored-by: Nitin Koche * Connect EventTracker to TB endpoint (#7240) #7091 EventTrackers send information of events to the TinyBird instance: In order to test: 1. Set ANALYTICS_ENABLED= true and TELEMETRY_ENABLED=true in evironment-variables.ts 2. Set the TINYBIRD_TOKEN in environment variables (go to TiniyBird Tokens) 3. Log in to twenty's TinyBird and go to datasources/analytics_events in twenty_analytics workspace 4. Run twenty and navigate it 5. New events will be logged in the datasources, containing their timestamp, sessionId and payload. Screenshot 2024-09-24 at 17 23 01 Example of payload when user is not logged in ``` {"hostName":"localhost", "pathname":"/welcome", "locale":"en-US", "userAgent":"Mozilla/5.0", "href":"http://localhost:3001/welcome", "referrer":"", "timeZone":"Europe/Barcelona"} ``` Example of payload when user is logged in ``` {"userId":"2020202", "workspaceId":"202", "workspaceDisplayName":"Apple", "workspaceDomainName":"apple.dev", "hostName":"localhost", "pathname":"/objects/companies", "locale":"en-US", "userAgent":"Mozilla/5.0Chrome/128.0.0.0Safari/537.36", "href":"http://localhost:3001/objects/companies", "referrer":"", "timeZone":"Europe/Paris"} ``` --------- Co-authored-by: Félix Malfait * Fix: Remove 'Soon' integrations from Settings when disabled (#7259) ## Description This PR addresses issue #7110, where Airtable, Stripe and PostgreSQL integrations were showing as "Soon" under Settings > Integrations. ## Changes - Update `getSettingsIntegrationAll` so that when these integrations are disabled (via feature flags), they are removed from the list instead of showing as "Soon". Screenshot 2024-09-25 at 11 21 07 a m - Tweaked `useSettingsIntegrationCategories` to only show the "All" category if there's at least one integration enabled. Screenshot 2024-09-25 at 11 21 15 a m ## Notes This is my first contribution to the project, so I'm open to feedback! 😄 Let me know if there's anything I should tweak or improve. * Fix email migration script (#7267) * Update clean view command + add dry run to favorite backfill (#7268) Clean favorites associated with activities * Add phone fields migration command to 0 30 (#7269) Add phone fields migration command to 0 30 * Fix analytics (#7271) Incorrect check * Change tinybird event format (#7272) Separate pageview analytics from core events * fix: Cursor pointer on Settings cards (#7291) > [!Note] > This PR solves the issue #7289 * Add Header to Email & Calendar Tabs #7288 (#7293) # Fix: 7288 - Add Header to Email & Calendar Tabs (No Account Connected) ## Description Added a header to the **Email** and **Calendar** tabs when no account is connected, matching the style and spacing of the account page to prevent layout issues when switching between pages. ### Header Content: - **Connected Accounts** - **Manage your internet accounts** ## Screenshot: Screenshot 2024-09-27 at 5 20 55 PM Fixes #7288 --------- Co-authored-by: Félix Malfait * 5922 - UI Overlap and State Persistence in Filter Menus (#7270) fixes #5922 https://github.com/user-attachments/assets/07d088da-cefb-4d87-9016-e14cef18567d * 7154 deleted event is not emitted when calling destroyone (#7159) Closes #7154 * Date filter improvements (#5917) (#7196) Solves issue #5917. This PR is now ready for the first review! Filters do not fully work yet, there's a problem applying multiple filters like the following: ``` { and: [ { [correspondingField.name]: { gte: start.toISOString(), } as DateFilter, }, { [correspondingField.name]: { lte: end.toISOString(), } as DateFilter, }, ], } ``` I'll do my best to dig into it tonight! --------- Co-authored-by: Félix Malfait * Fix use object metadata item (#7297) Fixes a bug which happened during workspace creation and remove duplicated code * Fix standardId issues with phones field migration (#7294) Co-authored-by: Weiko * Fix email migration (#7298) Checks if person standard email field exists before running the migration. * Fix viewFilter operand for dateTime fields (#7306) * Add 0.30 release notes (#7300) In this PR: - update your environment variables to default `CACHE_STORAGE_TYPE` to `redis` and `MESSAGE_QUEUE_TYPE` to `bull-mq` - add redis container to our default docker-compose - add `REDIS_HOST` and `REDIS_PORT` to docker-compose yaml - add upgrade instructions * remove extra files * update NavigationDrawerSectionForObjectMetadataItems --------- Co-authored-by: Charles Bochet Co-authored-by: Charles Bochet Co-authored-by: nitin <142569587+ehconitin@users.noreply.github.com> Co-authored-by: Thomas Trompette Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com> Co-authored-by: gitstart-twenty Co-authored-by: Lucas Bordeau Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com> Co-authored-by: martmull Co-authored-by: Naineel Soyantar <112230479+naineel1209@users.noreply.github.com> Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com> Co-authored-by: Baptiste Devessier Co-authored-by: Marie Stoppa Co-authored-by: BOHEUS <56270748+BOHEUS@users.noreply.github.com> Co-authored-by: Weiko Co-authored-by: Nabhag Motivaras <65061890+Nabhag8848@users.noreply.github.com> Co-authored-by: Rishi Kant <110294979+kant-github@users.noreply.github.com> Co-authored-by: Rishi Kant Co-authored-by: Antoine Moreaux Co-authored-by: Thomas des Francs Co-authored-by: Harshit Singh <73997189+harshit078@users.noreply.github.com> Co-authored-by: Pacifique LINJANJA Co-authored-by: ad-elias Co-authored-by: Lý Thanh Bách <40271986+bachtly@users.noreply.github.com> Co-authored-by: PB Borel Co-authored-by: pbb Co-authored-by: Félix Malfait Co-authored-by: Faisal-imtiyaz123 <142205282+Faisal-imtiyaz123@users.noreply.github.com> Co-authored-by: Viraj Jaiswal <157706576+Virajjai@users.noreply.github.com> Co-authored-by: Avinash Bhardwaj Co-authored-by: Sandheep-OSC <149194578+Sandheep-OSC@users.noreply.github.com> Co-authored-by: Shreyansh Kumar Co-authored-by: Gaurav Khanna Co-authored-by: Muhamad Fahri Mulyawan Co-authored-by: Félix Malfait Co-authored-by: Ana Sofia Marin Alexandre <61988046+anamarn@users.noreply.github.com> Co-authored-by: Quentin G. Co-authored-by: Divyesh Patel Co-authored-by: bosiraphael Co-authored-by: HKS07 <77383317+HKS07@users.noreply.github.com> Co-authored-by: Heber Santiago Alvarez Rincon <92112336+heber59@users.noreply.github.com> Co-authored-by: Jérémy M Co-authored-by: Subham Sharma <83713146+subhamengine@users.noreply.github.com> Co-authored-by: subham sharma Co-authored-by: Falgun Patel <92120797+falgunmpatel@users.noreply.github.com> Co-authored-by: sid0-0 <43578323+sid0-0@users.noreply.github.com> Co-authored-by: sid0-0 Co-authored-by: Nitin Koche Co-authored-by: Raul Villarreal --- .github/CODE_OF_CONDUCT.md | 2 +- .github/CONTRIBUTING.md | 59 +- .github/workflows/ci-server.yaml | 0 .gitignore | 4 +- .vscode/twenty.code-workspace | 4 + README.md | 2 + install.sh | 2 + package.json | 11 +- .../src/generated/graphql.tsx | 1 + packages/twenty-docker/.env.example | 6 +- packages/twenty-docker/docker-compose.yml | 8 +- packages/twenty-docker/twenty/Dockerfile | 2 + packages/twenty-docker/twenty/entrypoint.sh | 2 +- packages/twenty-emails/package.json | 2 +- .../src/emails/workflow-action.email.tsx | 29 + packages/twenty-emails/src/index.ts | 1 + packages/twenty-front/.eslintrc.cjs | 1 - packages/twenty-front/.storybook/main.ts | 3 - packages/twenty-front/jest.config.ts | 6 +- packages/twenty-front/package.json | 2 +- .../background/no_deleted_record_bg.png | Bin 0 -> 2920 bytes .../dark-background/no_deleted_record_bg.png | Bin 0 -> 2997 bytes .../dark-background/no_match_record_bg.png | Bin 6194 -> 2878 bytes .../dark-moving-image/no_deleted_record.png | Bin 0 -> 7584 bytes .../moving-image/no_deleted_record.png | Bin 0 -> 7617 bytes .../twenty-front/public/mockServiceWorker.js | 19 +- packages/twenty-front/setupTests.ts | 11 + packages/twenty-front/src/App.tsx | 196 +- packages/twenty-front/src/SettingsRoutes.tsx | 362 + .../effect-components/PageChangeEffect.tsx | 15 +- .../src/generated-metadata/gql.ts | 11 +- .../src/generated-metadata/graphql.ts | 1832 +- .../twenty-front/src/generated/graphql.tsx | 3000 +-- .../src/hooks/usePreventOverlapCallback.ts | 32 + packages/twenty-front/src/index.css | 2 +- .../modules/accounts/types/CalendarChannel.ts | 34 +- .../modules/accounts/types/MessageChannel.ts | 25 +- .../calendar/components/Calendar.tsx | 15 +- .../calendar/components/CalendarEventRow.tsx | 2 +- .../activities/components/RichTextEditor.tsx | 8 +- .../emails/components/EmailThreadMessage.tsx | 9 +- .../emails/components/EmailThreadPreview.tsx | 10 +- .../emails/components/EmailThreads.tsx | 12 +- ...ThreadMessagesOperationSignatureFactory.ts | 6 +- .../components/IntermediaryMessages.tsx | 7 +- .../components/RightDrawerEmailThread.tsx | 133 +- .../hooks/useRightDrawerEmailThread.ts | 44 +- .../types/EmailThreadMessageParticipant.ts | 3 + .../types/EmailThreadMessageWithSender.ts | 6 + .../getDisplayNameFromParticipant.test.ts | 3 + .../useActivityTargetObjectRecords.test.tsx | 12 +- .../__tests__/useCreateActivityInDB.test.tsx | 6 +- .../useOpenCreateActivityDrawer.test.tsx | 4 +- .../modules/activities/hooks/useActivities.ts | 13 +- .../hooks/useActivityTargetObjectRecords.ts | 42 +- .../components/ActivityTargetsInlineCell.tsx | 6 +- .../activities/notes/components/NoteCard.tsx | 6 +- .../tasks/components/TaskGroups.tsx | 30 +- .../activities/tasks/components/TaskRow.tsx | 20 +- .../hooks/__tests__/useCompleteTask.test.tsx | 13 +- .../components/EventRow.tsx | 6 +- .../components/TimelineActivities.tsx | 2 +- .../__tests__/useTimelineActivities.test.tsx | 24 +- ...s => useLinkedObjectObjectMetadataItem.ts} | 2 +- .../hooks/useLinkedObjectsTitle.ts | 43 + ...ctivities.tsx => useTimelineActivities.ts} | 18 +- .../activity/components/EventRowActivity.tsx | 41 +- .../message/components/EventCardMessage.tsx | 1 + .../types/TimelineActivityLinkedObject.ts | 1 + ...lterTimelineActivityByLinkedObjectTypes.ts | 12 + .../analytics/graphql/queries/track.ts | 4 +- .../hooks/__tests__/useEventTracker.test.tsx | 28 +- .../analytics/hooks/useEventTracker.ts | 50 +- .../hooks/__tests__/useApolloFactory.test.tsx | 6 +- .../utils/getRelationDefinition.ts | 62 - .../triggerUpdateRelationsOptimisticEffect.ts | 36 +- .../services/__tests__/apollo.factory.test.ts | 4 +- .../modules/auth/graphql/mutations/signUp.ts | 2 + .../auth/hooks/__test__/useAuth.test.tsx | 8 +- .../src/modules/auth/hooks/useAuth.ts | 54 +- .../auth/sign-in-up/hooks/useSignInUp.tsx | 7 +- .../sign-in-up/hooks/useSignInWithGoogle.ts | 10 +- .../hooks/useSignInWithMicrosoft.ts | 11 +- .../hooks/useWorkspaceFromInviteHash.ts | 1 + .../components/ClientConfigProviderEffect.tsx | 4 - .../graphql/queries/getClientConfig.ts | 3 - .../client-config/states/telemetryState.ts | 8 - .../command-menu/components/CommandMenu.tsx | 6 +- .../__stories__/CommandMenu.stories.tsx | 4 +- .../components/ExceptionHandlerProvider.tsx | 2 +- ...ryInitiEffect.tsx => SentryInitEffect.tsx} | 12 +- ...sx => CurrentWorkspaceMemberFavorites.tsx} | 20 +- .../components/WorkspaceFavorites.tsx | 45 + .../favorites/hooks/__mocks__/useFavorites.ts | 563 +- .../hooks/__tests__/useFavorites.test.tsx | 14 +- .../modules/favorites/hooks/useFavorites.ts | 64 +- .../src/modules/favorites/types/Favorite.ts | 1 + .../favorites/utils/sort-favorites.util.ts | 49 + .../KeyboardShortcutMenu.stories.tsx | 36 + .../formatDateISOStringToRelativeDate.ts | 25 + .../components/AppNavigationDrawer.tsx | 2 +- .../components/MainNavigationDrawerItems.tsx | 21 +- .../__tests__/useDefaultHomePagePath.test.ts | 13 +- ...ionDrawerSectionForObjectMetadataItems.tsx | 161 + ...onForObjectMetadataItemsSkeletonLoader.tsx | 29 + ...erSectionForObjectMetadataItemsWrapper.tsx | 40 + .../ObjectMetadataItemsLoadEffect.tsx | 12 +- .../components/ObjectMetadataNavItems.tsx | 107 - .../ObjectMetadataNavItemsSkeletonLoader.tsx | 28 - ...nForObjectMetadataItemsWrapper.stories.tsx | 44 + .../ObjectMetadataNavItems.stories.tsx | 41 - .../constants/SortableFieldMetadataTypes.ts | 1 + .../object-metadata/graphql/mutations.ts | 3 + .../object-metadata/graphql/queries.ts | 27 +- .../hooks/__mocks__/useFieldMetadataItem.ts | 3 + .../useFindManyObjectMetadataItems.ts | 28 +- ...ColumnDefinitionsFromFieldMetadata.test.ts | 14 +- .../useCreateOneRelationMetadataItem.test.tsx | 6 +- .../useFilteredObjectMetadataItems.test.tsx | 36 +- ...ectRecordIdentifierByNameSingular.test.tsx | 6 +- .../__tests__/useGetRelationMetadata.test.tsx | 14 +- .../__tests__/useObjectMetadataItem.test.tsx | 6 +- .../hooks/useFieldMetadataItem.ts | 10 +- .../hooks/useFilteredObjectMetadataItems.ts | 6 + .../hooks/useGetRelationMetadata.ts | 38 +- .../hooks/useGetStandardObjectIcon.ts | 37 + .../hooks/useObjectIsRemote.ts | 5 + .../object-metadata/hooks/useObjectLabel.ts | 5 + .../hooks/useObjectMetadataItem.ts | 21 +- .../hooks/useObjectNamePluralFromSingular.ts | 5 +- .../hooks/useObjectNameSingularFromPlural.ts | 6 +- .../types/CoreObjectNameSingular.ts | 1 + .../types/FieldMetadataItem.ts | 28 +- ...etObjectMetadataItemBySingularName.test.ts | 8 +- .../__tests__/getObjectOrderByField.test.ts | 6 +- .../utils/__tests__/getObjectSlug.test.ts | 6 +- ...ObjectMetadataAvailableForRelation.test.ts | 6 +- .../mapFieldMetadataToGraphQLQuery.test.tsx | 25 +- .../mapObjectMetadataToGraphQLQuery.test.tsx | 22 +- ...ormatFieldMetadataItemAsFieldDefinition.ts | 10 +- .../utils/formatFieldMetadataItemInput.ts | 9 +- ...atFieldMetadataItemsAsFilterDefinitions.ts | 6 + .../utils/formatRelationMetadataInput.ts | 7 +- .../utils/getLabelIdentifierFieldValue.ts | 8 - .../utils/getObjectMetadataItemsMock.ts | 15938 --------------- .../utils/getOrderByForFieldMetadataType.ts | 9 + .../utils/mapFieldMetadataToGraphQLQuery.ts | 25 +- .../utils/parseFieldRelationType.ts | 55 - .../fieldMetadataItemSchema.ts | 38 +- .../validation-schemas/selectOptionsSchema.ts | 4 - .../object-record/components/RecordChip.tsx | 10 +- .../graphql/types/RecordGqlOperationFilter.ts | 6 + .../hooks/__mocks__/personFragment.ts | 53 +- .../hooks/__mocks__/useCreateManyRecords.ts | 5 +- .../hooks/__mocks__/useCreateOneRecord.ts | 5 +- .../hooks/__mocks__/useUpdateOneRecord.ts | 3 +- .../__tests__/useFetchAllRecordIds.test.tsx | 4 +- .../__tests__/useFindManyRecords.test.tsx | 6 +- ...ordsForMultipleMetadataItemsQuery.test.tsx | 6 +- .../__tests__/useUpdateOneRecord.test.tsx | 15 +- .../hooks/useDestroyManyRecords.ts | 2 +- ...on.ts => useDestroyManyRecordsMutation.ts} | 0 .../hooks/useDestroyOneRecord.ts | 84 + .../hooks/useDestroyOneRecordMutation.ts | 39 + .../hooks/useCombinedFindManyRecords.ts | 5 +- .../MultipleFiltersDropdownButton.tsx | 11 +- .../MultipleFiltersDropdownContent.tsx | 143 +- ...ersDropdownFilterOnFilterChangedEffect.tsx | 1 + .../components/ObjectFilterDropdownButton.tsx | 14 +- .../ObjectFilterDropdownDateInput.tsx | 91 +- .../ObjectFilterDropdownFilterSelect.tsx | 113 +- ...jectFilterDropdownFilterSelectMenuItem.tsx | 43 + .../ObjectFilterDropdownOperandButton.tsx | 8 - .../ObjectFilterDropdownOperandSelect.tsx | 22 +- .../ObjectFilterDropdownOptionSelect.tsx | 8 +- .../ObjectFilterDropdownRecordSelect.tsx | 9 +- ...SingleEntityObjectFilterDropdownButton.tsx | 10 +- .../MultipleFiltersDropdownButton.stories.tsx | 125 + .../__tests__/useFilterDropdown.test.tsx | 10 +- .../hooks/useFilterDropdown.ts | 6 - .../hooks/useFilterDropdownStates.ts | 7 - .../hooks/useSelectFilter.ts | 59 + ...bjectFilterDropdownScopeInternalContext.ts | 4 +- .../object-filter-dropdown/types/Filter.ts | 1 - .../types/FilterType.ts | 4 +- .../getOperandsForFilterType.test.tsx | 13 +- .../utils/getInitialFilterValue.ts | 42 + .../utils/getOperandLabel.ts | 22 + .../utils/getOperandsForFilterType.ts | 16 +- .../utils/getRelativeDateDisplayValue.ts | 28 + .../components/ObjectSortDropdownButton.tsx | 118 +- .../hooks/__tests__/useSortDropdown.test.tsx | 10 +- .../hooks/useObjectSortDropdown.ts | 9 +- .../hooks/useSortDropdown.ts | 3 +- .../hooks/useSortDropdownStates.ts | 7 - .../ObjectSortDropdownScopeInternalContext.ts | 4 +- .../components/RecordBoardCard.tsx | 159 +- .../RecordBoardColumnCardsContainer.tsx | 4 +- .../components/RecordBoardColumnHeader.tsx | 18 +- .../components/RecordBoardColumnNewButton.tsx | 32 +- .../hooks/useAddNewCard.ts | 131 +- .../hooks/useAddNewOpportunity.ts | 31 +- .../hooks/useColumnNewCardActions.ts | 38 + .../useIsOpportunitiesCompanyFieldDisabled.ts | 17 + .../RecordBoardScopeInternalContext.ts | 4 +- ...NewRecordByColumnIdComponentFamilyState.ts | 19 + .../recordBoardNewRecordByColumnIdSelector.ts | 31 + .../__mocks__/fieldDefinitions.ts | 8 +- .../record-field/components/FieldDisplay.tsx | 8 + .../record-field/components/FieldInput.tsx | 8 + .../hooks/__tests__/useGetButtonIcon.test.tsx | 6 +- .../hooks/__tests__/useIsFieldEmpty.test.tsx | 6 +- .../__tests__/useIsFieldInputOnly.test.tsx | 4 +- .../__tests__/useIsFieldReadOnly.test.tsx | 4 +- .../hooks/__tests__/usePersistField.test.tsx | 21 +- .../__tests__/useToggleEditOnlyInput.test.tsx | 54 +- .../record-field/hooks/useInitDraftValueV2.ts | 2 +- .../record-field/hooks/usePersistField.ts | 14 +- .../display/components/ArrayFieldDisplay.tsx | 34 + .../display/components/DateFieldDisplay.tsx | 12 +- .../components/DateTimeFieldDisplay.tsx | 12 +- .../display/components/PhonesFieldDisplay.tsx | 11 + .../RelationFromManyFieldDisplay.tsx | 87 +- .../perf/RatingFieldDisplay.perf.stories.tsx | 4 +- ...ationFromManyFieldDisplay.perf.stories.tsx | 5 +- .../meta-types/hooks/useArrayField.ts | 44 + .../meta-types/hooks/useArrayFieldDisplay.ts | 24 + .../meta-types/hooks/useDateFieldDisplay.ts | 7 +- .../hooks/useDateTimeFieldDisplay.ts | 4 +- .../meta-types/hooks/usePhonesField.ts | 53 + .../meta-types/hooks/usePhonesFieldDisplay.ts | 22 + .../input/components/ArrayFieldInput.tsx | 39 + .../input/components/ArrayFieldMenuItem.tsx | 27 + .../input/components/EmailsFieldInput.tsx | 2 + .../input/components/FullNameFieldInput.tsx | 36 +- .../input/components/LinksFieldInput.tsx | 2 + .../input/components/MultiItemFieldInput.tsx | 48 +- .../components/MultiItemFieldMenuItem.tsx | 4 +- .../components/MultiSelectFieldInput.tsx | 25 +- .../input/components/NumberFieldInput.tsx | 2 +- .../input/components/PhonesFieldInput.tsx | 134 + .../input/components/PhonesFieldMenuItem.tsx | 32 + .../input/components/SelectFieldInput.tsx | 10 +- .../input/components/TextFieldInput.tsx | 14 +- .../RelationToOneFieldInput.stories.tsx | 8 +- .../input/utils/isDoubleTextFieldEmpty.ts | 9 + .../RecordFieldInputScopeInternalContext.ts | 4 +- .../record-field/types/FieldDefinition.ts | 11 - .../types/FieldInputDraftValue.ts | 69 +- .../record-field/types/FieldMetadata.ts | 52 +- .../types/guards/assertFieldMetadata.ts | 8 +- .../record-field/types/guards/isFieldArray.ts | 9 + .../types/guards/isFieldArrayValue.ts | 8 + .../types/guards/isFieldPhones.ts | 9 + .../types/guards/isFieldPhonesValue.ts | 15 + .../guards/isFieldRelationFromManyObjects.ts | 8 +- .../guards/isFieldRelationToOneObject.ts | 8 +- .../utils/computeDraftValueFromString.ts | 14 + .../record-field/utils/getFieldButtonIcon.tsx | 6 +- .../record-field/utils/isFieldValueEmpty.ts | 14 +- .../utils/isRecordMatchingFilter.ts | 22 + ...turnObjectDropdownFilterIntoQueryFilter.ts | 174 +- .../components/RecordIndexBoardContainer.tsx | 1 - .../components/RecordIndexContainer.tsx | 142 +- .../components/RecordIndexPageHeader.tsx | 32 +- .../RecordIndexPageKanbanAddButton.tsx | 166 + .../RecordIndexPageKanbanAddMenuItem.tsx | 55 + .../components/RecordIndexRecordChip.tsx | 13 +- .../RecordIndexRemoveSortingModal.tsx | 6 +- .../components/RecordIndexTableContainer.tsx | 9 +- .../RecordIndexTableContainerEffect.tsx | 10 +- .../contexts/RecordIndexEventContext.tsx | 9 - .../contexts/RecordIndexRootPropsContext.ts | 13 + .../hooks/useHandleIndexIdentifierClick.ts | 9 +- .../hooks/useHandleToggleColumnFilter.ts | 4 +- .../hooks/useHandleToggleColumnSort.ts | 4 +- .../hooks/useHandleToggleTrashColumnFilter.ts | 30 +- .../useRecordIndexPageKanbanAddButton.ts | 53 + .../useRecordIndexPageKanbanAddMenuItem.ts | 12 + .../hooks/useRecordTableRecordGqlFields.ts | 31 +- .../RecordIndexOptionsDropdownContent.tsx | 14 +- .../__tests__/useExportTableData.test.ts | 6 +- .../hooks/__tests__/useTableData.test.tsx | 122 +- .../options/hooks/useExportTableData.ts | 3 +- .../hooks/useRecordIndexOptionsForBoard.ts | 6 +- .../options/hooks/useTableData.ts | 8 +- .../components/RecordInlineCellContainer.tsx | 10 +- .../components/RecordInlineCellEditMode.tsx | 2 +- .../components/RecordShowContainer.tsx | 10 +- ...ordDetailRelationRecordsListEmptyState.tsx | 35 - .../RecordDetailRelationRecordsListItem.tsx | 10 +- .../RecordDetailRelationSection.tsx | 79 +- ...ordDetailRelationSectionSkeletonLoader.tsx | 31 - .../components/RecordDetailSectionHeader.tsx | 17 +- .../components/RecordTableActionBar.tsx | 11 +- .../record-table/components/RecordTable.tsx | 32 +- .../components/RecordTableEmptyState.tsx | 68 - .../components/RecordTableWithWrappers.tsx | 3 - .../perf/RecordTableCell.perf.stories.tsx | 7 +- .../components/__stories__/perf/mock.ts | 159 +- .../components/RecordTableEmptyState.tsx | 34 + .../RecordTableEmptyStateDisplay.tsx | 48 + .../RecordTableEmptyStateNoRecordAtAll.tsx | 36 + ...dTableEmptyStateNoRecordFoundForFilter.tsx | 36 + .../RecordTableEmptyStateRemote.tsx | 24 + .../RecordTableEmptyStateSoftDelete.tsx | 50 + ...rdTableEmptyStateNoRecordAtAll.stories.tsx | 39 + ...ptyStateNoRecordFoundForFilter.stories.tsx | 40 + .../RecordTableEmptyStateRemote.stories.tsx} | 36 +- ...ecordTableEmptyStateSoftDelete.stories.tsx | 39 + .../hooks/internal/useRecordTableStates.ts | 5 + .../hooks/useCreateNewTableRecords.ts | 33 + .../RecordTableCellDisplayContainer.tsx | 1 + .../components/RecordTableTd.tsx | 4 +- .../useSelectedTableCellEditMode.test.tsx | 4 +- .../hooks/__tests__/useUpsertRecord.test.tsx | 6 +- .../hooks/useOpenRecordTableCellV2.ts | 4 +- .../components/RecordTableHeader.tsx | 12 +- .../components/RecordTableHeaderCell.tsx | 11 +- .../RecordTableHeaderLastColumn.tsx | 5 +- .../RecordTableHeaderPlusButtonContent.tsx | 1 + .../components/RecordTableRowWrapper.tsx | 4 +- .../RecordTableScopeInternalContext.ts | 4 +- ...dTableFetchedAllRecordsComponentStateV2.ts | 4 +- ...isRecordTableScrolledLeftComponentState.ts | 4 +- .../isRecordTableScrolledTopComponentState.ts | 4 +- .../isSoftDeleteFilterActiveComponentState.ts | 7 + .../components/MultiRecordSelect.tsx | 10 +- .../MultipleObjectRecordSelectItem.tsx | 3 +- .../components/SelectableMenuItemSelect.tsx | 1 - .../SingleEntitySelectMenuItems.tsx | 18 +- ...attedAsObjectRecordForSelectArray.test.tsx | 6 +- .../RelationPickerScopeInternalContext.ts | 4 +- .../MultipleRecordSelectDropdown.tsx | 10 +- ...jectRecordsSpreasheetImportDialog.test.tsx | 54 +- ...OpenObjectRecordsSpreasheetImportDialog.ts | 8 +- .../utils/filterAvailableTableColumns.ts | 5 +- .../utils/generateDefaultFieldValue.ts | 5 +- .../utils/generateEmptyFieldValue.ts | 25 +- ...etDestroyOneRecordMutationResponseField.ts | 5 + .../utils/isFieldCellSupported.ts | 33 +- .../utils/sanitizeRecordInput.ts | 13 +- .../useFilteredSearchEntityQuery.test.tsx | 8 +- ...tingsAccountsCalendarChannelsContainer.tsx | 5 +- ...untsConnectedAccountsRowRightContainer.tsx | 36 +- .../SettingsAccountsMessageChannelDetails.tsx | 3 +- ...ttingsAccountsMessageChannelsContainer.tsx | 5 +- .../SettingsAccountsRowDropdownMenu.tsx | 6 +- .../SettingsAccountsSettingsSection.tsx | 30 +- .../settings/accounts/constants/SyncStatus.ts | 6 + .../utils/__tests__/computeSyncStatus.test.ts | 87 + .../accounts/utils/computeSyncStatus.ts | 42 + ...ngsNavigationCard.tsx => SettingsCard.tsx} | 43 +- .../SettingsNavigationDrawerItem.tsx | 14 +- .../SettingsNavigationDrawerItems.tsx | 82 +- .../components/SettingsPageContainer.tsx | 20 +- .../__stories__/SettingsCard.stories.tsx | 24 + ...ngsDataModelNewFieldBreadcrumbDropDown.tsx | 103 + .../SettingsDataModelPreviewFormCard.tsx | 13 +- .../data-model/constants/RelationTypes.ts | 28 +- .../constants/SettingsFieldTypeCategories.ts | 7 + .../SettingsFieldTypeCategoryDescriptions.ts | 10 + .../constants/SettingsFieldTypeConfigs.ts | 133 +- .../fields/components/StyledFormCardTitle.tsx | 9 + .../SettingsDataModelFieldAboutForm.tsx | 104 - .../SettingsDataModelFieldDescriptionForm.tsx | 47 + .../SettingsDataModelFieldIconLabelForm.tsx | 84 + ...SettingsDataModelFieldSettingsFormCard.tsx | 35 +- .../SettingsDataModelFieldToggle.tsx | 91 + .../SettingsDataModelFieldTypeSelect.tsx | 130 +- ...sDataModelFieldDescriptionForm.stories.tsx | 40 + ...gsDataModelFieldIconLabelForm.stories.tsx} | 20 +- ...ttingsDataModelFieldTypeSelect.stories.tsx | 6 - .../SettingsDataModelFieldDateForm.tsx | 63 + ...ingsDataModelFieldDateSettingsFormCard.tsx | 66 + .../hooks/useDateSettingsFormInitialValues.ts | 25 + .../SettingsDataModelFieldRelationForm.tsx | 13 +- ...DataModelFieldRelationSettingsFormCard.tsx | 6 +- .../useRelationSettingsFormInitialValues.ts | 9 +- .../settingsFieldFormSchema.ts | 8 +- .../SettingsDataModelFieldPreview.tsx | 3 +- .../SettingsDataModelOverviewEffect.tsx | 16 +- .../SettingsDataModelOverviewField.tsx | 21 +- .../SettingsObjectFieldDataType.tsx | 11 +- ...tingsObjectFieldDisabledActionDropdown.tsx | 20 +- .../SettingsObjectFieldItemTableRow.tsx | 23 +- .../components/SettingsObjectItemTableRow.tsx | 16 +- .../settings/data-model/types/RelationType.ts | 6 +- .../types/SettingsFieldTypeCategoryType.ts | 1 + .../developers/components/ApiKeyInput.tsx | 2 +- .../components/SettingsApiKeysTable.tsx | 2 + .../SettingsReadDocumentationButton.tsx | 2 +- .../components/SettingsWebhooksTable.tsx | 2 + .../hooks/useSettingsIntegrationCategories.ts | 18 +- .../utils/getSettingsIntegrationAll.ts | 27 +- .../profile/components/DeleteWorkspace.tsx | 15 +- .../SettingsServerlessFunctionsTable.tsx | 11 - .../queries/findManyAvailablePackages.ts | 7 + .../hooks/useGetAvailablePackages.ts | 20 + .../workspace/components/NameField.tsx | 4 +- .../SignInBackgroundMockContainer.tsx | 48 +- .../SignInBackgroundMockColumnDefinitions.ts | 20 +- .../SignInBackgroundMockFilterDefinitions.ts | 3 +- .../SignInBackgroundMockSortDefinitions.ts | 3 +- .../SignInBackgroundMockViewFields.ts | 3 +- .../components/UnmatchColumn.tsx | 114 +- .../components/UnmatchColumnBanner.tsx | 53 + .../DialogManagerScopeInternalContext.ts | 4 +- .../snack-bar-manager/components/SnackBar.tsx | 4 +- .../SnackBarManagerScopeInternalContext.ts | 4 +- .../field/display/components/ArrayDisplay.tsx | 62 + .../field/display/components/DateDisplay.tsx | 11 +- .../display/components/DateTimeDisplay.tsx | 11 +- .../field/display/components/PhoneDisplay.tsx | 4 +- .../display/components/PhonesDisplay.tsx | 122 + .../field/input/components/AddressInput.tsx | 19 +- .../input/components/DoubleTextInput.tsx | 28 +- .../field/input/components/TextAreaInput.tsx | 11 +- .../ui/field/input/components/TextInput.tsx | 9 +- .../ui/input/button/components/IconButton.tsx | 4 +- .../code-editor/components/CodeEditor.tsx | 64 +- .../components/ColorSchemeCard.tsx | 6 +- .../components/ColorSchemePicker.tsx | 4 + .../ui/input/components/ImageInput.tsx | 27 +- .../modules/ui/input/components/TextArea.tsx | 7 +- .../modules/ui/input/components/TextInput.tsx | 4 +- .../ui/input/components/TextInputV2.tsx | 8 +- .../components/AbsoluteDatePickerHeader.tsx | 108 + .../date/components/InternalDatePicker.tsx | 141 +- .../components/RelativeDatePickerHeader.tsx | 113 + .../RelativeDateDirectionSelectOptions.ts | 13 + .../RelativeDateUnitSelectOptions.ts | 13 + .../date/utils/getHighlightedDates.ts | 24 + .../date/utils/getMonthSelectOptions.ts | 16 + .../PhoneCountryPickerDropdownSelect.tsx | 2 +- .../input/editor/components/BlockEditor.tsx | 10 + .../useInputFocusWithoutScrollOnMount.ts | 14 + .../components/AnimatedPlaceholder.tsx | 8 +- .../constants/Background.ts | 1 + .../constants/DarkBackground.ts | 2 + .../constants/DarkMovingImage.ts | 2 + .../constants/MovingImage.ts | 1 + .../layout/dropdown/components/Dropdown.tsx | 9 +- .../dropdown/components/DropdownMenuInput.tsx | 39 +- .../components/DropdownMenuSearchInput.tsx | 25 +- .../DropdownScopeInternalContext.ts | 4 +- .../ui/layout/hooks/useShowAuthModal.ts | 6 + .../modal/components/ConfirmationModal.tsx | 24 +- .../src/modules/ui/layout/page/PageHeader.tsx | 10 +- .../ui/layout/page/SubMenuTopBarContainer.tsx | 34 +- .../right-drawer/components/RightDrawer.tsx | 2 +- .../components/RightDrawerRouter.tsx | 8 +- .../constants/RightDrawerPageIcons.ts | 3 +- .../constants/RightDrawerPageTitles.ts | 3 +- .../right-drawer/types/RightDrawerPages.ts | 3 +- .../components/SelectableItem.tsx | 10 +- .../hooks/useSelectableList.ts | 17 +- .../SelectableListScopeInternalContext.ts | 4 +- .../components/ShowPageActivityContainer.tsx | 25 +- .../components/ShowPageRightContainer.tsx | 27 +- .../components/ShowPageSummaryCard.tsx | 10 +- .../modules/ui/layout/tab/hooks/useTabList.ts | 2 +- .../TabListScopeInternalContext.ts | 4 +- .../ui/layout/table/components/TableRow.tsx | 6 +- .../action-bar/components/ActionBar.tsx | 2 +- .../bread-crumb/components/Breadcrumb.tsx | 64 +- .../link/components/RoundedLink.tsx | 2 +- .../link/components/UndecoratedLink.tsx | 15 +- .../components/StyledMenuItemBase.tsx | 6 +- .../MultiWorkspaceDropdownButton.tsx | 2 +- .../components/NavigationDrawer.tsx | 5 +- .../components/NavigationDrawerBackButton.tsx | 18 +- .../components/NavigationDrawerItem.tsx | 101 +- .../NavigationDrawerItemBreadcrumb.tsx | 79 + .../components/NavigationDrawerItemGroup.tsx | 1 - .../components/NavigationDrawerSubItem.tsx | 39 +- .../__stories__/NavigationDrawer.stories.tsx | 13 +- .../NavigationDrawerItem.stories.tsx | 109 + .../types/NavigationDrawerSubItemState.ts | 6 + .../utils/getNavigationSubItemState.ts | 35 + .../hooks/useRecoilScopedStateV2.ts | 4 +- .../utils/createScopeInternalContext.ts | 7 +- .../types/RecoilScopedSelector.ts | 4 +- .../recoil-scope/types/RecoilScopedState.ts | 4 +- .../utils/getScopeIdFromComponentId.ts | 2 +- .../scroll/contexts/ScrollWrapperContexts.tsx | 7 +- .../useAvailableComponentInstanceIdOrThrow.ts | 24 + .../hooks/useComponentInstanceStateContext.ts | 12 + .../hooks/useRecoilCallbackState.ts | 27 + .../useRecoilComponentCallbackStateV2.ts | 128 + .../hooks/useRecoilComponentFamilyValueV2.ts | 52 + .../hooks/useRecoilComponentState.ts | 28 + .../hooks/useRecoilComponentStateV2.ts | 26 + .../hooks/useRecoilComponentValue.ts | 4 +- .../hooks/useRecoilComponentValueV2.ts | 26 + .../hooks/useScopeIdFromStateContext.ts | 4 +- .../useSetRecoilComponentFamilyStateV2.ts | 52 + .../hooks/useSetRecoilComponentState.ts | 4 +- .../hooks/useSetRecoilComponentStateV2.ts | 26 + .../ComponentFamilyReadOnlySelectorV2.ts | 14 + .../types/ComponentFamilySelectorV2.ts | 14 + .../types/ComponentFamilyStateKeyV2.ts | 7 + .../types/ComponentFamilyStateV2.ts | 14 + .../types/ComponentInstanceStateContext.ts | 4 + .../types/ComponentReadOnlySelectorV2.ts | 11 + .../types/ComponentSelectorV2.ts | 11 + .../component-state/types/ComponentState.ts | 8 - .../types/ComponentStateKey.ts | 3 - .../types/ComponentStateKeyV2.ts | 3 + .../types/ComponentStateTypeV2.ts | 7 + .../component-state/types/ComponentStateV2.ts | 11 + .../types/RecoilComponentState.ts | 9 + .../types/RecoilComponentStateKey.ts | 3 + .../utils/createComponentFamilySelectorV2.ts | 58 + .../utils/createComponentFamilyStateV2.ts | 30 +- .../utils/createComponentInstanceContext.ts | 13 + .../utils/createComponentReadOnlySelector.ts | 6 +- .../utils/createComponentSelector.ts | 8 +- .../utils/createComponentSelectorV2.ts | 47 + .../utils/createComponentState.ts | 4 +- .../utils/createComponentStateV2.ts | 28 +- .../utils/createComponentStateV2_alpha.ts | 38 + .../utils/createEventContext.ts | 9 + .../utils/extractComponentReadOnlySelector.ts | 4 +- .../utils/extractComponentSelector.ts | 4 +- .../utils/extractComponentState.ts | 4 +- .../globalComponentInstanceContextMap.ts | 21 + .../EditableFilterDropdownButton.tsx | 36 +- .../views/components/EditableSortChip.tsx | 10 +- .../components/QueryParamsFiltersEffect.tsx | 28 +- .../components/QueryParamsViewIdEffect.tsx | 22 +- .../components/UpdateViewButtonGroup.tsx | 57 +- .../views/components/VariantFilterChip.tsx | 32 +- .../src/modules/views/components/ViewBar.tsx | 10 +- .../views/components/ViewBarDetails.tsx | 49 +- .../views/components/ViewBarEffect.tsx | 27 +- .../views/components/ViewBarFilterEffect.tsx | 25 +- .../views/components/ViewBarSortEffect.tsx | 30 +- .../views/events/contexts/ViewEventContext.ts | 8 + .../hooks/internal/useViewFromQueryParams.ts | 12 +- .../views/hooks/internal/useViewStates.ts | 91 - .../src/modules/views/hooks/useChangeView.ts | 24 + .../views/hooks/useCombinedViewFilters.ts | 161 - .../views/hooks/useCombinedViewSorts.ts | 159 - .../hooks/useCreateViewFiltersAndSorts.ts | 34 + .../hooks/useCreateViewFromCurrentView.ts | 122 + .../hooks/useDeleteCombinedViewFilters.ts | 101 + .../views/hooks/useDeleteCombinedViewSorts.ts | 100 + .../src/modules/views/hooks/useDeleteView.ts | 18 + .../views/hooks/useGetCombinedViewFilters.ts | 67 + .../views/hooks/useGetCombinedViewSorts.ts | 68 + .../modules/views/hooks/useGetCurrentView.ts | 93 +- .../src/modules/views/hooks/useHandleViews.ts | 165 - .../src/modules/views/hooks/useInitViewBar.ts | 39 +- .../views/hooks/useResetCurrentView.ts | 32 - .../views/hooks/useResetUnsavedViewStates.ts | 52 + .../views/hooks/useSaveCurrentViewFields.ts | 25 +- .../useSaveCurrentViewFiltersAndSorts.ts | 83 +- .../hooks/useSetRecordCountInCurrentView.ts | 12 +- .../views/hooks/useUpdateCurrentView.ts | 40 + .../src/modules/views/hooks/useUpdateView.ts | 27 + .../hooks/useUpsertCombinedViewFilters.ts | 131 + .../views/hooks/useUpsertCombinedViewSorts.ts | 123 + .../src/modules/views/scopes/ViewScope.tsx | 32 - .../init-effect/ViewScopeInitEffect.tsx | 24 - .../ViewScopeInternalContext.ts | 7 - ...availableFieldDefinitionsComponentState.ts | 6 +- ...vailableFilterDefinitionsComponentState.ts | 6 +- .../availableSortDefinitionsComponentState.ts | 6 +- .../contexts/ViewComponentInstanceContext.ts | 3 + .../states/currentViewIdComponentState.ts | 6 +- .../entityCountInCurrentViewComponentState.ts | 6 +- .../isCurrentViewIndexComponentState.ts | 6 +- .../isPersistingViewFieldsComponentState.ts | 6 +- .../states/isViewBarExpandedComponentState.ts | 6 +- .../onCurrentViewChangeComponentState.ts | 9 - .../canPersistViewComponentFamilySelector.ts | 42 + .../canPersistViewComponentSelector.ts | 21 - .../canResetViewComponentSelector.ts | 22 - ...DeleteViewFilterIdsComponentFamilyState.ts | 9 + ...avedToDeleteViewFilterIdsComponentState.ts | 8 - ...ToDeleteViewSortIdsComponentFamilyState.ts | 9 + ...nsavedToDeleteViewSortIdsComponentState.ts | 8 - ...ToUpsertViewFiltersComponentFamilyState.ts | 10 + ...nsavedToUpsertViewFiltersComponentState.ts | 10 - ...edToUpsertViewSortsComponentFamilyState.ts | 10 + .../unsavedToUpsertViewSortsComponentState.ts | 10 - .../viewObjectMetadataIdComponentState.ts | 6 +- .../modules/views/types/ViewFilterOperand.ts | 6 + .../__tests__/getCombinedViewFilters.test.ts | 112 + ...ewFilters.ts => getCombinedViewFilters.ts} | 2 +- ...edViewSorts.ts => getCombinedViewSorts.ts} | 2 +- .../computeVariableDateViewFilterValue.ts | 10 + .../resolveDateViewFilterValue.ts | 190 + .../view-filter-value/resolveFilterValue.ts | 42 + .../resolveNumberViewFilterValue.ts | 7 + ...nt.tsx => ViewPickerContentCreateMode.tsx} | 166 +- .../components/ViewPickerContentEditMode.tsx | 100 + .../components/ViewPickerContentEffect.tsx | 90 + .../components/ViewPickerCreateButton.tsx | 86 + .../ViewPickerCreateOrEditContentEffect.tsx | 83 - .../components/ViewPickerDropdown.tsx | 31 +- ...ditButton.tsx => ViewPickerEditButton.tsx} | 37 +- .../ViewPickerIconAndNameContainer.tsx | 10 + .../components/ViewPickerListContent.tsx | 21 +- .../ViewPickerSaveButtonContainer.tsx | 9 + .../components/ViewPickerSelectContainer.tsx | 11 + .../hooks/useCloseAndResetViewPicker.ts | 9 +- .../hooks/useCreateViewFromCurrentState.ts | 118 + .../hooks/useDeleteViewFromCurrentState.ts | 78 + .../hooks/useGetAvailableFieldsForKanban.ts | 9 +- .../hooks/useUpdateViewFromCurrentState.ts | 80 + .../view-picker/hooks/useViewPickerMode.ts | 13 +- .../hooks/useViewPickerPersistView.ts | 132 - .../view-picker/hooks/useViewPickerStates.ts | 55 - .../viewPickerInputNameComponentState.ts | 14 +- .../states/viewPickerIsDirtyComponentState.ts | 6 +- .../viewPickerIsPersistingComponentState.ts | 6 +- ...ckerKanbanFieldMetadataIdComponentState.ts | 6 +- .../states/viewPickerModeComponentState.ts | 16 +- ...viewPickerReferenceViewIdComponentState.ts | 6 +- .../viewPickerSelectedIconComponentState.ts | 6 +- .../states/viewPickerTypeComponentState.ts | 6 +- .../views/view-picker/types/ViewPickerMode.ts | 5 + .../RecordShowPageWorkflowHeader.tsx | 96 + .../RightDrawerWorkflowEditStep.tsx | 16 + .../RightDrawerWorkflowEditStepContent.tsx | 93 + .../RightDrawerWorkflowSelectAction.tsx | 16 + ...RightDrawerWorkflowSelectActionContent.tsx | 41 + .../modules/workflow/components/Workflow.tsx | 58 + .../WorkflowDiagramBaseStepNode.tsx | 109 + .../components/WorkflowDiagramCanvas.tsx | 109 + .../WorkflowDiagramCanvasEffect.tsx | 79 + .../WorkflowDiagramCreateStepNode.tsx | 18 + .../WorkflowDiagramEmptyTrigger.tsx | 30 + .../components/WorkflowDiagramStepNode.tsx | 54 + .../components/WorkflowEditActionForm.tsx | 103 + .../components/WorkflowEditTriggerForm.tsx | 154 + .../workflow/components/WorkflowEffect.tsx | 42 + .../components/WorkflowShowPageDiagram.tsx | 86 - ...kflowShowPageDiagramCreateStepNode.tsx.tsx | 26 - .../components/WorkflowShowPageEffect.tsx | 61 - .../components/WorkflowVersionStatusTag.tsx | 22 + .../RecordShowPageWorkflowHeader.stories.tsx | 666 + .../WorkflowVersionStatusTag.stories.tsx | 43 + .../src/modules/workflow/constants/Actions.ts | 14 + .../workflow/constants/ObjectEventTriggers.ts | 16 + .../workflow/constants/TriggerStepId.ts | 1 + .../graphql/activateWorkflowVersion.ts | 7 + .../graphql/deactivateWorkflowVersion.ts | 7 + .../hooks/useActivateWorkflowVersion.tsx | 45 + .../hooks/useCreateNewWorkflowVersion.tsx | 30 + .../modules/workflow/hooks/useCreateStep.tsx | 101 + .../hooks/useDeactivateWorkflowVersion.tsx | 45 + .../hooks/useDeleteOneWorkflowVersion.tsx | 37 + .../workflow/hooks/useStartNodeCreation.tsx | 29 + .../hooks/useUpdateWorkflowVersionStep.tsx | 61 + .../hooks/useUpdateWorkflowVersionTrigger.tsx | 52 + .../hooks/useWorkflowWithCurrentVersion.tsx | 62 + ...workflowCreateStepFromParentStepIdState.ts | 8 + .../workflow/states/workflowDiagramState.ts | 7 + ...orkflowDiagramTriggerNodeSelectionState.ts | 8 + .../workflow/states/workflowIdState.ts | 6 + .../states/workflowSelectedNodeState.ts | 6 + .../src/modules/workflow/types/Workflow.ts | 26 +- .../modules/workflow/types/WorkflowDiagram.ts | 5 +- .../__tests__/addCreateStepNodes.test.ts | 4 +- .../__tests__/generateWorkflowDiagram.test.ts | 16 +- .../getWorkflowLastDiagramVersion.test.ts | 79 - .../getWorkflowVersionDiagram.test.ts | 101 + .../utils/__tests__/insertStep.test.ts | 221 + .../utils/__tests__/replaceStep.test.ts | 127 + .../workflow/utils/addCreateStepNodes.ts | 5 +- ...ertWorkflowWithCurrentVersionIsDefined.tsx | 15 + .../workflow/utils/findStepPositionOrThrow.ts | 41 + .../workflow/utils/generateWorkflowDiagram.ts | 56 +- .../workflow/utils/getOrganizedDiagram.ts | 3 - .../utils/getStepDefaultDefinition.ts | 33 + .../utils/getWorkflowLastDiagramVersion.ts | 27 - .../utils/getWorkflowVersionDiagram.ts | 22 + .../src/modules/workflow/utils/insertStep.ts | 27 + .../src/modules/workflow/utils/replaceStep.ts | 26 + .../utils/splitWorkflowTriggerEventName.ts | 8 + .../mutations/deleteWorkspaceInvitation.ts | 7 + .../mutations/resendWorkspaceInvitation.ts | 17 + .../graphql/mutations/sendInvitations.ts | 17 + .../queries/getWorkspaceInvitations.ts | 11 + .../hooks/useCreateWorkspaceInvitation.ts | 26 + .../hooks/useDeleteWorkspaceInvitation.ts | 34 + .../hooks/useResendWorkspaceInvitation.ts | 35 + .../states/workspaceInvitationsStates.ts | 9 + .../addUserToWorkspaceByInviteToken.ts | 9 + .../workspace-member/types/WorkspaceMember.ts | 7 + .../components/WorkspaceInviteTeam.tsx | 59 +- .../components/WorkspaceMemberCard.tsx | 57 - .../graphql/mutations/sendInviteLink.ts | 9 - .../modules/workspace/types/FeatureFlagKey.ts | 4 +- .../twenty-front/src/pages/auth/Invite.tsx | 34 +- .../pages/auth/__stories__/Invite.stories.tsx | 6 +- .../__stories__/PasswordReset.stories.tsx | 6 +- .../__stories__/NotFound.stories.tsx | 16 +- .../pages/object-record/RecordIndexPage.tsx | 72 +- .../pages/object-record/RecordShowPage.tsx | 37 +- .../RecordShowPageBaseHeader.tsx | 40 + .../__stories__/RecordIndexPage.stories.tsx | 6 +- .../__stories__/RecordShowPage.stories.tsx | 4 +- .../src/pages/onboarding/InviteTeam.tsx | 27 +- .../__stories__/ChooseYourPlan.stories.tsx | 8 +- .../src/pages/settings/Releases.tsx | 25 +- .../src/pages/settings/SettingsBilling.tsx | 14 +- .../src/pages/settings/SettingsProfile.tsx | 14 +- .../src/pages/settings/SettingsWorkspace.tsx | 14 +- .../settings/SettingsWorkspaceMembers.tsx | 246 +- .../SettingsAppearance.stories.tsx | 74 +- .../settings/accounts/SettingsAccounts.tsx | 19 +- .../accounts/SettingsAccountsCalendars.tsx | 24 +- .../accounts/SettingsAccountsEmails.tsx | 23 +- .../settings/accounts/SettingsNewAccount.tsx | 23 +- .../__stories__/SettingsAccounts.stories.tsx | 4 +- .../crm-migration/SettingsCRMMigration.tsx | 12 +- .../settings/data-model/SettingsNewObject.tsx | 26 +- .../SettingsObjectDetailPageContent.tsx | 18 +- .../data-model/SettingsObjectEdit.tsx | 55 +- .../data-model/SettingsObjectFieldEdit.tsx | 153 +- .../data-model/SettingsObjectFieldTable.tsx | 1 + .../SettingsObjectNewFieldStep1.tsx | 31 +- .../SettingsObjectNewFieldStep2.tsx | 163 +- .../data-model/SettingsObjectOverview.tsx | 23 +- .../settings/data-model/SettingsObjects.tsx | 10 + .../SettingsObjectEdit.stories.tsx | 2 +- .../SettingsObjectNewFieldStep1.stories.tsx | 1 - .../SettingsObjectNewFieldStep2.stories.tsx | 14 +- .../__stories__/SettingsObjects.stories.tsx | 8 +- .../developers/SettingsDevelopers.tsx | 9 + .../SettingsDevelopers.stories.tsx | 6 +- ...ettingsDevelopersApiKeysDetail.stories.tsx | 38 +- .../SettingsDevelopersApiKeysNew.stories.tsx | 3 +- .../SettingsDevelopersApiKeyDetail.tsx | 91 +- .../api-keys/SettingsDevelopersApiKeysNew.tsx | 23 +- .../SettingsDevelopersWebhookDetail.tsx | 228 +- .../SettingsDevelopersWebhooksNew.tsx | 71 +- .../SettingsIntegrationDatabase.tsx | 24 +- ...tingsIntegrationEditDatabaseConnection.tsx | 23 +- ...ttingsIntegrationNewDatabaseConnection.tsx | 32 +- ...tingsIntegrationShowDatabaseConnection.tsx | 18 +- .../integrations/SettingsIntegrations.tsx | 14 +- ...egrationEditDatabaseConnection.stories.tsx | 2 +- ...tegrationNewDatabaseConnection.stories.tsx | 6 +- .../components/SettingsAppearance.tsx | 16 +- .../SettingsServerlessFunctionDetail.tsx | 39 +- .../SettingsServerlessFunctions.tsx | 14 +- .../SettingsServerlessFunctionsNew.tsx | 25 +- .../SettingsServerlessFunctions.stories.tsx | 7 +- .../src/pages/workflows/WorkflowShowPage.tsx | 64 - .../src/testing/decorators/PageDecorator.tsx | 8 +- .../decorators/RecordTableDecorator.tsx | 39 + .../twenty-front/src/testing/graphqlMocks.ts | 127 + .../jest/JestObjectMetadataItemSetter.tsx | 4 +- .../src/testing/jest/getJestHookWrapper.tsx | 7 +- .../src/testing/mock-data/config.ts | 4 - .../generated/mock-metadata-query-result.ts | 16986 ++++++++++++++++ .../standard-metadata-query-result.ts | 16015 --------------- .../src/testing/mock-data/metadata.ts | 32 +- .../testing/mock-data/objectMetadataItems.ts | 2 +- .../src/testing/mock-data/people.ts | 97 +- .../testing/mock-data/timeline-activities.ts | 2 +- .../src/testing/mock-data/view-fields.ts | 2 +- .../src/testing/mock-data/views.ts | 4 +- .../src/utils/createRootPropsContext.ts | 11 + .../src/utils/format/spiltFullName.ts | 13 + .../src/utils/getDisplayValueByUrlType.ts | 2 +- .../turnIntoEmptyStringIfWhitespacesOnly.ts | 3 + .../turnIntoUndefinedIfWhitespacesOnly.ts | 5 + .../utils/url/__tests__/isValidUrl.test.ts | 25 + .../twenty-front/src/utils/url/isValidUrl.ts | 8 + packages/twenty-front/tsconfig.json | 1 - packages/twenty-front/vite.config.ts | 8 +- .../linux/provision-postgres-linux.sh | 8 +- packages/twenty-server/.env.example | 2 + packages/twenty-server/.env.test | 46 +- packages/twenty-server/.eslintrc.cjs | 6 + packages/twenty-server/.gitignore | 1 + packages/twenty-server/.idea/.gitignore | 5 + .../.idea/codeStyles/Project.xml | 119 + .../.idea/codeStyles/codeStyleConfig.xml | 5 + .../inspectionProfiles/Project_Default.xml | 6 + packages/twenty-server/.idea/modules.xml | 8 + .../twenty-server/.idea/twenty-server.iml | 12 + packages/twenty-server/.idea/vcs.xml | 6 + packages/twenty-server/@types/jest.d.ts | 17 + .../twenty-server/jest-integration.config.ts | 34 + packages/twenty-server/jest.config.ts | 21 +- packages/twenty-server/nest-cli.json | 17 +- packages/twenty-server/package.json | 12 +- ...patch => @graphql-yoga+nestjs+2.1.0.patch} | 64 +- packages/twenty-server/project.json | 26 +- .../generate-integration-tests/index.ts | 213 + .../introspection-query.ts | 89 + .../introspection.interface.ts | 60 + .../twenty-server/scripts/run-integration.sh | 8 - .../twenty-server/scripts/set-env-test.sh | 25 - packages/twenty-server/src/app.module.ts | 24 +- packages/twenty-server/src/command/command.ts | 4 +- .../commands/active-workspaces.command.ts | 92 + .../src/database/commands/base.command.ts | 46 + ...t-data-seed-demo-workspace.cron.command.ts | 6 +- ...p-data-seed-demo-workspace.cron.command.ts | 6 +- .../data-seed-demo-workspace.module.ts | 12 +- .../jobs/data-seed-demo-workspace.job.ts | 6 +- .../data-seed-demo-workspace.service.ts | 28 +- .../data-seed-dev-workspace.command.ts | 55 +- .../commands/database-command.module.ts | 12 +- .../0-24-set-message-direction.command.ts | 222 - .../0-24/0-24-upgrade-version.command.ts | 42 - .../0-24/0-24-upgrade-version.module.ts | 38 - .../0-30-fix-email-field-migration.command.ts | 161 + ...ew-filter-operand-for-date-time.command.ts | 110 + ...-migrate-email-fields-to-emails.command.ts | 360 + ...-migrate-phone-fields-to-phones.command.ts | 366 + ...-set-stale-message-sync-back-to-pending.ts | 90 + .../0-30/0-30-upgrade-version.command.ts | 76 + .../0-30/0-30-upgrade-version.module.ts | 43 + ...ex-key-to-tasks-and-notes-views.command.ts | 128 + ...31-backfill-workspace-favorites.command.ts | 162 + ...ssociated-with-outdated-objects.command.ts | 119 + .../0-31/0-31-upgrade-version.command.ts | 62 + .../0-31/0-31-upgrade-version.module.ts | 25 + .../core/demo/user-workspaces.ts | 2 +- .../database/typeorm-seeds/core/demo/users.ts | 10 +- .../typeorm-seeds/core/feature-flags.ts | 21 +- .../typeorm-seeds/metadata/fieldsMetadata.ts | 2 +- .../typeorm-seeds/metadata/objectsMetadata.ts | 20 + .../typeorm-seeds/workspace/favorites.ts | 23 + .../typeorm-seeds/workspace/people.ts | 144 +- .../database/typeorm/core/core.datasource.ts | 12 +- .../migrations/1724056827317-addInvitation.ts | 51 + ...726849473832-addUniqueConstraintOnUsers.ts | 19 + .../typeorm/metadata/metadata.datasource.ts | 15 +- ...addServerlessFunctionLayerVersionColumn.ts | 19 + ...275-removeObjectMetadataIsSoftDeletable.ts | 19 + .../database/typeorm/raw/raw.datasource.ts | 2 +- .../src/database/typeorm/typeorm.module.ts | 2 +- .../src/database/typeorm/typeorm.service.ts | 12 +- .../__mocks__/object-metadata-item.mock.ts | 42 +- .../__tests__/workspace.factory.spec.ts | 4 +- .../api/graphql/core-graphql-api.module.ts | 11 +- .../graphql-config/graphql-config.module.ts | 2 +- .../graphql-config/graphql-config.service.ts | 21 +- .../errors/graphql-query-runner.exception.ts | 5 + .../graphql-query-filter-condition.parser.ts | 195 +- .../graphql-query-filter-field.parser.ts | 210 +- .../graphql-query-order.parser.ts | 43 +- ...graphql-selected-fields-relation.parser.ts | 6 +- .../graphql-selected-fields.parser.ts | 2 +- .../graphql-query.parser.ts | 81 +- .../graphql-query-runner.module.ts | 3 + .../graphql-query-runner.service.ts | 390 +- .../process-nested-relations.helper.ts | 194 + ...ct-records-to-graphql-connection.mapper.ts | 37 +- ...phql-query-create-many-resolver.service.ts | 79 + ...phql-query-destroy-one-resolver.service.ts | 33 + ...raphql-query-find-many-resolver.service.ts | 283 + ...graphql-query-find-one-resolver.service.ts | 130 + .../utils/compute-cursor-arg-filter.ts | 133 + .../utils/cursors.util.ts | 32 +- .../get-object-metadata-or-throw.util.ts | 21 + .../get-relation-object-metadata.util.ts | 27 +- .../graphql/metadata-graphql-api.module.ts | 6 +- .../api/graphql/metadata.module-factory.ts | 6 +- .../factories/find-many-query.factory.ts | 2 +- .../factories/find-one-query.factory.ts | 4 +- .../factories/relation-field-alias.factory.ts | 12 +- .../0-20-record-position-backfill.command.ts | 6 +- .../jobs/call-webhook-jobs.job.ts | 11 +- .../jobs/call-webhook.job.ts | 6 +- .../jobs/record-position-backfill.job.ts | 6 +- .../listeners/entity-events-to-db.listener.ts | 33 +- .../listeners/telemetry.listener.ts | 41 +- ...nner-graphql-api-exception-handler.util.ts | 23 + .../workspace-query-hook.interface.ts | 8 + .../storage/workspace-query-hook.storage.ts | 21 + .../types/workspace-query-hook.type.ts | 5 +- .../workspace-query-hook.service.ts | 33 +- .../workspace-query-runner.module.ts | 6 +- .../workspace-query-runner.service.ts | 291 +- .../factories/create-many-resolver.factory.ts | 23 +- .../factories/create-one-resolver.factory.ts | 25 +- .../factories/destroy-one-resolver.factory.ts | 42 + .../factories/factories.ts | 3 + .../factories/find-many-resolver.factory.ts | 12 +- .../factories/find-one-resolver.factory.ts | 12 +- .../workspace-resolvers-builder.interface.ts | 5 + .../workspace-resolver-builder.module.ts | 8 +- .../workspace-resolver.factory.ts | 3 + .../factories/enum-type-definition.factory.ts | 7 +- .../input/array-filter.input-type.ts | 10 + .../graphql-types/input/index.ts | 1 + .../services/type-mapper.service.ts | 10 +- .../utils/get-resolver-args.util.ts | 7 + .../api/graphql/workspace-schema.factory.ts | 61 +- .../rest-api-core-batch.controller.ts | 5 +- .../controllers/rest-api-core.controller.ts | 4 + .../core-query-builder.factory.ts | 4 +- .../filter-utils/format-field-values.utils.ts | 14 +- ...p-field-metadata-to-graphql-query.utils.ts | 10 + .../api/rest/errors/RestApiException.ts | 28 +- .../utils/fetch-metadata-fields.utils.ts | 63 +- .../metadata/rest-api-metadata.service.ts | 4 +- .../src/engine/api/rest/rest-api.module.ts | 16 +- .../src/engine/api/rest/rest-api.service.ts | 2 +- .../ai-sql-query/ai-sql-query.module.ts | 6 +- .../ai-sql-query/ai-sql-query.resolver.ts | 5 +- .../ai-sql-query/ai-sql-query.service.ts | 4 +- .../analytics/analytics.module.ts | 8 +- .../analytics/analytics.resolver.spec.ts | 2 +- .../analytics/analytics.resolver.ts | 21 +- .../analytics/analytics.service.spec.ts | 2 +- .../analytics/analytics.service.ts | 75 +- .../analytics/dtos/create-analytics.input.ts | 8 +- .../app-token/app-token.auto-resolver-opts.ts | 4 +- .../app-token/app-token.entity.ts | 8 +- .../hooks/before-create-one-app-token.hook.ts | 2 +- .../engine/core-modules/auth/auth.module.ts | 6 +- .../core-modules/auth/auth.resolver.spec.ts | 10 +- .../engine/core-modules/auth/auth.resolver.ts | 25 +- .../google-apis-auth.controller.ts | 4 +- .../controllers/google-auth.controller.ts | 13 +- .../controllers/microsoft-auth.controller.ts | 13 +- .../verify-auth.controller.spec.ts | 2 +- .../controllers/verify-auth.controller.ts | 2 +- .../core-modules/auth/dto/sign-up.input.ts | 5 + .../auth/dto/workspace-invite-token.input.ts | 12 + ...pis-oauth-exchange-code-for-token.guard.ts | 35 +- .../google-apis-oauth-request-code.guard.ts | 34 +- .../auth/guards/google-oauth.guard.ts | 9 + .../guards/google-provider-enabled.guard.ts | 2 +- .../auth/guards/microsoft-oauth.guard.ts | 9 + .../microsoft-provider-enabled.guard.ts | 2 +- .../auth/services/auth.service.spec.ts | 14 +- .../auth/services/auth.service.ts | 18 +- .../auth/services/google-apis.service.ts | 8 +- .../auth/services/sign-in-up.service.spec.ts | 7 +- .../auth/services/sign-in-up.service.ts | 106 +- .../google-apis-oauth-common.auth.strategy.ts | 9 +- ...h-exchange-code-for-token.auth.strategy.ts | 3 +- ...e-apis-oauth-request-code.auth.strategy.ts | 2 +- .../auth/strategies/google.auth.strategy.ts | 10 +- .../auth/strategies/jwt.auth.strategy.ts | 3 +- .../strategies/microsoft.auth.strategy.ts | 10 +- .../services/token.service.spec.ts | 4 +- .../{ => token}/services/token.service.ts | 39 +- .../core-modules/auth/token/token.module.ts | 26 + .../core-modules/billing/billing.module.ts | 4 +- .../core-modules/billing/billing.resolver.ts | 9 +- .../billing/jobs/update-subscription.job.ts | 6 +- .../billing-workspace-member.listener.ts | 10 +- .../billing-portal.workspace-service.ts | 12 +- .../services/billing-subscription.service.ts | 2 +- .../billing/services/billing.service.ts | 2 +- .../billing/stripe/stripe.service.ts | 4 +- .../cache-storage.module-factory.ts | 9 +- .../cache-storage/cache-storage.module.ts | 16 +- .../commands/flush-cache.command.ts | 29 + .../decorators/cache-storage.decorator.ts | 2 +- .../services}/cache-storage.service.ts | 2 +- .../types/cache-storage-namespace.enum.ts | 0 .../types/cache-storage-type.enum.ts | 0 .../dtos/timeline-calendar-event.dto.ts | 7 +- .../timeline-calendar-event.resolver.ts | 4 +- .../timeline-calendar-event.service.ts | 2 + .../captcha/captcha.constants.ts | 0 .../captcha/captcha.guard.ts | 2 +- .../captcha/captcha.module-factory.ts | 4 +- .../captcha/captcha.module.ts | 10 +- .../captcha/captcha.service.ts | 6 +- .../drivers/google-recaptcha.driver.ts | 6 +- .../interfaces/captcha-driver.interface.ts | 2 +- .../interfaces/captcha-server-response.ts | 0 .../captcha/drivers/turnstile.driver.ts | 6 +- .../captcha/interfaces/captcha.interface.ts | 0 .../core-modules/captcha/interfaces/index.ts | 1 + .../client-config/client-config.entity.ts | 5 +- .../client-config.resolver.spec.ts | 2 +- .../client-config/client-config.resolver.ts | 7 +- .../engine/core-modules/core-engine.module.ts | 70 + .../cron/sentry-cron-monitor.decorator.ts | 55 + .../interfaces/email-driver.interface.ts | 0 .../email/drivers/logger.driver.ts | 2 +- .../email/drivers/smtp.driver.ts | 2 +- .../email/email-sender.job.ts | 8 +- .../email/email-sender.service.ts | 4 +- .../email/email.constants.ts | 0 .../email/email.module-factory.ts | 4 +- .../email/email.module.ts | 12 +- .../email/email.service.ts | 8 +- .../email/interfaces/email.interface.ts | 0 .../cast-to-log-level-array.decorator.spec.ts | 2 +- .../cast-to-positive-number.decorator.spec.ts | 2 +- .../decorators/cast-to-boolean.decorator.ts | 0 .../cast-to-log-level-array.decorator.ts | 0 .../cast-to-positive-number.decorator.ts | 0 .../cast-to-string-array.decorator.ts | 0 .../decorators/is-aws-region.decorator.ts | 0 .../decorators/is-duration.decorator.ts | 0 .../is-strictly-lower-than.decorator.ts | 0 .../environment/environment-variables.ts | 66 +- .../environment.module-definition.ts | 0 .../environment/environment.module.ts | 7 +- .../environment/environment.service.spec.ts | 2 +- .../environment/environment.service.ts | 2 +- .../interfaces/aws-region.interface.ts | 0 .../interfaces/node-environment.interface.ts | 1 + .../interfaces/support.interface.ts | 0 .../types/object-record-create.event.ts | 2 +- .../types/object-record-delete.event.ts | 2 +- .../types/object-record-destroy.event.ts | 7 + .../types/object-record-update.event.ts | 2 +- .../types/object-record.base.event.ts | 0 .../object-record-changed-values.spec.ts | 2 +- .../object-record-changed-properties.util.ts | 0 .../utils/object-record-changed-values.ts | 0 .../utils/object-record-diff-merge.ts | 0 .../exception-handler.service.spec.ts | 4 +- .../drivers/console.driver.ts | 6 +- .../drivers/sentry.driver.ts | 28 +- .../exception-handler.constants.ts | 0 .../exception-handler.module-definition.ts | 2 +- .../exception-handler.module-factory.ts | 6 +- .../exception-handler.module.ts | 19 +- .../exception-handler.service.ts | 6 +- .../hooks/use-sentry-tracing.ts | 0 .../exception-handler-driver.interface.ts | 10 + .../exception-handler-options.interface.ts | 2 +- .../exception-handler-user.interface.ts | 0 .../interfaces/exception-handler.interface.ts | 0 .../exception-handler/interfaces/index.ts | 2 + .../enums/feature-flag-key.enum.ts | 4 +- .../__tests__/file-storage.service.spec.ts | 4 +- .../interfaces/storage-driver.interface.ts | 0 .../file-storage/drivers/local.driver.ts | 10 +- .../file-storage/drivers/s3.driver.ts | 96 +- .../file-storage/file-storage.constants.ts | 0 .../file-storage.module-definition.ts | 2 +- .../file-storage.module-factory.ts | 4 +- .../file-storage/file-storage.module.ts | 11 +- .../file-storage/file-storage.service.ts | 4 +- .../interfaces/file-storage-exception.ts | 0 .../interfaces/file-storage.interface.ts | 4 +- .../file-storage/interfaces/index.ts | 1 + .../file-storage/utils/read-file-content.ts | 0 .../file/controllers/file.controller.ts | 2 +- .../file/file-upload/file-upload.module.ts | 2 +- .../resolvers/file-upload.resolver.spec.ts | 5 + .../resolvers/file-upload.resolver.ts | 4 +- .../services/file-upload.service.ts | 2 +- .../engine/core-modules/file/file.module.ts | 2 +- .../file/guards/file-path-guard.ts | 2 +- .../file/services/file.service.spec.ts | 4 +- .../file/services/file.service.ts | 4 +- .../graphql/engine-graphql.module.ts | 2 +- .../hooks/use-graphql-error-handler.hook.ts | 2 +- .../src/engine/core-modules/jwt/jwt.module.ts | 4 +- .../llm-prompt-template-driver.interface.ts | 0 .../llm-chat-model/drivers/openai.driver.ts | 2 +- .../interfaces/llm-chat-model.interface.ts | 0 .../llm-chat-model.constants.ts | 0 .../llm-chat-model.module-factory.ts | 4 +- .../llm-chat-model/llm-chat-model.module.ts | 8 +- .../llm-chat-model/llm-chat-model.service.ts | 4 +- .../llm-tracing/drivers/console.driver.ts | 2 +- .../llm-tracing-driver.interface.ts | 0 .../llm-tracing/drivers/langfuse.driver.ts | 2 +- .../interfaces/llm-tracing.interface.ts | 2 +- .../llm-tracing/llm-tracing.constants.ts | 0 .../llm-tracing/llm-tracing.module-factory.ts | 4 +- .../llm-tracing/llm-tracing.module.ts | 10 +- .../llm-tracing/llm-tracing.service.ts | 4 +- .../logger/__tests__/logger.service.spec.ts | 4 +- .../core-modules/logger/interfaces/index.ts | 1 + .../logger/interfaces/logger.interface.ts | 0 .../logger/logger.constants.ts | 0 .../logger/logger.module-definition.ts | 2 +- .../logger/logger.module-factory.ts | 4 +- .../logger/logger.module.ts | 9 +- .../logger/logger.service.ts | 2 +- .../decorators/message-queue.decorator.ts | 4 +- .../decorators/process.decorator.ts | 2 +- .../decorators/processor.decorator.ts | 4 +- .../message-queue/drivers/bullmq.driver.ts | 11 +- .../interfaces/job-options.interface.ts | 0 .../message-queue-driver.interface.ts | 8 +- .../message-queue/drivers/pg-boss.driver.ts | 11 +- .../message-queue/drivers/sync.driver.ts | 7 +- .../message-queue/interfaces/index.ts | 1 + .../interfaces/message-queue-job.interface.ts | 0 .../message-queue-module-options.interface.ts | 4 +- .../message-queue-worker-options.interface.ts | 0 .../message-queue/jobs.module.ts | 6 +- .../message-queue-core.module.ts | 18 +- .../message-queue-metadata.accessor.ts | 6 +- .../message-queue/message-queue.constants.ts | 0 .../message-queue/message-queue.explorer.ts | 13 +- .../message-queue.module-definition.ts | 2 +- .../message-queue.module-factory.ts | 8 +- .../message-queue/message-queue.module.ts | 8 +- ...essage-queue-task-assigned.service.spec.ts | 6 +- .../services/message-queue.service.ts | 10 +- .../utils/get-queue-token.util.ts | 0 .../messaging/dtos/timeline-thread.dto.ts | 7 +- .../messaging/timeline-messaging.resolver.ts | 19 +- .../onboarding/onboarding.resolver.ts | 5 +- .../open-api/open-api.service.spec.ts | 4 +- .../core-modules/open-api/open-api.service.ts | 13 +- .../utils/__tests__/components.utils.spec.ts | 462 +- .../utils/__tests__/parameters.utils.spec.ts | 5 +- .../open-api/utils/components.utils.ts | 393 +- .../utils/get-error-responses.utils.ts | 2 +- .../open-api/utils/parameters.utils.ts | 5 +- .../core-modules/open-api/utils/path.utils.ts | 3 +- .../open-api/utils/request-body.utils.ts | 18 +- .../open-api/utils/responses.utils.ts | 107 +- .../postgres-credentials.module.ts | 2 +- .../postgres-credentials.resolver.ts | 10 +- .../postgres-credentials.service.ts | 2 +- .../drivers/base-serverless.driver.ts | 10 +- .../drivers/constants/build-file-name.ts | 0 .../drivers/constants/common-layer-name.ts | 1 + .../constants/serverless-tmpdir-folder.ts | 4 + .../drivers/constants/source-file-name.ts | 0 .../interfaces/serverless-driver.interface.ts | 2 +- .../serverless/drivers/lambda.driver.ts | 127 +- .../serverless/drivers/layers/1/package.json | 48 + .../serverless/drivers/layers/1/yarn.lock | 3211 +++ .../engine/.yarn/releases/yarn-4.4.0.cjs | 925 + .../drivers/layers/engine/.yarnrc.yml | 5 + .../drivers/layers/last-layer-version.ts | 1 + .../serverless/drivers/local.driver.ts | 60 +- .../drivers/utils/compile-typescript.ts | 0 .../utils/copy-and-build-dependencies.ts | 40 + .../drivers/utils/create-zip-file.ts | 0 .../utils/get-last-layer-dependencies.ts | 24 + .../utils/get-layer-dependencies-dir-name.ts | 12 + .../utils/lambda-build-directory-manager.ts} | 31 +- .../serverless/serverless-module.factory.ts | 9 +- .../serverless/serverless.constants.ts | 0 .../serverless/serverless.interface.ts | 4 +- .../serverless/serverless.module.ts | 13 +- .../serverless/serverless.service.ts | 6 +- .../utils/serverless-get-folder.utils.ts | 23 + .../telemetry/telemetry.module.ts | 15 + .../telemetry/telemetry.service.ts | 55 + .../throttler/throttler.service.ts | 6 +- .../user-workspace/user-workspace.module.ts | 10 +- .../user-workspace/user-workspace.resolver.ts | 31 +- .../user-workspace/user-workspace.service.ts | 59 +- .../user/services/user.service.ts | 11 +- .../user/user.auto-resolver-opts.ts | 6 +- .../engine/core-modules/user/user.entity.ts | 2 + .../engine/core-modules/user/user.resolver.ts | 20 +- ...ow-trigger-graphql-api-exception.filter.ts | 2 +- .../workflow/workflow-trigger.resolver.ts | 15 +- .../dtos/send-invitations.input.ts} | 2 +- .../dtos/send-invitations.output.ts | 17 + .../dtos/workspace-invitation.dto.ts | 17 + .../workspace-invitation.service.spec.ts | 55 + .../services/workspace-invitation.service.ts | 293 + .../workspace-invitation.exception.ts | 17 + .../workspace-invitation.module.ts | 21 + .../workspace-invitation.resolver.ts | 66 + .../workspace/dtos/send-invite-link.entity.ts | 9 - .../handle-workspace-member-deleted.job.ts | 6 +- .../services/workspace.service.spec.ts | 9 +- .../workspace/services/workspace.service.ts | 77 +- .../workspace-workspace-member.listener.ts | 10 +- .../workspace/workspace.auto-resolver-opts.ts | 4 +- .../workspace/workspace.module.ts | 6 +- .../workspace/workspace.resolver.ts | 24 +- .../dataloaders/dataloader.interface.ts | 6 +- .../engine/dataloaders/dataloader.service.ts | 22 +- .../decorators/auth/auth-user.decorator.ts | 4 +- .../auth/auth-workspace.decorator.ts | 2 +- .../src/engine/guards/demo.env.guard.ts | 30 +- .../src/engine/guards/jwt-auth.guard.ts | 35 + .../src/engine/guards/jwt.auth.guard.ts | 40 - .../engine/guards/optional-jwt.auth.guard.ts | 23 - .../src/engine/guards/user-auth.guard.ts | 15 + .../src/engine/guards/workspace-auth.guard.ts | 15 + .../integrations/captcha/interfaces/index.ts | 1 - .../exception-handler-driver.interface.ts | 10 - .../exception-handler/interfaces/index.ts | 2 - .../file-storage/interfaces/index.ts | 1 - .../integrations/integrations.module.ts | 81 - .../integrations/logger/interfaces/index.ts | 1 - .../message-queue/interfaces/index.ts | 1 - .../composite-types/emails.composite-type.ts | 2 +- .../field-metadata/composite-types/index.ts | 2 + .../composite-types/phones.composite-type.ts | 33 + .../dtos/default-value.input.ts | 16 +- .../field-metadata/dtos/field-metadata.dto.ts | 10 +- .../field-metadata/field-metadata.entity.ts | 2 + .../field-metadata/field-metadata.module.ts | 12 +- .../field-metadata/field-metadata.resolver.ts | 10 +- .../field-metadata/field-metadata.service.ts | 105 +- .../field-metadata-default-value.interface.ts | 2 + .../field-metadata-settings.interface.ts | 10 + .../interfaces/object-metadata.interface.ts | 1 - .../utils/generate-default-value.ts | 6 + .../is-composite-field-metadata-type.util.ts | 4 +- .../validate-default-value-for-type.util.ts | 2 + ...-field-metadata-default-value.validator.ts | 2 +- .../index-metadata/index-metadata.module.ts | 11 +- .../index-metadata/index-metadata.service.ts | 87 + .../dtos/object-metadata.dto.ts | 2 +- .../hooks/before-create-one-object.hook.ts | 2 +- .../hooks/before-delete-one-object.hook.ts | 2 +- .../object-metadata/object-metadata.entity.ts | 3 - .../object-metadata/object-metadata.module.ts | 6 +- .../object-metadata.resolver.ts | 8 +- .../object-metadata.service.ts | 66 +- ...sert-mutation-not-on-remote-object.util.ts | 2 +- .../dtos/relation-metadata.dto.ts | 10 +- .../hooks/before-create-one-relation.hook.ts | 2 +- .../hooks/before-delete-one-relation.hook.ts | 2 +- .../relation-metadata.module.ts | 8 +- .../relation-metadata.resolver.ts | 10 +- .../relation-metadata.service.ts | 162 +- .../remote-server/remote-server.resolver.ts | 6 +- .../remote-server/remote-server.service.ts | 2 +- .../foreign-table/foreign-table.service.ts | 2 +- .../remote-table/remote-table.resolver.ts | 4 +- .../remote-table/remote-table.service.ts | 2 +- .../dtos/execute-serverless-function.input.ts | 6 +- .../dtos/serverless-function.dto.ts | 3 +- .../dtos/update-serverless-function.input.ts | 1 - .../serverless-function.entity.ts | 3 + .../serverless-function.module.ts | 6 +- .../serverless-function.resolver.ts | 22 +- .../serverless-function.service.ts | 98 +- .../generate-object-metadata-map.util.ts | 36 + .../validate-field-name-availability.utils.ts | 4 + .../workspace-metadata-cache.exception.ts | 12 + .../workspace-metadata-cache.service.ts | 120 + .../workspace-metadata-cache.module.ts | 18 + .../workspace-metadata-version.exception.ts | 12 + .../workspace-metadata-version.service.ts | 52 + .../workspace-metadata-version.module.ts | 4 +- .../workspace-metadata-version.service.ts | 81 - .../factories/basic-column-action.factory.ts | 6 +- .../composite-column-action.factory.ts | 3 +- ...field-metadata-type-to-column-type.util.ts | 1 + .../workspace-migration.factory.ts | 5 + .../workspace-migration.service.ts | 8 +- ...l-hydrate-request-from-token.middleware.ts | 11 +- .../twenty-orm/base.workspace-entity.ts | 9 + .../twenty-orm/custom.workspace-entity.ts | 4 +- .../workspace-custom-entity.decorator.ts | 9 +- .../decorators/workspace-entity.decorator.ts | 2 - .../decorators/workspace-field.decorator.ts | 1 + .../decorators/workspace-index.decorator.ts | 4 +- .../exceptions/twenty-orm.exception.ts | 15 + .../factories/entity-schema-column.factory.ts | 23 +- .../entity-schema-relation.factory.ts | 27 +- .../factories/entity-schema.factory.ts | 12 +- .../scoped-workspace-context.factory.ts | 4 +- .../factories/workspace-datasource.factory.ts | 298 +- ...orkspace-entity-metadata-args.interface.ts | 5 - ...extended-entity-metadata-args.interface.ts | 5 - ...workspace-field-metadata-args.interface.ts | 6 + .../workspace-internal-context.interface.ts | 4 +- .../repository/workspace.repository.ts | 225 +- .../storage/cache-manager.storage.ts | 10 + .../storage/metadata-args.storage.ts | 4 +- .../twenty-orm/twenty-orm-global.manager.ts | 10 +- .../engine/twenty-orm/twenty-orm.module.ts | 4 +- .../utils/compute-relation-type.util.ts | 7 +- .../utils/determine-relation-details.util.ts | 34 +- .../twenty-orm/utils/format-data.util.ts | 65 + .../twenty-orm/utils/format-result.util.ts | 131 + ...get-composite-field-metadata-collection.ts | 12 + .../engine/utils/get-resolver-name.util.ts | 2 + .../utils/global-exception-handler.util.ts | 4 +- .../src/engine/utils/transform-enum-value.ts | 14 + .../workspace-cache-storage.service.ts | 111 +- .../demo-objects-prefill-data.ts | 22 +- .../demo-objects-prefill-data/person.ts | 4 +- .../workspace-member.ts | 14 +- .../standard-objects-prefill-data/company.ts | 12 + .../standard-objects-prefill-data/person.ts | 44 +- .../standard-objects-prefill-data.ts | 17 +- .../standard-objects-prefill-data/view.ts | 13 +- .../views/activities-all.view.ts | 71 - .../views/notes-all.view.ts | 17 +- .../views/people-all.view.ts | 4 +- .../views/tasks-all.view.ts | 21 +- .../views/workflows-all.view.ts | 2 +- .../clean-inactive-workspaces.command.ts | 6 +- ...-clean-inactive-workspaces.cron.command.ts | 6 +- ...-clean-inactive-workspaces.cron.command.ts | 6 +- .../crons/clean-inactive-workspace.job.ts | 10 +- .../workspace-manager.module.ts | 6 +- .../workspace-manager.service.ts | 15 + .../services/workspace-status.service.ts | 72 - .../workspace-manager.module.ts | 21 - .../sync-workspace-metadata.command.ts | 43 +- ...workspace-sync-metadata-commands.module.ts | 2 - .../constants/standard-field-ids.ts | 6 +- .../factories/standard-field.factory.ts | 9 +- .../factories/standard-object.factory.ts | 7 +- .../workspace-sync-metadata.service.ts | 2 +- .../funnelmink-crew.workspace-entity.ts | 1 - .../funnelmink-job.workspace-entity.ts | 1 - .../funnelmink-material.workspace-entity.ts | 1 - .../funnelmink-service.workspace-entity.ts | 1 - .../funnelmink-workorder.workspace-entity.ts | 1 - packages/twenty-server/src/instrument.ts | 29 + packages/twenty-server/src/main.ts | 10 +- .../is-email-blocklisted.util.spec.ts | 32 +- .../utils/is-email-blocklisted.util.ts | 6 +- .../calendar-blocklist-manager.module.ts | 4 +- ...ocklist-item-delete-calendar-events.job.ts | 167 +- .../blocklist-reimport-calendar-events.job.ts | 69 +- .../listeners/calendar-blocklist.listener.ts | 70 +- ...ed-account-associated-calendar-data.job.ts | 6 +- ...vent-cleaner-connected-account.listener.ts | 12 +- .../calendar-event-import-manager.module.ts | 4 +- .../calendar-event-list-fetch.cron.command.ts | 13 +- .../calendar-ongoing-stale.cron.command.ts | 13 +- .../calendar-event-list-fetch.cron.job.ts | 19 +- .../jobs/calendar-ongoing-stale.cron.job.ts | 19 +- .../google-calendar-driver.module.ts | 2 +- .../jobs/calendar-event-list-fetch.job.ts | 6 +- .../jobs/calendar-ongoing-stale.job.ts | 16 +- ...-event-import-exception-handler.service.ts | 16 +- .../calendar-events-import.service.ts | 15 +- .../services/calendar-save-events.service.ts | 6 +- .../utils/filter-events.util.ts | 5 +- .../filter-out-blocklisted-events.util.ts | 4 +- ...eate-company-and-contact-after-sync.job.ts | 6 +- ...event-participant-match-participant.job.ts | 6 +- ...ent-participant-unmatch-participant.job.ts | 6 +- ...endar-event-participant-person.listener.ts | 29 +- ...t-participant-workspace-member.listener.ts | 12 +- .../src/modules/calendar/calendar.module.ts | 2 + .../calendar/common/calendar-common.module.ts | 18 + .../calendar-channel-sync-status.service.ts | 190 +- .../calendar-channel.workspace-entity.ts | 18 + .../company.workspace-entity.ts | 1 - .../listeners/connected-account.listener.ts | 6 +- .../google-oauth2-client-manager.service.ts | 2 +- ...ected-account-delete-one.pre-query.hook.ts | 6 +- ...google-api-refresh-access-token.service.ts | 2 +- .../contact-creation-manager.module.ts | 6 +- .../jobs/create-company-and-contact.job.ts | 6 +- ...acts-creation-calendar-channel.listener.ts | 10 +- ...tacts-creation-message-channel.listener.ts | 10 +- .../create-company-and-contact.service.ts | 28 +- .../services/create-contact.service.ts | 2 +- .../favorite.workspace-entity.ts | 17 + .../send-email.workflow-action.ts | 77 + .../match-participant.module.ts | 4 +- .../match-participant.service.ts | 45 +- ...ging-blocklist-item-delete-messages.job.ts | 157 +- ...ssaging-blocklist-reimport-messages.job.ts | 63 + .../listeners/messaging-blocklist.listener.ts | 127 +- .../messaging-blocklist-manager.module.ts | 7 +- .../message-channel-sync-status.service.ts | 259 +- .../message-channel.workspace-entity.ts | 22 + ...-connected-account-deletion-cleanup.job.ts | 6 +- ...sage-cleaner-connected-account.listener.ts | 12 +- .../messaging-message-cleaner.service.ts | 126 +- ...messaging-single-message-import.command.ts | 6 +- ...ssaging-message-list-fetch.cron.command.ts | 13 +- .../messaging-messages-import.cron.command.ts | 13 +- .../messaging-ongoing-stale.cron.command.ts | 13 +- .../messaging-message-list-fetch.cron.job.ts | 19 +- .../messaging-messages-import.cron.job.ts | 19 +- .../jobs/messaging-ongoing-stale.cron.job.ts | 19 +- .../gmail/messaging-gmail-driver.module.ts | 2 +- ...-single-message-to-cache-for-import.job.ts | 14 +- .../jobs/messaging-clean-cache.ts | 14 +- .../jobs/messaging-message-list-fetch.job.ts | 6 +- .../jobs/messaging-messages-import.job.ts | 6 +- .../jobs/messaging-ongoing-stale.job.ts | 16 +- ...import-manager-message-channel.listener.ts | 12 +- .../messaging-import-manager.module.ts | 2 + ...essage-import-exception-handler.service.ts | 20 +- ...ssaging-full-message-list-fetch.service.ts | 43 +- .../messaging-messages-import.service.ts | 42 +- ...ging-partial-message-list-fetch.service.ts | 34 +- ...es-and-enqueue-contact-creation.service.ts | 6 +- .../utils/filter-emails.util.ts | 8 +- ...ssage-participant-match-participant.job.ts | 6 +- ...age-participant-unmatch-participant.job.ts | 6 +- ...eate-company-and-contact-after-sync.job.ts | 6 +- .../message-participant-person.listener.ts | 35 +- ...e-participant-workspace-member.listener.ts | 12 +- ...nel-sync-status-monitoring.cron.command.ts | 14 +- ...hannel-sync-status-monitoring.cron.job.ts} | 62 +- .../monitoring/messaging-monitoring.module.ts | 2 +- .../services/messaging-telemetry.service.ts | 9 +- .../note-target.workspace-entity.ts | 1 - .../standard-objects/note.workspace-entity.ts | 6 +- .../opportunity.workspace-entity.ts | 1 - .../person.workspace-entity.ts | 34 +- .../workflow-actions/code.workflow-action.ts} | 19 +- .../task-target.workspace-entity.ts | 1 - .../standard-objects/task.workspace-entity.ts | 6 +- .../create-audit-log-from-internal-event.ts | 8 +- ...meline-activity-from-internal-event.job.ts | 8 +- .../timeline-activity.repository.ts | 2 +- .../services/timeline-activity.service.ts | 2 +- .../src/modules/view/services/view.service.ts | 24 +- .../view-filter.workspace-entity.ts | 14 +- .../standard-objects/view.workspace-entity.ts | 13 + .../workflow-query-validation.exception.ts | 11 + .../workflow-create-many.post-query.hook.ts | 42 + .../workflow-create-many.pre-query.hook.ts | 24 + .../workflow-create-one.post-query.hook.ts | 40 + .../workflow-create-one.pre-query.hook.ts | 22 + .../query-hooks/workflow-query-hook.module.ts | 38 + ...workflow-run-create-many.pre-query.hook.ts | 21 + .../workflow-run-create-one.pre-query.hook.ts | 21 + ...workflow-run-delete-many.pre-query.hook.ts | 21 + .../workflow-run-delete-one.pre-query.hook.ts | 20 + ...workflow-run-update-many.pre-query.hook.ts | 21 + .../workflow-run-update-one.pre-query.hook.ts | 21 + .../workflow-update-many.pre-query.hook.ts | 21 + .../workflow-update-one.pre-query.hook.ts | 22 + ...flow-version-create-many.pre-query.hook.ts | 37 + ...kflow-version-create-one.pre-query.hook.ts | 28 + ...flow-version-delete-many.pre-query.hook.ts | 23 + ...kflow-version-delete-one.pre-query.hook.ts | 27 + ...flow-version-update-many.pre-query.hook.ts | 23 + ...kflow-version-update-one.pre-query.hook.ts | 28 + .../workflow-version.workspace-entity.ts | 15 +- .../workflow.workspace-entity.ts | 37 +- .../common/types/workflow-result.type.ts | 10 - .../common/types/workflow-settings.type.ts | 14 - .../common/types/workflow-step.type.ts | 18 - ...sert-workflow-statuses-not-set-or-empty.ts | 16 + .../utils/assert-workflow-statuses-not-set.ts | 16 + .../assert-workflow-version-is-draft.util.ts | 19 + ...orkflow-version-trigger-is-defined.util.ts | 22 + .../workflow/common/workflow-common.module.ts | 4 +- .../workflow-common.workspace-service.ts | 35 +- ...ow-version-validation.workspace-service.ts | 112 + .../workflow-executor.exception.ts | 0 .../workflow-step-executor.exception.ts | 13 + .../factories/workflow-action.factory.ts | 33 + .../interfaces/workflow-action.interface.ts | 12 + .../types/workflow-action-result.type.ts | 10 + .../types/workflow-action.type.ts | 27 + .../types/workflow-step-settings.type.ts | 24 + .../workflow-executor.module.ts | 18 +- .../workflow-executor.workspace-service.ts | 24 +- .../exceptions/workflow-run.exception.ts | 14 + .../workflow-runner/jobs/run-workflow.job.ts | 12 +- .../workflow-run/workflow-run.module.ts | 11 - .../workflow-runner/workflow-runner.module.ts | 12 +- .../workflow-run.workspace-service.ts | 4 +- .../workflow-runner.workspace-service.ts | 8 +- .../constants/workflow-status.constants.ts | 19 + .../enums/workflow-status.enum.ts | 8 + .../workflow-statuses-update.job.spec.ts | 268 + .../jobs/workflow-statuses-update.job.ts | 201 + .../workflow-version-status.listener.ts | 96 + .../get-status-combination-from-array.util.ts | 37 + ...get-status-combination-from-update.util.ts | 75 + .../get-statuses-from-combination.util.ts | 29 + .../workflow-status/workflow-status.module.ts | 9 + .../workflow-step-executor.factory.ts | 26 - .../workflow-step-executor.interface.ts | 12 - .../workflow-step-executor.module.ts | 17 - .../database-event-trigger.service.ts | 2 +- .../database-event-trigger.listener.ts | 21 +- .../workflow-trigger.exception.ts | 0 .../jobs/workflow-event-trigger.job.ts | 10 +- .../types/workflow-trigger.type.ts | 0 .../assert-version-can-be-activated.util.ts | 17 +- .../workflow-trigger.module.ts | 2 +- .../workflow-trigger.workspace-service.ts | 237 - .../workflow-trigger.workspace-service.ts | 368 + .../src/modules/workflow/workflow.module.ts | 3 +- .../src/queue-worker/queue-worker.module.ts | 8 +- .../src/queue-worker/queue-worker.ts | 5 +- .../src/utils/generate-front-config.ts | 2 +- .../test/activities.integration-spec.ts | 67 + .../test/activity-targets.integration-spec.ts | 59 + .../test/api-keys.integration-spec.ts | 57 + packages/twenty-server/test/app.e2e-spec.ts | 31 - .../test/attachments.integration-spec.ts | 71 + .../test/audit-logs.integration-spec.ts | 65 + .../test/auth.integration-spec.ts | 80 + .../test/blocklists.integration-spec.ts | 55 + ...nel-event-associations.integration-spec.ts | 63 + .../calendar-channels.integration-spec.ts | 75 + ...dar-event-participants.integration-spec.ts | 65 + .../test/comments.integration-spec.ts | 57 + .../test/companies.integration-spec.ts | 67 + .../twenty-server/test/company.e2e-spec.ts | 310 - .../test/company.integration-spec.ts | 48 + .../connected-accounts.integration-spec.ts | 67 + .../test/favorites.integration-spec.ts | 67 + packages/twenty-server/test/jest-e2e.json | 14 - ...l-message-associations.integration-spec.ts | 67 + .../test/message-channels.integration-spec.ts | 85 + .../message-participants.integration-spec.ts | 63 + .../test/message-threads.integration-spec.ts | 51 + .../twenty-server/test/mock-data/user.json | 9 - .../test/mock-data/workspace.json | 7 - .../test/note-targets.integration-spec.ts | 59 + .../test/notes.integration-spec.ts | 57 + .../test/objects.integration-spec.ts | 75 + .../test/opportunities.integration-spec.ts | 63 + .../test/people.integration-spec.ts | 77 + .../serverless-functions.integration-spec.ts | 61 + .../test/task-targets.integration-spec.ts | 59 + .../test/tasks.integration-spec.ts | 63 + .../timeline-activities.integration-spec.ts | 75 + .../twenty-server/test/utils/create-app.ts | 21 +- .../twenty-server/test/utils/setup-test.ts | 16 + .../twenty-server/test/utils/setup-tests.ts | 3 - .../twenty-server/test/utils/teardown-test.ts | 5 + .../test/view-fields.integration-spec.ts | 61 + .../test/view-filters.integration-spec.ts | 61 + .../test/view-sorts.integration-spec.ts | 57 + .../test/views.integration-spec.ts | 67 + .../test/webhooks.integration-spec.ts | 57 + .../workspace-members.integration-spec.ts | 67 + packages/twenty-server/tsconfig.json | 2 +- packages/twenty-server/tsconfig.scripts.json | 5 + packages/twenty-ui/package.json | 2 +- .../src/display/avatar/components/Avatar.tsx | 26 +- .../src/display/avatar/types/AvatarType.ts | 2 +- .../src/display/banner/components/Banner.tsx | 16 +- .../display/chip/components/AvatarChip.tsx | 8 +- .../icon/assets/illustration-array.svg | 8 + .../assets/illustration-calendar-event.svg | 8 + .../assets/illustration-calendar-time.svg | 9 + .../icon/assets/illustration-currency.svg | 13 + .../display/icon/assets/illustration-json.svg | 5 + .../display/icon/assets/illustration-link.svg | 17 + .../display/icon/assets/illustration-mail.svg | 14 + .../icon/assets/illustration-many-to-many.svg | 8 + .../display/icon/assets/illustration-map.svg | 14 + .../icon/assets/illustration-numbers.svg | 14 + .../icon/assets/illustration-one-to-many.svg | 8 + .../icon/assets/illustration-one-to-one.svg | 8 + .../icon/assets/illustration-phone.svg | 12 + .../icon/assets/illustration-setting.svg | 6 + .../display/icon/assets/illustration-star.svg | 10 + .../display/icon/assets/illustration-tag.svg | 6 + .../display/icon/assets/illustration-tags.svg | 6 + .../display/icon/assets/illustration-text.svg | 17 + .../icon/assets/illustration-toggle.svg | 13 + .../display/icon/assets/illustration-uid.svg | 8 + .../display/icon/assets/illustration-user.svg | 6 + .../icon/components/IllustrationIconArray.tsx | 21 + .../IllustrationIconCalendarEvent.tsx | 23 + .../IllustrationIconCalendarTime.tsx | 24 + .../components/IllustrationIconCurrency.tsx | 25 + .../icon/components/IllustrationIconJson.tsx | 23 + .../icon/components/IllustrationIconMail.tsx | 22 + .../components/IllustrationIconManyToMany.tsx | 24 + .../icon/components/IllustrationIconMap.tsx | 22 + .../components/IllustrationIconNumbers.tsx | 24 + .../components/IllustrationIconOneToMany.tsx | 25 + .../components/IllustrationIconOneToOne.tsx | 25 + .../icon/components/IllustrationIconPhone.tsx | 24 + .../components/IllustrationIconSetting.tsx | 26 + .../icon/components/IllustrationIconStar.tsx | 24 + .../icon/components/IllustrationIconTag.tsx | 23 + .../icon/components/IllustrationIconTags.tsx | 23 + .../icon/components/IllustrationIconText.tsx | 23 + .../components/IllustrationIconToggle.tsx | 23 + .../icon/components/IllustrationIconUid.tsx | 23 + .../icon/components/IllustrationIconUser.tsx | 23 + .../components/IllustrationIconWrapper.tsx | 11 + .../display/icon/components/TablerIcons.ts | 8 + .../icon/components/llustrationIconLink.tsx | 23 + packages/twenty-ui/src/display/index.ts | 23 + .../typography/components/StyledText.tsx | 52 + packages/twenty-ui/src/index.ts | 1 + .../components/ExpandableContainer.tsx | 42 + .../ExpandableContainer.stories.tsx | 81 + packages/twenty-ui/src/layout/index.ts | 1 + .../twenty-ui/src/theme/constants/Icon.ts | 2 +- .../theme/constants/IllustrationIconDark.ts | 6 + .../theme/constants/IllustrationIconLight.ts | 6 + .../src/theme/constants/ThemeDark.ts | 6 +- .../src/theme/constants/ThemeLight.ts | 5 +- packages/twenty-ui/src/theme/index.ts | 2 + packages/twenty-ui/tsconfig.dev.json | 2 +- packages/twenty-website/package.json | 2 +- .../images/releases/0.30/0.30-array-field.png | Bin 0 -> 168345 bytes .../images/releases/0.30/0.30-emails.png | Bin 0 -> 147906 bytes .../releases/0.30/0.30-new-settings.png | Bin 0 -> 321910 bytes .../playground/rest-api-wrapper.tsx | 6 +- .../self-hosting/docker-compose.mdx | 229 +- .../self-hosting/self-hosting-var.mdx | 6 +- .../developers/self-hosting/upgrade-guide.mdx | 35 +- .../src/content/releases/0.30.0.mdx | 22 + .../getting-started/what-is-twenty.mdx | 2 +- .../github/contributors/save-issues-to-db.tsx | 27 +- .../github/contributors/save-prs-to-db.tsx | 28 +- yarn.lock | 1271 +- 1606 files changed, 57973 insertions(+), 46173 deletions(-) create mode 100644 .github/workflows/ci-server.yaml create mode 100644 packages/twenty-emails/src/emails/workflow-action.email.tsx create mode 100644 packages/twenty-front/public/images/placeholders/background/no_deleted_record_bg.png create mode 100644 packages/twenty-front/public/images/placeholders/dark-background/no_deleted_record_bg.png create mode 100644 packages/twenty-front/public/images/placeholders/dark-moving-image/no_deleted_record.png create mode 100644 packages/twenty-front/public/images/placeholders/moving-image/no_deleted_record.png create mode 100644 packages/twenty-front/src/SettingsRoutes.tsx create mode 100644 packages/twenty-front/src/hooks/usePreventOverlapCallback.ts create mode 100644 packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageWithSender.ts rename packages/twenty-front/src/modules/activities/timelineActivities/hooks/{useLinkedObject.ts => useLinkedObjectObjectMetadataItem.ts} (86%) create mode 100644 packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectsTitle.ts rename packages/twenty-front/src/modules/activities/timelineActivities/hooks/{useTimelineActivities.tsx => useTimelineActivities.ts} (71%) create mode 100644 packages/twenty-front/src/modules/activities/timelineActivities/types/TimelineActivityLinkedObject.ts create mode 100644 packages/twenty-front/src/modules/activities/timelineActivities/utils/filterTimelineActivityByLinkedObjectTypes.ts delete mode 100644 packages/twenty-front/src/modules/apollo/optimistic-effect/utils/getRelationDefinition.ts delete mode 100644 packages/twenty-front/src/modules/client-config/states/telemetryState.ts rename packages/twenty-front/src/modules/error-handler/components/{SentryInitiEffect.tsx => SentryInitEffect.tsx} (89%) rename packages/twenty-front/src/modules/favorites/components/{Favorites.tsx => CurrentWorkspaceMemberFavorites.tsx} (83%) create mode 100644 packages/twenty-front/src/modules/favorites/components/WorkspaceFavorites.tsx create mode 100644 packages/twenty-front/src/modules/favorites/utils/sort-favorites.util.ts create mode 100644 packages/twenty-front/src/modules/keyboard-shortcut-menu/components/__stories__/KeyboardShortcutMenu.stories.tsx create mode 100644 packages/twenty-front/src/modules/localization/utils/formatDateISOStringToRelativeDate.ts create mode 100644 packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx create mode 100644 packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx create mode 100644 packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper.tsx delete mode 100644 packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx delete mode 100644 packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx create mode 100644 packages/twenty-front/src/modules/object-metadata/components/__stories__/NavigationDrawerSectionForObjectMetadataItemsWrapper.stories.tsx delete mode 100644 packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx create mode 100644 packages/twenty-front/src/modules/object-metadata/hooks/useGetStandardObjectIcon.ts create mode 100644 packages/twenty-front/src/modules/object-metadata/hooks/useObjectIsRemote.ts create mode 100644 packages/twenty-front/src/modules/object-metadata/hooks/useObjectLabel.ts delete mode 100644 packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts delete mode 100644 packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts rename packages/twenty-front/src/modules/object-record/hooks/{useDestroyManyRecordMutation.ts => useDestroyManyRecordsMutation.ts} (100%) create mode 100644 packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecord.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecordMutation.ts create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getInitialFilterValue.ts create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useColumnNewCardActions.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ArrayFieldDisplay.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhonesFieldDisplay.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayField.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayFieldDisplay.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesField.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesFieldDisplay.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldInput.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldMenuItem.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldInput.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArray.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArrayValue.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhones.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhonesValue.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddButton.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem.tsx delete mode 100644 packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexEventContext.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexRootPropsContext.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddButton.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddMenuItem.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState.tsx delete mode 100644 packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader.tsx delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyState.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordAtAll.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordFoundForFilter.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateRemote.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordAtAll.stories.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordFoundForFilter.stories.tsx rename packages/twenty-front/src/modules/object-record/record-table/{components/__stories__/RecordTableEmptyState.stories.tsx => empty-state/components/__stories__/RecordTableEmptyStateRemote.stories.tsx} (53%) create mode 100644 packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateSoftDelete.stories.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/hooks/useCreateNewTableRecords.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/isSoftDeleteFilterActiveComponentState.ts create mode 100644 packages/twenty-front/src/modules/object-record/utils/getDestroyOneRecordMutationResponseField.ts create mode 100644 packages/twenty-front/src/modules/settings/accounts/constants/SyncStatus.ts create mode 100644 packages/twenty-front/src/modules/settings/accounts/utils/__tests__/computeSyncStatus.test.ts create mode 100644 packages/twenty-front/src/modules/settings/accounts/utils/computeSyncStatus.ts rename packages/twenty-front/src/modules/settings/components/{SettingsNavigationCard.tsx => SettingsCard.tsx} (67%) create mode 100644 packages/twenty-front/src/modules/settings/components/__stories__/SettingsCard.stories.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelNewFieldBreadcrumbDropDown.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategories.ts create mode 100644 packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategoryDescriptions.ts create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/components/StyledFormCardTitle.tsx delete mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldToggle.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldDescriptionForm.stories.tsx rename packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/{SettingsDataModelFieldAboutForm.stories.tsx => SettingsDataModelFieldIconLabelForm.stories.tsx} (65%) create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateSettingsFormCard.tsx create mode 100644 packages/twenty-front/src/modules/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues.ts create mode 100644 packages/twenty-front/src/modules/settings/data-model/types/SettingsFieldTypeCategoryType.ts create mode 100644 packages/twenty-front/src/modules/settings/serverless-functions/graphql/queries/findManyAvailablePackages.ts create mode 100644 packages/twenty-front/src/modules/settings/serverless-functions/hooks/useGetAvailablePackages.ts create mode 100644 packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumnBanner.tsx create mode 100644 packages/twenty-front/src/modules/ui/field/display/components/ArrayDisplay.tsx create mode 100644 packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx create mode 100644 packages/twenty-front/src/modules/ui/input/components/internal/date/components/AbsoluteDatePickerHeader.tsx create mode 100644 packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx create mode 100644 packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateDirectionSelectOptions.ts create mode 100644 packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateUnitSelectOptions.ts create mode 100644 packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getHighlightedDates.ts create mode 100644 packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getMonthSelectOptions.ts create mode 100644 packages/twenty-front/src/modules/ui/input/hooks/useInputFocusWithoutScrollOnMount.ts create mode 100644 packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx create mode 100644 packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts create mode 100644 packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilCallbackState.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentState.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilySelectorV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentInstanceStateContext.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentSelectorV2.ts delete mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentState.ts delete mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKey.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKeyV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateTypeV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentState.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentStateKey.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentInstanceContext.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelectorV2.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2_alpha.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createEventContext.ts create mode 100644 packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap.ts create mode 100644 packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useChangeView.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useCreateViewFiltersAndSorts.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useDeleteView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/useHandleViews.ts delete mode 100644 packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useResetUnsavedViewStates.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useUpdateView.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts create mode 100644 packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts delete mode 100644 packages/twenty-front/src/modules/views/scopes/ViewScope.tsx delete mode 100644 packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx delete mode 100644 packages/twenty-front/src/modules/views/scopes/scope-internal-context/ViewScopeInternalContext.ts create mode 100644 packages/twenty-front/src/modules/views/states/contexts/ViewComponentInstanceContext.ts delete mode 100644 packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentFamilySelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts delete mode 100644 packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentFamilyState.ts delete mode 100644 packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts create mode 100644 packages/twenty-front/src/modules/views/utils/__tests__/getCombinedViewFilters.test.ts rename packages/twenty-front/src/modules/views/utils/{combinedViewFilters.ts => getCombinedViewFilters.ts} (96%) rename packages/twenty-front/src/modules/views/utils/{combinedViewSorts.ts => getCombinedViewSorts.ts} (96%) create mode 100644 packages/twenty-front/src/modules/views/utils/view-filter-value/computeVariableDateViewFilterValue.ts create mode 100644 packages/twenty-front/src/modules/views/utils/view-filter-value/resolveDateViewFilterValue.ts create mode 100644 packages/twenty-front/src/modules/views/utils/view-filter-value/resolveFilterValue.ts create mode 100644 packages/twenty-front/src/modules/views/utils/view-filter-value/resolveNumberViewFilterValue.ts rename packages/twenty-front/src/modules/views/view-picker/components/{ViewPickerCreateOrEditContent.tsx => ViewPickerContentCreateMode.tsx} (51%) create mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEditMode.tsx create mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx create mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateButton.tsx delete mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContentEffect.tsx rename packages/twenty-front/src/modules/views/view-picker/components/{ViewPickerCreateOrEditButton.tsx => ViewPickerEditButton.tsx} (53%) create mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerIconAndNameContainer.tsx create mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSaveButtonContainer.tsx create mode 100644 packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSelectContainer.tsx create mode 100644 packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts create mode 100644 packages/twenty-front/src/modules/views/view-picker/hooks/useDeleteViewFromCurrentState.ts create mode 100644 packages/twenty-front/src/modules/views/view-picker/hooks/useUpdateViewFromCurrentState.ts delete mode 100644 packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerPersistView.ts delete mode 100644 packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerStates.ts create mode 100644 packages/twenty-front/src/modules/views/view-picker/types/ViewPickerMode.ts create mode 100644 packages/twenty-front/src/modules/workflow/components/RecordShowPageWorkflowHeader.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStep.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStepContent.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectAction.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectActionContent.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/Workflow.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvas.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEffect.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowDiagramEmptyTrigger.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNode.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowEditActionForm.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowEditTriggerForm.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowEffect.tsx delete mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagram.tsx delete mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagramCreateStepNode.tsx.tsx delete mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowShowPageEffect.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/WorkflowVersionStatusTag.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/__stories__/RecordShowPageWorkflowHeader.stories.tsx create mode 100644 packages/twenty-front/src/modules/workflow/components/__stories__/WorkflowVersionStatusTag.stories.tsx create mode 100644 packages/twenty-front/src/modules/workflow/constants/Actions.ts create mode 100644 packages/twenty-front/src/modules/workflow/constants/ObjectEventTriggers.ts create mode 100644 packages/twenty-front/src/modules/workflow/constants/TriggerStepId.ts create mode 100644 packages/twenty-front/src/modules/workflow/graphql/activateWorkflowVersion.ts create mode 100644 packages/twenty-front/src/modules/workflow/graphql/deactivateWorkflowVersion.ts create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useActivateWorkflowVersion.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useCreateNewWorkflowVersion.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useCreateStep.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useDeactivateWorkflowVersion.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useDeleteOneWorkflowVersion.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useStartNodeCreation.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionStep.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionTrigger.tsx create mode 100644 packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.tsx create mode 100644 packages/twenty-front/src/modules/workflow/states/workflowCreateStepFromParentStepIdState.ts create mode 100644 packages/twenty-front/src/modules/workflow/states/workflowDiagramState.ts create mode 100644 packages/twenty-front/src/modules/workflow/states/workflowDiagramTriggerNodeSelectionState.ts create mode 100644 packages/twenty-front/src/modules/workflow/states/workflowIdState.ts create mode 100644 packages/twenty-front/src/modules/workflow/states/workflowSelectedNodeState.ts delete mode 100644 packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowLastDiagramVersion.test.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowVersionDiagram.test.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/__tests__/insertStep.test.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/__tests__/replaceStep.test.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/assertWorkflowWithCurrentVersionIsDefined.tsx create mode 100644 packages/twenty-front/src/modules/workflow/utils/findStepPositionOrThrow.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/getStepDefaultDefinition.ts delete mode 100644 packages/twenty-front/src/modules/workflow/utils/getWorkflowLastDiagramVersion.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/getWorkflowVersionDiagram.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/insertStep.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/replaceStep.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/splitWorkflowTriggerEventName.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/deleteWorkspaceInvitation.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/resendWorkspaceInvitation.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/sendInvitations.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/graphql/queries/getWorkspaceInvitations.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/hooks/useCreateWorkspaceInvitation.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/hooks/useResendWorkspaceInvitation.ts create mode 100644 packages/twenty-front/src/modules/workspace-invitation/states/workspaceInvitationsStates.ts create mode 100644 packages/twenty-front/src/modules/workspace-member/grapqhql/mutations/addUserToWorkspaceByInviteToken.ts delete mode 100644 packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx delete mode 100644 packages/twenty-front/src/modules/workspace/graphql/mutations/sendInviteLink.ts create mode 100644 packages/twenty-front/src/pages/object-record/RecordShowPageBaseHeader.tsx delete mode 100644 packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx create mode 100644 packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx create mode 100644 packages/twenty-front/src/testing/mock-data/generated/mock-metadata-query-result.ts delete mode 100644 packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts create mode 100644 packages/twenty-front/src/utils/createRootPropsContext.ts create mode 100644 packages/twenty-front/src/utils/format/spiltFullName.ts create mode 100644 packages/twenty-front/src/utils/string/turnIntoEmptyStringIfWhitespacesOnly.ts create mode 100644 packages/twenty-front/src/utils/string/turnIntoUndefinedIfWhitespacesOnly.ts create mode 100644 packages/twenty-front/src/utils/url/__tests__/isValidUrl.test.ts create mode 100644 packages/twenty-front/src/utils/url/isValidUrl.ts create mode 100644 packages/twenty-server/.idea/.gitignore create mode 100644 packages/twenty-server/.idea/codeStyles/Project.xml create mode 100644 packages/twenty-server/.idea/codeStyles/codeStyleConfig.xml create mode 100644 packages/twenty-server/.idea/inspectionProfiles/Project_Default.xml create mode 100644 packages/twenty-server/.idea/modules.xml create mode 100644 packages/twenty-server/.idea/twenty-server.iml create mode 100644 packages/twenty-server/.idea/vcs.xml create mode 100644 packages/twenty-server/@types/jest.d.ts create mode 100644 packages/twenty-server/jest-integration.config.ts rename packages/twenty-server/patches/{@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch => @graphql-yoga+nestjs+2.1.0.patch} (92%) create mode 100644 packages/twenty-server/scripts/generate-integration-tests/index.ts create mode 100644 packages/twenty-server/scripts/generate-integration-tests/introspection-query.ts create mode 100644 packages/twenty-server/scripts/generate-integration-tests/introspection.interface.ts delete mode 100755 packages/twenty-server/scripts/run-integration.sh delete mode 100755 packages/twenty-server/scripts/set-env-test.sh create mode 100644 packages/twenty-server/src/database/commands/active-workspaces.command.ts create mode 100644 packages/twenty-server/src/database/commands/base.command.ts delete mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command.ts delete mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.command.ts delete mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.module.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-view-filter-operand-for-date-time.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-phone-fields-to-phones.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.module.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-add-index-key-to-tasks-and-notes-views.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-backfill-workspace-favorites.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-clean-views-associated-with-outdated-objects.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.command.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.module.ts create mode 100644 packages/twenty-server/src/database/typeorm-seeds/metadata/objectsMetadata.ts create mode 100644 packages/twenty-server/src/database/typeorm-seeds/workspace/favorites.ts create mode 100644 packages/twenty-server/src/database/typeorm/core/migrations/1724056827317-addInvitation.ts create mode 100644 packages/twenty-server/src/database/typeorm/core/migrations/1726849473832-addUniqueConstraintOnUsers.ts create mode 100644 packages/twenty-server/src/database/typeorm/metadata/migrations/1724946099627-addServerlessFunctionLayerVersionColumn.ts create mode 100644 packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-create-many-resolver.service.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-destroy-one-resolver.service.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/compute-cursor-arg-filter.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/destroy-one-resolver.factory.ts create mode 100644 packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/array-filter.input-type.ts create mode 100644 packages/twenty-server/src/engine/core-modules/auth/dto/workspace-invite-token.input.ts rename packages/twenty-server/src/engine/core-modules/auth/{ => token}/services/token.service.spec.ts (98%) rename packages/twenty-server/src/engine/core-modules/auth/{ => token}/services/token.service.ts (95%) create mode 100644 packages/twenty-server/src/engine/core-modules/auth/token/token.module.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/cache-storage/cache-storage.module-factory.ts (81%) rename packages/twenty-server/src/engine/{integrations => core-modules}/cache-storage/cache-storage.module.ts (58%) create mode 100644 packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/cache-storage/decorators/cache-storage.decorator.ts (78%) rename packages/twenty-server/src/engine/{integrations/cache-storage => core-modules/cache-storage/services}/cache-storage.service.ts (96%) rename packages/twenty-server/src/engine/{integrations => core-modules}/cache-storage/types/cache-storage-namespace.enum.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/cache-storage/types/cache-storage-type.enum.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/captcha.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/captcha.guard.ts (91%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/captcha.module-factory.ts (85%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/captcha.module.ts (76%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/captcha.service.ts (71%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/drivers/google-recaptcha.driver.ts (86%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/drivers/interfaces/captcha-driver.interface.ts (64%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/drivers/interfaces/captcha-server-response.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/drivers/turnstile.driver.ts (86%) rename packages/twenty-server/src/engine/{integrations => core-modules}/captcha/interfaces/captcha.interface.ts (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/captcha/interfaces/index.ts create mode 100644 packages/twenty-server/src/engine/core-modules/cron/sentry-cron-monitor.decorator.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/email/drivers/interfaces/email-driver.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/drivers/logger.driver.ts (90%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/drivers/smtp.driver.ts (92%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/email-sender.job.ts (63%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/email-sender.service.ts (76%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/email.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/email.module-factory.ts (89%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/email.module.ts (65%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/email.service.ts (70%) rename packages/twenty-server/src/engine/{integrations => core-modules}/email/interfaces/email.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts (96%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts (96%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/cast-to-boolean.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/cast-to-log-level-array.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/cast-to-positive-number.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/cast-to-string-array.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/is-aws-region.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/is-duration.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/decorators/is-strictly-lower-than.decorator.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/environment-variables.ts (82%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/environment.module-definition.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/environment.module.ts (50%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/environment.service.spec.ts (86%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/environment.service.ts (88%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/interfaces/aws-region.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/interfaces/node-environment.interface.ts (84%) rename packages/twenty-server/src/engine/{integrations => core-modules}/environment/interfaces/support.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/types/object-record-create.event.ts (70%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/types/object-record-delete.event.ts (71%) create mode 100644 packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-destroy.event.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/types/object-record-update.event.ts (77%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/types/object-record.base.event.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/utils/__tests__/object-record-changed-values.spec.ts (96%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/utils/object-record-changed-properties.util.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/utils/object-record-changed-values.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/event-emitter/utils/object-record-diff-merge.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/__tests__/exception-handler.service.spec.ts (83%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/drivers/console.driver.ts (74%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/drivers/sentry.driver.ts (71%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/exception-handler.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/exception-handler.module-definition.ts (75%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/exception-handler.module-factory.ts (86%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/exception-handler.module.ts (65%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/exception-handler.service.ts (69%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/hooks/use-sentry-tracing.ts (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-driver.interface.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/interfaces/exception-handler-options.interface.ts (63%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/interfaces/exception-handler-user.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/exception-handler/interfaces/exception-handler.interface.ts (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/index.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/__tests__/file-storage.service.spec.ts (82%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/drivers/interfaces/storage-driver.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/drivers/local.driver.ts (90%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/drivers/s3.driver.ts (72%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/file-storage.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/file-storage.module-definition.ts (76%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/file-storage.module-factory.ts (93%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/file-storage.module.ts (73%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/file-storage.service.ts (83%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/interfaces/file-storage-exception.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/interfaces/file-storage.interface.ts (85%) create mode 100644 packages/twenty-server/src/engine/core-modules/file-storage/interfaces/index.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/file-storage/utils/read-file-content.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/drivers/openai.driver.ts (89%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/interfaces/llm-chat-model.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/llm-chat-model.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/llm-chat-model.module-factory.ts (76%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/llm-chat-model.module.ts (77%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-chat-model/llm-chat-model.service.ts (74%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/drivers/console.driver.ts (92%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/drivers/interfaces/llm-tracing-driver.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/drivers/langfuse.driver.ts (91%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/interfaces/llm-tracing.interface.ts (91%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/llm-tracing.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/llm-tracing.module-factory.ts (88%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/llm-tracing.module.ts (75%) rename packages/twenty-server/src/engine/{integrations => core-modules}/llm-tracing/llm-tracing.service.ts (78%) rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/__tests__/logger.service.spec.ts (80%) create mode 100644 packages/twenty-server/src/engine/core-modules/logger/interfaces/index.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/interfaces/logger.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/logger.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/logger.module-definition.ts (78%) rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/logger.module-factory.ts (85%) rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/logger.module.ts (83%) rename packages/twenty-server/src/engine/{integrations => core-modules}/logger/logger.service.ts (93%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/decorators/message-queue.decorator.ts (63%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/decorators/process.decorator.ts (90%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/decorators/processor.decorator.ts (91%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/drivers/bullmq.driver.ts (87%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/drivers/interfaces/job-options.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/drivers/interfaces/message-queue-driver.interface.ts (72%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/drivers/pg-boss.driver.ts (83%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/drivers/sync.driver.ts (86%) create mode 100644 packages/twenty-server/src/engine/core-modules/message-queue/interfaces/index.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/interfaces/message-queue-job.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/interfaces/message-queue-module-options.interface.ts (83%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/interfaces/message-queue-worker-options.interface.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/jobs.module.ts (93%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue-core.module.ts (84%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue-metadata.accessor.ts (77%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue.explorer.ts (91%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue.module-definition.ts (80%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue.module-factory.ts (81%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/message-queue.module.ts (74%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts (85%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/services/message-queue.service.ts (78%) rename packages/twenty-server/src/engine/{integrations => core-modules}/message-queue/utils/get-queue-token.util.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/base-serverless.driver.ts (71%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/constants/build-file-name.ts (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/common-layer-name.ts create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/serverless-tmpdir-folder.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/constants/source-file-name.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/interfaces/serverless-driver.interface.ts (96%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/lambda.driver.ts (60%) create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/package.json create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/yarn.lock create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarn/releases/yarn-4.4.0.cjs create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarnrc.yml create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/last-layer-version.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/local.driver.ts (73%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/utils/compile-typescript.ts (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/copy-and-build-dependencies.ts rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/drivers/utils/create-zip-file.ts (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-last-layer-dependencies.ts create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-layer-dependencies-dir-name.ts rename packages/twenty-server/src/engine/{integrations/serverless/drivers/services/build-directory-manager.service.ts => core-modules/serverless/drivers/utils/lambda-build-directory-manager.ts} (50%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/serverless-module.factory.ts (78%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/serverless.constants.ts (100%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/serverless.interface.ts (85%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/serverless.module.ts (61%) rename packages/twenty-server/src/engine/{integrations => core-modules}/serverless/serverless.service.ts (86%) create mode 100644 packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts create mode 100644 packages/twenty-server/src/engine/core-modules/telemetry/telemetry.module.ts create mode 100644 packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts rename packages/twenty-server/src/engine/core-modules/{workspace/dtos/send-invite-link.input.ts => workspace-invitation/dtos/send-invitations.input.ts} (86%) create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.output.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.exception.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.module.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.resolver.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.entity.ts create mode 100644 packages/twenty-server/src/engine/guards/jwt-auth.guard.ts delete mode 100644 packages/twenty-server/src/engine/guards/jwt.auth.guard.ts delete mode 100644 packages/twenty-server/src/engine/guards/optional-jwt.auth.guard.ts create mode 100644 packages/twenty-server/src/engine/guards/user-auth.guard.ts create mode 100644 packages/twenty-server/src/engine/guards/workspace-auth.guard.ts delete mode 100644 packages/twenty-server/src/engine/integrations/captcha/interfaces/index.ts delete mode 100644 packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-driver.interface.ts delete mode 100644 packages/twenty-server/src/engine/integrations/exception-handler/interfaces/index.ts delete mode 100644 packages/twenty-server/src/engine/integrations/file-storage/interfaces/index.ts delete mode 100644 packages/twenty-server/src/engine/integrations/integrations.module.ts delete mode 100644 packages/twenty-server/src/engine/integrations/logger/interfaces/index.ts delete mode 100644 packages/twenty-server/src/engine/integrations/message-queue/interfaces/index.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.service.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/utils/generate-object-metadata-map.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/exceptions/workspace-metadata-cache.exception.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/exceptions/workspace-metadata-version.exception.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service.ts create mode 100644 packages/twenty-server/src/engine/twenty-orm/exceptions/twenty-orm.exception.ts create mode 100644 packages/twenty-server/src/engine/twenty-orm/utils/format-data.util.ts create mode 100644 packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts create mode 100644 packages/twenty-server/src/engine/twenty-orm/utils/get-composite-field-metadata-collection.ts create mode 100644 packages/twenty-server/src/engine/utils/transform-enum-value.ts delete mode 100644 packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/activities-all.view.ts delete mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-status/services/workspace-status.service.ts delete mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-status/workspace-manager.module.ts create mode 100644 packages/twenty-server/src/instrument.ts create mode 100644 packages/twenty-server/src/modules/calendar/common/calendar-common.module.ts rename packages/twenty-server/src/modules/calendar/{calendar-event-import-manager => common}/services/calendar-channel-sync-status.service.ts (54%) create mode 100644 packages/twenty-server/src/modules/mail-sender/workflow-actions/send-email.workflow-action.ts create mode 100644 packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts rename packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/{messaging-message-channel-sync-status-monitoring.cron.ts => messaging-message-channel-sync-status-monitoring.cron.job.ts} (51%) rename packages/twenty-server/src/modules/{workflow/workflow-step-executor/workflow-step-executors/code-action-executor.ts => serverless/workflow-actions/code.workflow-action.ts} (65%) create mode 100644 packages/twenty-server/src/modules/workflow/common/exceptions/workflow-query-validation.exception.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.post-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.post-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-query-hook.module.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-one.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-one.pre-query.hook.ts delete mode 100644 packages/twenty-server/src/modules/workflow/common/types/workflow-result.type.ts delete mode 100644 packages/twenty-server/src/modules/workflow/common/types/workflow-settings.type.ts delete mode 100644 packages/twenty-server/src/modules/workflow/common/types/workflow-step.type.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-is-draft.util.ts create mode 100644 packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-trigger-is-defined.util.ts rename packages/twenty-server/src/modules/workflow/common/{ => workspace-services}/workflow-common.workspace-service.ts (53%) create mode 100644 packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service.ts rename packages/twenty-server/src/modules/workflow/workflow-executor/{ => exceptions}/workflow-executor.exception.ts (100%) create mode 100644 packages/twenty-server/src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-executor/interfaces/workflow-action.interface.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action-result.type.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action.type.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-step-settings.type.ts rename packages/twenty-server/src/modules/workflow/workflow-executor/{ => workspace-services}/workflow-executor.workspace-service.ts (71%) create mode 100644 packages/twenty-server/src/modules/workflow/workflow-runner/exceptions/workflow-run.exception.ts delete mode 100644 packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.module.ts rename packages/twenty-server/src/modules/workflow/workflow-runner/{workflow-run => workspace-services}/workflow-run.workspace-service.ts (95%) rename packages/twenty-server/src/modules/workflow/workflow-runner/{ => workspace-services}/workflow-runner.workspace-service.ts (82%) create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/constants/workflow-status.constants.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/enums/workflow-status.enum.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/jobs/__tests__/workflow-statuses-update.job.spec.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/listeners/workflow-version-status.listener.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-array.util.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-update.util.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/utils/get-statuses-from-combination.util.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-status/workflow-status.module.ts delete mode 100644 packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.factory.ts delete mode 100644 packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.interface.ts delete mode 100644 packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.module.ts rename packages/twenty-server/src/modules/workflow/workflow-trigger/{ => exceptions}/workflow-trigger.exception.ts (100%) rename packages/twenty-server/src/modules/workflow/{common => workflow-trigger}/types/workflow-trigger.type.ts (100%) delete mode 100644 packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.workspace-service.ts create mode 100644 packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts create mode 100644 packages/twenty-server/test/activities.integration-spec.ts create mode 100644 packages/twenty-server/test/activity-targets.integration-spec.ts create mode 100644 packages/twenty-server/test/api-keys.integration-spec.ts delete mode 100644 packages/twenty-server/test/app.e2e-spec.ts create mode 100644 packages/twenty-server/test/attachments.integration-spec.ts create mode 100644 packages/twenty-server/test/audit-logs.integration-spec.ts create mode 100644 packages/twenty-server/test/auth.integration-spec.ts create mode 100644 packages/twenty-server/test/blocklists.integration-spec.ts create mode 100644 packages/twenty-server/test/calendar-channel-event-associations.integration-spec.ts create mode 100644 packages/twenty-server/test/calendar-channels.integration-spec.ts create mode 100644 packages/twenty-server/test/calendar-event-participants.integration-spec.ts create mode 100644 packages/twenty-server/test/comments.integration-spec.ts create mode 100644 packages/twenty-server/test/companies.integration-spec.ts delete mode 100644 packages/twenty-server/test/company.e2e-spec.ts create mode 100644 packages/twenty-server/test/company.integration-spec.ts create mode 100644 packages/twenty-server/test/connected-accounts.integration-spec.ts create mode 100644 packages/twenty-server/test/favorites.integration-spec.ts delete mode 100644 packages/twenty-server/test/jest-e2e.json create mode 100644 packages/twenty-server/test/message-channel-message-associations.integration-spec.ts create mode 100644 packages/twenty-server/test/message-channels.integration-spec.ts create mode 100644 packages/twenty-server/test/message-participants.integration-spec.ts create mode 100644 packages/twenty-server/test/message-threads.integration-spec.ts delete mode 100644 packages/twenty-server/test/mock-data/user.json delete mode 100644 packages/twenty-server/test/mock-data/workspace.json create mode 100644 packages/twenty-server/test/note-targets.integration-spec.ts create mode 100644 packages/twenty-server/test/notes.integration-spec.ts create mode 100644 packages/twenty-server/test/objects.integration-spec.ts create mode 100644 packages/twenty-server/test/opportunities.integration-spec.ts create mode 100644 packages/twenty-server/test/people.integration-spec.ts create mode 100644 packages/twenty-server/test/serverless-functions.integration-spec.ts create mode 100644 packages/twenty-server/test/task-targets.integration-spec.ts create mode 100644 packages/twenty-server/test/tasks.integration-spec.ts create mode 100644 packages/twenty-server/test/timeline-activities.integration-spec.ts create mode 100644 packages/twenty-server/test/utils/setup-test.ts delete mode 100644 packages/twenty-server/test/utils/setup-tests.ts create mode 100644 packages/twenty-server/test/utils/teardown-test.ts create mode 100644 packages/twenty-server/test/view-fields.integration-spec.ts create mode 100644 packages/twenty-server/test/view-filters.integration-spec.ts create mode 100644 packages/twenty-server/test/view-sorts.integration-spec.ts create mode 100644 packages/twenty-server/test/views.integration-spec.ts create mode 100644 packages/twenty-server/test/webhooks.integration-spec.ts create mode 100644 packages/twenty-server/test/workspace-members.integration-spec.ts create mode 100644 packages/twenty-server/tsconfig.scripts.json create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-array.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-calendar-event.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-calendar-time.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-currency.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-json.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-link.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-mail.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-many-to-many.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-map.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-numbers.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-one-to-many.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-one-to-one.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-phone.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-setting.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-star.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-tag.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-tags.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-text.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-toggle.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-uid.svg create mode 100644 packages/twenty-ui/src/display/icon/assets/illustration-user.svg create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconArray.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarEvent.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarTime.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconCurrency.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconJson.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconMail.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconManyToMany.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconMap.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconNumbers.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconOneToMany.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconOneToOne.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconPhone.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconSetting.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconStar.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconTag.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconTags.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconText.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconToggle.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconUid.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconUser.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/IllustrationIconWrapper.tsx create mode 100644 packages/twenty-ui/src/display/icon/components/llustrationIconLink.tsx create mode 100644 packages/twenty-ui/src/display/typography/components/StyledText.tsx create mode 100644 packages/twenty-ui/src/layout/expandableContainer/components/ExpandableContainer.tsx create mode 100644 packages/twenty-ui/src/layout/expandableContainer/components/__stories__/ExpandableContainer.stories.tsx create mode 100644 packages/twenty-ui/src/layout/index.ts create mode 100644 packages/twenty-ui/src/theme/constants/IllustrationIconDark.ts create mode 100644 packages/twenty-ui/src/theme/constants/IllustrationIconLight.ts create mode 100644 packages/twenty-website/public/images/releases/0.30/0.30-array-field.png create mode 100644 packages/twenty-website/public/images/releases/0.30/0.30-emails.png create mode 100644 packages/twenty-website/public/images/releases/0.30/0.30-new-settings.png create mode 100644 packages/twenty-website/src/content/releases/0.30.0.mdx diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 10ab982ff999..8897ad01ab38 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -2,7 +2,7 @@ ## Twenty's Pledge -The contributors and maintainers of this project pledge to ensure a harassment-free experience for everyone in the community. This commitment applies to individuals of all backgrounds, including age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity, experience, education, socio-economic status, nationality, appearance, race, religion. It also applies to individuals of all sexual identities and orientations. +The contributors and maintainers of this project pledge to ensure a harassment-free experience for everyone in the community. The focus of both contributors and maintainers is on acting and interacting in ways that promote an open, welcoming, friendly, diverse, inclusive, and healthy community. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8a57d7b34744..bbaa50483fc9 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,47 +1,38 @@ # Contributing to Twenty +Thanks for considering contributing to Twenty! -Thank you for considering contributing to Twenty! All community contributions are welcome. - -This guide outlines the process for contributing to this project. Please make sure to go through the [documentation](https://docs.twenty.com) before making your contribution. - - -> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation: -> - Star the project -> - Tweet about it - +Please make sure to go through the [documentation](https://docs.twenty.com) before.
-## Getting Started - -Good first issues are a great way to start contributing to the project and get familiar with the codebase. Here's how to find them: - -1. Visit the "[Issues](https://github.com/twentyhq/twenty/issues)" tab on the main [repository](https://github.com/twentyhq/twenty). -2. Use the "Labels" filter and select "[Good First Issue](https://github.com/twentyhq/twenty/labels/good%20first%20issue)" to see a list of beginner-friendly tasks. -3. Choose an issue that interests you, fork the project, and start working on it. Once you solve and test the issue, open a PR for review. +## Good first issues -Note: We are aware that having multiple contributors address the same issue can cause frustration. To prevent this, we adhere to a specific guideline: if a core team member has assigned an issue to a contributor, either as the issue assignee or through explicit assignment in the issue comments within the past three days, that contributor's pull request takes precedence. Otherwise, the first PR submitted will be given priority. This delay is reduced to one day for PR tagged with "size: minutes" and extended to a week for PR tagged "size: days". +Good first issues are a great way to start contributing and get familiar with the codebase. You can find them on by filtering on the [good first issue](https://github.com/twentyhq/twenty/labels/good%20first%20issue) label. -Therefore, ensure you are assigned to an issue before beginning work on it. +## Issue assignment -
+Having multiple contributors address the same issue can cause frustration. +To avoid conflicts, we follow these guidelines: +1. If a core team member assigned you the issue within the last three days, your PR takes priority. +2. Otherwise, the first submitted PR is prioritized. +3. For "size: long" PRs, the assignment period extends to one week. -## Contributing Guidelines +Please ensure you're assigned to an issue before starting work. +## How to Contribute 1. **Fork the Repository:** Click on the 'Fork' button in the upper right corner of the repository's GitHub page. This will create a copy of the repository in your GitHub account. - 2. **Clone the Repository:** Clone your forked repository to your local machine using `git clone`. - ```shell git clone https://github.com/yourusername/twenty.git cd twenty ``` + 3. **Create a New Branch:** Create a new branch for your changes instead of using the main branch. ```shell @@ -56,40 +47,24 @@ git checkout -b your-branch-name 6. **Commit Changes:** Commit your changes with a clear and concise commit message. - ```shell git commit -m "Add your detailed description here" ``` -7. **Push Changes:** Push your changes to your forked repository. +7. **Push Changes:** Push your changes to your forked repository. ```shell git push origin your-branch-name ``` +8. **Create a Pull Request:** Go to the original Twenty repository and create a pull request. Please provide a detailed description of your changes. Submitting a PR means you agree to the CLA. -8. **Create a Pull Request:** Go to the original Twenty repository and create a pull request. Please provide a detailed description of your changes. To have your pull request accepted, you must sign a CLA. - - -9. **Code Review:** Your pull request will undergo a code review. Note that you might need to make any necessary adjustments based on feedback. - +9. **Code Review:** Your pull request will undergo a code review. 10. **Merge:** Once approved, maintainers will merge your pull request into the main repository. -
- -## Code of Conduct - -Please note that by contributing to this project, you're expected to follow Twenty's [Code of Conduct](./CODE_OF_CONDUCT.md). All maintainers strive to maintain a welcoming, friendly, and inclusive community for all contributors. - -
## Reporting Issues -If you encounter any issues or have suggestions for improvements, please feel free to (create an issue on Twenty's GitHub repository)[https://github.com/twentyhq/twenty/issues/new]. When reporting issues, please provide as much detail as possible to help in understanding and addressing the problem effectively. - ---- - -Thank you for considering contributing to Twenty. Your contributions help make Twenty's CRM platform even better! - +If you face any issues or have suggestions, please feel free to (create an issue on Twenty's GitHub repository)[https://github.com/twentyhq/twenty/issues/new]. Please provide as much detail as possible. \ No newline at end of file diff --git a/.github/workflows/ci-server.yaml b/.github/workflows/ci-server.yaml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/.gitignore b/.gitignore index febe678d4530..11f7c37e5683 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,7 @@ dist storybook-static *.tsbuildinfo .eslintcache +.cache .nyc_output -test-results/ \ No newline at end of file +test-results/ +dump.rdb diff --git a/.vscode/twenty.code-workspace b/.vscode/twenty.code-workspace index 41549b6f9d6e..ce2498959c8e 100644 --- a/.vscode/twenty.code-workspace +++ b/.vscode/twenty.code-workspace @@ -20,6 +20,10 @@ "name": "packages/twenty-ui", "path": "../packages/twenty-ui" }, + { + "name": "packages/twenty-emails", + "path": "../packages/twenty-emails" + }, { "name": "packages/twenty-postgres", "path": "../packages/twenty-postgres" diff --git a/README.md b/README.md index d46caec8d4f9..f0c96b0a32ac 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ We felt the need for a CRM platform that empowers rather than constrains. We bel # Demo Go to
demo.twenty.com and login with the following credentials: + ``` email: noah@demo.dev password: Applecar2025 @@ -67,6 +68,7 @@ Below are some features we have implemented to date: + [Create tasks on records](#create-tasks-on-records) + [Navigate quickly through the app using keyboard shortcuts and search](#navigate-quickly-through-the-app-using-keyboard-shortcuts-and-search) + ## Add, filter, sort, edit, and track customers:

diff --git a/install.sh b/install.sh index 2b7a2d46ee9b..39eb096b8e25 100755 --- a/install.sh +++ b/install.sh @@ -112,8 +112,10 @@ if command -v nc &> /dev/null; then read -p "Enter a new port number: " new_port if [[ $(uname) == "Darwin" ]]; then sed -i '' "s/$port:$port/$new_port:$port/g" docker-compose.yml + sed -E -i '' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env else sed -i'' "s/$port:$port/$new_port:$port/g" docker-compose.yml + sed -E -i'' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env fi port=$new_port done diff --git a/package.json b/package.json index 3fa3c5449f44..7b24d7ca5668 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,6 @@ "@aws-sdk/credential-providers": "^3.363.0", "@blocknote/mantine": "^0.15.3", "@blocknote/react": "^0.15.3", - "@chakra-ui/accordion": "^2.3.0", - "@chakra-ui/system": "^2.6.0", "@codesandbox/sandpack-react": "^2.13.5", "@dagrejs/dagre": "^1.1.2", "@docusaurus/core": "^3.1.0", @@ -48,10 +46,9 @@ "@ptc-org/nestjs-query-typeorm": "4.2.1-alpha.2", "@react-email/components": "0.0.12", "@react-email/render": "0.0.10", - "@sentry/node": "^7.99.0", - "@sentry/profiling-node": "^1.3.4", - "@sentry/react": "^7.88.0", - "@sentry/tracing": "^7.99.0", + "@sentry/node": "^8", + "@sentry/profiling-node": "^8", + "@sentry/react": "^8", "@sniptt/guards": "^0.2.0", "@stoplight/elements": "^8.0.5", "@swc/jest": "^0.2.29", @@ -94,7 +91,6 @@ "facepaint": "^1.2.1", "file-type": "16.5.4", "framer-motion": "^10.12.17", - "fs-extra": "^11.2.0", "googleapis": "105", "graphiql": "^3.1.1", "graphql": "16.8.0", @@ -277,6 +273,7 @@ "@types/node": "18.19.26", "@types/passport-google-oauth20": "^2.0.11", "@types/passport-jwt": "^3.0.8", + "@types/pluralize": "^0.0.33", "@types/react": "^18.2.39", "@types/react-datepicker": "^6.2.0", "@types/react-dom": "^18.2.15", diff --git a/packages/twenty-chrome-extension/src/generated/graphql.tsx b/packages/twenty-chrome-extension/src/generated/graphql.tsx index 27d954014743..8b388aebc971 100644 --- a/packages/twenty-chrome-extension/src/generated/graphql.tsx +++ b/packages/twenty-chrome-extension/src/generated/graphql.tsx @@ -2527,6 +2527,7 @@ export enum FieldMetadataType { Number = 'NUMBER', Numeric = 'NUMERIC', Phone = 'PHONE', + Phones = 'PHONES', Position = 'POSITION', Rating = 'RATING', RawJson = 'RAW_JSON', diff --git a/packages/twenty-docker/.env.example b/packages/twenty-docker/.env.example index d7ab15672a9b..59d8d03f93a7 100644 --- a/packages/twenty-docker/.env.example +++ b/packages/twenty-docker/.env.example @@ -5,8 +5,8 @@ TAG=latest PG_DATABASE_HOST=db:5432 SERVER_URL=http://localhost:3000 -# Uncoment if you are serving your front on another server than the API (eg. bucket) -# FRONT_BASE_URL=http://localhost:3000 +# REDIS_HOST=redis +# REDIS_PORT=6379 # Use openssl rand -base64 32 for each secret # ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access @@ -21,5 +21,3 @@ STORAGE_TYPE=local # STORAGE_S3_REGION=eu-west3 # STORAGE_S3_NAME=my-bucket # STORAGE_S3_ENDPOINT= - -MESSAGE_QUEUE_TYPE=pg-boss diff --git a/packages/twenty-docker/docker-compose.yml b/packages/twenty-docker/docker-compose.yml index 73cfc46de61c..7a2c28873d89 100644 --- a/packages/twenty-docker/docker-compose.yml +++ b/packages/twenty-docker/docker-compose.yml @@ -64,8 +64,8 @@ services: NODE_ENV: ${NODE_ENV} PG_DATABASE_URL: postgres://twenty:${POSTGRES_ADMIN_PASSWORD}@${PG_DATABASE_HOST}/default PORT: 3000 - REDIS_HOST: redis - REDIS_PORT: 6379 + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_HOST: ${REDIS_HOST:-redis} REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET} REFRESH_TOKEN_EXPIRES_IN: ${REFRESH_TOKEN_EXPIRES_IN} SENTRY_DSN: ${SENTRY_DSN} @@ -135,8 +135,8 @@ services: MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED} NODE_ENV: ${NODE_ENV} PG_DATABASE_URL: postgres://twenty:${POSTGRES_ADMIN_PASSWORD}@${PG_DATABASE_HOST}/default - REDIS_HOST: redis - REDIS_PORT: 6379 + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_HOST: ${REDIS_HOST:-redis} REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET} REFRESH_TOKEN_EXPIRES_IN: ${REFRESH_TOKEN_EXPIRES_IN} SENTRY_DSN: ${SENTRY_DSN} diff --git a/packages/twenty-docker/twenty/Dockerfile b/packages/twenty-docker/twenty/Dockerfile index ee0b05215b77..e57cf30d1469 100644 --- a/packages/twenty-docker/twenty/Dockerfile +++ b/packages/twenty-docker/twenty/Dockerfile @@ -50,6 +50,8 @@ FROM node:18.17.1-alpine as twenty # Used to run healthcheck in docker RUN apk add --no-cache curl jq +RUN npm install -g tsx + COPY ./packages/twenty-docker/twenty/entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh diff --git a/packages/twenty-docker/twenty/entrypoint.sh b/packages/twenty-docker/twenty/entrypoint.sh index 17adc89521ab..9733781fd5e1 100755 --- a/packages/twenty-docker/twenty/entrypoint.sh +++ b/packages/twenty-docker/twenty/entrypoint.sh @@ -5,7 +5,7 @@ if [ "${ENABLE_DB_MIGRATIONS}" = "true" ] && [ ! -f /app/docker-data/db_status ] echo "Running database setup and migrations..." # Run setup and migration scripts - NODE_OPTIONS="--max-old-space-size=1500" npx ts-node ./scripts/setup-db.ts + NODE_OPTIONS="--max-old-space-size=1500" tsx ./scripts/setup-db.ts yarn database:migrate:prod # Mark initialization as done diff --git a/packages/twenty-emails/package.json b/packages/twenty-emails/package.json index 8e0785846bce..dc0b89328e3c 100644 --- a/packages/twenty-emails/package.json +++ b/packages/twenty-emails/package.json @@ -1,6 +1,6 @@ { "name": "twenty-emails", - "version": "0.24.0", + "version": "0.30.0", "description": "", "author": "", "private": true, diff --git a/packages/twenty-emails/src/emails/workflow-action.email.tsx b/packages/twenty-emails/src/emails/workflow-action.email.tsx new file mode 100644 index 000000000000..2eaa3a451ebb --- /dev/null +++ b/packages/twenty-emails/src/emails/workflow-action.email.tsx @@ -0,0 +1,29 @@ +import { BaseEmail } from 'src/components/BaseEmail'; +import { Title } from 'src/components/Title'; +import { CallToAction } from 'src/components/CallToAction'; + +type WorkflowActionEmailProps = { + dangerousHTML?: string; + title?: string; + callToAction?: { + value: string; + href: string; + }; +}; +export const WorkflowActionEmail = ({ + dangerousHTML, + title, + callToAction, +}: WorkflowActionEmailProps) => { + return ( + + {title && } + {dangerousHTML && ( + <div dangerouslySetInnerHTML={{ __html: dangerousHTML }} /> + )} + {callToAction && ( + <CallToAction value={callToAction.value} href={callToAction.href} /> + )} + </BaseEmail> + ); +}; diff --git a/packages/twenty-emails/src/index.ts b/packages/twenty-emails/src/index.ts index ddecb05c8655..9fca13d73b55 100644 --- a/packages/twenty-emails/src/index.ts +++ b/packages/twenty-emails/src/index.ts @@ -3,3 +3,4 @@ export * from './emails/delete-inactive-workspaces.email'; export * from './emails/password-reset-link.email'; export * from './emails/password-update-notify.email'; export * from './emails/send-invite-link.email'; +export * from './emails/workflow-action.email'; diff --git a/packages/twenty-front/.eslintrc.cjs b/packages/twenty-front/.eslintrc.cjs index bb57531265be..df4daf7633a4 100644 --- a/packages/twenty-front/.eslintrc.cjs +++ b/packages/twenty-front/.eslintrc.cjs @@ -6,7 +6,6 @@ module.exports = { 'mockServiceWorker.js', '**/generated*/*', '**/generated/standard-metadata-query-result.ts', - '**/getObjectMetadataItemsMock.ts', 'tsup.config.ts', 'build', 'coverage', diff --git a/packages/twenty-front/.storybook/main.ts b/packages/twenty-front/.storybook/main.ts index 3bd4d16b2a57..8b65348c4b69 100644 --- a/packages/twenty-front/.storybook/main.ts +++ b/packages/twenty-front/.storybook/main.ts @@ -51,9 +51,6 @@ const config: StorybookConfig = { return mergeConfig(config, { // Add dependencies to pre-optimization - optimizeDeps: { - exclude: ['@tabler/icons-react'], - }, }); }, }; diff --git a/packages/twenty-front/jest.config.ts b/packages/twenty-front/jest.config.ts index b9c8205189c7..c71df7b77aff 100644 --- a/packages/twenty-front/jest.config.ts +++ b/packages/twenty-front/jest.config.ts @@ -24,9 +24,9 @@ const jestConfig: JestConfigWithTsJest = { extensionsToTreatAsEsm: ['.ts', '.tsx'], coverageThreshold: { global: { - statements: 62, - lines: 61, - functions: 52, + statements: 60, + lines: 60, + functions: 50, }, }, collectCoverageFrom: ['<rootDir>/src/**/*.ts'], diff --git a/packages/twenty-front/package.json b/packages/twenty-front/package.json index ed72dc01963c..e1a632247380 100644 --- a/packages/twenty-front/package.json +++ b/packages/twenty-front/package.json @@ -1,6 +1,6 @@ { "name": "twenty-front", - "version": "0.24.0", + "version": "0.30.0", "private": true, "type": "module", "scripts": { diff --git a/packages/twenty-front/public/images/placeholders/background/no_deleted_record_bg.png b/packages/twenty-front/public/images/placeholders/background/no_deleted_record_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f69676ba702440672deea2fa898ab0f5b7c37db7 GIT binary patch literal 2920 zcmV-u3zzhXP)<h;3K|Lk000e1NJLTq005N$004Ce1^@s6N9Lo=00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH3jIk$K~#7F?VV3- z990s=zp#7oi41!{Tp%4GBqS1fh&W^+Qrh9LPB=K(OOid{$w~;2K*2&pyF|hc0<9Jf zi4~-cFPjM$vmA)c!QQ>ZZHY)AL2#5DkRo>5a6udvC#QrH_4Ob7F`gbz&rHws>#m<v zneMhHk>hXPt5>h8-Zm($sE9dYuGkLaK4wkK7h4ru5%Zv68<d!8WWxxBQ-vX*%J%K3 z+<!luM;=*!!`kiJ@W1~)cs20EE{V+{6kX{kqo^Eg2!;Z3(I6h@;fGP(y&J<%Jb@h| zB3|=Z5^HzvVCBXQ%r7oteqjOrci#n%5en-J!qKcW6j@Z9s?5<R7EðIR4m+Jzl* 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 S-P>#c0000<MNUMnLSTZ-8i4fx literal 0 HcmV?d00001 diff --git a/packages/twenty-front/public/images/placeholders/dark-background/no_deleted_record_bg.png b/packages/twenty-front/public/images/placeholders/dark-background/no_deleted_record_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..3a7dd1cabf32697749064837f2386c3970d78edc GIT binary patch literal 2997 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 literal 0 HcmV?d00001 diff --git a/packages/twenty-front/public/images/placeholders/dark-background/no_match_record_bg.png b/packages/twenty-front/public/images/placeholders/dark-background/no_match_record_bg.png index da554e159f2aab9c3036beb7943cae2623e68e49..bb55a0b9c1df144507952fbbe5c190167e718a4e 100644 GIT binary patch delta 2877 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 b<$#|7Fq#LzD4zNV00000NkvXXu0mjfZPi|s literal 6194 zcmW+)c_3767auz#yNN7=q8Q<&QLkk%BwLoo7-ZkFFImcxB|?!UOfkZcVa(Xq5-Ce| z*=2uGvQ75M?z??|-1VIEd(Lxy_nz}S=Y@%p4jWhi3<81J^mK2dKp+|zaKFmT2%OX9 zL!SZ{7C&9f01)V+#NUHP4<)_@yrc<0>1cw=2ZUCE2YOeeArb_tN?|>5U;u&mI`wWN z(ZMv7Sz|vTm(b2_o#B-{ndxfz`q%r5ws#$2a~X!;NwHc93wMk@%P3KP)GK|NOH1#N z!j7~`VR;rarhsdQdxsP{!RALLdvMI;#V__wf(Eah_1?XD`)4&5+A@NB{ooGb^v`jL zhi9Xrg7)ND|E}8Rv@Zt>XUppH!;-^&i(RsJw@~l0Uv@=I#b;S9+CAg8PA>IS+4~j3 zt0|0Qn!5*;hhvZoC^FVZX_<&yDm`!rOx0M6^-K;4XqrAr;J!@cTz)R1xuAjjO})iW zLN_@%uRXtDe#h#UgNmSFb#s;Muv@U52(IGTFLn?n5lw1pZL1f}Xk-^RlXrkG3Y#h@ z$h&`nVi&eqR^u7XoV>N`%{P0;hY{|XPAOad{qoWgZu$Q)ll+-AiJNM}TkX$8bZz;C zUk$DDgfpS!>R)emkLPR_M*ONT`8=-D+yS8_Z!wb`9~Opx$6%p!dhu>4B=G<tYFo+3 zpp1Lc7-X_(8*A<z#4KaZT-th>xFeN$)DZ8Ly!TxPOnPVk9i#N<GSAam5n=XmLu}or z0~fS?vv}Xdi(n+yyXx-wdS$;LDXSu)E)f38!HWB)Zv+p-!Z&Nl(7_uc#)+QH&qrft z%}^7q;f2@PrWq+uS;&nnWhV9?G=t2T>CGBR%fTH&75W_cycecnBc0i1!}sJedN_5% zhJLcICr&iOq;E@;Es;K4=<bo8Rkna8S)09##kXg2iO(1C><p1oT@ukSrDP@9?04g< z*$b2Pg+=Fy`eZVe%v$aJ04x(~FyPs0^3P*t(w7mEJLUvTN{Smf=;Kj%w3CtbP(}86 z9<}`D%sN%Ve8uV~J5teNDlAk-Q>*FTh!rkyfXj$QtaK*@FYq$ijF$!rrC62OeDtvM zkFD%si-tucD@90;U!SXVk2XdGJdM)NlI0$&to|)Bnv0Etc$O(7;}hPLhaV+bh$%i? z*2_{2E8jC<sxHuSQIw0Y5No?b|8OXESl{E0F+7v~{LrrJM~cuT0q8~Nn1ND{*pESf z9{F{1MH0`Riq<fbg6YM6D)#S-w7zONk-ns|ohcdyFNLzRg-mzB5pod~YYC$1{71rX zuV9SzwboWT@<OG*zVasL*<p{$#$k^rrU+^H#Elp7-Cx`ov~_=uE);(Yi+o^s<a(I= zf5X0(gvgfMiF9S^#y92?p`p3_Ik^vql!-4AIw#kbo``qx!boRh?Ty0Asee}Q>i$fk zlCQok-Y^KwPQUVh*}slu|4wMX<xzivN;M9(bD8a<RV$s?N2`19ecKO5J}|krU%X#J zMkIIF7_;n920!dl-3@VCq0V#=vrVCZK89;La#_oV-`|VQ2eRhm^s|LEFz9@bMBE?} zLmw*z=c|aU#05#l4GPnn<&%0YM3ZhMTd)P5CMGQocBgLN@NWLv8+})l7&?M6l<zfH z<tdJI%focEtb?Sk5JPu8wxTURISzA(%ytd#1R&R#Nx#PmKM09^m*ww(&z*^()1e{( zDF<BW*)WOV{5Cb-H$HxD;hYQ{VcH3Ru2~G9Q%Vju@AOJ{C&d)E24FUtLOfada4Q|R z9yXSFj3*>4*!|V46(A{J*Vtyem3MQteM`=T-s~~y3+s{TPp%`AQ0-KKXpcz6s^9BN zG;BZRr{)q%!6+>gN`>NvVBX<Vyef=hV6tLLc#faSKKoh9cx{P7etpj`bl%Rb`Rx^5 z24r1>9fRC^m!h{YQ&Z|{Vl<i)J>=nNW;zpPZG=WoYM5v*F*<i`9TbMIF{6+sK{utn zRf185ShLs!7!NaPmIUag5167&C2pcG)fs2)8?Ye92DsKIeUyI)s`t}=Q>b}#f=(8N z(2rgD2)){q$^qlW=+Yqfb)^e=jaBc6@}gZCUR)ub=zAEIW*dcMN~X%VRJg}1*h&`$ zXG&75uIpN7Ny9pY@^mHtzG#Ks6rirAi9U2;gRvFY=kkihO6KD=!9DzF#VSpGK|*}q zA&XdSvZmNiFzQ}Cbga}OQ7MR}bu>0{VXRZ5m-@9ayr)u5!Uarf=-UqUD-i48rr-GG z;MA)oK}4bA@WWZn^Uv#eqJ895f)==04=XDub&%sgWNJdexj~TlC_L}q-9jPd$F@;E zUNW;a#x_V;!pz;xe`|Df^Z9^;OqGI|=_d%F6&)UMFcsd2m?nE`wQw+$NG=ZgVlpSS zE(nnSP)0(K9tjuGeH&sotseVM7hgC=p)>G~4>+nkYdMbRcnXV{&l7|J1o@FO^t<q{ zn+c+dA-+X7YT}=+4CXmjxhCug{eJ{H%}AKlj`ChM<N@^`jr`c$y<*hs&c8@>V-Bah zrzIIbrHH_&m+N1DYB2s4dxl=y*^!&!dO%H0{pvqm>1&(Xs0ts+n$#-LTrXZ`DCrF~ z8GDw65Px}wraFhL+>!=-bePg@s28#2J~GWp9s7%2!c19N1uKYoB0Kt^s1E4rWCkJf zH2FYmEOY>RBTRS7#08y-uw;Sh1P?$J?B6&0Kc>%0jm7(m^P-e%Zbck1(TdBU?-{Zx zh*5sBBnMhVXy}T`96cVy)ehm6rFCs^$e#e+$(dOQO|ZM5yB)15q)@gDKWt305$h0; za(+4hw<1N45+LZ!=VR&0dwVyY@hUj|*t&PTXO?e{ZG=aAU{2JZe9JHXc4J1X$W0rv zX4)*NJN8_Boh{%bz;96odGP9r#`uO;10_q%Dfux&iJk&cDBwf~5G|i<=dq+}V@uvu z1L^8&)uX*puJeU=<)RQhwo{?)>|bY*fsSdAUtRE=|1RAUDY{4@50mxvP>`{TLZvY7 z8T-EGurB2?(prNr!$&DMUH7FmI^<#+GYNOV7Wi#pSN&DbkQ1%*?BG^qLlG%rJ^R1m z-DQiLojTFC*_4Sw+rDsWkx6Zc+IIUTnjOdXmmsKz)9IPN->S=Yn3)&x4IasaWk1|A z?GoG({@`~ns_7EqA!_ZhZ*N;D;(cMSC$W?p-i0T<Q2e1nonhT0q*^T%KiG)C4)=KI zem6yMX({k0TQqc4y09kLyE<uM%4MJZK|k)_POA)bz%!cN>rXg;(U!^)yC7rv4;HIB zQx%3$79_G}2?t!qEftAAieUzR$8+f06&Zz@&iI1CEDeg~D$^EqiiF@D&2f(ui#Yet zIvE1zL(-8KP6HjR4eeg$Jeir^6q39w3@(?mebb*kf4f=xkF_0Vq{YgkgE{{d-1Neq zmAwGMbT8sJ-oJ0V_&?_(*U0{KCzD_s`f+>^SgxV%ct$otmU&QO-6A!kLl|A=;qhdd zMd`^|G{_~t?eo#!HOe2A5kEUcntE9VZgkx4;{2aXx8ROT=wuT^8W{oWq&kRP<zC2B zj5>M$bgPcSzHpJf$w>VTt@+7ds5!Sq0hg=EJwqC)?N-l^d4to!c;yW5)22A@WB->% z)&Wi4$$y+Rdf|&;63OD@6#%lMz=5#dDbV}J*>iQywrxr&ph-%e31f{Uh?$M?p-nZm zy|X@(vb$ptn(H##<m={+oSn*maYK*L!uGnx!fOAN(>3D|L3{RFzBBA`FAYOeD$1os zEZgYjKMU)a)Imq_V;N9Tj}~9xddqRoHjizP3&ZR3sfkMeb`J8ViAdqV6>~_aDd>7* zu2=YW?^f!dVyEZuuj;rM3>s|;nsSRJXtl;`X;JAEY8!{GULH+7Togr`{WZC~;?xNn zxz?1W>B(~2?1-5hLk}6_jY2ROKF*P-y$LPVPjMLYH8G3z0Bi8U1p`@kyhohpZ9Qe6 zW%?X{B|xB7USKf!pUlh}FOVamNibl<BYZe{uuXw9+;O&hN{^M**@Cv~Dl*{B8@KJ< z_=z8BHV?(uZ1Xa#)0b0?4RaCKK!fBGSJ})<UzVs6;ib7e`)9T>YyMlB(oz>6)2_U! zPuinqUlk@a^X$*rMw6}rLpT;RQ%a~zE$EI&ldrPPd&FA!Zm8+ef%GhgFo@kT*lUJ< zoai<CQP6rgJ1bHq|Csh;8PQ|7w5S#>sBTCntf9L1NRVtt=otLD71mfrygxSDo>lV~ zn809iidkRaKUyKxTYmO|k#GRV{Gv8?ko#++7_%TAbl)Bg|NB9D8?%$1o*FwKQ3AoC ztz`z6l^unwhaI0>2O`-1j6}l0!<NDru%EiO=WZ)9h|-)vG2S<#=C*t*@C7*9)b~bh zEkrzt1<>ZbTl*_XP3W=$kyr#O)J(i09T0e6PT@r><^zfaL)3-&4kPIiEAk)*B3$i+ z4)l-T(Lc}2J~qURWG^KAKOm@^3PJ5^vx<AbIzxU{RRWY6_e$p&UE;1njP8^RyOWZ` z3DS-EZRT=ol!7NQ%GJts+!cv}ud12Rs1WbBeHuzHrUwl>tIzhZlg4v;u+%#jL4`18 z(l|nq<o{BF1yp^7nS{|z0)o-S|FK}_<=}0mRC%OHU9P2;HiIZ@U{I*NxweZj3$4ce zdULCkC!4%z2u&1xax9~2bp6UKjs1WBFL?~nV2x$?>&?kxdPvm9<b4lT(xE7E=0ANm zFJ{mS&swH2tSIqyw6u!gIxWb(Wd3kK&E}tYLHaRAKP;X$wdiQJ9*>)_i^kt)F29K} zX8;XXdV>i^{k{|f-*vf1DLsN`?%LXUU=0DyW+~tA#d2|4d<bfS2}rl+Xffz`uk1hV zPCPh?3-AZnR5;xU6#P=+nfy40M};`YVLQ4xa}lJABI0m$#v6DXAK4fpAWi%Ev#MW( z4#pJLq!2C}{AG(ngFCRu*J<0}c-ZRzv4HnrI}dE?+7O9CT7B553SZMF;!q2CoG;W? z*L%i-7sQ`2m}=ZSx*DG2qwhnQ{5oNG&y0ruc~S+R3ftj~(I!B2z?bY266k`aQ&30W zPF?KiTcx>|q362o`!4Qkb2faD$vL=J4)v0ZoOIr~6%j{aAr=)(Z-8v{AUTPc_W}&F zIk8lXzoMd2T~mK~>4q^gNaz^`C4kB&Fi*W{{4nt?X=589ygRlRdscKb82`8OfKI>P zKbm_sdTl{}P2$Ch!6X$7Ge3z}Q?0m`gmw8_OyWAfGJrz!lXmOAorx-IdioQ3Q&Czr zO}}{D)$~Gw9W|4!PfA|iy$c2fI#Cimt3#HgkJF?P&ob7o{w<>QhuBKmL5PiFrGJpv z6P3B9gQQ)8ZA66+^!I;LEmc%9roz@C91^9gT+?v!@%%!3hR<{X7Hup>xYPI~@6ium zy@2lMn{D;KXR+I+Hx%G~F<v0m0>fRbbW2V4@*3NuQ_g5aBO8oha53;|B?L2F^ktx$ z0rZsJFrX~g_GV|rPf#ce4B}O8K4url|GxQy7?5UJqWnjSLRMb$PYB6nE+q(=R3Hgz zUJ+$$a*h5um9#y*p18=Pu*t^o-cP04NpYiwFOcd;!lPKMK#rOikb|?A|EM3zrPFvD zR}2>&<~FqNk>>FzZwH8~bS_{nR^YDYnH-sxDJ)LRh#Px1w*Cxa0_HN@ZMo6e(hU-V z6Gxer531ni6+9S?D#{T2T$fQi8IRi3lPrz9c8#DAbQ{Fm1_ktAL4D#^b$}wW++imt z|L&UAV;{f-xiJFY3?YP60Gw9vO;rpZ)5<aM70FtsRi&q}Mm^c7cbyEMo+%Zw2Xq$M zVFU+)itN90k$BX$k7H3a?T$|NGDrFO(5J$&k@>{=-+Fzb(fUe`l=m7IG>1H$)awr~ zp-rT8G#!HWKKz=5GIqUxPO+?YFF%zuNBz@P#$jDGJaL@YvQssYL6>UCHC@xEr;kP3 zr$Wp=bG5h<nx${f(J8=K4R<B==&{3=8p4d+7!5{kcz+N_$zut+G%&1Ax-=Q_Cwk%| zZEEiGq7T$}7sanET5o+2nf<+hQ#!*K*ETu7F%d-^m%`7j6~w#os3Z0HdIL!Z25~t@ z!r|M4TNgX4<I!)^*kN^^21_|*%7U9TEUR0!j*6bicKR>FbUUPy07k3?Y78V(FL>kP zA5d%E&sYPRWG=nNn3ULjeD>Sxmh(ot9t~#;)9)b5^ASE^mwpm4%9Qrdoe}H7K|b!C zV+pgQ*&bSR->*4;ebjJkqc_V7r=zDr<h2r@qZ{_X&A0g4<)**9+5gU23?Lfv@fodr zkJE^%J|<e9G9`iL!f0&nOu<vqe)R15tgh{Q`1v1Xu_{F1isk8Mhl@hu5&bvnhMUYS zFOUF-xG|s4nu-qV)Ptv^tWdML60(-o?Bx<9AE_bz^SW;paSb^jdzN}v79cMaHX#hG zt3&4#;>@OtqZ(eB@4n~*L5Cvw8Yisci$3^VQr%*b6BkR=QqR8P<$mGzRMTOS>iY<p z8Thw8fZpy<fZozdM>*-w=Iuox8LISH|7Vr7s`n9P;oBcZeZxKNWN!oWumwJg*4JMp zmArB5M??xWg7Wqt@n6=Vlr?eVY>f|#-|T}U`KSK<;lL%Cj(3NGODv^K0JB^e31lVk zF0f}9m^;DBt&wmGwKi9B_BG7Q{blrSz3UK@+{Om|8|&`wzs@-QpAT+~q(FuHS?Bqy ze!+8ByMeL4B2N>kQ@RnhQrmH!dib4JZks_rM~n*{)S_ep(rPG{i)p{`C=taL%sw9= z=BllC4cYqqNmW{D28dn=2do3|9U#9VoLX{Av(jzk#ICSCffJn|lk_T#%P_zuZTC}# z^}T5QDuTSfRDt{N1Q8U$1E(W}GLZuC%5MW-Y=c$Kq_hn%siD7|4hItzVAyw^^j&EP z-151ogf~v7dkJ6{Ku{pJ=?4%DcddWBtGQ{j!vKV<Sog5k?|GGoqve&#M>D%#P4Vd4 zUf&k=k@c+5!h(6<>M(;PX^|R&JohgI^XSPeYitJ9G!LTbVdwH*egLx0W1v39EG_Py zLb2S_svVrJX(z1w<#dBP;n@&8MJEd&NYg@0Oc=L(AF-M&A_5LY)#Fjg7FGhg&Vubp zMIk4^X1IroT#bq!$a(YPhB4TWbMEp0nRUT+qo4JZNGG)jc)w!D-#ld6>sL`d<uTX# znR0Vw;_F0W^&^T$@UIxl?LTl=!XZsYT><!CZc^!;K2E>2R_!Cq3QiU=80B$&wnlC} zKA&+kESgT*QyVhaa<@_G>?NEpHgsBG{?sV$j?Su;gPkp8f3kStcz?O0rR3lW@_G*x zt#7bn-;zf<TSWY`IN<GGS{8ik28a0_hDvXl@J)o>H_uG<DRuqTVY=p$%n0<$9<@Ez z0C6}kI^8udtt#spKYOd-@@k{xsVHj}UnJT7_k<t_MtXE4#ecn>%*Yo+<`-u7ASimZ zCV<IL_P(8cd2>GPo>?5}dUo#wmT>xx@mT^42kiIS!Pg0ix1~oq4Y5JVU^0De^c2vw zY-m-jZM5#!`yxWf1sWD-9?S2q=P%#|6rTd?=&DYm?ZV~gA?WDQ;+uu6rq4|Wz3dha zxt!6YFvS<l*A+u|9&XCpV4XTkYW?-4i-K+>HUJ&B1IESAO`IkrKqKi-!9l)RVrUFI zM-bvQ#v0qEbMoop0#;AJD7(Q&*TywO#oXA#mYIm=LZ1e-Z`w7>j(>d;woO}l$>NdU zYUL1AnLWk0);6A8L(LO(>6&B`9{0{N8P-cfwCWuj`Mziw7=RQe;1lAnM7T8%pD4>n z4T@fHd(Jj3_P~~@1{=n(^gAysFt^iwZ@fLrernSC59zA#aFAQV^l}G>WLd6Tnkzk0 zk^c>@vt!v@=W?i3$OEQ1+b_f^t<jSi-O+D#d7HPK=j3brznJIbPfyNl`7n=X$Lvq3 z<@09pon!dQa+!-STqdRkVW14-wYBE9$@`7-oB1l`2VdZFXrm7rCXhtN%u|rowY~6b zahtI*3hVG^7fYAI#WMZl@vX?5I$M?e&B<R6%~I<LgA4a{I873xXO1I_Ug);8^OUCm QEq;)mw$bf!P5bEo0ZohTYybcN diff --git a/packages/twenty-front/public/images/placeholders/dark-moving-image/no_deleted_record.png b/packages/twenty-front/public/images/placeholders/dark-moving-image/no_deleted_record.png new file mode 100644 index 0000000000000000000000000000000000000000..3e52331a1d80c91fe4812ccc6588501cefcf63e6 GIT binary patch literal 7584 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 C_@PDs literal 0 HcmV?d00001 diff --git a/packages/twenty-front/public/images/placeholders/moving-image/no_deleted_record.png b/packages/twenty-front/public/images/placeholders/moving-image/no_deleted_record.png new file mode 100644 index 0000000000000000000000000000000000000000..9ee5863d4317fd18c1f79b6290cb623bad4ca787 GIT binary patch literal 7617 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 literal 0 HcmV?d00001 diff --git a/packages/twenty-front/public/mockServiceWorker.js b/packages/twenty-front/public/mockServiceWorker.js index e369128ec00c..15751fa1994f 100644 --- a/packages/twenty-front/public/mockServiceWorker.js +++ b/packages/twenty-front/public/mockServiceWorker.js @@ -2,13 +2,14 @@ /* tslint:disable */ /** - * Mock Service Worker (2.0.11). + * Mock Service Worker. * @see https://github.com/mswjs/msw * - Please do NOT modify this file. * - Please do NOT serve this file on production. */ -const INTEGRITY_CHECKSUM = 'c5f7f8e188b673ea4e677df7ea3c5a39' +const PACKAGE_VERSION = '2.3.5' +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') const activeClientIds = new Set() @@ -48,7 +49,10 @@ self.addEventListener('message', async function (event) { case 'INTEGRITY_CHECK_REQUEST': { sendToClient(client, { type: 'INTEGRITY_CHECK_RESPONSE', - payload: INTEGRITY_CHECKSUM, + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, }) break } @@ -202,13 +206,6 @@ async function getResponse(event, client, requestId) { return passthrough() } - // Bypass requests with the explicit bypass header. - // Such requests can be issued by "ctx.fetch()". - const mswIntention = request.headers.get('x-msw-intention') - if (['bypass', 'passthrough'].includes(mswIntention)) { - return passthrough() - } - // Notify the client that a request has been intercepted. const requestBuffer = await request.arrayBuffer() const clientMessage = await sendToClient( @@ -240,7 +237,7 @@ async function getResponse(event, client, requestId) { return respondWithMock(clientMessage.data) } - case 'MOCK_NOT_FOUND': { + case 'PASSTHROUGH': { return passthrough() } } diff --git a/packages/twenty-front/setupTests.ts b/packages/twenty-front/setupTests.ts index 8f2609b7b3e0..e5aa41c46c9f 100644 --- a/packages/twenty-front/setupTests.ts +++ b/packages/twenty-front/setupTests.ts @@ -3,3 +3,14 @@ // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom import '@testing-library/jest-dom'; + +/** + * The structuredClone global function is not available in jsdom, it needs to be mocked for now. + * + * The most naive way to mock structuredClone is to use JSON.stringify and JSON.parse. This works + * for arguments with simple types like primitives, arrays and objects, but doesn't work with functions, + * Map, Set, etc. + */ +global.structuredClone = (val) => { + return JSON.parse(JSON.stringify(val)); +}; diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx index 3b165129832e..1c6adcfdf60e 100644 --- a/packages/twenty-front/src/App.tsx +++ b/packages/twenty-front/src/App.tsx @@ -5,7 +5,6 @@ import { Outlet, Route, RouterProvider, - Routes, useLocation, } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; @@ -24,7 +23,6 @@ import { ApolloMetadataClientProvider } from '@/object-metadata/components/Apoll import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider'; import { PrefetchDataProvider } from '@/prefetch/components/PrefetchDataProvider'; import { AppPath } from '@/types/AppPath'; -import { SettingsPath } from '@/types/SettingsPath'; import { DialogManager } from '@/ui/feedback/dialog-manager/components/DialogManager'; import { DialogManagerScope } from '@/ui/feedback/dialog-manager/scopes/DialogManagerScope'; import { SnackBarProvider } from '@/ui/feedback/snack-bar-manager/components/SnackBarProvider'; @@ -52,39 +50,7 @@ import { CreateWorkspace } from '~/pages/onboarding/CreateWorkspace'; import { InviteTeam } from '~/pages/onboarding/InviteTeam'; import { PaymentSuccess } from '~/pages/onboarding/PaymentSuccess'; import { SyncEmails } from '~/pages/onboarding/SyncEmails'; -import { SettingsAccounts } from '~/pages/settings/accounts/SettingsAccounts'; -import { SettingsAccountsCalendars } from '~/pages/settings/accounts/SettingsAccountsCalendars'; -import { SettingsAccountsEmails } from '~/pages/settings/accounts/SettingsAccountsEmails'; -import { SettingsNewAccount } from '~/pages/settings/accounts/SettingsNewAccount'; -import { SettingsCRMMigration } from '~/pages/settings/crm-migration/SettingsCRMMigration'; -import { SettingsNewObject } from '~/pages/settings/data-model/SettingsNewObject'; -import { SettingsObjectDetailPage } from '~/pages/settings/data-model/SettingsObjectDetailPage'; -import { SettingsObjectEdit } from '~/pages/settings/data-model/SettingsObjectEdit'; -import { SettingsObjectFieldEdit } from '~/pages/settings/data-model/SettingsObjectFieldEdit'; -import { SettingsObjectNewFieldStep1 } from '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1'; -import { SettingsObjectNewFieldStep2 } from '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2'; -import { SettingsObjectOverview } from '~/pages/settings/data-model/SettingsObjectOverview'; -import { SettingsObjects } from '~/pages/settings/data-model/SettingsObjects'; -import { SettingsDevelopersApiKeyDetail } from '~/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail'; -import { SettingsDevelopersApiKeysNew } from '~/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew'; -import { SettingsDevelopers } from '~/pages/settings/developers/SettingsDevelopers'; -import { SettingsDevelopersWebhooksDetail } from '~/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail'; -import { SettingsDevelopersWebhooksNew } from '~/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew'; -import { SettingsIntegrationDatabase } from '~/pages/settings/integrations/SettingsIntegrationDatabase'; -import { SettingsIntegrationEditDatabaseConnection } from '~/pages/settings/integrations/SettingsIntegrationEditDatabaseConnection'; -import { SettingsIntegrationNewDatabaseConnection } from '~/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection'; -import { SettingsIntegrations } from '~/pages/settings/integrations/SettingsIntegrations'; -import { SettingsIntegrationShowDatabaseConnection } from '~/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection'; -import { SettingsAppearance } from '~/pages/settings/profile/appearance/components/SettingsAppearance'; -import { Releases } from '~/pages/settings/Releases'; -import { SettingsServerlessFunctionDetailWrapper } from '~/pages/settings/serverless-functions/SettingsServerlessFunctionDetailWrapper'; -import { SettingsServerlessFunctions } from '~/pages/settings/serverless-functions/SettingsServerlessFunctions'; -import { SettingsServerlessFunctionsNew } from '~/pages/settings/serverless-functions/SettingsServerlessFunctionsNew'; -import { SettingsBilling } from '~/pages/settings/SettingsBilling'; -import { SettingsProfile } from '~/pages/settings/SettingsProfile'; -import { SettingsWorkspace } from '~/pages/settings/SettingsWorkspace'; -import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMembers'; -import { WorkflowShowPage } from '~/pages/workflows/WorkflowShowPage'; +import { SettingsRoutes } from '~/SettingsRoutes'; import { getPageTitleFromPath } from '~/utils/title-utils'; const ProvidersThatNeedRouterContext = () => { @@ -136,7 +102,6 @@ const createRouter = ( isBillingEnabled?: boolean, isCRMMigrationEnabled?: boolean, isServerlessFunctionSettingsEnabled?: boolean, - isWorkflowEnabled?: boolean, ) => createBrowserRouter( createRoutesFromElements( @@ -164,159 +129,16 @@ const createRouter = ( <Route path={AppPath.Impersonate} element={<ImpersonateEffect />} /> <Route path={AppPath.RecordIndexPage} element={<RecordIndexPage />} /> <Route path={AppPath.RecordShowPage} element={<RecordShowPage />} /> - - {isWorkflowEnabled === true ? ( - <Route - path={AppPath.WorkflowShowPage} - element={<WorkflowShowPage />} - /> - ) : null} - <Route path={AppPath.SettingsCatchAll} element={ - <Routes> - <Route - path={SettingsPath.ProfilePage} - element={<SettingsProfile />} - /> - <Route - path={SettingsPath.Appearance} - element={<SettingsAppearance />} - /> - <Route - path={SettingsPath.Accounts} - element={<SettingsAccounts />} - /> - <Route - path={SettingsPath.NewAccount} - element={<SettingsNewAccount />} - /> - <Route - path={SettingsPath.AccountsCalendars} - element={<SettingsAccountsCalendars />} - /> - <Route - path={SettingsPath.AccountsEmails} - element={<SettingsAccountsEmails />} - /> - {isBillingEnabled && ( - <Route - path={SettingsPath.Billing} - element={<SettingsBilling />} - /> - )} - <Route - path={SettingsPath.WorkspaceMembersPage} - element={<SettingsWorkspaceMembers />} - /> - <Route - path={SettingsPath.Workspace} - element={<SettingsWorkspace />} - /> - <Route - path={SettingsPath.Objects} - element={<SettingsObjects />} - /> - <Route - path={SettingsPath.ObjectOverview} - element={<SettingsObjectOverview />} - /> - <Route - path={SettingsPath.ObjectDetail} - element={<SettingsObjectDetailPage />} - /> - <Route - path={SettingsPath.ObjectEdit} - element={<SettingsObjectEdit />} - /> - <Route - path={SettingsPath.NewObject} - element={<SettingsNewObject />} - /> - <Route - path={SettingsPath.Developers} - element={<SettingsDevelopers />} - /> - {isCRMMigrationEnabled && ( - <Route - path={SettingsPath.CRMMigration} - element={<SettingsCRMMigration />} - /> - )} - <Route - path={AppPath.DevelopersCatchAll} - element={ - <Routes> - <Route - path={SettingsPath.DevelopersNewApiKey} - element={<SettingsDevelopersApiKeysNew />} - /> - <Route - path={SettingsPath.DevelopersApiKeyDetail} - element={<SettingsDevelopersApiKeyDetail />} - /> - <Route - path={SettingsPath.DevelopersNewWebhook} - element={<SettingsDevelopersWebhooksNew />} - /> - <Route - path={SettingsPath.DevelopersNewWebhookDetail} - element={<SettingsDevelopersWebhooksDetail />} - /> - </Routes> - } - /> - {isServerlessFunctionSettingsEnabled && ( - <> - <Route - path={SettingsPath.ServerlessFunctions} - element={<SettingsServerlessFunctions />} - /> - <Route - path={SettingsPath.NewServerlessFunction} - element={<SettingsServerlessFunctionsNew />} - /> - <Route - path={SettingsPath.ServerlessFunctionDetail} - element={<SettingsServerlessFunctionDetailWrapper />} - /> - </> - )} - <Route - path={SettingsPath.Integrations} - element={<SettingsIntegrations />} - /> - <Route - path={SettingsPath.IntegrationDatabase} - element={<SettingsIntegrationDatabase />} - /> - <Route - path={SettingsPath.IntegrationNewDatabaseConnection} - element={<SettingsIntegrationNewDatabaseConnection />} - /> - <Route - path={SettingsPath.IntegrationEditDatabaseConnection} - element={<SettingsIntegrationEditDatabaseConnection />} - /> - <Route - path={SettingsPath.IntegrationDatabaseConnection} - element={<SettingsIntegrationShowDatabaseConnection />} - /> - <Route - path={SettingsPath.ObjectNewFieldStep1} - element={<SettingsObjectNewFieldStep1 />} - /> - <Route - path={SettingsPath.ObjectNewFieldStep2} - element={<SettingsObjectNewFieldStep2 />} - /> - <Route - path={SettingsPath.ObjectFieldEdit} - element={<SettingsObjectFieldEdit />} - /> - <Route path={SettingsPath.Releases} element={<Releases />} /> - </Routes> + <SettingsRoutes + isBillingEnabled={isBillingEnabled} + isCRMMigrationEnabled={isCRMMigrationEnabled} + isServerlessFunctionSettingsEnabled={ + isServerlessFunctionSettingsEnabled + } + /> } /> <Route path={AppPath.NotFoundWildcard} element={<NotFound />} /> @@ -335,7 +157,6 @@ export const App = () => { const isServerlessFunctionSettingsEnabled = useIsFeatureEnabled( 'IS_FUNCTION_SETTINGS_ENABLED', ); - const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED'); const isBillingPageEnabled = billing?.isBillingEnabled && !isFreeAccessEnabled; @@ -346,7 +167,6 @@ export const App = () => { isBillingPageEnabled, isCRMMigrationEnabled, isServerlessFunctionSettingsEnabled, - isWorkflowEnabled, )} /> ); diff --git a/packages/twenty-front/src/SettingsRoutes.tsx b/packages/twenty-front/src/SettingsRoutes.tsx new file mode 100644 index 000000000000..05e852e2bed0 --- /dev/null +++ b/packages/twenty-front/src/SettingsRoutes.tsx @@ -0,0 +1,362 @@ +import { lazy, Suspense } from 'react'; +import { Route, Routes } from 'react-router-dom'; + +import { AppPath } from '@/types/AppPath'; +import { SettingsPath } from '@/types/SettingsPath'; + +const SettingsAccountsCalendars = lazy(() => + import('~/pages/settings/accounts/SettingsAccountsCalendars').then( + (module) => ({ + default: module.SettingsAccountsCalendars, + }), + ), +); + +const SettingsAccountsEmails = lazy(() => + import('~/pages/settings/accounts/SettingsAccountsEmails').then((module) => ({ + default: module.SettingsAccountsEmails, + })), +); + +const SettingsNewAccount = lazy(() => + import('~/pages/settings/accounts/SettingsNewAccount').then((module) => ({ + default: module.SettingsNewAccount, + })), +); + +const SettingsNewObject = lazy(() => + import('~/pages/settings/data-model/SettingsNewObject').then((module) => ({ + default: module.SettingsNewObject, + })), +); + +const SettingsObjectDetailPage = lazy(() => + import('~/pages/settings/data-model/SettingsObjectDetailPage').then( + (module) => ({ + default: module.SettingsObjectDetailPage, + }), + ), +); + +const SettingsObjectOverview = lazy(() => + import('~/pages/settings/data-model/SettingsObjectOverview').then( + (module) => ({ + default: module.SettingsObjectOverview, + }), + ), +); + +const SettingsDevelopersApiKeyDetail = lazy(() => + import( + '~/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail' + ).then((module) => ({ + default: module.SettingsDevelopersApiKeyDetail, + })), +); + +const SettingsDevelopersApiKeysNew = lazy(() => + import( + '~/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew' + ).then((module) => ({ + default: module.SettingsDevelopersApiKeysNew, + })), +); + +const SettingsDevelopersWebhooksNew = lazy(() => + import( + '~/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew' + ).then((module) => ({ + default: module.SettingsDevelopersWebhooksNew, + })), +); + +const Releases = lazy(() => + import('~/pages/settings/Releases').then((module) => ({ + default: module.Releases, + })), +); + +const SettingsServerlessFunctions = lazy(() => + import( + '~/pages/settings/serverless-functions/SettingsServerlessFunctions' + ).then((module) => ({ default: module.SettingsServerlessFunctions })), +); + +const SettingsServerlessFunctionDetailWrapper = lazy(() => + import( + '~/pages/settings/serverless-functions/SettingsServerlessFunctionDetailWrapper' + ).then((module) => ({ + default: module.SettingsServerlessFunctionDetailWrapper, + })), +); + +const SettingsServerlessFunctionsNew = lazy(() => + import( + '~/pages/settings/serverless-functions/SettingsServerlessFunctionsNew' + ).then((module) => ({ + default: module.SettingsServerlessFunctionsNew, + })), +); + +const SettingsWorkspace = lazy(() => + import('~/pages/settings/SettingsWorkspace').then((module) => ({ + default: module.SettingsWorkspace, + })), +); + +const SettingsWorkspaceMembers = lazy(() => + import('~/pages/settings/SettingsWorkspaceMembers').then((module) => ({ + default: module.SettingsWorkspaceMembers, + })), +); + +const SettingsProfile = lazy(() => + import('~/pages/settings/SettingsProfile').then((module) => ({ + default: module.SettingsProfile, + })), +); + +const SettingsAppearance = lazy(() => + import( + '~/pages/settings/profile/appearance/components/SettingsAppearance' + ).then((module) => ({ + default: module.SettingsAppearance, + })), +); + +const SettingsAccounts = lazy(() => + import('~/pages/settings/accounts/SettingsAccounts').then((module) => ({ + default: module.SettingsAccounts, + })), +); + +const SettingsBilling = lazy(() => + import('~/pages/settings/SettingsBilling').then((module) => ({ + default: module.SettingsBilling, + })), +); + +const SettingsDevelopers = lazy(() => + import('~/pages/settings/developers/SettingsDevelopers').then((module) => ({ + default: module.SettingsDevelopers, + })), +); + +const SettingsObjectEdit = lazy(() => + import('~/pages/settings/data-model/SettingsObjectEdit').then((module) => ({ + default: module.SettingsObjectEdit, + })), +); + +const SettingsIntegrations = lazy(() => + import('~/pages/settings/integrations/SettingsIntegrations').then( + (module) => ({ + default: module.SettingsIntegrations, + }), + ), +); + +const SettingsObjects = lazy(() => + import('~/pages/settings/data-model/SettingsObjects').then((module) => ({ + default: module.SettingsObjects, + })), +); + +const SettingsDevelopersWebhooksDetail = lazy(() => + import( + '~/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail' + ).then((module) => ({ + default: module.SettingsDevelopersWebhooksDetail, + })), +); + +const SettingsIntegrationDatabase = lazy(() => + import('~/pages/settings/integrations/SettingsIntegrationDatabase').then( + (module) => ({ + default: module.SettingsIntegrationDatabase, + }), + ), +); + +const SettingsIntegrationNewDatabaseConnection = lazy(() => + import( + '~/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection' + ).then((module) => ({ + default: module.SettingsIntegrationNewDatabaseConnection, + })), +); + +const SettingsIntegrationEditDatabaseConnection = lazy(() => + import( + '~/pages/settings/integrations/SettingsIntegrationEditDatabaseConnection' + ).then((module) => ({ + default: module.SettingsIntegrationEditDatabaseConnection, + })), +); + +const SettingsIntegrationShowDatabaseConnection = lazy(() => + import( + '~/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection' + ).then((module) => ({ + default: module.SettingsIntegrationShowDatabaseConnection, + })), +); + +const SettingsObjectNewFieldStep1 = lazy(() => + import( + '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1' + ).then((module) => ({ + default: module.SettingsObjectNewFieldStep1, + })), +); + +const SettingsObjectNewFieldStep2 = lazy(() => + import( + '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2' + ).then((module) => ({ + default: module.SettingsObjectNewFieldStep2, + })), +); + +const SettingsObjectFieldEdit = lazy(() => + import('~/pages/settings/data-model/SettingsObjectFieldEdit').then( + (module) => ({ + default: module.SettingsObjectFieldEdit, + }), + ), +); + +const SettingsCRMMigration = lazy(() => + import('~/pages/settings/crm-migration/SettingsCRMMigration').then( + (module) => ({ + default: module.SettingsCRMMigration, + }), + ), +); + +type SettingsRoutesProps = { + isBillingEnabled?: boolean; + isCRMMigrationEnabled?: boolean; + isServerlessFunctionSettingsEnabled?: boolean; +}; + +export const SettingsRoutes = ({ + isBillingEnabled, + isCRMMigrationEnabled, + isServerlessFunctionSettingsEnabled, +}: SettingsRoutesProps) => ( + <Suspense fallback={null}> + <Routes> + <Route path={SettingsPath.ProfilePage} element={<SettingsProfile />} /> + <Route path={SettingsPath.Appearance} element={<SettingsAppearance />} /> + <Route path={SettingsPath.Accounts} element={<SettingsAccounts />} /> + <Route path={SettingsPath.NewAccount} element={<SettingsNewAccount />} /> + <Route + path={SettingsPath.AccountsCalendars} + element={<SettingsAccountsCalendars />} + /> + <Route + path={SettingsPath.AccountsEmails} + element={<SettingsAccountsEmails />} + /> + {isBillingEnabled && ( + <Route path={SettingsPath.Billing} element={<SettingsBilling />} /> + )} + <Route + path={SettingsPath.WorkspaceMembersPage} + element={<SettingsWorkspaceMembers />} + /> + <Route path={SettingsPath.Workspace} element={<SettingsWorkspace />} /> + <Route path={SettingsPath.Objects} element={<SettingsObjects />} /> + <Route + path={SettingsPath.ObjectOverview} + element={<SettingsObjectOverview />} + /> + <Route + path={SettingsPath.ObjectDetail} + element={<SettingsObjectDetailPage />} + /> + <Route path={SettingsPath.ObjectEdit} element={<SettingsObjectEdit />} /> + <Route path={SettingsPath.NewObject} element={<SettingsNewObject />} /> + <Route path={SettingsPath.Developers} element={<SettingsDevelopers />} /> + {isCRMMigrationEnabled && ( + <Route + path={SettingsPath.CRMMigration} + element={<SettingsCRMMigration />} + /> + )} + <Route + path={AppPath.DevelopersCatchAll} + element={ + <Routes> + <Route + path={SettingsPath.DevelopersNewApiKey} + element={<SettingsDevelopersApiKeysNew />} + /> + <Route + path={SettingsPath.DevelopersApiKeyDetail} + element={<SettingsDevelopersApiKeyDetail />} + /> + <Route + path={SettingsPath.DevelopersNewWebhook} + element={<SettingsDevelopersWebhooksNew />} + /> + <Route + path={SettingsPath.DevelopersNewWebhookDetail} + element={<SettingsDevelopersWebhooksDetail />} + /> + </Routes> + } + /> + {isServerlessFunctionSettingsEnabled && ( + <> + <Route + path={SettingsPath.ServerlessFunctions} + element={<SettingsServerlessFunctions />} + /> + <Route + path={SettingsPath.NewServerlessFunction} + element={<SettingsServerlessFunctionsNew />} + /> + <Route + path={SettingsPath.ServerlessFunctionDetail} + element={<SettingsServerlessFunctionDetailWrapper />} + /> + </> + )} + <Route + path={SettingsPath.Integrations} + element={<SettingsIntegrations />} + /> + <Route + path={SettingsPath.IntegrationDatabase} + element={<SettingsIntegrationDatabase />} + /> + <Route + path={SettingsPath.IntegrationNewDatabaseConnection} + element={<SettingsIntegrationNewDatabaseConnection />} + /> + <Route + path={SettingsPath.IntegrationEditDatabaseConnection} + element={<SettingsIntegrationEditDatabaseConnection />} + /> + <Route + path={SettingsPath.IntegrationDatabaseConnection} + element={<SettingsIntegrationShowDatabaseConnection />} + /> + <Route + path={SettingsPath.ObjectNewFieldStep1} + element={<SettingsObjectNewFieldStep1 />} + /> + <Route + path={SettingsPath.ObjectNewFieldStep2} + element={<SettingsObjectNewFieldStep2 />} + /> + <Route + path={SettingsPath.ObjectFieldEdit} + element={<SettingsObjectFieldEdit />} + /> + <Route path={SettingsPath.Releases} element={<Releases />} /> + </Routes> + </Suspense> +); diff --git a/packages/twenty-front/src/effect-components/PageChangeEffect.tsx b/packages/twenty-front/src/effect-components/PageChangeEffect.tsx index bf083a157e5a..05c99cc89d56 100644 --- a/packages/twenty-front/src/effect-components/PageChangeEffect.tsx +++ b/packages/twenty-front/src/effect-components/PageChangeEffect.tsx @@ -4,7 +4,10 @@ import { useRecoilValue } from 'recoil'; import { IconCheckbox } from 'twenty-ui'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; -import { useEventTracker } from '@/analytics/hooks/useEventTracker'; +import { + setSessionId, + useEventTracker, +} from '@/analytics/hooks/useEventTracker'; import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken'; import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; @@ -163,10 +166,14 @@ export const PageChangeEffect = () => { useEffect(() => { setTimeout(() => { + setSessionId(); eventTracker('pageview', { - location: { - pathname: location.pathname, - }, + pathname: location.pathname, + locale: navigator.language, + userAgent: window.navigator.userAgent, + href: window.location.href, + referrer: document.referrer, + timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, }); }, 500); }, [eventTracker, location.pathname]); diff --git a/packages/twenty-front/src/generated-metadata/gql.ts b/packages/twenty-front/src/generated-metadata/gql.ts index 4c43b04b58b2..2635b40c2b0f 100644 --- a/packages/twenty-front/src/generated-metadata/gql.ts +++ b/packages/twenty-front/src/generated-metadata/gql.ts @@ -32,13 +32,14 @@ const documents = { "\n mutation DeleteOneObjectMetadataItem($idToDelete: UUID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n": types.DeleteOneObjectMetadataItemDocument, "\n mutation DeleteOneFieldMetadataItem($idToDelete: UUID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneFieldMetadataItemDocument, "\n mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) {\n deleteOneRelation(input: { id: $idToDelete }) {\n id\n }\n }\n": types.DeleteOneRelationMetadataItemDocument, - "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n toFieldMetadataId\n }\n toRelationMetadata {\n id\n relationType\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n fromFieldMetadataId\n }\n defaultValue\n options\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n": types.ObjectMetadataItemsDocument, + "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n defaultValue\n options\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n": types.ObjectMetadataItemsDocument, "\n fragment ServerlessFunctionFields on ServerlessFunction {\n id\n name\n description\n sourceCodeHash\n runtime\n syncStatus\n latestVersion\n createdAt\n updatedAt\n }\n": types.ServerlessFunctionFieldsFragmentDoc, "\n \n mutation CreateOneServerlessFunctionItem(\n $input: CreateServerlessFunctionInput!\n ) {\n createOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.CreateOneServerlessFunctionItemDocument, "\n \n mutation DeleteOneServerlessFunction($input: DeleteServerlessFunctionInput!) {\n deleteOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.DeleteOneServerlessFunctionDocument, "\n mutation ExecuteOneServerlessFunction(\n $input: ExecuteServerlessFunctionInput!\n ) {\n executeOneServerlessFunction(input: $input) {\n data\n duration\n status\n error\n }\n }\n": types.ExecuteOneServerlessFunctionDocument, "\n \n mutation PublishOneServerlessFunction(\n $input: PublishServerlessFunctionInput!\n ) {\n publishServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.PublishOneServerlessFunctionDocument, "\n \n mutation UpdateOneServerlessFunction($input: UpdateServerlessFunctionInput!) {\n updateOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.UpdateOneServerlessFunctionDocument, + "\n query FindManyAvailablePackages {\n getAvailablePackages\n }\n": types.FindManyAvailablePackagesDocument, "\n \n query GetManyServerlessFunctions {\n serverlessFunctions(paging: { first: 100 }) {\n edges {\n node {\n ...ServerlessFunctionFields\n }\n }\n }\n }\n": types.GetManyServerlessFunctionsDocument, "\n \n query GetOneServerlessFunction($id: UUID!) {\n serverlessFunction(id: $id) {\n ...ServerlessFunctionFields\n }\n }\n": types.GetOneServerlessFunctionDocument, "\n query FindOneServerlessFunctionSourceCode(\n $input: GetServerlessFunctionSourceCodeInput!\n ) {\n getServerlessFunctionSourceCode(input: $input)\n }\n": types.FindOneServerlessFunctionSourceCodeDocument, @@ -137,7 +138,7 @@ export function graphql(source: "\n mutation DeleteOneRelationMetadataItem($idT /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n toFieldMetadataId\n }\n toRelationMetadata {\n id\n relationType\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n fromFieldMetadataId\n }\n defaultValue\n options\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"): (typeof documents)["\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n fromRelationMetadata {\n id\n relationType\n toObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n toFieldMetadataId\n }\n toRelationMetadata {\n id\n relationType\n fromObjectMetadata {\n id\n dataSourceId\n nameSingular\n namePlural\n isSystem\n isRemote\n }\n fromFieldMetadataId\n }\n defaultValue\n options\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"]; +export function graphql(source: "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n defaultValue\n options\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"): (typeof documents)["\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n createdAt\n updatedAt\n defaultValue\n options\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -162,6 +163,10 @@ export function graphql(source: "\n \n mutation PublishOneServerlessFunction(\ * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "\n \n mutation UpdateOneServerlessFunction($input: UpdateServerlessFunctionInput!) {\n updateOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n"): (typeof documents)["\n \n mutation UpdateOneServerlessFunction($input: UpdateServerlessFunctionInput!) {\n updateOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n query FindManyAvailablePackages {\n getAvailablePackages\n }\n"): (typeof documents)["\n query FindManyAvailablePackages {\n getAvailablePackages\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -176,7 +181,7 @@ export function graphql(source: "\n \n query GetOneServerlessFunction($id: UUI export function graphql(source: "\n query FindOneServerlessFunctionSourceCode(\n $input: GetServerlessFunctionSourceCodeInput!\n ) {\n getServerlessFunctionSourceCode(input: $input)\n }\n"): (typeof documents)["\n query FindOneServerlessFunctionSourceCode(\n $input: GetServerlessFunctionSourceCodeInput!\n ) {\n getServerlessFunctionSourceCode(input: $input)\n }\n"]; export function graphql(source: string) { - return (documents as any)[source] ?? {}; + return (documents as any)[source] ?? {}; } export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never; \ No newline at end of file diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index c02633c4c993..2c6e115bb521 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -9,1586 +9,1588 @@ export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - /** Cursor for paging through collections */ - ConnectionCursor: { input: any; output: any; } - /** A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. */ - DateTime: { input: any; output: any; } - /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ - JSON: { input: any; output: any; } - /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ - JSONObject: { input: any; output: any; } - /** A UUID scalar type */ - UUID: { input: any; output: any; } - /** The `Upload` scalar type represents a file upload. */ - Upload: { input: any; output: any; } + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } + /** Cursor for paging through collections */ + ConnectionCursor: { input: any; output: any; } + /** A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. */ + DateTime: { input: any; output: any; } + /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ + JSON: { input: any; output: any; } + /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ + JSONObject: { input: any; output: any; } + /** A UUID scalar type */ + UUID: { input: any; output: any; } + /** The `Upload` scalar type represents a file upload. */ + Upload: { input: any; output: any; } }; export type AisqlQueryResult = { - __typename?: 'AISQLQueryResult'; - queryFailedErrorMessage?: Maybe<Scalars['String']['output']>; - sqlQuery: Scalars['String']['output']; - sqlQueryResult?: Maybe<Scalars['String']['output']>; + __typename?: 'AISQLQueryResult'; + queryFailedErrorMessage?: Maybe<Scalars['String']['output']>; + sqlQuery: Scalars['String']['output']; + sqlQueryResult?: Maybe<Scalars['String']['output']>; }; export type ActivateWorkspaceInput = { - displayName?: InputMaybe<Scalars['String']['input']>; + displayName?: InputMaybe<Scalars['String']['input']>; }; export type Analytics = { - __typename?: 'Analytics'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']['output']; + __typename?: 'Analytics'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']['output']; }; export type ApiConfig = { - __typename?: 'ApiConfig'; - mutationMaximumAffectedRecords: Scalars['Float']['output']; + __typename?: 'ApiConfig'; + mutationMaximumAffectedRecords: Scalars['Float']['output']; }; export type ApiKeyToken = { - __typename?: 'ApiKeyToken'; - token: Scalars['String']['output']; + __typename?: 'ApiKeyToken'; + token: Scalars['String']['output']; }; export type AppToken = { - __typename?: 'AppToken'; - createdAt: Scalars['DateTime']['output']; - expiresAt: Scalars['DateTime']['output']; - id: Scalars['UUID']['output']; - type: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; + __typename?: 'AppToken'; + createdAt: Scalars['DateTime']['output']; + expiresAt: Scalars['DateTime']['output']; + id: Scalars['UUID']['output']; + type: Scalars['String']['output']; + updatedAt: Scalars['DateTime']['output']; }; export type AppTokenEdge = { - __typename?: 'AppTokenEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the AppToken */ - node: AppToken; + __typename?: 'AppTokenEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the AppToken */ + node: AppToken; }; export type AuthProviders = { - __typename?: 'AuthProviders'; - google: Scalars['Boolean']['output']; - magicLink: Scalars['Boolean']['output']; - microsoft: Scalars['Boolean']['output']; - password: Scalars['Boolean']['output']; + __typename?: 'AuthProviders'; + google: Scalars['Boolean']['output']; + magicLink: Scalars['Boolean']['output']; + microsoft: Scalars['Boolean']['output']; + password: Scalars['Boolean']['output']; }; export type AuthToken = { - __typename?: 'AuthToken'; - expiresAt: Scalars['DateTime']['output']; - token: Scalars['String']['output']; + __typename?: 'AuthToken'; + expiresAt: Scalars['DateTime']['output']; + token: Scalars['String']['output']; }; export type AuthTokenPair = { - __typename?: 'AuthTokenPair'; - accessToken: AuthToken; - refreshToken: AuthToken; + __typename?: 'AuthTokenPair'; + accessToken: AuthToken; + refreshToken: AuthToken; }; export type AuthTokens = { - __typename?: 'AuthTokens'; - tokens: AuthTokenPair; + __typename?: 'AuthTokens'; + tokens: AuthTokenPair; }; export type AuthorizeApp = { - __typename?: 'AuthorizeApp'; - redirectUrl: Scalars['String']['output']; + __typename?: 'AuthorizeApp'; + redirectUrl: Scalars['String']['output']; }; export type Billing = { - __typename?: 'Billing'; - billingFreeTrialDurationInDays?: Maybe<Scalars['Float']['output']>; - billingUrl?: Maybe<Scalars['String']['output']>; - isBillingEnabled: Scalars['Boolean']['output']; + __typename?: 'Billing'; + billingFreeTrialDurationInDays?: Maybe<Scalars['Float']['output']>; + billingUrl?: Maybe<Scalars['String']['output']>; + isBillingEnabled: Scalars['Boolean']['output']; }; export type BillingSubscription = { - __typename?: 'BillingSubscription'; - id: Scalars['UUID']['output']; - interval?: Maybe<SubscriptionInterval>; - status: SubscriptionStatus; + __typename?: 'BillingSubscription'; + id: Scalars['UUID']['output']; + interval?: Maybe<SubscriptionInterval>; + status: SubscriptionStatus; }; export type BillingSubscriptionFilter = { - and?: InputMaybe<Array<BillingSubscriptionFilter>>; - id?: InputMaybe<UuidFilterComparison>; - or?: InputMaybe<Array<BillingSubscriptionFilter>>; + and?: InputMaybe<Array<BillingSubscriptionFilter>>; + id?: InputMaybe<UuidFilterComparison>; + or?: InputMaybe<Array<BillingSubscriptionFilter>>; }; export type BillingSubscriptionSort = { - direction: SortDirection; - field: BillingSubscriptionSortFields; - nulls?: InputMaybe<SortNulls>; + direction: SortDirection; + field: BillingSubscriptionSortFields; + nulls?: InputMaybe<SortNulls>; }; export enum BillingSubscriptionSortFields { - Id = 'id' + Id = 'id' } export type BooleanFieldComparison = { - is?: InputMaybe<Scalars['Boolean']['input']>; - isNot?: InputMaybe<Scalars['Boolean']['input']>; + is?: InputMaybe<Scalars['Boolean']['input']>; + isNot?: InputMaybe<Scalars['Boolean']['input']>; }; -/** Visibility of the calendar channel */ export enum CalendarChannelVisibility { - Metadata = 'METADATA', - ShareEverything = 'SHARE_EVERYTHING' + Metadata = 'METADATA', + ShareEverything = 'SHARE_EVERYTHING' } export type Captcha = { - __typename?: 'Captcha'; - provider?: Maybe<CaptchaDriverType>; - siteKey?: Maybe<Scalars['String']['output']>; + __typename?: 'Captcha'; + provider?: Maybe<CaptchaDriverType>; + siteKey?: Maybe<Scalars['String']['output']>; }; export enum CaptchaDriverType { - GoogleRecaptcha = 'GoogleRecaptcha', - Turnstile = 'Turnstile' + GoogleRecaptcha = 'GoogleRecaptcha', + Turnstile = 'Turnstile' } export type ClientConfig = { - __typename?: 'ClientConfig'; - api: ApiConfig; - authProviders: AuthProviders; - billing: Billing; - captcha: Captcha; - chromeExtensionId?: Maybe<Scalars['String']['output']>; - debugMode: Scalars['Boolean']['output']; - sentry: Sentry; - signInPrefilled: Scalars['Boolean']['output']; - signUpDisabled: Scalars['Boolean']['output']; - support: Support; - telemetry: Telemetry; + __typename?: 'ClientConfig'; + api: ApiConfig; + authProviders: AuthProviders; + billing: Billing; + captcha: Captcha; + chromeExtensionId?: Maybe<Scalars['String']['output']>; + debugMode: Scalars['Boolean']['output']; + sentry: Sentry; + signInPrefilled: Scalars['Boolean']['output']; + signUpDisabled: Scalars['Boolean']['output']; + support: Support; }; export type CreateAppTokenInput = { - expiresAt: Scalars['DateTime']['input']; + expiresAt: Scalars['DateTime']['input']; }; export type CreateFieldInput = { - defaultValue?: InputMaybe<Scalars['JSON']['input']>; - description?: InputMaybe<Scalars['String']['input']>; - icon?: InputMaybe<Scalars['String']['input']>; - isActive?: InputMaybe<Scalars['Boolean']['input']>; - isCustom?: InputMaybe<Scalars['Boolean']['input']>; - isNullable?: InputMaybe<Scalars['Boolean']['input']>; - isRemoteCreation?: InputMaybe<Scalars['Boolean']['input']>; - isSystem?: InputMaybe<Scalars['Boolean']['input']>; - label: Scalars['String']['input']; - name: Scalars['String']['input']; - objectMetadataId: Scalars['String']['input']; - options?: InputMaybe<Scalars['JSON']['input']>; - settings?: InputMaybe<Scalars['JSON']['input']>; - type: FieldMetadataType; + defaultValue?: InputMaybe<Scalars['JSON']['input']>; + description?: InputMaybe<Scalars['String']['input']>; + icon?: InputMaybe<Scalars['String']['input']>; + isActive?: InputMaybe<Scalars['Boolean']['input']>; + isCustom?: InputMaybe<Scalars['Boolean']['input']>; + isNullable?: InputMaybe<Scalars['Boolean']['input']>; + isRemoteCreation?: InputMaybe<Scalars['Boolean']['input']>; + isSystem?: InputMaybe<Scalars['Boolean']['input']>; + label: Scalars['String']['input']; + name: Scalars['String']['input']; + objectMetadataId: Scalars['String']['input']; + options?: InputMaybe<Scalars['JSON']['input']>; + settings?: InputMaybe<Scalars['JSON']['input']>; + type: FieldMetadataType; }; export type CreateObjectInput = { - description?: InputMaybe<Scalars['String']['input']>; - icon?: InputMaybe<Scalars['String']['input']>; - imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; - isRemote?: InputMaybe<Scalars['Boolean']['input']>; - labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; - labelPlural: Scalars['String']['input']; - labelSingular: Scalars['String']['input']; - namePlural: Scalars['String']['input']; - nameSingular: Scalars['String']['input']; - primaryKeyColumnType?: InputMaybe<Scalars['String']['input']>; - primaryKeyFieldMetadataSettings?: InputMaybe<Scalars['JSON']['input']>; + description?: InputMaybe<Scalars['String']['input']>; + icon?: InputMaybe<Scalars['String']['input']>; + imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; + isRemote?: InputMaybe<Scalars['Boolean']['input']>; + labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; + labelPlural: Scalars['String']['input']; + labelSingular: Scalars['String']['input']; + namePlural: Scalars['String']['input']; + nameSingular: Scalars['String']['input']; + primaryKeyColumnType?: InputMaybe<Scalars['String']['input']>; + primaryKeyFieldMetadataSettings?: InputMaybe<Scalars['JSON']['input']>; }; export type CreateOneAppTokenInput = { - /** The record to create */ - appToken: CreateAppTokenInput; + /** The record to create */ + appToken: CreateAppTokenInput; }; export type CreateOneFieldMetadataInput = { - /** The record to create */ - field: CreateFieldInput; + /** The record to create */ + field: CreateFieldInput; }; export type CreateOneObjectInput = { - /** The record to create */ - object: CreateObjectInput; + /** The record to create */ + object: CreateObjectInput; }; export type CreateOneRelationInput = { - /** The record to create */ - relation: CreateRelationInput; + /** The record to create */ + relation: CreateRelationInput; }; export type CreateRelationInput = { - description?: InputMaybe<Scalars['String']['input']>; - fromDescription?: InputMaybe<Scalars['String']['input']>; - fromIcon?: InputMaybe<Scalars['String']['input']>; - fromLabel: Scalars['String']['input']; - fromName: Scalars['String']['input']; - fromObjectMetadataId: Scalars['String']['input']; - relationType: RelationMetadataType; - toDescription?: InputMaybe<Scalars['String']['input']>; - toIcon?: InputMaybe<Scalars['String']['input']>; - toLabel: Scalars['String']['input']; - toName: Scalars['String']['input']; - toObjectMetadataId: Scalars['String']['input']; + description?: InputMaybe<Scalars['String']['input']>; + fromDescription?: InputMaybe<Scalars['String']['input']>; + fromIcon?: InputMaybe<Scalars['String']['input']>; + fromLabel: Scalars['String']['input']; + fromName: Scalars['String']['input']; + fromObjectMetadataId: Scalars['String']['input']; + relationType: RelationMetadataType; + toDescription?: InputMaybe<Scalars['String']['input']>; + toIcon?: InputMaybe<Scalars['String']['input']>; + toLabel: Scalars['String']['input']; + toName: Scalars['String']['input']; + toObjectMetadataId: Scalars['String']['input']; }; export type CreateRemoteServerInput = { - foreignDataWrapperOptions: Scalars['JSON']['input']; - foreignDataWrapperType: Scalars['String']['input']; - label: Scalars['String']['input']; - schema?: InputMaybe<Scalars['String']['input']>; - userMappingOptions?: InputMaybe<UserMappingOptions>; + foreignDataWrapperOptions: Scalars['JSON']['input']; + foreignDataWrapperType: Scalars['String']['input']; + label: Scalars['String']['input']; + schema?: InputMaybe<Scalars['String']['input']>; + userMappingOptions?: InputMaybe<UserMappingOptions>; }; export type CreateServerlessFunctionFromFileInput = { - description?: InputMaybe<Scalars['String']['input']>; - name: Scalars['String']['input']; + description?: InputMaybe<Scalars['String']['input']>; + name: Scalars['String']['input']; }; export type CreateServerlessFunctionInput = { - code: Scalars['String']['input']; - description?: InputMaybe<Scalars['String']['input']>; - name: Scalars['String']['input']; + code: Scalars['String']['input']; + description?: InputMaybe<Scalars['String']['input']>; + name: Scalars['String']['input']; }; export type CursorPaging = { - /** Paginate after opaque cursor */ - after?: InputMaybe<Scalars['ConnectionCursor']['input']>; - /** Paginate before opaque cursor */ - before?: InputMaybe<Scalars['ConnectionCursor']['input']>; - /** Paginate first */ - first?: InputMaybe<Scalars['Int']['input']>; - /** Paginate last */ - last?: InputMaybe<Scalars['Int']['input']>; + /** Paginate after opaque cursor */ + after?: InputMaybe<Scalars['ConnectionCursor']['input']>; + /** Paginate before opaque cursor */ + before?: InputMaybe<Scalars['ConnectionCursor']['input']>; + /** Paginate first */ + first?: InputMaybe<Scalars['Int']['input']>; + /** Paginate last */ + last?: InputMaybe<Scalars['Int']['input']>; }; export type DeleteOneFieldInput = { - /** The id of the field to delete. */ - id: Scalars['UUID']['input']; + /** The id of the field to delete. */ + id: Scalars['UUID']['input']; }; export type DeleteOneObjectInput = { - /** The id of the record to delete. */ - id: Scalars['UUID']['input']; + /** The id of the record to delete. */ + id: Scalars['UUID']['input']; }; export type DeleteOneRelationInput = { - /** The id of the relation to delete. */ - id: Scalars['UUID']['input']; + /** The id of the relation to delete. */ + id: Scalars['UUID']['input']; }; export type DeleteServerlessFunctionInput = { - /** The id of the function. */ - id: Scalars['ID']['input']; + /** The id of the function. */ + id: Scalars['ID']['input']; }; /** Schema update on a table */ export enum DistantTableUpdate { - ColumnsAdded = 'COLUMNS_ADDED', - ColumnsDeleted = 'COLUMNS_DELETED', - ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED', - TableDeleted = 'TABLE_DELETED' + ColumnsAdded = 'COLUMNS_ADDED', + ColumnsDeleted = 'COLUMNS_DELETED', + ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED', + TableDeleted = 'TABLE_DELETED' } export type EmailPasswordResetLink = { - __typename?: 'EmailPasswordResetLink'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']['output']; + __typename?: 'EmailPasswordResetLink'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']['output']; }; export type ExchangeAuthCode = { - __typename?: 'ExchangeAuthCode'; - accessToken: AuthToken; - loginToken: AuthToken; - refreshToken: AuthToken; + __typename?: 'ExchangeAuthCode'; + accessToken: AuthToken; + loginToken: AuthToken; + refreshToken: AuthToken; }; export type ExecuteServerlessFunctionInput = { - /** Id of the serverless function to execute */ - id: Scalars['UUID']['input']; - /** Payload in JSON format */ - payload?: InputMaybe<Scalars['JSON']['input']>; - /** Version of the serverless function to execute */ - version?: Scalars['String']['input']; + /** Id of the serverless function to execute */ + id: Scalars['UUID']['input']; + /** Payload in JSON format */ + payload: Scalars['JSON']['input']; + /** Version of the serverless function to execute */ + version?: Scalars['String']['input']; }; export type FeatureFlag = { - __typename?: 'FeatureFlag'; - id: Scalars['UUID']['output']; - key: Scalars['String']['output']; - value: Scalars['Boolean']['output']; - workspaceId: Scalars['String']['output']; + __typename?: 'FeatureFlag'; + id: Scalars['UUID']['output']; + key: Scalars['String']['output']; + value: Scalars['Boolean']['output']; + workspaceId: Scalars['String']['output']; }; export type FeatureFlagFilter = { - and?: InputMaybe<Array<FeatureFlagFilter>>; - id?: InputMaybe<UuidFilterComparison>; - or?: InputMaybe<Array<FeatureFlagFilter>>; + and?: InputMaybe<Array<FeatureFlagFilter>>; + id?: InputMaybe<UuidFilterComparison>; + or?: InputMaybe<Array<FeatureFlagFilter>>; }; export type FeatureFlagSort = { - direction: SortDirection; - field: FeatureFlagSortFields; - nulls?: InputMaybe<SortNulls>; + direction: SortDirection; + field: FeatureFlagSortFields; + nulls?: InputMaybe<SortNulls>; }; export enum FeatureFlagSortFields { - Id = 'id' + Id = 'id' } export type FieldConnection = { - __typename?: 'FieldConnection'; - /** Array of edges. */ - edges: Array<FieldEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'FieldConnection'; + /** Array of edges. */ + edges: Array<FieldEdge>; + /** Paging information */ + pageInfo: PageInfo; }; /** Type of the field */ export enum FieldMetadataType { - Actor = 'ACTOR', - Address = 'ADDRESS', - Boolean = 'BOOLEAN', - Currency = 'CURRENCY', - Date = 'DATE', - DateTime = 'DATE_TIME', - Email = 'EMAIL', - Emails = 'EMAILS', - FullName = 'FULL_NAME', - Link = 'LINK', - Links = 'LINKS', - MultiSelect = 'MULTI_SELECT', - Number = 'NUMBER', - Numeric = 'NUMERIC', - Phone = 'PHONE', - Position = 'POSITION', - Rating = 'RATING', - RawJson = 'RAW_JSON', - Relation = 'RELATION', - RichText = 'RICH_TEXT', - Select = 'SELECT', - Text = 'TEXT', - Uuid = 'UUID' + Actor = 'ACTOR', + Address = 'ADDRESS', + Array = 'ARRAY', + Boolean = 'BOOLEAN', + Currency = 'CURRENCY', + Date = 'DATE', + DateTime = 'DATE_TIME', + Email = 'EMAIL', + Emails = 'EMAILS', + FullName = 'FULL_NAME', + Link = 'LINK', + Links = 'LINKS', + MultiSelect = 'MULTI_SELECT', + Number = 'NUMBER', + Numeric = 'NUMERIC', + Phone = 'PHONE', + Phones = 'PHONES', + Position = 'POSITION', + Rating = 'RATING', + RawJson = 'RAW_JSON', + Relation = 'RELATION', + RichText = 'RICH_TEXT', + Select = 'SELECT', + Text = 'TEXT', + Uuid = 'UUID' } export enum FileFolder { - Attachment = 'Attachment', - PersonPicture = 'PersonPicture', - ProfilePicture = 'ProfilePicture', - ServerlessFunction = 'ServerlessFunction', - WorkspaceLogo = 'WorkspaceLogo' + Attachment = 'Attachment', + PersonPicture = 'PersonPicture', + ProfilePicture = 'ProfilePicture', + ServerlessFunction = 'ServerlessFunction', + WorkspaceLogo = 'WorkspaceLogo' } export type FindManyRemoteTablesInput = { - /** The id of the remote server. */ - id: Scalars['ID']['input']; - /** Indicates if pending schema updates status should be computed. */ - shouldFetchPendingSchemaUpdates?: InputMaybe<Scalars['Boolean']['input']>; + /** The id of the remote server. */ + id: Scalars['ID']['input']; + /** Indicates if pending schema updates status should be computed. */ + shouldFetchPendingSchemaUpdates?: InputMaybe<Scalars['Boolean']['input']>; }; export type FullName = { - __typename?: 'FullName'; - firstName: Scalars['String']['output']; - lastName: Scalars['String']['output']; + __typename?: 'FullName'; + firstName: Scalars['String']['output']; + lastName: Scalars['String']['output']; }; export type GetServerlessFunctionSourceCodeInput = { - /** The id of the function. */ - id: Scalars['ID']['input']; - /** The version of the function */ - version?: Scalars['String']['input']; + /** The id of the function. */ + id: Scalars['ID']['input']; + /** The version of the function */ + version?: Scalars['String']['input']; }; export type InvalidatePassword = { - __typename?: 'InvalidatePassword'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']['output']; + __typename?: 'InvalidatePassword'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']['output']; }; export type LinkMetadata = { - __typename?: 'LinkMetadata'; - label: Scalars['String']['output']; - url: Scalars['String']['output']; + __typename?: 'LinkMetadata'; + label: Scalars['String']['output']; + url: Scalars['String']['output']; }; export type LinksMetadata = { - __typename?: 'LinksMetadata'; - primaryLinkLabel: Scalars['String']['output']; - primaryLinkUrl: Scalars['String']['output']; - secondaryLinks?: Maybe<Array<LinkMetadata>>; + __typename?: 'LinksMetadata'; + primaryLinkLabel: Scalars['String']['output']; + primaryLinkUrl: Scalars['String']['output']; + secondaryLinks?: Maybe<Array<LinkMetadata>>; }; export type LoginToken = { - __typename?: 'LoginToken'; - loginToken: AuthToken; + __typename?: 'LoginToken'; + loginToken: AuthToken; }; -/** Visibility of the message channel */ export enum MessageChannelVisibility { - Metadata = 'METADATA', - ShareEverything = 'SHARE_EVERYTHING', - Subject = 'SUBJECT' + Metadata = 'METADATA', + ShareEverything = 'SHARE_EVERYTHING', + Subject = 'SUBJECT' } export type Mutation = { - __typename?: 'Mutation'; - activateWorkspace: Workspace; - addUserToWorkspace: User; - authorizeApp: AuthorizeApp; - challenge: LoginToken; - checkoutSession: SessionEntity; - createOneAppToken: AppToken; - createOneField: Field; - createOneObject: Object; - createOneRelation: Relation; - createOneRemoteServer: RemoteServer; - createOneServerlessFunction: ServerlessFunction; - createOneServerlessFunctionFromFile: ServerlessFunction; - deleteCurrentWorkspace: Workspace; - deleteOneField: Field; - deleteOneObject: Object; - deleteOneRelation: Relation; - deleteOneRemoteServer: RemoteServer; - deleteOneServerlessFunction: ServerlessFunction; - deleteUser: User; - disablePostgresProxy: PostgresCredentials; - emailPasswordResetLink: EmailPasswordResetLink; - enablePostgresProxy: PostgresCredentials; - enableWorkflowTrigger: Scalars['Boolean']['output']; - exchangeAuthorizationCode: ExchangeAuthCode; - executeOneServerlessFunction: ServerlessFunctionExecutionResult; - generateApiKeyToken: ApiKeyToken; - generateJWT: AuthTokens; - generateTransientToken: TransientToken; - impersonate: Verify; - publishServerlessFunction: ServerlessFunction; - renewToken: AuthTokens; - runWorkflowVersion: WorkflowRun; - sendInviteLink: SendInviteLink; - signUp: LoginToken; - skipSyncEmailOnboardingStep: OnboardingStepSuccess; - syncRemoteTable: RemoteTable; - syncRemoteTableSchemaChanges: RemoteTable; - track: Analytics; - unsyncRemoteTable: RemoteTable; - updateBillingSubscription: UpdateBillingEntity; - updateOneField: Field; - updateOneObject: Object; - updateOneRemoteServer: RemoteServer; - updateOneServerlessFunction: ServerlessFunction; - updatePasswordViaResetToken: InvalidatePassword; - updateWorkspace: Workspace; - uploadFile: Scalars['String']['output']; - uploadImage: Scalars['String']['output']; - uploadProfilePicture: Scalars['String']['output']; - uploadWorkspaceLogo: Scalars['String']['output']; - verify: Verify; + __typename?: 'Mutation'; + activateWorkflowVersion: Scalars['Boolean']['output']; + activateWorkspace: Workspace; + addUserToWorkspace: User; + authorizeApp: AuthorizeApp; + challenge: LoginToken; + checkoutSession: SessionEntity; + createOneAppToken: AppToken; + createOneField: Field; + createOneObject: Object; + createOneRelation: Relation; + createOneRemoteServer: RemoteServer; + createOneServerlessFunction: ServerlessFunction; + createOneServerlessFunctionFromFile: ServerlessFunction; + deactivateWorkflowVersion: Scalars['Boolean']['output']; + deleteCurrentWorkspace: Workspace; + deleteOneField: Field; + deleteOneObject: Object; + deleteOneRelation: Relation; + deleteOneRemoteServer: RemoteServer; + deleteOneServerlessFunction: ServerlessFunction; + deleteUser: User; + disablePostgresProxy: PostgresCredentials; + emailPasswordResetLink: EmailPasswordResetLink; + enablePostgresProxy: PostgresCredentials; + exchangeAuthorizationCode: ExchangeAuthCode; + executeOneServerlessFunction: ServerlessFunctionExecutionResult; + generateApiKeyToken: ApiKeyToken; + generateJWT: AuthTokens; + generateTransientToken: TransientToken; + impersonate: Verify; + publishServerlessFunction: ServerlessFunction; + renewToken: AuthTokens; + runWorkflowVersion: WorkflowRun; + sendInviteLink: SendInviteLink; + signUp: LoginToken; + skipSyncEmailOnboardingStep: OnboardingStepSuccess; + syncRemoteTable: RemoteTable; + syncRemoteTableSchemaChanges: RemoteTable; + track: Analytics; + unsyncRemoteTable: RemoteTable; + updateBillingSubscription: UpdateBillingEntity; + updateOneField: Field; + updateOneObject: Object; + updateOneRemoteServer: RemoteServer; + updateOneServerlessFunction: ServerlessFunction; + updatePasswordViaResetToken: InvalidatePassword; + updateWorkspace: Workspace; + uploadFile: Scalars['String']['output']; + uploadImage: Scalars['String']['output']; + uploadProfilePicture: Scalars['String']['output']; + uploadWorkspaceLogo: Scalars['String']['output']; + verify: Verify; +}; + + +export type MutationActivateWorkflowVersionArgs = { + workflowVersionId: Scalars['String']['input']; }; export type MutationActivateWorkspaceArgs = { - data: ActivateWorkspaceInput; + data: ActivateWorkspaceInput; }; export type MutationAddUserToWorkspaceArgs = { - inviteHash: Scalars['String']['input']; + inviteHash: Scalars['String']['input']; }; export type MutationAuthorizeAppArgs = { - clientId: Scalars['String']['input']; - codeChallenge?: InputMaybe<Scalars['String']['input']>; - redirectUrl: Scalars['String']['input']; + clientId: Scalars['String']['input']; + codeChallenge?: InputMaybe<Scalars['String']['input']>; + redirectUrl: Scalars['String']['input']; }; export type MutationChallengeArgs = { - captchaToken?: InputMaybe<Scalars['String']['input']>; - email: Scalars['String']['input']; - password: Scalars['String']['input']; + captchaToken?: InputMaybe<Scalars['String']['input']>; + email: Scalars['String']['input']; + password: Scalars['String']['input']; }; export type MutationCheckoutSessionArgs = { - recurringInterval: SubscriptionInterval; - successUrlPath?: InputMaybe<Scalars['String']['input']>; + recurringInterval: SubscriptionInterval; + successUrlPath?: InputMaybe<Scalars['String']['input']>; }; export type MutationCreateOneAppTokenArgs = { - input: CreateOneAppTokenInput; + input: CreateOneAppTokenInput; }; export type MutationCreateOneFieldArgs = { - input: CreateOneFieldMetadataInput; + input: CreateOneFieldMetadataInput; }; export type MutationCreateOneObjectArgs = { - input: CreateOneObjectInput; + input: CreateOneObjectInput; }; export type MutationCreateOneRelationArgs = { - input: CreateOneRelationInput; + input: CreateOneRelationInput; }; export type MutationCreateOneRemoteServerArgs = { - input: CreateRemoteServerInput; + input: CreateRemoteServerInput; }; export type MutationCreateOneServerlessFunctionArgs = { - input: CreateServerlessFunctionInput; + input: CreateServerlessFunctionInput; }; export type MutationCreateOneServerlessFunctionFromFileArgs = { - file: Scalars['Upload']['input']; - input: CreateServerlessFunctionFromFileInput; + file: Scalars['Upload']['input']; + input: CreateServerlessFunctionFromFileInput; +}; + + +export type MutationDeactivateWorkflowVersionArgs = { + workflowVersionId: Scalars['String']['input']; }; export type MutationDeleteOneFieldArgs = { - input: DeleteOneFieldInput; + input: DeleteOneFieldInput; }; export type MutationDeleteOneObjectArgs = { - input: DeleteOneObjectInput; + input: DeleteOneObjectInput; }; export type MutationDeleteOneRelationArgs = { - input: DeleteOneRelationInput; + input: DeleteOneRelationInput; }; export type MutationDeleteOneRemoteServerArgs = { - input: RemoteServerIdInput; + input: RemoteServerIdInput; }; export type MutationDeleteOneServerlessFunctionArgs = { - input: DeleteServerlessFunctionInput; + input: DeleteServerlessFunctionInput; }; export type MutationEmailPasswordResetLinkArgs = { - email: Scalars['String']['input']; -}; - - -export type MutationEnableWorkflowTriggerArgs = { - workflowVersionId: Scalars['String']['input']; + email: Scalars['String']['input']; }; export type MutationExchangeAuthorizationCodeArgs = { - authorizationCode: Scalars['String']['input']; - clientSecret?: InputMaybe<Scalars['String']['input']>; - codeVerifier?: InputMaybe<Scalars['String']['input']>; + authorizationCode: Scalars['String']['input']; + clientSecret?: InputMaybe<Scalars['String']['input']>; + codeVerifier?: InputMaybe<Scalars['String']['input']>; }; export type MutationExecuteOneServerlessFunctionArgs = { - input: ExecuteServerlessFunctionInput; + input: ExecuteServerlessFunctionInput; }; export type MutationGenerateApiKeyTokenArgs = { - apiKeyId: Scalars['String']['input']; - expiresAt: Scalars['String']['input']; + apiKeyId: Scalars['String']['input']; + expiresAt: Scalars['String']['input']; }; export type MutationGenerateJwtArgs = { - workspaceId: Scalars['String']['input']; + workspaceId: Scalars['String']['input']; }; export type MutationImpersonateArgs = { - userId: Scalars['String']['input']; + userId: Scalars['String']['input']; }; export type MutationPublishServerlessFunctionArgs = { - input: PublishServerlessFunctionInput; + input: PublishServerlessFunctionInput; }; export type MutationRenewTokenArgs = { - appToken: Scalars['String']['input']; + appToken: Scalars['String']['input']; }; export type MutationRunWorkflowVersionArgs = { - input: RunWorkflowVersionInput; + input: RunWorkflowVersionInput; }; export type MutationSendInviteLinkArgs = { - emails: Array<Scalars['String']['input']>; + emails: Array<Scalars['String']['input']>; }; export type MutationSignUpArgs = { - captchaToken?: InputMaybe<Scalars['String']['input']>; - email: Scalars['String']['input']; - password: Scalars['String']['input']; - workspaceInviteHash?: InputMaybe<Scalars['String']['input']>; + captchaToken?: InputMaybe<Scalars['String']['input']>; + email: Scalars['String']['input']; + password: Scalars['String']['input']; + workspaceInviteHash?: InputMaybe<Scalars['String']['input']>; }; export type MutationSyncRemoteTableArgs = { - input: RemoteTableInput; + input: RemoteTableInput; }; export type MutationSyncRemoteTableSchemaChangesArgs = { - input: RemoteTableInput; + input: RemoteTableInput; }; export type MutationTrackArgs = { - data: Scalars['JSON']['input']; - type: Scalars['String']['input']; + data: Scalars['JSON']['input']; + type: Scalars['String']['input']; }; export type MutationUnsyncRemoteTableArgs = { - input: RemoteTableInput; + input: RemoteTableInput; }; export type MutationUpdateOneFieldArgs = { - input: UpdateOneFieldMetadataInput; + input: UpdateOneFieldMetadataInput; }; export type MutationUpdateOneObjectArgs = { - input: UpdateOneObjectInput; + input: UpdateOneObjectInput; }; export type MutationUpdateOneRemoteServerArgs = { - input: UpdateRemoteServerInput; + input: UpdateRemoteServerInput; }; export type MutationUpdateOneServerlessFunctionArgs = { - input: UpdateServerlessFunctionInput; + input: UpdateServerlessFunctionInput; }; export type MutationUpdatePasswordViaResetTokenArgs = { - newPassword: Scalars['String']['input']; - passwordResetToken: Scalars['String']['input']; + newPassword: Scalars['String']['input']; + passwordResetToken: Scalars['String']['input']; }; export type MutationUpdateWorkspaceArgs = { - data: UpdateWorkspaceInput; + data: UpdateWorkspaceInput; }; export type MutationUploadFileArgs = { - file: Scalars['Upload']['input']; - fileFolder?: InputMaybe<FileFolder>; + file: Scalars['Upload']['input']; + fileFolder?: InputMaybe<FileFolder>; }; export type MutationUploadImageArgs = { - file: Scalars['Upload']['input']; - fileFolder?: InputMaybe<FileFolder>; + file: Scalars['Upload']['input']; + fileFolder?: InputMaybe<FileFolder>; }; export type MutationUploadProfilePictureArgs = { - file: Scalars['Upload']['input']; + file: Scalars['Upload']['input']; }; export type MutationUploadWorkspaceLogoArgs = { - file: Scalars['Upload']['input']; + file: Scalars['Upload']['input']; }; export type MutationVerifyArgs = { - loginToken: Scalars['String']['input']; + loginToken: Scalars['String']['input']; }; export type ObjectConnection = { - __typename?: 'ObjectConnection'; - /** Array of edges. */ - edges: Array<ObjectEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'ObjectConnection'; + /** Array of edges. */ + edges: Array<ObjectEdge>; + /** Paging information */ + pageInfo: PageInfo; }; export type ObjectFieldsConnection = { - __typename?: 'ObjectFieldsConnection'; - /** Array of edges. */ - edges: Array<FieldEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'ObjectFieldsConnection'; + /** Array of edges. */ + edges: Array<FieldEdge>; + /** Paging information */ + pageInfo: PageInfo; }; /** Onboarding status */ export enum OnboardingStatus { - Completed = 'COMPLETED', - InviteTeam = 'INVITE_TEAM', - PlanRequired = 'PLAN_REQUIRED', - ProfileCreation = 'PROFILE_CREATION', - SyncEmail = 'SYNC_EMAIL', - WorkspaceActivation = 'WORKSPACE_ACTIVATION' + Completed = 'COMPLETED', + InviteTeam = 'INVITE_TEAM', + PlanRequired = 'PLAN_REQUIRED', + ProfileCreation = 'PROFILE_CREATION', + SyncEmail = 'SYNC_EMAIL', + WorkspaceActivation = 'WORKSPACE_ACTIVATION' } export type OnboardingStepSuccess = { - __typename?: 'OnboardingStepSuccess'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']['output']; + __typename?: 'OnboardingStepSuccess'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']['output']; }; export type PageInfo = { - __typename?: 'PageInfo'; - /** The cursor of the last returned record. */ - endCursor?: Maybe<Scalars['ConnectionCursor']['output']>; - /** true if paging forward and there are more records. */ - hasNextPage?: Maybe<Scalars['Boolean']['output']>; - /** true if paging backwards and there are more records. */ - hasPreviousPage?: Maybe<Scalars['Boolean']['output']>; - /** The cursor of the first returned record. */ - startCursor?: Maybe<Scalars['ConnectionCursor']['output']>; + __typename?: 'PageInfo'; + /** The cursor of the last returned record. */ + endCursor?: Maybe<Scalars['ConnectionCursor']['output']>; + /** true if paging forward and there are more records. */ + hasNextPage?: Maybe<Scalars['Boolean']['output']>; + /** true if paging backwards and there are more records. */ + hasPreviousPage?: Maybe<Scalars['Boolean']['output']>; + /** The cursor of the first returned record. */ + startCursor?: Maybe<Scalars['ConnectionCursor']['output']>; }; export type PostgresCredentials = { - __typename?: 'PostgresCredentials'; - id: Scalars['UUID']['output']; - password: Scalars['String']['output']; - user: Scalars['String']['output']; - workspaceId: Scalars['String']['output']; + __typename?: 'PostgresCredentials'; + id: Scalars['UUID']['output']; + password: Scalars['String']['output']; + user: Scalars['String']['output']; + workspaceId: Scalars['String']['output']; }; export type ProductPriceEntity = { - __typename?: 'ProductPriceEntity'; - created: Scalars['Float']['output']; - recurringInterval: SubscriptionInterval; - stripePriceId: Scalars['String']['output']; - unitAmount: Scalars['Float']['output']; + __typename?: 'ProductPriceEntity'; + created: Scalars['Float']['output']; + recurringInterval: SubscriptionInterval; + stripePriceId: Scalars['String']['output']; + unitAmount: Scalars['Float']['output']; }; export type ProductPricesEntity = { - __typename?: 'ProductPricesEntity'; - productPrices: Array<ProductPriceEntity>; - totalNumberOfPrices: Scalars['Int']['output']; + __typename?: 'ProductPricesEntity'; + productPrices: Array<ProductPriceEntity>; + totalNumberOfPrices: Scalars['Int']['output']; }; export type PublishServerlessFunctionInput = { - /** The id of the function. */ - id: Scalars['ID']['input']; + /** The id of the function. */ + id: Scalars['ID']['input']; }; export type Query = { - __typename?: 'Query'; - billingPortalSession: SessionEntity; - checkUserExists: UserExists; - checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; - clientConfig: ClientConfig; - currentUser: User; - currentWorkspace: Workspace; - field: Field; - fields: FieldConnection; - findDistantTablesWithStatus: Array<RemoteTable>; - findManyRemoteServersByType: Array<RemoteServer>; - findOneRemoteServerById: RemoteServer; - findWorkspaceFromInviteHash: Workspace; - getAISQLQuery: AisqlQueryResult; - getPostgresCredentials?: Maybe<PostgresCredentials>; - getProductPrices: ProductPricesEntity; - getServerlessFunctionSourceCode: Scalars['String']['output']; - getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; - getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; - getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal; - getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; - object: Object; - objects: ObjectConnection; - relation: Relation; - relations: RelationConnection; - serverlessFunction: ServerlessFunction; - serverlessFunctions: ServerlessFunctionConnection; - validatePasswordResetToken: ValidatePasswordResetToken; + __typename?: 'Query'; + billingPortalSession: SessionEntity; + checkUserExists: UserExists; + checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; + clientConfig: ClientConfig; + currentUser: User; + currentWorkspace: Workspace; + field: Field; + fields: FieldConnection; + findDistantTablesWithStatus: Array<RemoteTable>; + findManyRemoteServersByType: Array<RemoteServer>; + findOneRemoteServerById: RemoteServer; + findWorkspaceFromInviteHash: Workspace; + getAISQLQuery: AisqlQueryResult; + getAvailablePackages: Scalars['JSON']['output']; + getPostgresCredentials?: Maybe<PostgresCredentials>; + getProductPrices: ProductPricesEntity; + getServerlessFunctionSourceCode?: Maybe<Scalars['String']['output']>; + getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; + getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; + getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal; + getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; + object: Object; + objects: ObjectConnection; + relation: Relation; + relations: RelationConnection; + serverlessFunction: ServerlessFunction; + serverlessFunctions: ServerlessFunctionConnection; + validatePasswordResetToken: ValidatePasswordResetToken; }; export type QueryBillingPortalSessionArgs = { - returnUrlPath?: InputMaybe<Scalars['String']['input']>; + returnUrlPath?: InputMaybe<Scalars['String']['input']>; }; export type QueryCheckUserExistsArgs = { - captchaToken?: InputMaybe<Scalars['String']['input']>; - email: Scalars['String']['input']; + captchaToken?: InputMaybe<Scalars['String']['input']>; + email: Scalars['String']['input']; }; export type QueryCheckWorkspaceInviteHashIsValidArgs = { - inviteHash: Scalars['String']['input']; + inviteHash: Scalars['String']['input']; }; export type QueryFieldArgs = { - id: Scalars['UUID']['input']; + id: Scalars['UUID']['input']; }; export type QueryFieldsArgs = { - filter?: FieldFilter; - paging?: CursorPaging; + filter?: FieldFilter; + paging?: CursorPaging; }; export type QueryFindDistantTablesWithStatusArgs = { - input: FindManyRemoteTablesInput; + input: FindManyRemoteTablesInput; }; export type QueryFindManyRemoteServersByTypeArgs = { - input: RemoteServerTypeInput; + input: RemoteServerTypeInput; }; export type QueryFindOneRemoteServerByIdArgs = { - input: RemoteServerIdInput; + input: RemoteServerIdInput; }; export type QueryFindWorkspaceFromInviteHashArgs = { - inviteHash: Scalars['String']['input']; + inviteHash: Scalars['String']['input']; }; export type QueryGetAisqlQueryArgs = { - text: Scalars['String']['input']; + text: Scalars['String']['input']; }; export type QueryGetProductPricesArgs = { - product: Scalars['String']['input']; + product: Scalars['String']['input']; }; export type QueryGetServerlessFunctionSourceCodeArgs = { - input: GetServerlessFunctionSourceCodeInput; + input: GetServerlessFunctionSourceCodeInput; }; export type QueryGetTimelineCalendarEventsFromCompanyIdArgs = { - companyId: Scalars['UUID']['input']; - page: Scalars['Int']['input']; - pageSize: Scalars['Int']['input']; + companyId: Scalars['UUID']['input']; + page: Scalars['Int']['input']; + pageSize: Scalars['Int']['input']; }; export type QueryGetTimelineCalendarEventsFromPersonIdArgs = { - page: Scalars['Int']['input']; - pageSize: Scalars['Int']['input']; - personId: Scalars['UUID']['input']; + page: Scalars['Int']['input']; + pageSize: Scalars['Int']['input']; + personId: Scalars['UUID']['input']; }; export type QueryGetTimelineThreadsFromCompanyIdArgs = { - companyId: Scalars['UUID']['input']; - page: Scalars['Int']['input']; - pageSize: Scalars['Int']['input']; + companyId: Scalars['UUID']['input']; + page: Scalars['Int']['input']; + pageSize: Scalars['Int']['input']; }; export type QueryGetTimelineThreadsFromPersonIdArgs = { - page: Scalars['Int']['input']; - pageSize: Scalars['Int']['input']; - personId: Scalars['UUID']['input']; + page: Scalars['Int']['input']; + pageSize: Scalars['Int']['input']; + personId: Scalars['UUID']['input']; }; export type QueryObjectArgs = { - id: Scalars['UUID']['input']; + id: Scalars['UUID']['input']; }; export type QueryObjectsArgs = { - filter?: ObjectFilter; - paging?: CursorPaging; + filter?: ObjectFilter; + paging?: CursorPaging; }; export type QueryRelationArgs = { - id: Scalars['UUID']['input']; + id: Scalars['UUID']['input']; }; export type QueryRelationsArgs = { - paging?: CursorPaging; + paging?: CursorPaging; }; export type QueryServerlessFunctionArgs = { - id: Scalars['UUID']['input']; + id: Scalars['UUID']['input']; }; export type QueryServerlessFunctionsArgs = { - filter?: ServerlessFunctionFilter; - paging?: CursorPaging; - sorting?: Array<ServerlessFunctionSort>; + filter?: ServerlessFunctionFilter; + paging?: CursorPaging; + sorting?: Array<ServerlessFunctionSort>; }; export type QueryValidatePasswordResetTokenArgs = { - passwordResetToken: Scalars['String']['input']; + passwordResetToken: Scalars['String']['input']; }; export type RelationConnection = { - __typename?: 'RelationConnection'; - /** Array of edges. */ - edges: Array<RelationEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'RelationConnection'; + /** Array of edges. */ + edges: Array<RelationEdge>; + /** Paging information */ + pageInfo: PageInfo; }; export type RelationDefinition = { - __typename?: 'RelationDefinition'; - direction: RelationDefinitionType; - relationId: Scalars['UUID']['output']; - sourceFieldMetadata: Field; - sourceObjectMetadata: Object; - targetFieldMetadata: Field; - targetObjectMetadata: Object; + __typename?: 'RelationDefinition'; + direction: RelationDefinitionType; + relationId: Scalars['UUID']['output']; + sourceFieldMetadata: Field; + sourceObjectMetadata: Object; + targetFieldMetadata: Field; + targetObjectMetadata: Object; }; /** Relation definition type */ export enum RelationDefinitionType { - ManyToMany = 'MANY_TO_MANY', - ManyToOne = 'MANY_TO_ONE', - OneToMany = 'ONE_TO_MANY', - OneToOne = 'ONE_TO_ONE' + ManyToMany = 'MANY_TO_MANY', + ManyToOne = 'MANY_TO_ONE', + OneToMany = 'ONE_TO_MANY', + OneToOne = 'ONE_TO_ONE' } /** Type of the relation */ export enum RelationMetadataType { - ManyToMany = 'MANY_TO_MANY', - ManyToOne = 'MANY_TO_ONE', - OneToMany = 'ONE_TO_MANY', - OneToOne = 'ONE_TO_ONE' + ManyToMany = 'MANY_TO_MANY', + ManyToOne = 'MANY_TO_ONE', + OneToMany = 'ONE_TO_MANY', + OneToOne = 'ONE_TO_ONE' } export type RemoteServer = { - __typename?: 'RemoteServer'; - createdAt: Scalars['DateTime']['output']; - foreignDataWrapperId: Scalars['ID']['output']; - foreignDataWrapperOptions?: Maybe<Scalars['JSON']['output']>; - foreignDataWrapperType: Scalars['String']['output']; - id: Scalars['ID']['output']; - label: Scalars['String']['output']; - schema?: Maybe<Scalars['String']['output']>; - updatedAt: Scalars['DateTime']['output']; - userMappingOptions?: Maybe<UserMappingOptionsUser>; + __typename?: 'RemoteServer'; + createdAt: Scalars['DateTime']['output']; + foreignDataWrapperId: Scalars['ID']['output']; + foreignDataWrapperOptions?: Maybe<Scalars['JSON']['output']>; + foreignDataWrapperType: Scalars['String']['output']; + id: Scalars['ID']['output']; + label: Scalars['String']['output']; + schema?: Maybe<Scalars['String']['output']>; + updatedAt: Scalars['DateTime']['output']; + userMappingOptions?: Maybe<UserMappingOptionsUser>; }; export type RemoteServerIdInput = { - /** The id of the record. */ - id: Scalars['ID']['input']; + /** The id of the record. */ + id: Scalars['ID']['input']; }; export type RemoteServerTypeInput = { - foreignDataWrapperType: Scalars['String']['input']; + foreignDataWrapperType: Scalars['String']['input']; }; export type RemoteTable = { - __typename?: 'RemoteTable'; - id?: Maybe<Scalars['UUID']['output']>; - name: Scalars['String']['output']; - schema?: Maybe<Scalars['String']['output']>; - schemaPendingUpdates?: Maybe<Array<DistantTableUpdate>>; - status: RemoteTableStatus; + __typename?: 'RemoteTable'; + id?: Maybe<Scalars['UUID']['output']>; + name: Scalars['String']['output']; + schema?: Maybe<Scalars['String']['output']>; + schemaPendingUpdates?: Maybe<Array<DistantTableUpdate>>; + status: RemoteTableStatus; }; export type RemoteTableInput = { - name: Scalars['String']['input']; - remoteServerId: Scalars['ID']['input']; + name: Scalars['String']['input']; + remoteServerId: Scalars['ID']['input']; }; /** Status of the table */ export enum RemoteTableStatus { - NotSynced = 'NOT_SYNCED', - Synced = 'SYNCED' + NotSynced = 'NOT_SYNCED', + Synced = 'SYNCED' } export type RunWorkflowVersionInput = { - /** Execution result in JSON format */ - payload?: InputMaybe<Scalars['JSON']['input']>; - /** Workflow version ID */ - workflowVersionId: Scalars['String']['input']; + /** Execution result in JSON format */ + payload?: InputMaybe<Scalars['JSON']['input']>; + /** Workflow version ID */ + workflowVersionId: Scalars['String']['input']; }; export type SendInviteLink = { - __typename?: 'SendInviteLink'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']['output']; + __typename?: 'SendInviteLink'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']['output']; }; export type Sentry = { - __typename?: 'Sentry'; - dsn?: Maybe<Scalars['String']['output']>; - environment?: Maybe<Scalars['String']['output']>; - release?: Maybe<Scalars['String']['output']>; + __typename?: 'Sentry'; + dsn?: Maybe<Scalars['String']['output']>; + environment?: Maybe<Scalars['String']['output']>; + release?: Maybe<Scalars['String']['output']>; }; export type ServerlessFunction = { - __typename?: 'ServerlessFunction'; - createdAt: Scalars['DateTime']['output']; - description?: Maybe<Scalars['String']['output']>; - id: Scalars['UUID']['output']; - latestVersion?: Maybe<Scalars['String']['output']>; - name: Scalars['String']['output']; - runtime: Scalars['String']['output']; - sourceCodeHash: Scalars['String']['output']; - syncStatus: ServerlessFunctionSyncStatus; - updatedAt: Scalars['DateTime']['output']; + __typename?: 'ServerlessFunction'; + createdAt: Scalars['DateTime']['output']; + description?: Maybe<Scalars['String']['output']>; + id: Scalars['UUID']['output']; + latestVersion?: Maybe<Scalars['String']['output']>; + name: Scalars['String']['output']; + runtime: Scalars['String']['output']; + sourceCodeHash: Scalars['String']['output']; + syncStatus: ServerlessFunctionSyncStatus; + updatedAt: Scalars['DateTime']['output']; }; export type ServerlessFunctionConnection = { - __typename?: 'ServerlessFunctionConnection'; - /** Array of edges. */ - edges: Array<ServerlessFunctionEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'ServerlessFunctionConnection'; + /** Array of edges. */ + edges: Array<ServerlessFunctionEdge>; + /** Paging information */ + pageInfo: PageInfo; }; export type ServerlessFunctionEdge = { - __typename?: 'ServerlessFunctionEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the ServerlessFunction */ - node: ServerlessFunction; + __typename?: 'ServerlessFunctionEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the ServerlessFunction */ + node: ServerlessFunction; }; export type ServerlessFunctionExecutionResult = { - __typename?: 'ServerlessFunctionExecutionResult'; - /** Execution result in JSON format */ - data?: Maybe<Scalars['JSON']['output']>; - /** Execution duration in milliseconds */ - duration: Scalars['Float']['output']; - /** Execution error in JSON format */ - error?: Maybe<Scalars['JSON']['output']>; - /** Execution status */ - status: ServerlessFunctionExecutionStatus; + __typename?: 'ServerlessFunctionExecutionResult'; + /** Execution result in JSON format */ + data?: Maybe<Scalars['JSON']['output']>; + /** Execution duration in milliseconds */ + duration: Scalars['Float']['output']; + /** Execution error in JSON format */ + error?: Maybe<Scalars['JSON']['output']>; + /** Execution status */ + status: ServerlessFunctionExecutionStatus; }; /** Status of the serverless function execution */ export enum ServerlessFunctionExecutionStatus { - Error = 'ERROR', - Success = 'SUCCESS' + Error = 'ERROR', + Success = 'SUCCESS' } export type ServerlessFunctionFilter = { - and?: InputMaybe<Array<ServerlessFunctionFilter>>; - id?: InputMaybe<UuidFilterComparison>; - or?: InputMaybe<Array<ServerlessFunctionFilter>>; + and?: InputMaybe<Array<ServerlessFunctionFilter>>; + id?: InputMaybe<UuidFilterComparison>; + or?: InputMaybe<Array<ServerlessFunctionFilter>>; }; export type ServerlessFunctionSort = { - direction: SortDirection; - field: ServerlessFunctionSortFields; - nulls?: InputMaybe<SortNulls>; + direction: SortDirection; + field: ServerlessFunctionSortFields; + nulls?: InputMaybe<SortNulls>; }; export enum ServerlessFunctionSortFields { - Id = 'id' + Id = 'id' } /** SyncStatus of the serverlessFunction */ export enum ServerlessFunctionSyncStatus { - NotReady = 'NOT_READY', - Ready = 'READY' + NotReady = 'NOT_READY', + Ready = 'READY' } export type SessionEntity = { - __typename?: 'SessionEntity'; - url?: Maybe<Scalars['String']['output']>; + __typename?: 'SessionEntity'; + url?: Maybe<Scalars['String']['output']>; }; /** Sort Directions */ export enum SortDirection { - Asc = 'ASC', - Desc = 'DESC' + Asc = 'ASC', + Desc = 'DESC' } /** Sort Nulls Options */ export enum SortNulls { - NullsFirst = 'NULLS_FIRST', - NullsLast = 'NULLS_LAST' + NullsFirst = 'NULLS_FIRST', + NullsLast = 'NULLS_LAST' } export enum SubscriptionInterval { - Day = 'Day', - Month = 'Month', - Week = 'Week', - Year = 'Year' + Day = 'Day', + Month = 'Month', + Week = 'Week', + Year = 'Year' } export enum SubscriptionStatus { - Active = 'Active', - Canceled = 'Canceled', - Incomplete = 'Incomplete', - IncompleteExpired = 'IncompleteExpired', - PastDue = 'PastDue', - Paused = 'Paused', - Trialing = 'Trialing', - Unpaid = 'Unpaid' + Active = 'Active', + Canceled = 'Canceled', + Incomplete = 'Incomplete', + IncompleteExpired = 'IncompleteExpired', + PastDue = 'PastDue', + Paused = 'Paused', + Trialing = 'Trialing', + Unpaid = 'Unpaid' } export type Support = { - __typename?: 'Support'; - supportDriver: Scalars['String']['output']; - supportFrontChatId?: Maybe<Scalars['String']['output']>; -}; - -export type Telemetry = { - __typename?: 'Telemetry'; - enabled: Scalars['Boolean']['output']; + __typename?: 'Support'; + supportDriver: Scalars['String']['output']; + supportFrontChatId?: Maybe<Scalars['String']['output']>; }; export type TimelineCalendarEvent = { - __typename?: 'TimelineCalendarEvent'; - conferenceLink: LinksMetadata; - conferenceSolution: Scalars['String']['output']; - description: Scalars['String']['output']; - endsAt: Scalars['DateTime']['output']; - id: Scalars['UUID']['output']; - isCanceled: Scalars['Boolean']['output']; - isFullDay: Scalars['Boolean']['output']; - location: Scalars['String']['output']; - participants: Array<TimelineCalendarEventParticipant>; - startsAt: Scalars['DateTime']['output']; - title: Scalars['String']['output']; - visibility: CalendarChannelVisibility; + __typename?: 'TimelineCalendarEvent'; + conferenceLink: LinksMetadata; + conferenceSolution: Scalars['String']['output']; + description: Scalars['String']['output']; + endsAt: Scalars['DateTime']['output']; + id: Scalars['UUID']['output']; + isCanceled: Scalars['Boolean']['output']; + isFullDay: Scalars['Boolean']['output']; + location: Scalars['String']['output']; + participants: Array<TimelineCalendarEventParticipant>; + startsAt: Scalars['DateTime']['output']; + title: Scalars['String']['output']; + visibility: CalendarChannelVisibility; }; export type TimelineCalendarEventParticipant = { - __typename?: 'TimelineCalendarEventParticipant'; - avatarUrl: Scalars['String']['output']; - displayName: Scalars['String']['output']; - firstName: Scalars['String']['output']; - handle: Scalars['String']['output']; - lastName: Scalars['String']['output']; - personId?: Maybe<Scalars['UUID']['output']>; - workspaceMemberId?: Maybe<Scalars['UUID']['output']>; + __typename?: 'TimelineCalendarEventParticipant'; + avatarUrl: Scalars['String']['output']; + displayName: Scalars['String']['output']; + firstName: Scalars['String']['output']; + handle: Scalars['String']['output']; + lastName: Scalars['String']['output']; + personId?: Maybe<Scalars['UUID']['output']>; + workspaceMemberId?: Maybe<Scalars['UUID']['output']>; }; export type TimelineCalendarEventsWithTotal = { - __typename?: 'TimelineCalendarEventsWithTotal'; - timelineCalendarEvents: Array<TimelineCalendarEvent>; - totalNumberOfCalendarEvents: Scalars['Int']['output']; + __typename?: 'TimelineCalendarEventsWithTotal'; + timelineCalendarEvents: Array<TimelineCalendarEvent>; + totalNumberOfCalendarEvents: Scalars['Int']['output']; }; export type TimelineThread = { - __typename?: 'TimelineThread'; - firstParticipant: TimelineThreadParticipant; - id: Scalars['UUID']['output']; - lastMessageBody: Scalars['String']['output']; - lastMessageReceivedAt: Scalars['DateTime']['output']; - lastTwoParticipants: Array<TimelineThreadParticipant>; - numberOfMessagesInThread: Scalars['Float']['output']; - participantCount: Scalars['Float']['output']; - read: Scalars['Boolean']['output']; - subject: Scalars['String']['output']; - visibility: MessageChannelVisibility; + __typename?: 'TimelineThread'; + firstParticipant: TimelineThreadParticipant; + id: Scalars['UUID']['output']; + lastMessageBody: Scalars['String']['output']; + lastMessageReceivedAt: Scalars['DateTime']['output']; + lastTwoParticipants: Array<TimelineThreadParticipant>; + numberOfMessagesInThread: Scalars['Float']['output']; + participantCount: Scalars['Float']['output']; + read: Scalars['Boolean']['output']; + subject: Scalars['String']['output']; + visibility: MessageChannelVisibility; }; export type TimelineThreadParticipant = { - __typename?: 'TimelineThreadParticipant'; - avatarUrl: Scalars['String']['output']; - displayName: Scalars['String']['output']; - firstName: Scalars['String']['output']; - handle: Scalars['String']['output']; - lastName: Scalars['String']['output']; - personId?: Maybe<Scalars['UUID']['output']>; - workspaceMemberId?: Maybe<Scalars['UUID']['output']>; + __typename?: 'TimelineThreadParticipant'; + avatarUrl: Scalars['String']['output']; + displayName: Scalars['String']['output']; + firstName: Scalars['String']['output']; + handle: Scalars['String']['output']; + lastName: Scalars['String']['output']; + personId?: Maybe<Scalars['UUID']['output']>; + workspaceMemberId?: Maybe<Scalars['UUID']['output']>; }; export type TimelineThreadsWithTotal = { - __typename?: 'TimelineThreadsWithTotal'; - timelineThreads: Array<TimelineThread>; - totalNumberOfThreads: Scalars['Int']['output']; + __typename?: 'TimelineThreadsWithTotal'; + timelineThreads: Array<TimelineThread>; + totalNumberOfThreads: Scalars['Int']['output']; }; export type TransientToken = { - __typename?: 'TransientToken'; - transientToken: AuthToken; + __typename?: 'TransientToken'; + transientToken: AuthToken; }; export type UuidFilterComparison = { - eq?: InputMaybe<Scalars['UUID']['input']>; - gt?: InputMaybe<Scalars['UUID']['input']>; - gte?: InputMaybe<Scalars['UUID']['input']>; - iLike?: InputMaybe<Scalars['UUID']['input']>; - in?: InputMaybe<Array<Scalars['UUID']['input']>>; - is?: InputMaybe<Scalars['Boolean']['input']>; - isNot?: InputMaybe<Scalars['Boolean']['input']>; - like?: InputMaybe<Scalars['UUID']['input']>; - lt?: InputMaybe<Scalars['UUID']['input']>; - lte?: InputMaybe<Scalars['UUID']['input']>; - neq?: InputMaybe<Scalars['UUID']['input']>; - notILike?: InputMaybe<Scalars['UUID']['input']>; - notIn?: InputMaybe<Array<Scalars['UUID']['input']>>; - notLike?: InputMaybe<Scalars['UUID']['input']>; + eq?: InputMaybe<Scalars['UUID']['input']>; + gt?: InputMaybe<Scalars['UUID']['input']>; + gte?: InputMaybe<Scalars['UUID']['input']>; + iLike?: InputMaybe<Scalars['UUID']['input']>; + in?: InputMaybe<Array<Scalars['UUID']['input']>>; + is?: InputMaybe<Scalars['Boolean']['input']>; + isNot?: InputMaybe<Scalars['Boolean']['input']>; + like?: InputMaybe<Scalars['UUID']['input']>; + lt?: InputMaybe<Scalars['UUID']['input']>; + lte?: InputMaybe<Scalars['UUID']['input']>; + neq?: InputMaybe<Scalars['UUID']['input']>; + notILike?: InputMaybe<Scalars['UUID']['input']>; + notIn?: InputMaybe<Array<Scalars['UUID']['input']>>; + notLike?: InputMaybe<Scalars['UUID']['input']>; }; export type UpdateBillingEntity = { - __typename?: 'UpdateBillingEntity'; - /** Boolean that confirms query was successful */ - success: Scalars['Boolean']['output']; + __typename?: 'UpdateBillingEntity'; + /** Boolean that confirms query was successful */ + success: Scalars['Boolean']['output']; }; export type UpdateFieldInput = { - defaultValue?: InputMaybe<Scalars['JSON']['input']>; - description?: InputMaybe<Scalars['String']['input']>; - icon?: InputMaybe<Scalars['String']['input']>; - isActive?: InputMaybe<Scalars['Boolean']['input']>; - isCustom?: InputMaybe<Scalars['Boolean']['input']>; - isNullable?: InputMaybe<Scalars['Boolean']['input']>; - isSystem?: InputMaybe<Scalars['Boolean']['input']>; - label?: InputMaybe<Scalars['String']['input']>; - name?: InputMaybe<Scalars['String']['input']>; - options?: InputMaybe<Scalars['JSON']['input']>; - settings?: InputMaybe<Scalars['JSON']['input']>; + defaultValue?: InputMaybe<Scalars['JSON']['input']>; + description?: InputMaybe<Scalars['String']['input']>; + icon?: InputMaybe<Scalars['String']['input']>; + isActive?: InputMaybe<Scalars['Boolean']['input']>; + isCustom?: InputMaybe<Scalars['Boolean']['input']>; + isNullable?: InputMaybe<Scalars['Boolean']['input']>; + isSystem?: InputMaybe<Scalars['Boolean']['input']>; + label?: InputMaybe<Scalars['String']['input']>; + name?: InputMaybe<Scalars['String']['input']>; + options?: InputMaybe<Scalars['JSON']['input']>; + settings?: InputMaybe<Scalars['JSON']['input']>; }; export type UpdateObjectPayload = { - description?: InputMaybe<Scalars['String']['input']>; - icon?: InputMaybe<Scalars['String']['input']>; - imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; - isActive?: InputMaybe<Scalars['Boolean']['input']>; - labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; - labelPlural?: InputMaybe<Scalars['String']['input']>; - labelSingular?: InputMaybe<Scalars['String']['input']>; - namePlural?: InputMaybe<Scalars['String']['input']>; - nameSingular?: InputMaybe<Scalars['String']['input']>; + description?: InputMaybe<Scalars['String']['input']>; + icon?: InputMaybe<Scalars['String']['input']>; + imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; + isActive?: InputMaybe<Scalars['Boolean']['input']>; + labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']['input']>; + labelPlural?: InputMaybe<Scalars['String']['input']>; + labelSingular?: InputMaybe<Scalars['String']['input']>; + namePlural?: InputMaybe<Scalars['String']['input']>; + nameSingular?: InputMaybe<Scalars['String']['input']>; }; export type UpdateOneFieldMetadataInput = { - /** The id of the record to update */ - id: Scalars['UUID']['input']; - /** The record to update */ - update: UpdateFieldInput; + /** The id of the record to update */ + id: Scalars['UUID']['input']; + /** The record to update */ + update: UpdateFieldInput; }; export type UpdateOneObjectInput = { - /** The id of the object to update */ - id: Scalars['UUID']['input']; - update: UpdateObjectPayload; + /** The id of the object to update */ + id: Scalars['UUID']['input']; + update: UpdateObjectPayload; }; export type UpdateRemoteServerInput = { - foreignDataWrapperOptions?: InputMaybe<Scalars['JSON']['input']>; - id: Scalars['String']['input']; - label?: InputMaybe<Scalars['String']['input']>; - schema?: InputMaybe<Scalars['String']['input']>; - userMappingOptions?: InputMaybe<UserMappingOptionsUpdateInput>; + foreignDataWrapperOptions?: InputMaybe<Scalars['JSON']['input']>; + id: Scalars['String']['input']; + label?: InputMaybe<Scalars['String']['input']>; + schema?: InputMaybe<Scalars['String']['input']>; + userMappingOptions?: InputMaybe<UserMappingOptionsUpdateInput>; }; export type UpdateServerlessFunctionInput = { - code: Scalars['String']['input']; - description?: InputMaybe<Scalars['String']['input']>; - /** Id of the serverless function to execute */ - id: Scalars['UUID']['input']; - name: Scalars['String']['input']; + code: Scalars['String']['input']; + description?: InputMaybe<Scalars['String']['input']>; + /** Id of the serverless function to execute */ + id: Scalars['UUID']['input']; + name: Scalars['String']['input']; }; export type UpdateWorkspaceInput = { - allowImpersonation?: InputMaybe<Scalars['Boolean']['input']>; - displayName?: InputMaybe<Scalars['String']['input']>; - domainName?: InputMaybe<Scalars['String']['input']>; - inviteHash?: InputMaybe<Scalars['String']['input']>; - logo?: InputMaybe<Scalars['String']['input']>; + allowImpersonation?: InputMaybe<Scalars['Boolean']['input']>; + displayName?: InputMaybe<Scalars['String']['input']>; + domainName?: InputMaybe<Scalars['String']['input']>; + inviteHash?: InputMaybe<Scalars['String']['input']>; + logo?: InputMaybe<Scalars['String']['input']>; }; export type User = { - __typename?: 'User'; - canImpersonate: Scalars['Boolean']['output']; - createdAt: Scalars['DateTime']['output']; - defaultAvatarUrl?: Maybe<Scalars['String']['output']>; - defaultWorkspace: Workspace; - defaultWorkspaceId: Scalars['String']['output']; - deletedAt?: Maybe<Scalars['DateTime']['output']>; - disabled?: Maybe<Scalars['Boolean']['output']>; - email: Scalars['String']['output']; - emailVerified: Scalars['Boolean']['output']; - firstName: Scalars['String']['output']; - id: Scalars['UUID']['output']; - lastName: Scalars['String']['output']; - onboardingStatus?: Maybe<OnboardingStatus>; - passwordHash?: Maybe<Scalars['String']['output']>; - supportUserHash?: Maybe<Scalars['String']['output']>; - updatedAt: Scalars['DateTime']['output']; - userVars: Scalars['JSONObject']['output']; - workspaceMember?: Maybe<WorkspaceMember>; - workspaceMembers?: Maybe<Array<WorkspaceMember>>; - workspaces: Array<UserWorkspace>; + __typename?: 'User'; + canImpersonate: Scalars['Boolean']['output']; + createdAt: Scalars['DateTime']['output']; + defaultAvatarUrl?: Maybe<Scalars['String']['output']>; + defaultWorkspace: Workspace; + defaultWorkspaceId: Scalars['String']['output']; + deletedAt?: Maybe<Scalars['DateTime']['output']>; + disabled?: Maybe<Scalars['Boolean']['output']>; + email: Scalars['String']['output']; + emailVerified: Scalars['Boolean']['output']; + firstName: Scalars['String']['output']; + id: Scalars['UUID']['output']; + lastName: Scalars['String']['output']; + onboardingStatus?: Maybe<OnboardingStatus>; + passwordHash?: Maybe<Scalars['String']['output']>; + supportUserHash?: Maybe<Scalars['String']['output']>; + updatedAt: Scalars['DateTime']['output']; + userVars: Scalars['JSONObject']['output']; + workspaceMember?: Maybe<WorkspaceMember>; + workspaceMembers?: Maybe<Array<WorkspaceMember>>; + workspaces: Array<UserWorkspace>; }; export type UserEdge = { - __typename?: 'UserEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the User */ - node: User; + __typename?: 'UserEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the User */ + node: User; }; export type UserExists = { - __typename?: 'UserExists'; - exists: Scalars['Boolean']['output']; + __typename?: 'UserExists'; + exists: Scalars['Boolean']['output']; }; export type UserMappingOptions = { - password?: InputMaybe<Scalars['String']['input']>; - user?: InputMaybe<Scalars['String']['input']>; + password?: InputMaybe<Scalars['String']['input']>; + user?: InputMaybe<Scalars['String']['input']>; }; export type UserMappingOptionsUpdateInput = { - password?: InputMaybe<Scalars['String']['input']>; - user?: InputMaybe<Scalars['String']['input']>; + password?: InputMaybe<Scalars['String']['input']>; + user?: InputMaybe<Scalars['String']['input']>; }; export type UserMappingOptionsUser = { - __typename?: 'UserMappingOptionsUser'; - user?: Maybe<Scalars['String']['output']>; + __typename?: 'UserMappingOptionsUser'; + user?: Maybe<Scalars['String']['output']>; }; export type UserWorkspace = { - __typename?: 'UserWorkspace'; - createdAt: Scalars['DateTime']['output']; - deletedAt?: Maybe<Scalars['DateTime']['output']>; - id: Scalars['UUID']['output']; - updatedAt: Scalars['DateTime']['output']; - user: User; - userId: Scalars['String']['output']; - workspace?: Maybe<Workspace>; - workspaceId: Scalars['String']['output']; + __typename?: 'UserWorkspace'; + createdAt: Scalars['DateTime']['output']; + deletedAt?: Maybe<Scalars['DateTime']['output']>; + id: Scalars['UUID']['output']; + updatedAt: Scalars['DateTime']['output']; + user: User; + userId: Scalars['String']['output']; + workspace?: Maybe<Workspace>; + workspaceId: Scalars['String']['output']; }; export type ValidatePasswordResetToken = { - __typename?: 'ValidatePasswordResetToken'; - email: Scalars['String']['output']; - id: Scalars['String']['output']; + __typename?: 'ValidatePasswordResetToken'; + email: Scalars['String']['output']; + id: Scalars['String']['output']; }; export type Verify = { - __typename?: 'Verify'; - tokens: AuthTokenPair; - user: User; + __typename?: 'Verify'; + tokens: AuthTokenPair; + user: User; }; export type WorkflowRun = { - __typename?: 'WorkflowRun'; - workflowRunId: Scalars['UUID']['output']; + __typename?: 'WorkflowRun'; + workflowRunId: Scalars['UUID']['output']; }; export type Workspace = { - __typename?: 'Workspace'; - activationStatus: WorkspaceActivationStatus; - allowImpersonation: Scalars['Boolean']['output']; - billingSubscriptions?: Maybe<Array<BillingSubscription>>; - createdAt: Scalars['DateTime']['output']; - currentBillingSubscription?: Maybe<BillingSubscription>; - databaseSchema: Scalars['String']['output']; - databaseUrl: Scalars['String']['output']; - deletedAt?: Maybe<Scalars['DateTime']['output']>; - displayName?: Maybe<Scalars['String']['output']>; - domainName?: Maybe<Scalars['String']['output']>; - featureFlags?: Maybe<Array<FeatureFlag>>; - id: Scalars['UUID']['output']; - inviteHash?: Maybe<Scalars['String']['output']>; - logo?: Maybe<Scalars['String']['output']>; - metadataVersion: Scalars['Float']['output']; - updatedAt: Scalars['DateTime']['output']; - workspaceMembersCount?: Maybe<Scalars['Float']['output']>; + __typename?: 'Workspace'; + activationStatus: WorkspaceActivationStatus; + allowImpersonation: Scalars['Boolean']['output']; + billingSubscriptions?: Maybe<Array<BillingSubscription>>; + createdAt: Scalars['DateTime']['output']; + currentBillingSubscription?: Maybe<BillingSubscription>; + databaseSchema: Scalars['String']['output']; + databaseUrl: Scalars['String']['output']; + deletedAt?: Maybe<Scalars['DateTime']['output']>; + displayName?: Maybe<Scalars['String']['output']>; + domainName?: Maybe<Scalars['String']['output']>; + featureFlags?: Maybe<Array<FeatureFlag>>; + id: Scalars['UUID']['output']; + inviteHash?: Maybe<Scalars['String']['output']>; + logo?: Maybe<Scalars['String']['output']>; + metadataVersion: Scalars['Float']['output']; + updatedAt: Scalars['DateTime']['output']; + workspaceMembersCount?: Maybe<Scalars['Float']['output']>; }; export type WorkspaceBillingSubscriptionsArgs = { - filter?: BillingSubscriptionFilter; - sorting?: Array<BillingSubscriptionSort>; + filter?: BillingSubscriptionFilter; + sorting?: Array<BillingSubscriptionSort>; }; export type WorkspaceFeatureFlagsArgs = { - filter?: FeatureFlagFilter; - sorting?: Array<FeatureFlagSort>; + filter?: FeatureFlagFilter; + sorting?: Array<FeatureFlagSort>; }; export enum WorkspaceActivationStatus { - Active = 'ACTIVE', - Inactive = 'INACTIVE', - OngoingCreation = 'ONGOING_CREATION', - PendingCreation = 'PENDING_CREATION' + Active = 'ACTIVE', + Inactive = 'INACTIVE', + OngoingCreation = 'ONGOING_CREATION', + PendingCreation = 'PENDING_CREATION' } export type WorkspaceEdge = { - __typename?: 'WorkspaceEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the Workspace */ - node: Workspace; + __typename?: 'WorkspaceEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the Workspace */ + node: Workspace; }; export type WorkspaceInviteHashValid = { - __typename?: 'WorkspaceInviteHashValid'; - isValid: Scalars['Boolean']['output']; + __typename?: 'WorkspaceInviteHashValid'; + isValid: Scalars['Boolean']['output']; }; export type WorkspaceMember = { - __typename?: 'WorkspaceMember'; - avatarUrl?: Maybe<Scalars['String']['output']>; - colorScheme: Scalars['String']['output']; - dateFormat?: Maybe<WorkspaceMemberDateFormatEnum>; - id: Scalars['UUID']['output']; - locale?: Maybe<Scalars['String']['output']>; - name: FullName; - timeFormat?: Maybe<WorkspaceMemberTimeFormatEnum>; - timeZone?: Maybe<Scalars['String']['output']>; + __typename?: 'WorkspaceMember'; + avatarUrl?: Maybe<Scalars['String']['output']>; + colorScheme: Scalars['String']['output']; + dateFormat?: Maybe<WorkspaceMemberDateFormatEnum>; + id: Scalars['UUID']['output']; + locale?: Maybe<Scalars['String']['output']>; + name: FullName; + timeFormat?: Maybe<WorkspaceMemberTimeFormatEnum>; + timeZone?: Maybe<Scalars['String']['output']>; }; /** Date format as Month first, Day first, Year first or system as default */ export enum WorkspaceMemberDateFormatEnum { - DayFirst = 'DAY_FIRST', - MonthFirst = 'MONTH_FIRST', - System = 'SYSTEM', - YearFirst = 'YEAR_FIRST' + DayFirst = 'DAY_FIRST', + MonthFirst = 'MONTH_FIRST', + System = 'SYSTEM', + YearFirst = 'YEAR_FIRST' } /** Time time as Military, Standard or system as default */ export enum WorkspaceMemberTimeFormatEnum { - Hour_12 = 'HOUR_12', - Hour_24 = 'HOUR_24', - System = 'SYSTEM' + Hour_12 = 'HOUR_12', + Hour_24 = 'HOUR_24', + System = 'SYSTEM' } export type Field = { - __typename?: 'field'; - createdAt: Scalars['DateTime']['output']; - defaultValue?: Maybe<Scalars['JSON']['output']>; - description?: Maybe<Scalars['String']['output']>; - fromRelationMetadata?: Maybe<Relation>; - icon?: Maybe<Scalars['String']['output']>; - id: Scalars['UUID']['output']; - isActive?: Maybe<Scalars['Boolean']['output']>; - isCustom?: Maybe<Scalars['Boolean']['output']>; - isNullable?: Maybe<Scalars['Boolean']['output']>; - isSystem?: Maybe<Scalars['Boolean']['output']>; - label: Scalars['String']['output']; - name: Scalars['String']['output']; - options?: Maybe<Scalars['JSON']['output']>; - relationDefinition?: Maybe<RelationDefinition>; - settings?: Maybe<Scalars['JSON']['output']>; - toRelationMetadata?: Maybe<Relation>; - type: FieldMetadataType; - updatedAt: Scalars['DateTime']['output']; + __typename?: 'field'; + createdAt: Scalars['DateTime']['output']; + defaultValue?: Maybe<Scalars['JSON']['output']>; + description?: Maybe<Scalars['String']['output']>; + fromRelationMetadata?: Maybe<Relation>; + icon?: Maybe<Scalars['String']['output']>; + id: Scalars['UUID']['output']; + isActive?: Maybe<Scalars['Boolean']['output']>; + isCustom?: Maybe<Scalars['Boolean']['output']>; + isNullable?: Maybe<Scalars['Boolean']['output']>; + isSystem?: Maybe<Scalars['Boolean']['output']>; + label: Scalars['String']['output']; + name: Scalars['String']['output']; + object?: Maybe<Object>; + options?: Maybe<Scalars['JSON']['output']>; + relationDefinition?: Maybe<RelationDefinition>; + settings?: Maybe<Scalars['JSON']['output']>; + toRelationMetadata?: Maybe<Relation>; + type: FieldMetadataType; + updatedAt: Scalars['DateTime']['output']; }; export type FieldEdge = { - __typename?: 'fieldEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the field */ - node: Field; + __typename?: 'fieldEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the field */ + node: Field; }; export type FieldFilter = { - and?: InputMaybe<Array<FieldFilter>>; - id?: InputMaybe<UuidFilterComparison>; - isActive?: InputMaybe<BooleanFieldComparison>; - isCustom?: InputMaybe<BooleanFieldComparison>; - isSystem?: InputMaybe<BooleanFieldComparison>; - or?: InputMaybe<Array<FieldFilter>>; + and?: InputMaybe<Array<FieldFilter>>; + id?: InputMaybe<UuidFilterComparison>; + isActive?: InputMaybe<BooleanFieldComparison>; + isCustom?: InputMaybe<BooleanFieldComparison>; + isSystem?: InputMaybe<BooleanFieldComparison>; + or?: InputMaybe<Array<FieldFilter>>; }; export type Object = { - __typename?: 'object'; - createdAt: Scalars['DateTime']['output']; - dataSourceId: Scalars['String']['output']; - description?: Maybe<Scalars['String']['output']>; - fields: ObjectFieldsConnection; - icon?: Maybe<Scalars['String']['output']>; - id: Scalars['UUID']['output']; - imageIdentifierFieldMetadataId?: Maybe<Scalars['String']['output']>; - isActive: Scalars['Boolean']['output']; - isCustom: Scalars['Boolean']['output']; - isRemote: Scalars['Boolean']['output']; - isSystem: Scalars['Boolean']['output']; - labelIdentifierFieldMetadataId?: Maybe<Scalars['String']['output']>; - labelPlural: Scalars['String']['output']; - labelSingular: Scalars['String']['output']; - namePlural: Scalars['String']['output']; - nameSingular: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; + __typename?: 'object'; + createdAt: Scalars['DateTime']['output']; + dataSourceId: Scalars['String']['output']; + description?: Maybe<Scalars['String']['output']>; + fields: ObjectFieldsConnection; + icon?: Maybe<Scalars['String']['output']>; + id: Scalars['UUID']['output']; + imageIdentifierFieldMetadataId?: Maybe<Scalars['String']['output']>; + isActive: Scalars['Boolean']['output']; + isCustom: Scalars['Boolean']['output']; + isRemote: Scalars['Boolean']['output']; + isSystem: Scalars['Boolean']['output']; + labelIdentifierFieldMetadataId?: Maybe<Scalars['String']['output']>; + labelPlural: Scalars['String']['output']; + labelSingular: Scalars['String']['output']; + namePlural: Scalars['String']['output']; + nameSingular: Scalars['String']['output']; + updatedAt: Scalars['DateTime']['output']; }; export type ObjectFieldsArgs = { - filter?: FieldFilter; - paging?: CursorPaging; + filter?: FieldFilter; + paging?: CursorPaging; }; export type ObjectEdge = { - __typename?: 'objectEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the object */ - node: Object; + __typename?: 'objectEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the object */ + node: Object; }; export type ObjectFilter = { - and?: InputMaybe<Array<ObjectFilter>>; - id?: InputMaybe<UuidFilterComparison>; - isActive?: InputMaybe<BooleanFieldComparison>; - isCustom?: InputMaybe<BooleanFieldComparison>; - isRemote?: InputMaybe<BooleanFieldComparison>; - isSystem?: InputMaybe<BooleanFieldComparison>; - or?: InputMaybe<Array<ObjectFilter>>; + and?: InputMaybe<Array<ObjectFilter>>; + id?: InputMaybe<UuidFilterComparison>; + isActive?: InputMaybe<BooleanFieldComparison>; + isCustom?: InputMaybe<BooleanFieldComparison>; + isRemote?: InputMaybe<BooleanFieldComparison>; + isSystem?: InputMaybe<BooleanFieldComparison>; + or?: InputMaybe<Array<ObjectFilter>>; }; export type Relation = { - __typename?: 'relation'; - createdAt: Scalars['DateTime']['output']; - fromFieldMetadataId: Scalars['String']['output']; - fromObjectMetadata: Object; - fromObjectMetadataId: Scalars['String']['output']; - id: Scalars['UUID']['output']; - relationType: RelationMetadataType; - toFieldMetadataId: Scalars['String']['output']; - toObjectMetadata: Object; - toObjectMetadataId: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; + __typename?: 'relation'; + createdAt: Scalars['DateTime']['output']; + fromFieldMetadataId: Scalars['String']['output']; + fromObjectMetadata: Object; + fromObjectMetadataId: Scalars['String']['output']; + id: Scalars['UUID']['output']; + relationType: RelationMetadataType; + toFieldMetadataId: Scalars['String']['output']; + toObjectMetadata: Object; + toObjectMetadataId: Scalars['String']['output']; + updatedAt: Scalars['DateTime']['output']; }; export type RelationEdge = { - __typename?: 'relationEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']['output']; - /** The node containing the relation */ - node: Relation; + __typename?: 'relationEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']['output']; + /** The node containing the relation */ + node: Relation; }; export type RemoteServerFieldsFragment = { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, label: string, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null }; @@ -1596,189 +1598,194 @@ export type RemoteServerFieldsFragment = { __typename?: 'RemoteServer', id: stri export type RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null }; export type CreateServerMutationVariables = Exact<{ - input: CreateRemoteServerInput; + input: CreateRemoteServerInput; }>; export type CreateServerMutation = { __typename?: 'Mutation', createOneRemoteServer: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, label: string, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null } }; export type DeleteServerMutationVariables = Exact<{ - input: RemoteServerIdInput; + input: RemoteServerIdInput; }>; export type DeleteServerMutation = { __typename?: 'Mutation', deleteOneRemoteServer: { __typename?: 'RemoteServer', id: string } }; export type SyncRemoteTableMutationVariables = Exact<{ - input: RemoteTableInput; + input: RemoteTableInput; }>; export type SyncRemoteTableMutation = { __typename?: 'Mutation', syncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null } }; export type SyncRemoteTableSchemaChangesMutationVariables = Exact<{ - input: RemoteTableInput; + input: RemoteTableInput; }>; export type SyncRemoteTableSchemaChangesMutation = { __typename?: 'Mutation', syncRemoteTableSchemaChanges: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null } }; export type UnsyncRemoteTableMutationVariables = Exact<{ - input: RemoteTableInput; + input: RemoteTableInput; }>; export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null } }; export type UpdateServerMutationVariables = Exact<{ - input: UpdateRemoteServerInput; + input: UpdateRemoteServerInput; }>; export type UpdateServerMutation = { __typename?: 'Mutation', updateOneRemoteServer: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, label: string, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null } }; export type GetManyDatabaseConnectionsQueryVariables = Exact<{ - input: RemoteServerTypeInput; + input: RemoteServerTypeInput; }>; export type GetManyDatabaseConnectionsQuery = { __typename?: 'Query', findManyRemoteServersByType: Array<{ __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, label: string, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null }> }; export type GetManyRemoteTablesQueryVariables = Exact<{ - input: FindManyRemoteTablesInput; + input: FindManyRemoteTablesInput; }>; export type GetManyRemoteTablesQuery = { __typename?: 'Query', findDistantTablesWithStatus: Array<{ __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null }> }; export type GetOneDatabaseConnectionQueryVariables = Exact<{ - input: RemoteServerIdInput; + input: RemoteServerIdInput; }>; export type GetOneDatabaseConnectionQuery = { __typename?: 'Query', findOneRemoteServerById: { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, label: string, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null } }; export type CreateOneObjectMetadataItemMutationVariables = Exact<{ - input: CreateOneObjectInput; + input: CreateOneObjectInput; }>; export type CreateOneObjectMetadataItemMutation = { __typename?: 'Mutation', createOneObject: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null } }; export type CreateOneFieldMetadataItemMutationVariables = Exact<{ - input: CreateOneFieldMetadataInput; + input: CreateOneFieldMetadataInput; }>; export type CreateOneFieldMetadataItemMutation = { __typename?: 'Mutation', createOneField: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isNullable?: boolean | null, createdAt: any, updatedAt: any, defaultValue?: any | null, options?: any | null } }; export type CreateOneRelationMetadataMutationVariables = Exact<{ - input: CreateOneRelationInput; + input: CreateOneRelationInput; }>; export type CreateOneRelationMetadataMutation = { __typename?: 'Mutation', createOneRelation: { __typename?: 'relation', id: any, relationType: RelationMetadataType, fromObjectMetadataId: string, toObjectMetadataId: string, fromFieldMetadataId: string, toFieldMetadataId: string, createdAt: any, updatedAt: any } }; export type UpdateOneFieldMetadataItemMutationVariables = Exact<{ - idToUpdate: Scalars['UUID']['input']; - updatePayload: UpdateFieldInput; + idToUpdate: Scalars['UUID']['input']; + updatePayload: UpdateFieldInput; }>; export type UpdateOneFieldMetadataItemMutation = { __typename?: 'Mutation', updateOneField: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isNullable?: boolean | null, createdAt: any, updatedAt: any } }; export type UpdateOneObjectMetadataItemMutationVariables = Exact<{ - idToUpdate: Scalars['UUID']['input']; - updatePayload: UpdateObjectPayload; + idToUpdate: Scalars['UUID']['input']; + updatePayload: UpdateObjectPayload; }>; export type UpdateOneObjectMetadataItemMutation = { __typename?: 'Mutation', updateOneObject: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null } }; export type DeleteOneObjectMetadataItemMutationVariables = Exact<{ - idToDelete: Scalars['UUID']['input']; + idToDelete: Scalars['UUID']['input']; }>; export type DeleteOneObjectMetadataItemMutation = { __typename?: 'Mutation', deleteOneObject: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null } }; export type DeleteOneFieldMetadataItemMutationVariables = Exact<{ - idToDelete: Scalars['UUID']['input']; + idToDelete: Scalars['UUID']['input']; }>; export type DeleteOneFieldMetadataItemMutation = { __typename?: 'Mutation', deleteOneField: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isNullable?: boolean | null, createdAt: any, updatedAt: any } }; export type DeleteOneRelationMetadataItemMutationVariables = Exact<{ - idToDelete: Scalars['UUID']['input']; + idToDelete: Scalars['UUID']['input']; }>; export type DeleteOneRelationMetadataItemMutation = { __typename?: 'Mutation', deleteOneRelation: { __typename?: 'relation', id: any } }; export type ObjectMetadataItemsQueryVariables = Exact<{ - objectFilter?: InputMaybe<ObjectFilter>; - fieldFilter?: InputMaybe<FieldFilter>; + objectFilter?: InputMaybe<ObjectFilter>; + fieldFilter?: InputMaybe<FieldFilter>; }>; -export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, fields: { __typename?: 'ObjectFieldsConnection', edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isNullable?: boolean | null, createdAt: any, updatedAt: any, defaultValue?: any | null, options?: any | null, fromRelationMetadata?: { __typename?: 'relation', id: any, relationType: RelationMetadataType, toFieldMetadataId: string, toObjectMetadata: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, isSystem: boolean, isRemote: boolean } } | null, toRelationMetadata?: { __typename?: 'relation', id: any, relationType: RelationMetadataType, fromFieldMetadataId: string, fromObjectMetadata: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, isSystem: boolean, isRemote: boolean } } | null, relationDefinition?: { __typename?: 'RelationDefinition', relationId: any, direction: RelationDefinitionType, sourceObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'field', id: any, name: string }, targetObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, targetFieldMetadata: { __typename?: 'field', id: any, name: string } } | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } }; +export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, fields: { __typename?: 'ObjectFieldsConnection', edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isNullable?: boolean | null, createdAt: any, updatedAt: any, defaultValue?: any | null, options?: any | null, relationDefinition?: { __typename?: 'RelationDefinition', relationId: any, direction: RelationDefinitionType, sourceObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'field', id: any, name: string }, targetObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, targetFieldMetadata: { __typename?: 'field', id: any, name: string } } | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } }; export type ServerlessFunctionFieldsFragment = { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any }; export type CreateOneServerlessFunctionItemMutationVariables = Exact<{ - input: CreateServerlessFunctionInput; + input: CreateServerlessFunctionInput; }>; export type CreateOneServerlessFunctionItemMutation = { __typename?: 'Mutation', createOneServerlessFunction: { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any } }; export type DeleteOneServerlessFunctionMutationVariables = Exact<{ - input: DeleteServerlessFunctionInput; + input: DeleteServerlessFunctionInput; }>; export type DeleteOneServerlessFunctionMutation = { __typename?: 'Mutation', deleteOneServerlessFunction: { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any } }; export type ExecuteOneServerlessFunctionMutationVariables = Exact<{ - input: ExecuteServerlessFunctionInput; + input: ExecuteServerlessFunctionInput; }>; export type ExecuteOneServerlessFunctionMutation = { __typename?: 'Mutation', executeOneServerlessFunction: { __typename?: 'ServerlessFunctionExecutionResult', data?: any | null, duration: number, status: ServerlessFunctionExecutionStatus, error?: any | null } }; export type PublishOneServerlessFunctionMutationVariables = Exact<{ - input: PublishServerlessFunctionInput; + input: PublishServerlessFunctionInput; }>; export type PublishOneServerlessFunctionMutation = { __typename?: 'Mutation', publishServerlessFunction: { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any } }; export type UpdateOneServerlessFunctionMutationVariables = Exact<{ - input: UpdateServerlessFunctionInput; + input: UpdateServerlessFunctionInput; }>; export type UpdateOneServerlessFunctionMutation = { __typename?: 'Mutation', updateOneServerlessFunction: { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any } }; +export type FindManyAvailablePackagesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type FindManyAvailablePackagesQuery = { __typename?: 'Query', getAvailablePackages: any }; + export type GetManyServerlessFunctionsQueryVariables = Exact<{ [key: string]: never; }>; export type GetManyServerlessFunctionsQuery = { __typename?: 'Query', serverlessFunctions: { __typename?: 'ServerlessFunctionConnection', edges: Array<{ __typename?: 'ServerlessFunctionEdge', node: { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any } }> } }; export type GetOneServerlessFunctionQueryVariables = Exact<{ - id: Scalars['UUID']['input']; + id: Scalars['UUID']['input']; }>; export type GetOneServerlessFunctionQuery = { __typename?: 'Query', serverlessFunction: { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, sourceCodeHash: string, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, createdAt: any, updatedAt: any } }; export type FindOneServerlessFunctionSourceCodeQueryVariables = Exact<{ - input: GetServerlessFunctionSourceCodeInput; + input: GetServerlessFunctionSourceCodeInput; }>; -export type FindOneServerlessFunctionSourceCodeQuery = { __typename?: 'Query', getServerlessFunctionSourceCode: string }; +export type FindOneServerlessFunctionSourceCodeQuery = { __typename?: 'Query', getServerlessFunctionSourceCode?: string | null }; export const RemoteServerFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteServerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"userMappingOptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}},{"kind":"Field","name":{"kind":"Name","value":"label"}}]}}]} as unknown as DocumentNode<RemoteServerFieldsFragment, unknown>; export const RemoteTableFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteTableFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteTable"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"schema"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"schemaPendingUpdates"}}]}}]} as unknown as DocumentNode<RemoteTableFieldsFragment, unknown>; @@ -1800,12 +1807,13 @@ export const UpdateOneObjectMetadataItemDocument = {"kind":"Document","definitio export const DeleteOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}}]}}]}}]} as unknown as DocumentNode<DeleteOneObjectMetadataItemMutation, DeleteOneObjectMetadataItemMutationVariables>; export const DeleteOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<DeleteOneFieldMetadataItemMutation, DeleteOneFieldMetadataItemMutationVariables>; export const DeleteOneRelationMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneRelationMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneRelation"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<DeleteOneRelationMetadataItemMutation, DeleteOneRelationMetadataItemMutationVariables>; -export const ObjectMetadataItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ObjectMetadataItems"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"objectFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"fromRelationMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"relationType"}},{"kind":"Field","name":{"kind":"Name","value":"toObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}}]}},{"kind":"Field","name":{"kind":"Name","value":"toFieldMetadataId"}}]}},{"kind":"Field","name":{"kind":"Name","value":"toRelationMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"relationType"}},{"kind":"Field","name":{"kind":"Name","value":"fromObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}}]}},{"kind":"Field","name":{"kind":"Name","value":"fromFieldMetadataId"}}]}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"relationDefinition"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"relationId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode<ObjectMetadataItemsQuery, ObjectMetadataItemsQueryVariables>; +export const ObjectMetadataItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ObjectMetadataItems"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"objectFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"relationDefinition"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"relationId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode<ObjectMetadataItemsQuery, ObjectMetadataItemsQueryVariables>; export const CreateOneServerlessFunctionItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneServerlessFunctionItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"sourceCodeHash"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<CreateOneServerlessFunctionItemMutation, CreateOneServerlessFunctionItemMutationVariables>; export const DeleteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"sourceCodeHash"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<DeleteOneServerlessFunctionMutation, DeleteOneServerlessFunctionMutationVariables>; export const ExecuteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ExecuteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ExecuteServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"executeOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode<ExecuteOneServerlessFunctionMutation, ExecuteOneServerlessFunctionMutationVariables>; export const PublishOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"PublishOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PublishServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"publishServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"sourceCodeHash"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<PublishOneServerlessFunctionMutation, PublishOneServerlessFunctionMutationVariables>; export const UpdateOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"sourceCodeHash"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<UpdateOneServerlessFunctionMutation, UpdateOneServerlessFunctionMutationVariables>; +export const FindManyAvailablePackagesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManyAvailablePackages"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAvailablePackages"}}]}}]} as unknown as DocumentNode<FindManyAvailablePackagesQuery, FindManyAvailablePackagesQueryVariables>; export const GetManyServerlessFunctionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetManyServerlessFunctions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverlessFunctions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"sourceCodeHash"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<GetManyServerlessFunctionsQuery, GetManyServerlessFunctionsQueryVariables>; export const GetOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"sourceCodeHash"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<GetOneServerlessFunctionQuery, GetOneServerlessFunctionQueryVariables>; export const FindOneServerlessFunctionSourceCodeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindOneServerlessFunctionSourceCode"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"GetServerlessFunctionSourceCodeInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getServerlessFunctionSourceCode"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<FindOneServerlessFunctionSourceCodeQuery, FindOneServerlessFunctionSourceCodeQueryVariables>; \ No newline at end of file diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 4fd5f53ec6ae..0fe1775f6b9e 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -1,5 +1,5 @@ -import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; +import { gql } from '@apollo/client'; export type Maybe<T> = T | null; export type InputMaybe<T> = Maybe<T>; export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] }; @@ -8,1271 +8,1296 @@ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Mayb const defaultOptions = {} as const; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; - ConnectionCursor: any; - DateTime: string; - JSON: any; - JSONObject: any; - UUID: any; - Upload: any; + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + ConnectionCursor: any; + DateTime: string; + JSON: any; + JSONObject: any; + UUID: any; + Upload: any; }; export type AisqlQueryResult = { - __typename?: 'AISQLQueryResult'; - queryFailedErrorMessage?: Maybe<Scalars['String']>; - sqlQuery: Scalars['String']; - sqlQueryResult?: Maybe<Scalars['String']>; + __typename?: 'AISQLQueryResult'; + queryFailedErrorMessage?: Maybe<Scalars['String']>; + sqlQuery: Scalars['String']; + sqlQueryResult?: Maybe<Scalars['String']>; }; export type ActivateWorkspaceInput = { - displayName?: InputMaybe<Scalars['String']>; + displayName?: InputMaybe<Scalars['String']>; }; export type Analytics = { - __typename?: 'Analytics'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']; + __typename?: 'Analytics'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']; }; export type ApiConfig = { - __typename?: 'ApiConfig'; - mutationMaximumAffectedRecords: Scalars['Float']; + __typename?: 'ApiConfig'; + mutationMaximumAffectedRecords: Scalars['Float']; }; export type ApiKeyToken = { - __typename?: 'ApiKeyToken'; - token: Scalars['String']; + __typename?: 'ApiKeyToken'; + token: Scalars['String']; }; export type AppToken = { - __typename?: 'AppToken'; - createdAt: Scalars['DateTime']; - expiresAt: Scalars['DateTime']; - id: Scalars['UUID']; - type: Scalars['String']; - updatedAt: Scalars['DateTime']; + __typename?: 'AppToken'; + createdAt: Scalars['DateTime']; + expiresAt: Scalars['DateTime']; + id: Scalars['UUID']; + type: Scalars['String']; + updatedAt: Scalars['DateTime']; }; export type AppTokenEdge = { - __typename?: 'AppTokenEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the AppToken */ - node: AppToken; + __typename?: 'AppTokenEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the AppToken */ + node: AppToken; }; export type AuthProviders = { - __typename?: 'AuthProviders'; - google: Scalars['Boolean']; - magicLink: Scalars['Boolean']; - microsoft: Scalars['Boolean']; - password: Scalars['Boolean']; + __typename?: 'AuthProviders'; + google: Scalars['Boolean']; + magicLink: Scalars['Boolean']; + microsoft: Scalars['Boolean']; + password: Scalars['Boolean']; }; export type AuthToken = { - __typename?: 'AuthToken'; - expiresAt: Scalars['DateTime']; - token: Scalars['String']; + __typename?: 'AuthToken'; + expiresAt: Scalars['DateTime']; + token: Scalars['String']; }; export type AuthTokenPair = { - __typename?: 'AuthTokenPair'; - accessToken: AuthToken; - refreshToken: AuthToken; + __typename?: 'AuthTokenPair'; + accessToken: AuthToken; + refreshToken: AuthToken; }; export type AuthTokens = { - __typename?: 'AuthTokens'; - tokens: AuthTokenPair; + __typename?: 'AuthTokens'; + tokens: AuthTokenPair; }; export type AuthorizeApp = { - __typename?: 'AuthorizeApp'; - redirectUrl: Scalars['String']; + __typename?: 'AuthorizeApp'; + redirectUrl: Scalars['String']; }; export type Billing = { - __typename?: 'Billing'; - billingFreeTrialDurationInDays?: Maybe<Scalars['Float']>; - billingUrl?: Maybe<Scalars['String']>; - isBillingEnabled: Scalars['Boolean']; + __typename?: 'Billing'; + billingFreeTrialDurationInDays?: Maybe<Scalars['Float']>; + billingUrl?: Maybe<Scalars['String']>; + isBillingEnabled: Scalars['Boolean']; }; export type BillingSubscription = { - __typename?: 'BillingSubscription'; - id: Scalars['UUID']; - interval?: Maybe<SubscriptionInterval>; - status: SubscriptionStatus; + __typename?: 'BillingSubscription'; + id: Scalars['UUID']; + interval?: Maybe<SubscriptionInterval>; + status: SubscriptionStatus; }; export type BillingSubscriptionFilter = { - and?: InputMaybe<Array<BillingSubscriptionFilter>>; - id?: InputMaybe<UuidFilterComparison>; - or?: InputMaybe<Array<BillingSubscriptionFilter>>; + and?: InputMaybe<Array<BillingSubscriptionFilter>>; + id?: InputMaybe<UuidFilterComparison>; + or?: InputMaybe<Array<BillingSubscriptionFilter>>; }; export type BillingSubscriptionSort = { - direction: SortDirection; - field: BillingSubscriptionSortFields; - nulls?: InputMaybe<SortNulls>; + direction: SortDirection; + field: BillingSubscriptionSortFields; + nulls?: InputMaybe<SortNulls>; }; export enum BillingSubscriptionSortFields { - Id = 'id' + Id = 'id' } export type BooleanFieldComparison = { - is?: InputMaybe<Scalars['Boolean']>; - isNot?: InputMaybe<Scalars['Boolean']>; + is?: InputMaybe<Scalars['Boolean']>; + isNot?: InputMaybe<Scalars['Boolean']>; }; -/** Visibility of the calendar channel */ export enum CalendarChannelVisibility { - Metadata = 'METADATA', - ShareEverything = 'SHARE_EVERYTHING' + Metadata = 'METADATA', + ShareEverything = 'SHARE_EVERYTHING' } export type Captcha = { - __typename?: 'Captcha'; - provider?: Maybe<CaptchaDriverType>; - siteKey?: Maybe<Scalars['String']>; + __typename?: 'Captcha'; + provider?: Maybe<CaptchaDriverType>; + siteKey?: Maybe<Scalars['String']>; }; export enum CaptchaDriverType { - GoogleRecaptcha = 'GoogleRecaptcha', - Turnstile = 'Turnstile' + GoogleRecaptcha = 'GoogleRecaptcha', + Turnstile = 'Turnstile' } export type ClientConfig = { - __typename?: 'ClientConfig'; - api: ApiConfig; - authProviders: AuthProviders; - billing: Billing; - captcha: Captcha; - chromeExtensionId?: Maybe<Scalars['String']>; - debugMode: Scalars['Boolean']; - sentry: Sentry; - signInPrefilled: Scalars['Boolean']; - signUpDisabled: Scalars['Boolean']; - support: Support; - telemetry: Telemetry; + __typename?: 'ClientConfig'; + api: ApiConfig; + authProviders: AuthProviders; + billing: Billing; + captcha: Captcha; + chromeExtensionId?: Maybe<Scalars['String']>; + debugMode: Scalars['Boolean']; + sentry: Sentry; + signInPrefilled: Scalars['Boolean']; + signUpDisabled: Scalars['Boolean']; + support: Support; }; export type CreateServerlessFunctionFromFileInput = { - description?: InputMaybe<Scalars['String']>; - name: Scalars['String']; + description?: InputMaybe<Scalars['String']>; + name: Scalars['String']; }; export type CreateServerlessFunctionInput = { - code: Scalars['String']; - description?: InputMaybe<Scalars['String']>; - name: Scalars['String']; + code: Scalars['String']; + description?: InputMaybe<Scalars['String']>; + name: Scalars['String']; }; export type CursorPaging = { - /** Paginate after opaque cursor */ - after?: InputMaybe<Scalars['ConnectionCursor']>; - /** Paginate before opaque cursor */ - before?: InputMaybe<Scalars['ConnectionCursor']>; - /** Paginate first */ - first?: InputMaybe<Scalars['Int']>; - /** Paginate last */ - last?: InputMaybe<Scalars['Int']>; + /** Paginate after opaque cursor */ + after?: InputMaybe<Scalars['ConnectionCursor']>; + /** Paginate before opaque cursor */ + before?: InputMaybe<Scalars['ConnectionCursor']>; + /** Paginate first */ + first?: InputMaybe<Scalars['Int']>; + /** Paginate last */ + last?: InputMaybe<Scalars['Int']>; }; export type DeleteOneObjectInput = { - /** The id of the record to delete. */ - id: Scalars['UUID']; + /** The id of the record to delete. */ + id: Scalars['UUID']; }; export type DeleteServerlessFunctionInput = { - /** The id of the function. */ - id: Scalars['ID']; + /** The id of the function. */ + id: Scalars['ID']; }; /** Schema update on a table */ export enum DistantTableUpdate { - ColumnsAdded = 'COLUMNS_ADDED', - ColumnsDeleted = 'COLUMNS_DELETED', - ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED', - TableDeleted = 'TABLE_DELETED' + ColumnsAdded = 'COLUMNS_ADDED', + ColumnsDeleted = 'COLUMNS_DELETED', + ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED', + TableDeleted = 'TABLE_DELETED' } export type EmailPasswordResetLink = { - __typename?: 'EmailPasswordResetLink'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']; + __typename?: 'EmailPasswordResetLink'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']; }; export type ExchangeAuthCode = { - __typename?: 'ExchangeAuthCode'; - accessToken: AuthToken; - loginToken: AuthToken; - refreshToken: AuthToken; + __typename?: 'ExchangeAuthCode'; + accessToken: AuthToken; + loginToken: AuthToken; + refreshToken: AuthToken; }; export type ExecuteServerlessFunctionInput = { - /** Id of the serverless function to execute */ - id: Scalars['UUID']; - /** Payload in JSON format */ - payload?: InputMaybe<Scalars['JSON']>; - /** Version of the serverless function to execute */ - version?: Scalars['String']; + /** Id of the serverless function to execute */ + id: Scalars['UUID']; + /** Payload in JSON format */ + payload: Scalars['JSON']; + /** Version of the serverless function to execute */ + version?: Scalars['String']; }; export type FeatureFlag = { - __typename?: 'FeatureFlag'; - id: Scalars['UUID']; - key: Scalars['String']; - value: Scalars['Boolean']; - workspaceId: Scalars['String']; + __typename?: 'FeatureFlag'; + id: Scalars['UUID']; + key: Scalars['String']; + value: Scalars['Boolean']; + workspaceId: Scalars['String']; }; export type FeatureFlagFilter = { - and?: InputMaybe<Array<FeatureFlagFilter>>; - id?: InputMaybe<UuidFilterComparison>; - or?: InputMaybe<Array<FeatureFlagFilter>>; + and?: InputMaybe<Array<FeatureFlagFilter>>; + id?: InputMaybe<UuidFilterComparison>; + or?: InputMaybe<Array<FeatureFlagFilter>>; }; export type FeatureFlagSort = { - direction: SortDirection; - field: FeatureFlagSortFields; - nulls?: InputMaybe<SortNulls>; + direction: SortDirection; + field: FeatureFlagSortFields; + nulls?: InputMaybe<SortNulls>; }; export enum FeatureFlagSortFields { - Id = 'id' + Id = 'id' } export type FieldConnection = { - __typename?: 'FieldConnection'; - /** Array of edges. */ - edges: Array<FieldEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'FieldConnection'; + /** Array of edges. */ + edges: Array<FieldEdge>; + /** Paging information */ + pageInfo: PageInfo; }; /** Type of the field */ export enum FieldMetadataType { - Actor = 'ACTOR', - Address = 'ADDRESS', - Boolean = 'BOOLEAN', - Currency = 'CURRENCY', - Date = 'DATE', - DateTime = 'DATE_TIME', - Email = 'EMAIL', - Emails = 'EMAILS', - FullName = 'FULL_NAME', - Link = 'LINK', - Links = 'LINKS', - MultiSelect = 'MULTI_SELECT', - Number = 'NUMBER', - Numeric = 'NUMERIC', - Phone = 'PHONE', - Position = 'POSITION', - Rating = 'RATING', - RawJson = 'RAW_JSON', - Relation = 'RELATION', - RichText = 'RICH_TEXT', - Select = 'SELECT', - Text = 'TEXT', - Uuid = 'UUID' + Actor = 'ACTOR', + Address = 'ADDRESS', + Array = 'ARRAY', + Boolean = 'BOOLEAN', + Currency = 'CURRENCY', + Date = 'DATE', + DateTime = 'DATE_TIME', + Email = 'EMAIL', + Emails = 'EMAILS', + FullName = 'FULL_NAME', + Link = 'LINK', + Links = 'LINKS', + MultiSelect = 'MULTI_SELECT', + Number = 'NUMBER', + Numeric = 'NUMERIC', + Phone = 'PHONE', + Phones = 'PHONES', + Position = 'POSITION', + Rating = 'RATING', + RawJson = 'RAW_JSON', + Relation = 'RELATION', + RichText = 'RICH_TEXT', + Select = 'SELECT', + Text = 'TEXT', + Uuid = 'UUID' } export enum FileFolder { - Attachment = 'Attachment', - PersonPicture = 'PersonPicture', - ProfilePicture = 'ProfilePicture', - ServerlessFunction = 'ServerlessFunction', - WorkspaceLogo = 'WorkspaceLogo' + Attachment = 'Attachment', + PersonPicture = 'PersonPicture', + ProfilePicture = 'ProfilePicture', + ServerlessFunction = 'ServerlessFunction', + WorkspaceLogo = 'WorkspaceLogo' } export type FullName = { - __typename?: 'FullName'; - firstName: Scalars['String']; - lastName: Scalars['String']; + __typename?: 'FullName'; + firstName: Scalars['String']; + lastName: Scalars['String']; }; export type GetServerlessFunctionSourceCodeInput = { - /** The id of the function. */ - id: Scalars['ID']; - /** The version of the function */ - version?: Scalars['String']; + /** The id of the function. */ + id: Scalars['ID']; + /** The version of the function */ + version?: Scalars['String']; }; export type InvalidatePassword = { - __typename?: 'InvalidatePassword'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']; + __typename?: 'InvalidatePassword'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']; }; export type LinkMetadata = { - __typename?: 'LinkMetadata'; - label: Scalars['String']; - url: Scalars['String']; + __typename?: 'LinkMetadata'; + label: Scalars['String']; + url: Scalars['String']; }; export type LinksMetadata = { - __typename?: 'LinksMetadata'; - primaryLinkLabel: Scalars['String']; - primaryLinkUrl: Scalars['String']; - secondaryLinks?: Maybe<Array<LinkMetadata>>; + __typename?: 'LinksMetadata'; + primaryLinkLabel: Scalars['String']; + primaryLinkUrl: Scalars['String']; + secondaryLinks?: Maybe<Array<LinkMetadata>>; }; export type LoginToken = { - __typename?: 'LoginToken'; - loginToken: AuthToken; + __typename?: 'LoginToken'; + loginToken: AuthToken; }; -/** Visibility of the message channel */ export enum MessageChannelVisibility { - Metadata = 'METADATA', - ShareEverything = 'SHARE_EVERYTHING', - Subject = 'SUBJECT' + Metadata = 'METADATA', + ShareEverything = 'SHARE_EVERYTHING', + Subject = 'SUBJECT' } export type Mutation = { - __typename?: 'Mutation'; - activateWorkspace: Workspace; - addUserToWorkspace: User; - authorizeApp: AuthorizeApp; - challenge: LoginToken; - checkoutSession: SessionEntity; - createOneAppToken: AppToken; - createOneObject: Object; - createOneServerlessFunction: ServerlessFunction; - createOneServerlessFunctionFromFile: ServerlessFunction; - deleteCurrentWorkspace: Workspace; - deleteOneObject: Object; - deleteOneServerlessFunction: ServerlessFunction; - deleteUser: User; - disablePostgresProxy: PostgresCredentials; - disableWorkflowTrigger: Scalars['Boolean']; - emailPasswordResetLink: EmailPasswordResetLink; - enablePostgresProxy: PostgresCredentials; - enableWorkflowTrigger: Scalars['Boolean']; - exchangeAuthorizationCode: ExchangeAuthCode; - executeOneServerlessFunction: ServerlessFunctionExecutionResult; - generateApiKeyToken: ApiKeyToken; - generateJWT: AuthTokens; - generateTransientToken: TransientToken; - impersonate: Verify; - publishServerlessFunction: ServerlessFunction; - renewToken: AuthTokens; - runWorkflowVersion: WorkflowRun; - sendInviteLink: SendInviteLink; - signUp: LoginToken; - skipSyncEmailOnboardingStep: OnboardingStepSuccess; - track: Analytics; - updateBillingSubscription: UpdateBillingEntity; - updateOneObject: Object; - updateOneServerlessFunction: ServerlessFunction; - updatePasswordViaResetToken: InvalidatePassword; - updateWorkspace: Workspace; - uploadFile: Scalars['String']; - uploadImage: Scalars['String']; - uploadProfilePicture: Scalars['String']; - uploadWorkspaceLogo: Scalars['String']; - verify: Verify; + __typename?: 'Mutation'; + activateWorkflowVersion: Scalars['Boolean']; + activateWorkspace: Workspace; + addUserToWorkspace: User; + addUserToWorkspaceByInviteToken: User; + authorizeApp: AuthorizeApp; + challenge: LoginToken; + checkoutSession: SessionEntity; + createOneAppToken: AppToken; + createOneObject: Object; + createOneServerlessFunction: ServerlessFunction; + createOneServerlessFunctionFromFile: ServerlessFunction; + deactivateWorkflowVersion: Scalars['Boolean']; + deleteCurrentWorkspace: Workspace; + deleteOneObject: Object; + deleteOneServerlessFunction: ServerlessFunction; + deleteUser: User; + deleteWorkspaceInvitation: Scalars['String']; + disablePostgresProxy: PostgresCredentials; + emailPasswordResetLink: EmailPasswordResetLink; + enablePostgresProxy: PostgresCredentials; + exchangeAuthorizationCode: ExchangeAuthCode; + executeOneServerlessFunction: ServerlessFunctionExecutionResult; + generateApiKeyToken: ApiKeyToken; + generateJWT: AuthTokens; + generateTransientToken: TransientToken; + impersonate: Verify; + publishServerlessFunction: ServerlessFunction; + renewToken: AuthTokens; + resendWorkspaceInvitation: SendInvitationsOutput; + runWorkflowVersion: WorkflowRun; + sendInvitations: SendInvitationsOutput; + signUp: LoginToken; + skipSyncEmailOnboardingStep: OnboardingStepSuccess; + track: Analytics; + updateBillingSubscription: UpdateBillingEntity; + updateOneObject: Object; + updateOneServerlessFunction: ServerlessFunction; + updatePasswordViaResetToken: InvalidatePassword; + updateWorkspace: Workspace; + uploadFile: Scalars['String']; + uploadImage: Scalars['String']; + uploadProfilePicture: Scalars['String']; + uploadWorkspaceLogo: Scalars['String']; + verify: Verify; +}; + + +export type MutationActivateWorkflowVersionArgs = { + workflowVersionId: Scalars['String']; }; export type MutationActivateWorkspaceArgs = { - data: ActivateWorkspaceInput; + data: ActivateWorkspaceInput; }; export type MutationAddUserToWorkspaceArgs = { - inviteHash: Scalars['String']; + inviteHash: Scalars['String']; +}; + + +export type MutationAddUserToWorkspaceByInviteTokenArgs = { + inviteToken: Scalars['String']; }; export type MutationAuthorizeAppArgs = { - clientId: Scalars['String']; - codeChallenge?: InputMaybe<Scalars['String']>; - redirectUrl: Scalars['String']; + clientId: Scalars['String']; + codeChallenge?: InputMaybe<Scalars['String']>; + redirectUrl: Scalars['String']; }; export type MutationChallengeArgs = { - captchaToken?: InputMaybe<Scalars['String']>; - email: Scalars['String']; - password: Scalars['String']; + captchaToken?: InputMaybe<Scalars['String']>; + email: Scalars['String']; + password: Scalars['String']; }; export type MutationCheckoutSessionArgs = { - recurringInterval: SubscriptionInterval; - successUrlPath?: InputMaybe<Scalars['String']>; + recurringInterval: SubscriptionInterval; + successUrlPath?: InputMaybe<Scalars['String']>; }; export type MutationCreateOneServerlessFunctionArgs = { - input: CreateServerlessFunctionInput; + input: CreateServerlessFunctionInput; }; export type MutationCreateOneServerlessFunctionFromFileArgs = { - file: Scalars['Upload']; - input: CreateServerlessFunctionFromFileInput; + file: Scalars['Upload']; + input: CreateServerlessFunctionFromFileInput; }; -export type MutationDeleteOneObjectArgs = { - input: DeleteOneObjectInput; +export type MutationDeactivateWorkflowVersionArgs = { + workflowVersionId: Scalars['String']; }; -export type MutationDeleteOneServerlessFunctionArgs = { - input: DeleteServerlessFunctionInput; +export type MutationDeleteOneObjectArgs = { + input: DeleteOneObjectInput; }; -export type MutationDisableWorkflowTriggerArgs = { - workflowVersionId: Scalars['String']; +export type MutationDeleteOneServerlessFunctionArgs = { + input: DeleteServerlessFunctionInput; }; -export type MutationEmailPasswordResetLinkArgs = { - email: Scalars['String']; +export type MutationDeleteWorkspaceInvitationArgs = { + appTokenId: Scalars['String']; }; -export type MutationEnableWorkflowTriggerArgs = { - workflowVersionId: Scalars['String']; +export type MutationEmailPasswordResetLinkArgs = { + email: Scalars['String']; }; export type MutationExchangeAuthorizationCodeArgs = { - authorizationCode: Scalars['String']; - clientSecret?: InputMaybe<Scalars['String']>; - codeVerifier?: InputMaybe<Scalars['String']>; + authorizationCode: Scalars['String']; + clientSecret?: InputMaybe<Scalars['String']>; + codeVerifier?: InputMaybe<Scalars['String']>; }; export type MutationExecuteOneServerlessFunctionArgs = { - input: ExecuteServerlessFunctionInput; + input: ExecuteServerlessFunctionInput; }; export type MutationGenerateApiKeyTokenArgs = { - apiKeyId: Scalars['String']; - expiresAt: Scalars['String']; + apiKeyId: Scalars['String']; + expiresAt: Scalars['String']; }; export type MutationGenerateJwtArgs = { - workspaceId: Scalars['String']; + workspaceId: Scalars['String']; }; export type MutationImpersonateArgs = { - userId: Scalars['String']; + userId: Scalars['String']; }; export type MutationPublishServerlessFunctionArgs = { - input: PublishServerlessFunctionInput; + input: PublishServerlessFunctionInput; }; export type MutationRenewTokenArgs = { - appToken: Scalars['String']; + appToken: Scalars['String']; +}; + + +export type MutationResendWorkspaceInvitationArgs = { + appTokenId: Scalars['String']; }; export type MutationRunWorkflowVersionArgs = { - input: RunWorkflowVersionInput; + input: RunWorkflowVersionInput; }; -export type MutationSendInviteLinkArgs = { - emails: Array<Scalars['String']>; +export type MutationSendInvitationsArgs = { + emails: Array<Scalars['String']>; }; export type MutationSignUpArgs = { - captchaToken?: InputMaybe<Scalars['String']>; - email: Scalars['String']; - password: Scalars['String']; - workspaceInviteHash?: InputMaybe<Scalars['String']>; + captchaToken?: InputMaybe<Scalars['String']>; + email: Scalars['String']; + password: Scalars['String']; + workspaceInviteHash?: InputMaybe<Scalars['String']>; + workspacePersonalInviteToken?: InputMaybe<Scalars['String']>; }; export type MutationTrackArgs = { - data: Scalars['JSON']; - type: Scalars['String']; + data: Scalars['JSON']; + sessionId: Scalars['String']; + type: Scalars['String']; }; export type MutationUpdateOneObjectArgs = { - input: UpdateOneObjectInput; + input: UpdateOneObjectInput; }; export type MutationUpdateOneServerlessFunctionArgs = { - input: UpdateServerlessFunctionInput; + input: UpdateServerlessFunctionInput; }; export type MutationUpdatePasswordViaResetTokenArgs = { - newPassword: Scalars['String']; - passwordResetToken: Scalars['String']; + newPassword: Scalars['String']; + passwordResetToken: Scalars['String']; }; export type MutationUpdateWorkspaceArgs = { - data: UpdateWorkspaceInput; + data: UpdateWorkspaceInput; }; export type MutationUploadFileArgs = { - file: Scalars['Upload']; - fileFolder?: InputMaybe<FileFolder>; + file: Scalars['Upload']; + fileFolder?: InputMaybe<FileFolder>; }; export type MutationUploadImageArgs = { - file: Scalars['Upload']; - fileFolder?: InputMaybe<FileFolder>; + file: Scalars['Upload']; + fileFolder?: InputMaybe<FileFolder>; }; export type MutationUploadProfilePictureArgs = { - file: Scalars['Upload']; + file: Scalars['Upload']; }; export type MutationUploadWorkspaceLogoArgs = { - file: Scalars['Upload']; + file: Scalars['Upload']; }; export type MutationVerifyArgs = { - loginToken: Scalars['String']; + loginToken: Scalars['String']; }; export type ObjectConnection = { - __typename?: 'ObjectConnection'; - /** Array of edges. */ - edges: Array<ObjectEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'ObjectConnection'; + /** Array of edges. */ + edges: Array<ObjectEdge>; + /** Paging information */ + pageInfo: PageInfo; }; export type ObjectFieldsConnection = { - __typename?: 'ObjectFieldsConnection'; - /** Array of edges. */ - edges: Array<FieldEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'ObjectFieldsConnection'; + /** Array of edges. */ + edges: Array<FieldEdge>; + /** Paging information */ + pageInfo: PageInfo; }; /** Onboarding status */ export enum OnboardingStatus { - Completed = 'COMPLETED', - InviteTeam = 'INVITE_TEAM', - PlanRequired = 'PLAN_REQUIRED', - ProfileCreation = 'PROFILE_CREATION', - SyncEmail = 'SYNC_EMAIL', - WorkspaceActivation = 'WORKSPACE_ACTIVATION' + Completed = 'COMPLETED', + InviteTeam = 'INVITE_TEAM', + PlanRequired = 'PLAN_REQUIRED', + ProfileCreation = 'PROFILE_CREATION', + SyncEmail = 'SYNC_EMAIL', + WorkspaceActivation = 'WORKSPACE_ACTIVATION' } export type OnboardingStepSuccess = { - __typename?: 'OnboardingStepSuccess'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']; + __typename?: 'OnboardingStepSuccess'; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']; }; export type PageInfo = { - __typename?: 'PageInfo'; - /** The cursor of the last returned record. */ - endCursor?: Maybe<Scalars['ConnectionCursor']>; - /** true if paging forward and there are more records. */ - hasNextPage?: Maybe<Scalars['Boolean']>; - /** true if paging backwards and there are more records. */ - hasPreviousPage?: Maybe<Scalars['Boolean']>; - /** The cursor of the first returned record. */ - startCursor?: Maybe<Scalars['ConnectionCursor']>; + __typename?: 'PageInfo'; + /** The cursor of the last returned record. */ + endCursor?: Maybe<Scalars['ConnectionCursor']>; + /** true if paging forward and there are more records. */ + hasNextPage?: Maybe<Scalars['Boolean']>; + /** true if paging backwards and there are more records. */ + hasPreviousPage?: Maybe<Scalars['Boolean']>; + /** The cursor of the first returned record. */ + startCursor?: Maybe<Scalars['ConnectionCursor']>; }; export type PostgresCredentials = { - __typename?: 'PostgresCredentials'; - id: Scalars['UUID']; - password: Scalars['String']; - user: Scalars['String']; - workspaceId: Scalars['String']; + __typename?: 'PostgresCredentials'; + id: Scalars['UUID']; + password: Scalars['String']; + user: Scalars['String']; + workspaceId: Scalars['String']; }; export type ProductPriceEntity = { - __typename?: 'ProductPriceEntity'; - created: Scalars['Float']; - recurringInterval: SubscriptionInterval; - stripePriceId: Scalars['String']; - unitAmount: Scalars['Float']; + __typename?: 'ProductPriceEntity'; + created: Scalars['Float']; + recurringInterval: SubscriptionInterval; + stripePriceId: Scalars['String']; + unitAmount: Scalars['Float']; }; export type ProductPricesEntity = { - __typename?: 'ProductPricesEntity'; - productPrices: Array<ProductPriceEntity>; - totalNumberOfPrices: Scalars['Int']; + __typename?: 'ProductPricesEntity'; + productPrices: Array<ProductPriceEntity>; + totalNumberOfPrices: Scalars['Int']; }; export type PublishServerlessFunctionInput = { - /** The id of the function. */ - id: Scalars['ID']; + /** The id of the function. */ + id: Scalars['ID']; }; export type Query = { - __typename?: 'Query'; - billingPortalSession: SessionEntity; - checkUserExists: UserExists; - checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; - clientConfig: ClientConfig; - currentUser: User; - currentWorkspace: Workspace; - findWorkspaceFromInviteHash: Workspace; - getAISQLQuery: AisqlQueryResult; - getPostgresCredentials?: Maybe<PostgresCredentials>; - getProductPrices: ProductPricesEntity; - getServerlessFunctionSourceCode: Scalars['String']; - getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; - getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; - getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal; - getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; - object: Object; - objects: ObjectConnection; - serverlessFunction: ServerlessFunction; - serverlessFunctions: ServerlessFunctionConnection; - validatePasswordResetToken: ValidatePasswordResetToken; + __typename?: 'Query'; + billingPortalSession: SessionEntity; + checkUserExists: UserExists; + checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; + clientConfig: ClientConfig; + currentUser: User; + currentWorkspace: Workspace; + findWorkspaceFromInviteHash: Workspace; + findWorkspaceInvitations: Array<WorkspaceInvitation>; + getAISQLQuery: AisqlQueryResult; + getAvailablePackages: Scalars['JSON']; + getPostgresCredentials?: Maybe<PostgresCredentials>; + getProductPrices: ProductPricesEntity; + getServerlessFunctionSourceCode?: Maybe<Scalars['String']>; + getTimelineCalendarEventsFromCompanyId: TimelineCalendarEventsWithTotal; + getTimelineCalendarEventsFromPersonId: TimelineCalendarEventsWithTotal; + getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal; + getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; + object: Object; + objects: ObjectConnection; + serverlessFunction: ServerlessFunction; + serverlessFunctions: ServerlessFunctionConnection; + validatePasswordResetToken: ValidatePasswordResetToken; }; export type QueryBillingPortalSessionArgs = { - returnUrlPath?: InputMaybe<Scalars['String']>; + returnUrlPath?: InputMaybe<Scalars['String']>; }; export type QueryCheckUserExistsArgs = { - captchaToken?: InputMaybe<Scalars['String']>; - email: Scalars['String']; + captchaToken?: InputMaybe<Scalars['String']>; + email: Scalars['String']; }; export type QueryCheckWorkspaceInviteHashIsValidArgs = { - inviteHash: Scalars['String']; + inviteHash: Scalars['String']; }; export type QueryFindWorkspaceFromInviteHashArgs = { - inviteHash: Scalars['String']; + inviteHash: Scalars['String']; }; export type QueryGetAisqlQueryArgs = { - text: Scalars['String']; + text: Scalars['String']; }; export type QueryGetProductPricesArgs = { - product: Scalars['String']; + product: Scalars['String']; }; export type QueryGetServerlessFunctionSourceCodeArgs = { - input: GetServerlessFunctionSourceCodeInput; + input: GetServerlessFunctionSourceCodeInput; }; export type QueryGetTimelineCalendarEventsFromCompanyIdArgs = { - companyId: Scalars['UUID']; - page: Scalars['Int']; - pageSize: Scalars['Int']; + companyId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; }; export type QueryGetTimelineCalendarEventsFromPersonIdArgs = { - page: Scalars['Int']; - pageSize: Scalars['Int']; - personId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; + personId: Scalars['UUID']; }; export type QueryGetTimelineThreadsFromCompanyIdArgs = { - companyId: Scalars['UUID']; - page: Scalars['Int']; - pageSize: Scalars['Int']; + companyId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; }; export type QueryGetTimelineThreadsFromPersonIdArgs = { - page: Scalars['Int']; - pageSize: Scalars['Int']; - personId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; + personId: Scalars['UUID']; }; export type QueryValidatePasswordResetTokenArgs = { - passwordResetToken: Scalars['String']; + passwordResetToken: Scalars['String']; }; export type RelationConnection = { - __typename?: 'RelationConnection'; - /** Array of edges. */ - edges: Array<RelationEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'RelationConnection'; + /** Array of edges. */ + edges: Array<RelationEdge>; + /** Paging information */ + pageInfo: PageInfo; }; export type RelationDefinition = { - __typename?: 'RelationDefinition'; - direction: RelationDefinitionType; - relationId: Scalars['UUID']; - sourceFieldMetadata: Field; - sourceObjectMetadata: Object; - targetFieldMetadata: Field; - targetObjectMetadata: Object; + __typename?: 'RelationDefinition'; + direction: RelationDefinitionType; + relationId: Scalars['UUID']; + sourceFieldMetadata: Field; + sourceObjectMetadata: Object; + targetFieldMetadata: Field; + targetObjectMetadata: Object; }; /** Relation definition type */ export enum RelationDefinitionType { - ManyToMany = 'MANY_TO_MANY', - ManyToOne = 'MANY_TO_ONE', - OneToMany = 'ONE_TO_MANY', - OneToOne = 'ONE_TO_ONE' + ManyToMany = 'MANY_TO_MANY', + ManyToOne = 'MANY_TO_ONE', + OneToMany = 'ONE_TO_MANY', + OneToOne = 'ONE_TO_ONE' } /** Type of the relation */ export enum RelationMetadataType { - ManyToMany = 'MANY_TO_MANY', - ManyToOne = 'MANY_TO_ONE', - OneToMany = 'ONE_TO_MANY', - OneToOne = 'ONE_TO_ONE' + ManyToMany = 'MANY_TO_MANY', + ManyToOne = 'MANY_TO_ONE', + OneToMany = 'ONE_TO_MANY', + OneToOne = 'ONE_TO_ONE' } export type RemoteServer = { - __typename?: 'RemoteServer'; - createdAt: Scalars['DateTime']; - foreignDataWrapperId: Scalars['ID']; - foreignDataWrapperOptions?: Maybe<Scalars['JSON']>; - foreignDataWrapperType: Scalars['String']; - id: Scalars['ID']; - label: Scalars['String']; - schema?: Maybe<Scalars['String']>; - updatedAt: Scalars['DateTime']; - userMappingOptions?: Maybe<UserMappingOptionsUser>; + __typename?: 'RemoteServer'; + createdAt: Scalars['DateTime']; + foreignDataWrapperId: Scalars['ID']; + foreignDataWrapperOptions?: Maybe<Scalars['JSON']>; + foreignDataWrapperType: Scalars['String']; + id: Scalars['ID']; + label: Scalars['String']; + schema?: Maybe<Scalars['String']>; + updatedAt: Scalars['DateTime']; + userMappingOptions?: Maybe<UserMappingOptionsUser>; }; export type RemoteTable = { - __typename?: 'RemoteTable'; - id?: Maybe<Scalars['UUID']>; - name: Scalars['String']; - schema?: Maybe<Scalars['String']>; - schemaPendingUpdates?: Maybe<Array<DistantTableUpdate>>; - status: RemoteTableStatus; + __typename?: 'RemoteTable'; + id?: Maybe<Scalars['UUID']>; + name: Scalars['String']; + schema?: Maybe<Scalars['String']>; + schemaPendingUpdates?: Maybe<Array<DistantTableUpdate>>; + status: RemoteTableStatus; }; /** Status of the table */ export enum RemoteTableStatus { - NotSynced = 'NOT_SYNCED', - Synced = 'SYNCED' + NotSynced = 'NOT_SYNCED', + Synced = 'SYNCED' } export type RunWorkflowVersionInput = { - /** Execution result in JSON format */ - payload?: InputMaybe<Scalars['JSON']>; - /** Workflow version ID */ - workflowVersionId: Scalars['String']; + /** Execution result in JSON format */ + payload?: InputMaybe<Scalars['JSON']>; + /** Workflow version ID */ + workflowVersionId: Scalars['String']; }; -export type SendInviteLink = { - __typename?: 'SendInviteLink'; - /** Boolean that confirms query was dispatched */ - success: Scalars['Boolean']; +export type SendInvitationsOutput = { + __typename?: 'SendInvitationsOutput'; + errors: Array<Scalars['String']>; + result: Array<WorkspaceInvitation>; + /** Boolean that confirms query was dispatched */ + success: Scalars['Boolean']; }; export type Sentry = { - __typename?: 'Sentry'; - dsn?: Maybe<Scalars['String']>; - environment?: Maybe<Scalars['String']>; - release?: Maybe<Scalars['String']>; + __typename?: 'Sentry'; + dsn?: Maybe<Scalars['String']>; + environment?: Maybe<Scalars['String']>; + release?: Maybe<Scalars['String']>; }; export type ServerlessFunction = { - __typename?: 'ServerlessFunction'; - createdAt: Scalars['DateTime']; - description?: Maybe<Scalars['String']>; - id: Scalars['UUID']; - latestVersion?: Maybe<Scalars['String']>; - name: Scalars['String']; - runtime: Scalars['String']; - sourceCodeHash: Scalars['String']; - syncStatus: ServerlessFunctionSyncStatus; - updatedAt: Scalars['DateTime']; + __typename?: 'ServerlessFunction'; + createdAt: Scalars['DateTime']; + description?: Maybe<Scalars['String']>; + id: Scalars['UUID']; + latestVersion?: Maybe<Scalars['String']>; + name: Scalars['String']; + runtime: Scalars['String']; + sourceCodeHash: Scalars['String']; + syncStatus: ServerlessFunctionSyncStatus; + updatedAt: Scalars['DateTime']; }; export type ServerlessFunctionConnection = { - __typename?: 'ServerlessFunctionConnection'; - /** Array of edges. */ - edges: Array<ServerlessFunctionEdge>; - /** Paging information */ - pageInfo: PageInfo; + __typename?: 'ServerlessFunctionConnection'; + /** Array of edges. */ + edges: Array<ServerlessFunctionEdge>; + /** Paging information */ + pageInfo: PageInfo; }; export type ServerlessFunctionEdge = { - __typename?: 'ServerlessFunctionEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the ServerlessFunction */ - node: ServerlessFunction; + __typename?: 'ServerlessFunctionEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the ServerlessFunction */ + node: ServerlessFunction; }; export type ServerlessFunctionExecutionResult = { - __typename?: 'ServerlessFunctionExecutionResult'; - /** Execution result in JSON format */ - data?: Maybe<Scalars['JSON']>; - /** Execution duration in milliseconds */ - duration: Scalars['Float']; - /** Execution error in JSON format */ - error?: Maybe<Scalars['JSON']>; - /** Execution status */ - status: ServerlessFunctionExecutionStatus; + __typename?: 'ServerlessFunctionExecutionResult'; + /** Execution result in JSON format */ + data?: Maybe<Scalars['JSON']>; + /** Execution duration in milliseconds */ + duration: Scalars['Float']; + /** Execution error in JSON format */ + error?: Maybe<Scalars['JSON']>; + /** Execution status */ + status: ServerlessFunctionExecutionStatus; }; /** Status of the serverless function execution */ export enum ServerlessFunctionExecutionStatus { - Error = 'ERROR', - Success = 'SUCCESS' + Error = 'ERROR', + Success = 'SUCCESS' } /** SyncStatus of the serverlessFunction */ export enum ServerlessFunctionSyncStatus { - NotReady = 'NOT_READY', - Ready = 'READY' + NotReady = 'NOT_READY', + Ready = 'READY' } export type SessionEntity = { - __typename?: 'SessionEntity'; - url?: Maybe<Scalars['String']>; + __typename?: 'SessionEntity'; + url?: Maybe<Scalars['String']>; }; /** Sort Directions */ export enum SortDirection { - Asc = 'ASC', - Desc = 'DESC' + Asc = 'ASC', + Desc = 'DESC' } /** Sort Nulls Options */ export enum SortNulls { - NullsFirst = 'NULLS_FIRST', - NullsLast = 'NULLS_LAST' + NullsFirst = 'NULLS_FIRST', + NullsLast = 'NULLS_LAST' } export enum SubscriptionInterval { - Day = 'Day', - Month = 'Month', - Week = 'Week', - Year = 'Year' + Day = 'Day', + Month = 'Month', + Week = 'Week', + Year = 'Year' } export enum SubscriptionStatus { - Active = 'Active', - Canceled = 'Canceled', - Incomplete = 'Incomplete', - IncompleteExpired = 'IncompleteExpired', - PastDue = 'PastDue', - Paused = 'Paused', - Trialing = 'Trialing', - Unpaid = 'Unpaid' + Active = 'Active', + Canceled = 'Canceled', + Incomplete = 'Incomplete', + IncompleteExpired = 'IncompleteExpired', + PastDue = 'PastDue', + Paused = 'Paused', + Trialing = 'Trialing', + Unpaid = 'Unpaid' } export type Support = { - __typename?: 'Support'; - supportDriver: Scalars['String']; - supportFrontChatId?: Maybe<Scalars['String']>; -}; - -export type Telemetry = { - __typename?: 'Telemetry'; - enabled: Scalars['Boolean']; + __typename?: 'Support'; + supportDriver: Scalars['String']; + supportFrontChatId?: Maybe<Scalars['String']>; }; export type TimelineCalendarEvent = { - __typename?: 'TimelineCalendarEvent'; - conferenceLink: LinksMetadata; - conferenceSolution: Scalars['String']; - description: Scalars['String']; - endsAt: Scalars['DateTime']; - id: Scalars['UUID']; - isCanceled: Scalars['Boolean']; - isFullDay: Scalars['Boolean']; - location: Scalars['String']; - participants: Array<TimelineCalendarEventParticipant>; - startsAt: Scalars['DateTime']; - title: Scalars['String']; - visibility: CalendarChannelVisibility; + __typename?: 'TimelineCalendarEvent'; + conferenceLink: LinksMetadata; + conferenceSolution: Scalars['String']; + description: Scalars['String']; + endsAt: Scalars['DateTime']; + id: Scalars['UUID']; + isCanceled: Scalars['Boolean']; + isFullDay: Scalars['Boolean']; + location: Scalars['String']; + participants: Array<TimelineCalendarEventParticipant>; + startsAt: Scalars['DateTime']; + title: Scalars['String']; + visibility: CalendarChannelVisibility; }; export type TimelineCalendarEventParticipant = { - __typename?: 'TimelineCalendarEventParticipant'; - avatarUrl: Scalars['String']; - displayName: Scalars['String']; - firstName: Scalars['String']; - handle: Scalars['String']; - lastName: Scalars['String']; - personId?: Maybe<Scalars['UUID']>; - workspaceMemberId?: Maybe<Scalars['UUID']>; + __typename?: 'TimelineCalendarEventParticipant'; + avatarUrl: Scalars['String']; + displayName: Scalars['String']; + firstName: Scalars['String']; + handle: Scalars['String']; + lastName: Scalars['String']; + personId?: Maybe<Scalars['UUID']>; + workspaceMemberId?: Maybe<Scalars['UUID']>; }; export type TimelineCalendarEventsWithTotal = { - __typename?: 'TimelineCalendarEventsWithTotal'; - timelineCalendarEvents: Array<TimelineCalendarEvent>; - totalNumberOfCalendarEvents: Scalars['Int']; + __typename?: 'TimelineCalendarEventsWithTotal'; + timelineCalendarEvents: Array<TimelineCalendarEvent>; + totalNumberOfCalendarEvents: Scalars['Int']; }; export type TimelineThread = { - __typename?: 'TimelineThread'; - firstParticipant: TimelineThreadParticipant; - id: Scalars['UUID']; - lastMessageBody: Scalars['String']; - lastMessageReceivedAt: Scalars['DateTime']; - lastTwoParticipants: Array<TimelineThreadParticipant>; - numberOfMessagesInThread: Scalars['Float']; - participantCount: Scalars['Float']; - read: Scalars['Boolean']; - subject: Scalars['String']; - visibility: MessageChannelVisibility; + __typename?: 'TimelineThread'; + firstParticipant: TimelineThreadParticipant; + id: Scalars['UUID']; + lastMessageBody: Scalars['String']; + lastMessageReceivedAt: Scalars['DateTime']; + lastTwoParticipants: Array<TimelineThreadParticipant>; + numberOfMessagesInThread: Scalars['Float']; + participantCount: Scalars['Float']; + read: Scalars['Boolean']; + subject: Scalars['String']; + visibility: MessageChannelVisibility; }; export type TimelineThreadParticipant = { - __typename?: 'TimelineThreadParticipant'; - avatarUrl: Scalars['String']; - displayName: Scalars['String']; - firstName: Scalars['String']; - handle: Scalars['String']; - lastName: Scalars['String']; - personId?: Maybe<Scalars['UUID']>; - workspaceMemberId?: Maybe<Scalars['UUID']>; + __typename?: 'TimelineThreadParticipant'; + avatarUrl: Scalars['String']; + displayName: Scalars['String']; + firstName: Scalars['String']; + handle: Scalars['String']; + lastName: Scalars['String']; + personId?: Maybe<Scalars['UUID']>; + workspaceMemberId?: Maybe<Scalars['UUID']>; }; export type TimelineThreadsWithTotal = { - __typename?: 'TimelineThreadsWithTotal'; - timelineThreads: Array<TimelineThread>; - totalNumberOfThreads: Scalars['Int']; + __typename?: 'TimelineThreadsWithTotal'; + timelineThreads: Array<TimelineThread>; + totalNumberOfThreads: Scalars['Int']; }; export type TransientToken = { - __typename?: 'TransientToken'; - transientToken: AuthToken; + __typename?: 'TransientToken'; + transientToken: AuthToken; }; export type UuidFilterComparison = { - eq?: InputMaybe<Scalars['UUID']>; - gt?: InputMaybe<Scalars['UUID']>; - gte?: InputMaybe<Scalars['UUID']>; - iLike?: InputMaybe<Scalars['UUID']>; - in?: InputMaybe<Array<Scalars['UUID']>>; - is?: InputMaybe<Scalars['Boolean']>; - isNot?: InputMaybe<Scalars['Boolean']>; - like?: InputMaybe<Scalars['UUID']>; - lt?: InputMaybe<Scalars['UUID']>; - lte?: InputMaybe<Scalars['UUID']>; - neq?: InputMaybe<Scalars['UUID']>; - notILike?: InputMaybe<Scalars['UUID']>; - notIn?: InputMaybe<Array<Scalars['UUID']>>; - notLike?: InputMaybe<Scalars['UUID']>; + eq?: InputMaybe<Scalars['UUID']>; + gt?: InputMaybe<Scalars['UUID']>; + gte?: InputMaybe<Scalars['UUID']>; + iLike?: InputMaybe<Scalars['UUID']>; + in?: InputMaybe<Array<Scalars['UUID']>>; + is?: InputMaybe<Scalars['Boolean']>; + isNot?: InputMaybe<Scalars['Boolean']>; + like?: InputMaybe<Scalars['UUID']>; + lt?: InputMaybe<Scalars['UUID']>; + lte?: InputMaybe<Scalars['UUID']>; + neq?: InputMaybe<Scalars['UUID']>; + notILike?: InputMaybe<Scalars['UUID']>; + notIn?: InputMaybe<Array<Scalars['UUID']>>; + notLike?: InputMaybe<Scalars['UUID']>; }; export type UpdateBillingEntity = { - __typename?: 'UpdateBillingEntity'; - /** Boolean that confirms query was successful */ - success: Scalars['Boolean']; + __typename?: 'UpdateBillingEntity'; + /** Boolean that confirms query was successful */ + success: Scalars['Boolean']; }; export type UpdateObjectPayload = { - description?: InputMaybe<Scalars['String']>; - icon?: InputMaybe<Scalars['String']>; - imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']>; - isActive?: InputMaybe<Scalars['Boolean']>; - labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']>; - labelPlural?: InputMaybe<Scalars['String']>; - labelSingular?: InputMaybe<Scalars['String']>; - namePlural?: InputMaybe<Scalars['String']>; - nameSingular?: InputMaybe<Scalars['String']>; + description?: InputMaybe<Scalars['String']>; + icon?: InputMaybe<Scalars['String']>; + imageIdentifierFieldMetadataId?: InputMaybe<Scalars['String']>; + isActive?: InputMaybe<Scalars['Boolean']>; + labelIdentifierFieldMetadataId?: InputMaybe<Scalars['String']>; + labelPlural?: InputMaybe<Scalars['String']>; + labelSingular?: InputMaybe<Scalars['String']>; + namePlural?: InputMaybe<Scalars['String']>; + nameSingular?: InputMaybe<Scalars['String']>; }; export type UpdateOneObjectInput = { - /** The id of the object to update */ - id: Scalars['UUID']; - update: UpdateObjectPayload; + /** The id of the object to update */ + id: Scalars['UUID']; + update: UpdateObjectPayload; }; export type UpdateServerlessFunctionInput = { - code: Scalars['String']; - description?: InputMaybe<Scalars['String']>; - /** Id of the serverless function to execute */ - id: Scalars['UUID']; - name: Scalars['String']; + code: Scalars['String']; + description?: InputMaybe<Scalars['String']>; + /** Id of the serverless function to execute */ + id: Scalars['UUID']; + name: Scalars['String']; }; export type UpdateWorkspaceInput = { - allowImpersonation?: InputMaybe<Scalars['Boolean']>; - displayName?: InputMaybe<Scalars['String']>; - domainName?: InputMaybe<Scalars['String']>; - inviteHash?: InputMaybe<Scalars['String']>; - logo?: InputMaybe<Scalars['String']>; + allowImpersonation?: InputMaybe<Scalars['Boolean']>; + displayName?: InputMaybe<Scalars['String']>; + domainName?: InputMaybe<Scalars['String']>; + inviteHash?: InputMaybe<Scalars['String']>; + logo?: InputMaybe<Scalars['String']>; }; export type User = { - __typename?: 'User'; - canImpersonate: Scalars['Boolean']; - createdAt: Scalars['DateTime']; - defaultAvatarUrl?: Maybe<Scalars['String']>; - defaultWorkspace: Workspace; - defaultWorkspaceId: Scalars['String']; - deletedAt?: Maybe<Scalars['DateTime']>; - disabled?: Maybe<Scalars['Boolean']>; - email: Scalars['String']; - emailVerified: Scalars['Boolean']; - firstName: Scalars['String']; - id: Scalars['UUID']; - lastName: Scalars['String']; - onboardingStatus?: Maybe<OnboardingStatus>; - passwordHash?: Maybe<Scalars['String']>; - supportUserHash?: Maybe<Scalars['String']>; - updatedAt: Scalars['DateTime']; - userVars: Scalars['JSONObject']; - workspaceMember?: Maybe<WorkspaceMember>; - workspaceMembers?: Maybe<Array<WorkspaceMember>>; - workspaces: Array<UserWorkspace>; + __typename?: 'User'; + canImpersonate: Scalars['Boolean']; + createdAt: Scalars['DateTime']; + defaultAvatarUrl?: Maybe<Scalars['String']>; + defaultWorkspace: Workspace; + defaultWorkspaceId: Scalars['String']; + deletedAt?: Maybe<Scalars['DateTime']>; + disabled?: Maybe<Scalars['Boolean']>; + email: Scalars['String']; + emailVerified: Scalars['Boolean']; + firstName: Scalars['String']; + id: Scalars['UUID']; + lastName: Scalars['String']; + onboardingStatus?: Maybe<OnboardingStatus>; + passwordHash?: Maybe<Scalars['String']>; + supportUserHash?: Maybe<Scalars['String']>; + updatedAt: Scalars['DateTime']; + userVars: Scalars['JSONObject']; + workspaceMember?: Maybe<WorkspaceMember>; + workspaceMembers?: Maybe<Array<WorkspaceMember>>; + workspaces: Array<UserWorkspace>; }; export type UserEdge = { - __typename?: 'UserEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the User */ - node: User; + __typename?: 'UserEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the User */ + node: User; }; export type UserExists = { - __typename?: 'UserExists'; - exists: Scalars['Boolean']; + __typename?: 'UserExists'; + exists: Scalars['Boolean']; }; export type UserMappingOptionsUser = { - __typename?: 'UserMappingOptionsUser'; - user?: Maybe<Scalars['String']>; + __typename?: 'UserMappingOptionsUser'; + user?: Maybe<Scalars['String']>; }; export type UserWorkspace = { - __typename?: 'UserWorkspace'; - createdAt: Scalars['DateTime']; - deletedAt?: Maybe<Scalars['DateTime']>; - id: Scalars['UUID']; - updatedAt: Scalars['DateTime']; - user: User; - userId: Scalars['String']; - workspace?: Maybe<Workspace>; - workspaceId: Scalars['String']; + __typename?: 'UserWorkspace'; + createdAt: Scalars['DateTime']; + deletedAt?: Maybe<Scalars['DateTime']>; + id: Scalars['UUID']; + updatedAt: Scalars['DateTime']; + user: User; + userId: Scalars['String']; + workspace?: Maybe<Workspace>; + workspaceId: Scalars['String']; }; export type ValidatePasswordResetToken = { - __typename?: 'ValidatePasswordResetToken'; - email: Scalars['String']; - id: Scalars['String']; + __typename?: 'ValidatePasswordResetToken'; + email: Scalars['String']; + id: Scalars['String']; }; export type Verify = { - __typename?: 'Verify'; - tokens: AuthTokenPair; - user: User; + __typename?: 'Verify'; + tokens: AuthTokenPair; + user: User; }; export type WorkflowRun = { - __typename?: 'WorkflowRun'; - workflowRunId: Scalars['UUID']; + __typename?: 'WorkflowRun'; + workflowRunId: Scalars['UUID']; }; export type Workspace = { - __typename?: 'Workspace'; - activationStatus: WorkspaceActivationStatus; - allowImpersonation: Scalars['Boolean']; - billingSubscriptions?: Maybe<Array<BillingSubscription>>; - createdAt: Scalars['DateTime']; - currentBillingSubscription?: Maybe<BillingSubscription>; - databaseSchema: Scalars['String']; - databaseUrl: Scalars['String']; - deletedAt?: Maybe<Scalars['DateTime']>; - displayName?: Maybe<Scalars['String']>; - domainName?: Maybe<Scalars['String']>; - featureFlags?: Maybe<Array<FeatureFlag>>; - id: Scalars['UUID']; - inviteHash?: Maybe<Scalars['String']>; - logo?: Maybe<Scalars['String']>; - metadataVersion: Scalars['Float']; - updatedAt: Scalars['DateTime']; - workspaceMembersCount?: Maybe<Scalars['Float']>; + __typename?: 'Workspace'; + activationStatus: WorkspaceActivationStatus; + allowImpersonation: Scalars['Boolean']; + billingSubscriptions?: Maybe<Array<BillingSubscription>>; + createdAt: Scalars['DateTime']; + currentBillingSubscription?: Maybe<BillingSubscription>; + databaseSchema: Scalars['String']; + databaseUrl: Scalars['String']; + deletedAt?: Maybe<Scalars['DateTime']>; + displayName?: Maybe<Scalars['String']>; + domainName?: Maybe<Scalars['String']>; + featureFlags?: Maybe<Array<FeatureFlag>>; + id: Scalars['UUID']; + inviteHash?: Maybe<Scalars['String']>; + logo?: Maybe<Scalars['String']>; + metadataVersion: Scalars['Float']; + updatedAt: Scalars['DateTime']; + workspaceMembersCount?: Maybe<Scalars['Float']>; }; export type WorkspaceBillingSubscriptionsArgs = { - filter?: BillingSubscriptionFilter; - sorting?: Array<BillingSubscriptionSort>; + filter?: BillingSubscriptionFilter; + sorting?: Array<BillingSubscriptionSort>; }; export type WorkspaceFeatureFlagsArgs = { - filter?: FeatureFlagFilter; - sorting?: Array<FeatureFlagSort>; + filter?: FeatureFlagFilter; + sorting?: Array<FeatureFlagSort>; }; export enum WorkspaceActivationStatus { - Active = 'ACTIVE', - Inactive = 'INACTIVE', - OngoingCreation = 'ONGOING_CREATION', - PendingCreation = 'PENDING_CREATION' + Active = 'ACTIVE', + Inactive = 'INACTIVE', + OngoingCreation = 'ONGOING_CREATION', + PendingCreation = 'PENDING_CREATION' } export type WorkspaceEdge = { - __typename?: 'WorkspaceEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the Workspace */ - node: Workspace; + __typename?: 'WorkspaceEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the Workspace */ + node: Workspace; +}; + +export type WorkspaceInvitation = { + __typename?: 'WorkspaceInvitation'; + email: Scalars['String']; + expiresAt: Scalars['DateTime']; + id: Scalars['UUID']; }; export type WorkspaceInviteHashValid = { - __typename?: 'WorkspaceInviteHashValid'; - isValid: Scalars['Boolean']; + __typename?: 'WorkspaceInviteHashValid'; + isValid: Scalars['Boolean']; }; export type WorkspaceMember = { - __typename?: 'WorkspaceMember'; - avatarUrl?: Maybe<Scalars['String']>; - colorScheme: Scalars['String']; - dateFormat?: Maybe<WorkspaceMemberDateFormatEnum>; - id: Scalars['UUID']; - locale?: Maybe<Scalars['String']>; - name: FullName; - timeFormat?: Maybe<WorkspaceMemberTimeFormatEnum>; - timeZone?: Maybe<Scalars['String']>; + __typename?: 'WorkspaceMember'; + avatarUrl?: Maybe<Scalars['String']>; + colorScheme: Scalars['String']; + dateFormat?: Maybe<WorkspaceMemberDateFormatEnum>; + id: Scalars['UUID']; + locale?: Maybe<Scalars['String']>; + name: FullName; + timeFormat?: Maybe<WorkspaceMemberTimeFormatEnum>; + timeZone?: Maybe<Scalars['String']>; }; /** Date format as Month first, Day first, Year first or system as default */ export enum WorkspaceMemberDateFormatEnum { - DayFirst = 'DAY_FIRST', - MonthFirst = 'MONTH_FIRST', - System = 'SYSTEM', - YearFirst = 'YEAR_FIRST' + DayFirst = 'DAY_FIRST', + MonthFirst = 'MONTH_FIRST', + System = 'SYSTEM', + YearFirst = 'YEAR_FIRST' } /** Time time as Military, Standard or system as default */ export enum WorkspaceMemberTimeFormatEnum { - Hour_12 = 'HOUR_12', - Hour_24 = 'HOUR_24', - System = 'SYSTEM' + Hour_12 = 'HOUR_12', + Hour_24 = 'HOUR_24', + System = 'SYSTEM' } export type Field = { - __typename?: 'field'; - createdAt: Scalars['DateTime']; - defaultValue?: Maybe<Scalars['JSON']>; - description?: Maybe<Scalars['String']>; - fromRelationMetadata?: Maybe<Relation>; - icon?: Maybe<Scalars['String']>; - id: Scalars['UUID']; - isActive?: Maybe<Scalars['Boolean']>; - isCustom?: Maybe<Scalars['Boolean']>; - isNullable?: Maybe<Scalars['Boolean']>; - isSystem?: Maybe<Scalars['Boolean']>; - label: Scalars['String']; - name: Scalars['String']; - object?: Maybe<Object>; - options?: Maybe<Scalars['JSON']>; - relationDefinition?: Maybe<RelationDefinition>; - settings?: Maybe<Scalars['JSON']>; - toRelationMetadata?: Maybe<Relation>; - type: FieldMetadataType; - updatedAt: Scalars['DateTime']; + __typename?: 'field'; + createdAt: Scalars['DateTime']; + defaultValue?: Maybe<Scalars['JSON']>; + description?: Maybe<Scalars['String']>; + fromRelationMetadata?: Maybe<Relation>; + icon?: Maybe<Scalars['String']>; + id: Scalars['UUID']; + isActive?: Maybe<Scalars['Boolean']>; + isCustom?: Maybe<Scalars['Boolean']>; + isNullable?: Maybe<Scalars['Boolean']>; + isSystem?: Maybe<Scalars['Boolean']>; + label: Scalars['String']; + name: Scalars['String']; + object?: Maybe<Object>; + options?: Maybe<Scalars['JSON']>; + relationDefinition?: Maybe<RelationDefinition>; + settings?: Maybe<Scalars['JSON']>; + toRelationMetadata?: Maybe<Relation>; + type: FieldMetadataType; + updatedAt: Scalars['DateTime']; }; export type FieldEdge = { - __typename?: 'fieldEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the field */ - node: Field; + __typename?: 'fieldEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the field */ + node: Field; }; export type FieldFilter = { - and?: InputMaybe<Array<FieldFilter>>; - id?: InputMaybe<UuidFilterComparison>; - isActive?: InputMaybe<BooleanFieldComparison>; - isCustom?: InputMaybe<BooleanFieldComparison>; - isSystem?: InputMaybe<BooleanFieldComparison>; - or?: InputMaybe<Array<FieldFilter>>; + and?: InputMaybe<Array<FieldFilter>>; + id?: InputMaybe<UuidFilterComparison>; + isActive?: InputMaybe<BooleanFieldComparison>; + isCustom?: InputMaybe<BooleanFieldComparison>; + isSystem?: InputMaybe<BooleanFieldComparison>; + or?: InputMaybe<Array<FieldFilter>>; }; export type Object = { - __typename?: 'object'; - createdAt: Scalars['DateTime']; - dataSourceId: Scalars['String']; - description?: Maybe<Scalars['String']>; - fields: ObjectFieldsConnection; - icon?: Maybe<Scalars['String']>; - id: Scalars['UUID']; - imageIdentifierFieldMetadataId?: Maybe<Scalars['String']>; - isActive: Scalars['Boolean']; - isCustom: Scalars['Boolean']; - isRemote: Scalars['Boolean']; - isSystem: Scalars['Boolean']; - labelIdentifierFieldMetadataId?: Maybe<Scalars['String']>; - labelPlural: Scalars['String']; - labelSingular: Scalars['String']; - namePlural: Scalars['String']; - nameSingular: Scalars['String']; - updatedAt: Scalars['DateTime']; + __typename?: 'object'; + createdAt: Scalars['DateTime']; + dataSourceId: Scalars['String']; + description?: Maybe<Scalars['String']>; + fields: ObjectFieldsConnection; + icon?: Maybe<Scalars['String']>; + id: Scalars['UUID']; + imageIdentifierFieldMetadataId?: Maybe<Scalars['String']>; + isActive: Scalars['Boolean']; + isCustom: Scalars['Boolean']; + isRemote: Scalars['Boolean']; + isSystem: Scalars['Boolean']; + labelIdentifierFieldMetadataId?: Maybe<Scalars['String']>; + labelPlural: Scalars['String']; + labelSingular: Scalars['String']; + namePlural: Scalars['String']; + nameSingular: Scalars['String']; + updatedAt: Scalars['DateTime']; }; export type ObjectFieldsArgs = { - filter?: FieldFilter; - paging?: CursorPaging; + filter?: FieldFilter; + paging?: CursorPaging; }; export type ObjectEdge = { - __typename?: 'objectEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the object */ - node: Object; + __typename?: 'objectEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the object */ + node: Object; }; export type Relation = { - __typename?: 'relation'; - createdAt: Scalars['DateTime']; - fromFieldMetadataId: Scalars['String']; - fromObjectMetadata: Object; - fromObjectMetadataId: Scalars['String']; - id: Scalars['UUID']; - relationType: RelationMetadataType; - toFieldMetadataId: Scalars['String']; - toObjectMetadata: Object; - toObjectMetadataId: Scalars['String']; - updatedAt: Scalars['DateTime']; + __typename?: 'relation'; + createdAt: Scalars['DateTime']; + fromFieldMetadataId: Scalars['String']; + fromObjectMetadata: Object; + fromObjectMetadataId: Scalars['String']; + id: Scalars['UUID']; + relationType: RelationMetadataType; + toFieldMetadataId: Scalars['String']; + toObjectMetadata: Object; + toObjectMetadataId: Scalars['String']; + updatedAt: Scalars['DateTime']; }; export type RelationEdge = { - __typename?: 'relationEdge'; - /** Cursor for this node. */ - cursor: Scalars['ConnectionCursor']; - /** The node containing the relation */ - node: Relation; + __typename?: 'relationEdge'; + /** Cursor for this node. */ + cursor: Scalars['ConnectionCursor']; + /** The node containing the relation */ + node: Relation; }; export type TimelineCalendarEventFragmentFragment = { __typename?: 'TimelineCalendarEvent', id: any, title: string, description: string, location: string, startsAt: string, endsAt: string, isFullDay: boolean, visibility: CalendarChannelVisibility, participants: Array<{ __typename?: 'TimelineCalendarEventParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }; @@ -1282,18 +1307,18 @@ export type TimelineCalendarEventParticipantFragmentFragment = { __typename?: 'T export type TimelineCalendarEventsWithTotalFragmentFragment = { __typename?: 'TimelineCalendarEventsWithTotal', totalNumberOfCalendarEvents: number, timelineCalendarEvents: Array<{ __typename?: 'TimelineCalendarEvent', id: any, title: string, description: string, location: string, startsAt: string, endsAt: string, isFullDay: boolean, visibility: CalendarChannelVisibility, participants: Array<{ __typename?: 'TimelineCalendarEventParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> }; export type GetTimelineCalendarEventsFromCompanyIdQueryVariables = Exact<{ - companyId: Scalars['UUID']; - page: Scalars['Int']; - pageSize: Scalars['Int']; + companyId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; }>; export type GetTimelineCalendarEventsFromCompanyIdQuery = { __typename?: 'Query', getTimelineCalendarEventsFromCompanyId: { __typename?: 'TimelineCalendarEventsWithTotal', totalNumberOfCalendarEvents: number, timelineCalendarEvents: Array<{ __typename?: 'TimelineCalendarEvent', id: any, title: string, description: string, location: string, startsAt: string, endsAt: string, isFullDay: boolean, visibility: CalendarChannelVisibility, participants: Array<{ __typename?: 'TimelineCalendarEventParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; export type GetTimelineCalendarEventsFromPersonIdQueryVariables = Exact<{ - personId: Scalars['UUID']; - page: Scalars['Int']; - pageSize: Scalars['Int']; + personId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; }>; @@ -1306,42 +1331,42 @@ export type TimelineThreadFragmentFragment = { __typename?: 'TimelineThread', id export type TimelineThreadsWithTotalFragmentFragment = { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: any, read: boolean, visibility: MessageChannelVisibility, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> }; export type GetTimelineThreadsFromCompanyIdQueryVariables = Exact<{ - companyId: Scalars['UUID']; - page: Scalars['Int']; - pageSize: Scalars['Int']; + companyId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; }>; export type GetTimelineThreadsFromCompanyIdQuery = { __typename?: 'Query', getTimelineThreadsFromCompanyId: { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: any, read: boolean, visibility: MessageChannelVisibility, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; export type GetTimelineThreadsFromPersonIdQueryVariables = Exact<{ - personId: Scalars['UUID']; - page: Scalars['Int']; - pageSize: Scalars['Int']; + personId: Scalars['UUID']; + page: Scalars['Int']; + pageSize: Scalars['Int']; }>; export type GetTimelineThreadsFromPersonIdQuery = { __typename?: 'Query', getTimelineThreadsFromPersonId: { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: any, read: boolean, visibility: MessageChannelVisibility, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: any | null, workspaceMemberId?: any | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; export type TrackMutationVariables = Exact<{ - type: Scalars['String']; - data: Scalars['JSON']; + action: Scalars['String']; + payload: Scalars['JSON']; }>; export type TrackMutation = { __typename?: 'Mutation', track: { __typename?: 'Analytics', success: boolean } }; export type UploadFileMutationVariables = Exact<{ - file: Scalars['Upload']; - fileFolder?: InputMaybe<FileFolder>; + file: Scalars['Upload']; + fileFolder?: InputMaybe<FileFolder>; }>; export type UploadFileMutation = { __typename?: 'Mutation', uploadFile: string }; export type UploadImageMutationVariables = Exact<{ - file: Scalars['Upload']; - fileFolder?: InputMaybe<FileFolder>; + file: Scalars['Upload']; + fileFolder?: InputMaybe<FileFolder>; }>; @@ -1352,40 +1377,40 @@ export type AuthTokenFragmentFragment = { __typename?: 'AuthToken', token: strin export type AuthTokensFragmentFragment = { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } }; export type AuthorizeAppMutationVariables = Exact<{ - clientId: Scalars['String']; - codeChallenge: Scalars['String']; - redirectUrl: Scalars['String']; + clientId: Scalars['String']; + codeChallenge: Scalars['String']; + redirectUrl: Scalars['String']; }>; export type AuthorizeAppMutation = { __typename?: 'Mutation', authorizeApp: { __typename?: 'AuthorizeApp', redirectUrl: string } }; export type ChallengeMutationVariables = Exact<{ - email: Scalars['String']; - password: Scalars['String']; - captchaToken?: InputMaybe<Scalars['String']>; + email: Scalars['String']; + password: Scalars['String']; + captchaToken?: InputMaybe<Scalars['String']>; }>; export type ChallengeMutation = { __typename?: 'Mutation', challenge: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; export type EmailPasswordResetLinkMutationVariables = Exact<{ - email: Scalars['String']; + email: Scalars['String']; }>; export type EmailPasswordResetLinkMutation = { __typename?: 'Mutation', emailPasswordResetLink: { __typename?: 'EmailPasswordResetLink', success: boolean } }; export type GenerateApiKeyTokenMutationVariables = Exact<{ - apiKeyId: Scalars['String']; - expiresAt: Scalars['String']; + apiKeyId: Scalars['String']; + expiresAt: Scalars['String']; }>; export type GenerateApiKeyTokenMutation = { __typename?: 'Mutation', generateApiKeyToken: { __typename?: 'ApiKeyToken', token: string } }; export type GenerateJwtMutationVariables = Exact<{ - workspaceId: Scalars['String']; + workspaceId: Scalars['String']; }>; @@ -1397,76 +1422,77 @@ export type GenerateTransientTokenMutationVariables = Exact<{ [key: string]: nev export type GenerateTransientTokenMutation = { __typename?: 'Mutation', generateTransientToken: { __typename?: 'TransientToken', transientToken: { __typename?: 'AuthToken', token: string } } }; export type ImpersonateMutationVariables = Exact<{ - userId: Scalars['String']; + userId: Scalars['String']; }>; export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type RenewTokenMutationVariables = Exact<{ - appToken: Scalars['String']; + appToken: Scalars['String']; }>; export type RenewTokenMutation = { __typename?: 'Mutation', renewToken: { __typename?: 'AuthTokens', tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type SignUpMutationVariables = Exact<{ - email: Scalars['String']; - password: Scalars['String']; - workspaceInviteHash?: InputMaybe<Scalars['String']>; - captchaToken?: InputMaybe<Scalars['String']>; + email: Scalars['String']; + password: Scalars['String']; + workspaceInviteHash?: InputMaybe<Scalars['String']>; + workspacePersonalInviteToken?: InputMaybe<Scalars['String']>; + captchaToken?: InputMaybe<Scalars['String']>; }>; export type SignUpMutation = { __typename?: 'Mutation', signUp: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; export type UpdatePasswordViaResetTokenMutationVariables = Exact<{ - token: Scalars['String']; - newPassword: Scalars['String']; + token: Scalars['String']; + newPassword: Scalars['String']; }>; export type UpdatePasswordViaResetTokenMutation = { __typename?: 'Mutation', updatePasswordViaResetToken: { __typename?: 'InvalidatePassword', success: boolean } }; export type VerifyMutationVariables = Exact<{ - loginToken: Scalars['String']; + loginToken: Scalars['String']; }>; export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type CheckUserExistsQueryVariables = Exact<{ - email: Scalars['String']; - captchaToken?: InputMaybe<Scalars['String']>; + email: Scalars['String']; + captchaToken?: InputMaybe<Scalars['String']>; }>; export type CheckUserExistsQuery = { __typename?: 'Query', checkUserExists: { __typename?: 'UserExists', exists: boolean } }; export type ValidatePasswordResetTokenQueryVariables = Exact<{ - token: Scalars['String']; + token: Scalars['String']; }>; export type ValidatePasswordResetTokenQuery = { __typename?: 'Query', validatePasswordResetToken: { __typename?: 'ValidatePasswordResetToken', id: string, email: string } }; export type BillingPortalSessionQueryVariables = Exact<{ - returnUrlPath?: InputMaybe<Scalars['String']>; + returnUrlPath?: InputMaybe<Scalars['String']>; }>; export type BillingPortalSessionQuery = { __typename?: 'Query', billingPortalSession: { __typename?: 'SessionEntity', url?: string | null } }; export type CheckoutSessionMutationVariables = Exact<{ - recurringInterval: SubscriptionInterval; - successUrlPath?: InputMaybe<Scalars['String']>; + recurringInterval: SubscriptionInterval; + successUrlPath?: InputMaybe<Scalars['String']>; }>; export type CheckoutSessionMutation = { __typename?: 'Mutation', checkoutSession: { __typename?: 'SessionEntity', url?: string | null } }; export type GetProductPricesQueryVariables = Exact<{ - product: Scalars['String']; + product: Scalars['String']; }>; @@ -1480,7 +1506,7 @@ export type UpdateBillingSubscriptionMutation = { __typename?: 'Mutation', updat export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>; -export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, signUpDisabled: boolean, debugMode: boolean, chromeExtensionId?: string | null, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean, microsoft: boolean }, billing: { __typename?: 'Billing', isBillingEnabled: boolean, billingUrl?: string | null, billingFreeTrialDurationInDays?: number | null }, telemetry: { __typename?: 'Telemetry', enabled: boolean }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null }, sentry: { __typename?: 'Sentry', dsn?: string | null, environment?: string | null, release?: string | null }, captcha: { __typename?: 'Captcha', provider?: CaptchaDriverType | null, siteKey?: string | null }, api: { __typename?: 'ApiConfig', mutationMaximumAffectedRecords: number } } }; +export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, signUpDisabled: boolean, debugMode: boolean, chromeExtensionId?: string | null, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean, microsoft: boolean }, billing: { __typename?: 'Billing', isBillingEnabled: boolean, billingUrl?: string | null, billingFreeTrialDurationInDays?: number | null }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null }, sentry: { __typename?: 'Sentry', dsn?: string | null, environment?: string | null, release?: string | null }, captcha: { __typename?: 'Captcha', provider?: CaptchaDriverType | null, siteKey?: string | null }, api: { __typename?: 'ApiConfig', mutationMaximumAffectedRecords: number } } }; export type SkipSyncEmailOnboardingStepMutationVariables = Exact<{ [key: string]: never; }>; @@ -1488,7 +1514,7 @@ export type SkipSyncEmailOnboardingStepMutationVariables = Exact<{ [key: string] export type SkipSyncEmailOnboardingStepMutation = { __typename?: 'Mutation', skipSyncEmailOnboardingStep: { __typename?: 'OnboardingStepSuccess', success: boolean } }; export type GetAisqlQueryQueryVariables = Exact<{ - text: Scalars['String']; + text: Scalars['String']; }>; @@ -1502,7 +1528,7 @@ export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; } export type DeleteUserAccountMutation = { __typename?: 'Mutation', deleteUser: { __typename?: 'User', id: any } }; export type UploadProfilePictureMutationVariables = Exact<{ - file: Scalars['Upload']; + file: Scalars['Upload']; }>; @@ -1513,17 +1539,64 @@ export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>; export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } }; +export type ActivateWorkflowVersionMutationVariables = Exact<{ + workflowVersionId: Scalars['String']; +}>; + + +export type ActivateWorkflowVersionMutation = { __typename?: 'Mutation', activateWorkflowVersion: boolean }; + +export type DeactivateWorkflowVersionMutationVariables = Exact<{ + workflowVersionId: Scalars['String']; +}>; + + +export type DeactivateWorkflowVersionMutation = { __typename?: 'Mutation', deactivateWorkflowVersion: boolean }; + +export type DeleteWorkspaceInvitationMutationVariables = Exact<{ + appTokenId: Scalars['String']; +}>; + + +export type DeleteWorkspaceInvitationMutation = { __typename?: 'Mutation', deleteWorkspaceInvitation: string }; + +export type ResendWorkspaceInvitationMutationVariables = Exact<{ + appTokenId: Scalars['String']; +}>; + + +export type ResendWorkspaceInvitationMutation = { __typename?: 'Mutation', resendWorkspaceInvitation: { __typename?: 'SendInvitationsOutput', success: boolean, errors: Array<string>, result: Array<{ __typename?: 'WorkspaceInvitation', id: any, email: string, expiresAt: string }> } }; + +export type SendInvitationsMutationVariables = Exact<{ + emails: Array<Scalars['String']> | Scalars['String']; +}>; + + +export type SendInvitationsMutation = { __typename?: 'Mutation', sendInvitations: { __typename?: 'SendInvitationsOutput', success: boolean, errors: Array<string>, result: Array<{ __typename?: 'WorkspaceInvitation', id: any, email: string, expiresAt: string }> } }; + +export type GetWorkspaceInvitationsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetWorkspaceInvitationsQuery = { __typename?: 'Query', findWorkspaceInvitations: Array<{ __typename?: 'WorkspaceInvitation', id: any, email: string, expiresAt: string }> }; + export type WorkspaceMemberQueryFragmentFragment = { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }; export type AddUserToWorkspaceMutationVariables = Exact<{ - inviteHash: Scalars['String']; + inviteHash: Scalars['String']; }>; export type AddUserToWorkspaceMutation = { __typename?: 'Mutation', addUserToWorkspace: { __typename?: 'User', id: any } }; +export type AddUserToWorkspaceByInviteTokenMutationVariables = Exact<{ + inviteToken: Scalars['String']; +}>; + + +export type AddUserToWorkspaceByInviteTokenMutation = { __typename?: 'Mutation', addUserToWorkspaceByInviteToken: { __typename?: 'User', id: any } }; + export type ActivateWorkspaceMutationVariables = Exact<{ - input: ActivateWorkspaceInput; + input: ActivateWorkspaceInput; }>; @@ -1534,29 +1607,22 @@ export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: nev export type DeleteCurrentWorkspaceMutation = { __typename?: 'Mutation', deleteCurrentWorkspace: { __typename?: 'Workspace', id: any } }; -export type SendInviteLinkMutationVariables = Exact<{ - emails: Array<Scalars['String']> | Scalars['String']; -}>; - - -export type SendInviteLinkMutation = { __typename?: 'Mutation', sendInviteLink: { __typename?: 'SendInviteLink', success: boolean } }; - export type UpdateWorkspaceMutationVariables = Exact<{ - input: UpdateWorkspaceInput; + input: UpdateWorkspaceInput; }>; export type UpdateWorkspaceMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: any, domainName?: string | null, displayName?: string | null, logo?: string | null, allowImpersonation: boolean } }; export type UploadWorkspaceLogoMutationVariables = Exact<{ - file: Scalars['Upload']; + file: Scalars['Upload']; }>; export type UploadWorkspaceLogoMutation = { __typename?: 'Mutation', uploadWorkspaceLogo: string }; export type GetWorkspaceFromInviteHashQueryVariables = Exact<{ - inviteHash: Scalars['String']; + inviteHash: Scalars['String']; }>; @@ -1564,165 +1630,165 @@ export type GetWorkspaceFromInviteHashQuery = { __typename?: 'Query', findWorksp export const TimelineCalendarEventParticipantFragmentFragmentDoc = gql` fragment TimelineCalendarEventParticipantFragment on TimelineCalendarEventParticipant { - personId - workspaceMemberId - firstName - lastName - displayName - avatarUrl - handle -} - `; + personId + workspaceMemberId + firstName + lastName + displayName + avatarUrl + handle + } +`; export const TimelineCalendarEventFragmentFragmentDoc = gql` fragment TimelineCalendarEventFragment on TimelineCalendarEvent { - id - title - description - location - startsAt - endsAt - isFullDay - visibility - participants { - ...TimelineCalendarEventParticipantFragment - } -} - ${TimelineCalendarEventParticipantFragmentFragmentDoc}`; + id + title + description + location + startsAt + endsAt + isFullDay + visibility + participants { + ...TimelineCalendarEventParticipantFragment + } + } +${TimelineCalendarEventParticipantFragmentFragmentDoc}`; export const TimelineCalendarEventsWithTotalFragmentFragmentDoc = gql` fragment TimelineCalendarEventsWithTotalFragment on TimelineCalendarEventsWithTotal { - totalNumberOfCalendarEvents - timelineCalendarEvents { - ...TimelineCalendarEventFragment - } -} - ${TimelineCalendarEventFragmentFragmentDoc}`; + totalNumberOfCalendarEvents + timelineCalendarEvents { + ...TimelineCalendarEventFragment + } + } +${TimelineCalendarEventFragmentFragmentDoc}`; export const ParticipantFragmentFragmentDoc = gql` fragment ParticipantFragment on TimelineThreadParticipant { - personId - workspaceMemberId - firstName - lastName - displayName - avatarUrl - handle -} - `; + personId + workspaceMemberId + firstName + lastName + displayName + avatarUrl + handle + } +`; export const TimelineThreadFragmentFragmentDoc = gql` fragment TimelineThreadFragment on TimelineThread { - id - read - visibility - firstParticipant { - ...ParticipantFragment - } - lastTwoParticipants { - ...ParticipantFragment - } - lastMessageReceivedAt - lastMessageBody - subject - numberOfMessagesInThread - participantCount -} - ${ParticipantFragmentFragmentDoc}`; + id + read + visibility + firstParticipant { + ...ParticipantFragment + } + lastTwoParticipants { + ...ParticipantFragment + } + lastMessageReceivedAt + lastMessageBody + subject + numberOfMessagesInThread + participantCount + } +${ParticipantFragmentFragmentDoc}`; export const TimelineThreadsWithTotalFragmentFragmentDoc = gql` fragment TimelineThreadsWithTotalFragment on TimelineThreadsWithTotal { - totalNumberOfThreads - timelineThreads { - ...TimelineThreadFragment - } -} - ${TimelineThreadFragmentFragmentDoc}`; + totalNumberOfThreads + timelineThreads { + ...TimelineThreadFragment + } + } +${TimelineThreadFragmentFragmentDoc}`; export const AuthTokenFragmentFragmentDoc = gql` fragment AuthTokenFragment on AuthToken { - token - expiresAt -} - `; + token + expiresAt + } +`; export const AuthTokensFragmentFragmentDoc = gql` fragment AuthTokensFragment on AuthTokenPair { - accessToken { - ...AuthTokenFragment - } - refreshToken { - ...AuthTokenFragment - } -} - ${AuthTokenFragmentFragmentDoc}`; + accessToken { + ...AuthTokenFragment + } + refreshToken { + ...AuthTokenFragment + } + } +${AuthTokenFragmentFragmentDoc}`; export const WorkspaceMemberQueryFragmentFragmentDoc = gql` fragment WorkspaceMemberQueryFragment on WorkspaceMember { - id - name { - firstName - lastName - } - colorScheme - avatarUrl - locale - timeZone - dateFormat - timeFormat -} - `; + id + name { + firstName + lastName + } + colorScheme + avatarUrl + locale + timeZone + dateFormat + timeFormat + } +`; export const UserQueryFragmentFragmentDoc = gql` fragment UserQueryFragment on User { - id - firstName - lastName - email - canImpersonate - supportUserHash - onboardingStatus - workspaceMember { - ...WorkspaceMemberQueryFragment - } - workspaceMembers { - ...WorkspaceMemberQueryFragment - } - defaultWorkspace { - id - displayName - logo - domainName - inviteHash - allowImpersonation - activationStatus - featureFlags { - id - key - value - workspaceId - } - metadataVersion - currentBillingSubscription { - id - status - interval - } - workspaceMembersCount - } - workspaces { - workspace { - id - logo - displayName - domainName + id + firstName + lastName + email + canImpersonate + supportUserHash + onboardingStatus + workspaceMember { + ...WorkspaceMemberQueryFragment + } + workspaceMembers { + ...WorkspaceMemberQueryFragment + } + defaultWorkspace { + id + displayName + logo + domainName + inviteHash + allowImpersonation + activationStatus + featureFlags { + id + key + value + workspaceId + } + metadataVersion + currentBillingSubscription { + id + status + interval + } + workspaceMembersCount + } + workspaces { + workspace { + id + logo + displayName + domainName + } + } + userVars } - } - userVars -} - ${WorkspaceMemberQueryFragmentFragmentDoc}`; +${WorkspaceMemberQueryFragmentFragmentDoc}`; export const GetTimelineCalendarEventsFromCompanyIdDocument = gql` query GetTimelineCalendarEventsFromCompanyId($companyId: UUID!, $page: Int!, $pageSize: Int!) { - getTimelineCalendarEventsFromCompanyId( - companyId: $companyId - page: $page - pageSize: $pageSize - ) { - ...TimelineCalendarEventsWithTotalFragment - } -} - ${TimelineCalendarEventsWithTotalFragmentFragmentDoc}`; + getTimelineCalendarEventsFromCompanyId( + companyId: $companyId + page: $page + pageSize: $pageSize + ) { + ...TimelineCalendarEventsWithTotalFragment + } + } +${TimelineCalendarEventsWithTotalFragmentFragmentDoc}`; /** * __useGetTimelineCalendarEventsFromCompanyIdQuery__ @@ -1743,27 +1809,27 @@ export const GetTimelineCalendarEventsFromCompanyIdDocument = gql` * }); */ export function useGetTimelineCalendarEventsFromCompanyIdQuery(baseOptions: Apollo.QueryHookOptions<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>(GetTimelineCalendarEventsFromCompanyIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>(GetTimelineCalendarEventsFromCompanyIdDocument, options); +} export function useGetTimelineCalendarEventsFromCompanyIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>(GetTimelineCalendarEventsFromCompanyIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>(GetTimelineCalendarEventsFromCompanyIdDocument, options); +} export type GetTimelineCalendarEventsFromCompanyIdQueryHookResult = ReturnType<typeof useGetTimelineCalendarEventsFromCompanyIdQuery>; export type GetTimelineCalendarEventsFromCompanyIdLazyQueryHookResult = ReturnType<typeof useGetTimelineCalendarEventsFromCompanyIdLazyQuery>; export type GetTimelineCalendarEventsFromCompanyIdQueryResult = Apollo.QueryResult<GetTimelineCalendarEventsFromCompanyIdQuery, GetTimelineCalendarEventsFromCompanyIdQueryVariables>; export const GetTimelineCalendarEventsFromPersonIdDocument = gql` query GetTimelineCalendarEventsFromPersonId($personId: UUID!, $page: Int!, $pageSize: Int!) { - getTimelineCalendarEventsFromPersonId( - personId: $personId - page: $page - pageSize: $pageSize - ) { - ...TimelineCalendarEventsWithTotalFragment - } -} - ${TimelineCalendarEventsWithTotalFragmentFragmentDoc}`; + getTimelineCalendarEventsFromPersonId( + personId: $personId + page: $page + pageSize: $pageSize + ) { + ...TimelineCalendarEventsWithTotalFragment + } + } +${TimelineCalendarEventsWithTotalFragmentFragmentDoc}`; /** * __useGetTimelineCalendarEventsFromPersonIdQuery__ @@ -1784,27 +1850,27 @@ export const GetTimelineCalendarEventsFromPersonIdDocument = gql` * }); */ export function useGetTimelineCalendarEventsFromPersonIdQuery(baseOptions: Apollo.QueryHookOptions<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>(GetTimelineCalendarEventsFromPersonIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>(GetTimelineCalendarEventsFromPersonIdDocument, options); +} export function useGetTimelineCalendarEventsFromPersonIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>(GetTimelineCalendarEventsFromPersonIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>(GetTimelineCalendarEventsFromPersonIdDocument, options); +} export type GetTimelineCalendarEventsFromPersonIdQueryHookResult = ReturnType<typeof useGetTimelineCalendarEventsFromPersonIdQuery>; export type GetTimelineCalendarEventsFromPersonIdLazyQueryHookResult = ReturnType<typeof useGetTimelineCalendarEventsFromPersonIdLazyQuery>; export type GetTimelineCalendarEventsFromPersonIdQueryResult = Apollo.QueryResult<GetTimelineCalendarEventsFromPersonIdQuery, GetTimelineCalendarEventsFromPersonIdQueryVariables>; export const GetTimelineThreadsFromCompanyIdDocument = gql` query GetTimelineThreadsFromCompanyId($companyId: UUID!, $page: Int!, $pageSize: Int!) { - getTimelineThreadsFromCompanyId( - companyId: $companyId - page: $page - pageSize: $pageSize - ) { - ...TimelineThreadsWithTotalFragment - } -} - ${TimelineThreadsWithTotalFragmentFragmentDoc}`; + getTimelineThreadsFromCompanyId( + companyId: $companyId + page: $page + pageSize: $pageSize + ) { + ...TimelineThreadsWithTotalFragment + } + } +${TimelineThreadsWithTotalFragmentFragmentDoc}`; /** * __useGetTimelineThreadsFromCompanyIdQuery__ @@ -1825,27 +1891,27 @@ export const GetTimelineThreadsFromCompanyIdDocument = gql` * }); */ export function useGetTimelineThreadsFromCompanyIdQuery(baseOptions: Apollo.QueryHookOptions<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>(GetTimelineThreadsFromCompanyIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>(GetTimelineThreadsFromCompanyIdDocument, options); +} export function useGetTimelineThreadsFromCompanyIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>(GetTimelineThreadsFromCompanyIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>(GetTimelineThreadsFromCompanyIdDocument, options); +} export type GetTimelineThreadsFromCompanyIdQueryHookResult = ReturnType<typeof useGetTimelineThreadsFromCompanyIdQuery>; export type GetTimelineThreadsFromCompanyIdLazyQueryHookResult = ReturnType<typeof useGetTimelineThreadsFromCompanyIdLazyQuery>; export type GetTimelineThreadsFromCompanyIdQueryResult = Apollo.QueryResult<GetTimelineThreadsFromCompanyIdQuery, GetTimelineThreadsFromCompanyIdQueryVariables>; export const GetTimelineThreadsFromPersonIdDocument = gql` query GetTimelineThreadsFromPersonId($personId: UUID!, $page: Int!, $pageSize: Int!) { - getTimelineThreadsFromPersonId( - personId: $personId - page: $page - pageSize: $pageSize - ) { - ...TimelineThreadsWithTotalFragment - } -} - ${TimelineThreadsWithTotalFragmentFragmentDoc}`; + getTimelineThreadsFromPersonId( + personId: $personId + page: $page + pageSize: $pageSize + ) { + ...TimelineThreadsWithTotalFragment + } + } +${TimelineThreadsWithTotalFragmentFragmentDoc}`; /** * __useGetTimelineThreadsFromPersonIdQuery__ @@ -1866,23 +1932,23 @@ export const GetTimelineThreadsFromPersonIdDocument = gql` * }); */ export function useGetTimelineThreadsFromPersonIdQuery(baseOptions: Apollo.QueryHookOptions<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>(GetTimelineThreadsFromPersonIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>(GetTimelineThreadsFromPersonIdDocument, options); +} export function useGetTimelineThreadsFromPersonIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>(GetTimelineThreadsFromPersonIdDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>(GetTimelineThreadsFromPersonIdDocument, options); +} export type GetTimelineThreadsFromPersonIdQueryHookResult = ReturnType<typeof useGetTimelineThreadsFromPersonIdQuery>; export type GetTimelineThreadsFromPersonIdLazyQueryHookResult = ReturnType<typeof useGetTimelineThreadsFromPersonIdLazyQuery>; export type GetTimelineThreadsFromPersonIdQueryResult = Apollo.QueryResult<GetTimelineThreadsFromPersonIdQuery, GetTimelineThreadsFromPersonIdQueryVariables>; export const TrackDocument = gql` - mutation Track($type: String!, $data: JSON!) { - track(type: $type, data: $data) { - success - } -} - `; + mutation Track($action: String!, $payload: JSON!) { + track(action: $action, payload: $payload) { + success + } + } +`; export type TrackMutationFn = Apollo.MutationFunction<TrackMutation, TrackMutationVariables>; /** @@ -1898,23 +1964,23 @@ export type TrackMutationFn = Apollo.MutationFunction<TrackMutation, TrackMutati * @example * const [trackMutation, { data, loading, error }] = useTrackMutation({ * variables: { - * type: // value for 'type' - * data: // value for 'data' + * action: // value for 'type' + * payload: // value for 'payload' * }, * }); */ export function useTrackMutation(baseOptions?: Apollo.MutationHookOptions<TrackMutation, TrackMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<TrackMutation, TrackMutationVariables>(TrackDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<TrackMutation, TrackMutationVariables>(TrackDocument, options); +} export type TrackMutationHookResult = ReturnType<typeof useTrackMutation>; export type TrackMutationResult = Apollo.MutationResult<TrackMutation>; export type TrackMutationOptions = Apollo.BaseMutationOptions<TrackMutation, TrackMutationVariables>; export const UploadFileDocument = gql` mutation uploadFile($file: Upload!, $fileFolder: FileFolder) { - uploadFile(file: $file, fileFolder: $fileFolder) -} - `; + uploadFile(file: $file, fileFolder: $fileFolder) + } +`; export type UploadFileMutationFn = Apollo.MutationFunction<UploadFileMutation, UploadFileMutationVariables>; /** @@ -1936,17 +2002,17 @@ export type UploadFileMutationFn = Apollo.MutationFunction<UploadFileMutation, U * }); */ export function useUploadFileMutation(baseOptions?: Apollo.MutationHookOptions<UploadFileMutation, UploadFileMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UploadFileMutation, UploadFileMutationVariables>(UploadFileDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UploadFileMutation, UploadFileMutationVariables>(UploadFileDocument, options); +} export type UploadFileMutationHookResult = ReturnType<typeof useUploadFileMutation>; export type UploadFileMutationResult = Apollo.MutationResult<UploadFileMutation>; export type UploadFileMutationOptions = Apollo.BaseMutationOptions<UploadFileMutation, UploadFileMutationVariables>; export const UploadImageDocument = gql` mutation uploadImage($file: Upload!, $fileFolder: FileFolder) { - uploadImage(file: $file, fileFolder: $fileFolder) -} - `; + uploadImage(file: $file, fileFolder: $fileFolder) + } +`; export type UploadImageMutationFn = Apollo.MutationFunction<UploadImageMutation, UploadImageMutationVariables>; /** @@ -1968,23 +2034,23 @@ export type UploadImageMutationFn = Apollo.MutationFunction<UploadImageMutation, * }); */ export function useUploadImageMutation(baseOptions?: Apollo.MutationHookOptions<UploadImageMutation, UploadImageMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UploadImageMutation, UploadImageMutationVariables>(UploadImageDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UploadImageMutation, UploadImageMutationVariables>(UploadImageDocument, options); +} export type UploadImageMutationHookResult = ReturnType<typeof useUploadImageMutation>; export type UploadImageMutationResult = Apollo.MutationResult<UploadImageMutation>; export type UploadImageMutationOptions = Apollo.BaseMutationOptions<UploadImageMutation, UploadImageMutationVariables>; export const AuthorizeAppDocument = gql` mutation authorizeApp($clientId: String!, $codeChallenge: String!, $redirectUrl: String!) { - authorizeApp( - clientId: $clientId - codeChallenge: $codeChallenge - redirectUrl: $redirectUrl - ) { - redirectUrl - } -} - `; + authorizeApp( + clientId: $clientId + codeChallenge: $codeChallenge + redirectUrl: $redirectUrl + ) { + redirectUrl + } + } +`; export type AuthorizeAppMutationFn = Apollo.MutationFunction<AuthorizeAppMutation, AuthorizeAppMutationVariables>; /** @@ -2007,21 +2073,21 @@ export type AuthorizeAppMutationFn = Apollo.MutationFunction<AuthorizeAppMutatio * }); */ export function useAuthorizeAppMutation(baseOptions?: Apollo.MutationHookOptions<AuthorizeAppMutation, AuthorizeAppMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<AuthorizeAppMutation, AuthorizeAppMutationVariables>(AuthorizeAppDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<AuthorizeAppMutation, AuthorizeAppMutationVariables>(AuthorizeAppDocument, options); +} export type AuthorizeAppMutationHookResult = ReturnType<typeof useAuthorizeAppMutation>; export type AuthorizeAppMutationResult = Apollo.MutationResult<AuthorizeAppMutation>; export type AuthorizeAppMutationOptions = Apollo.BaseMutationOptions<AuthorizeAppMutation, AuthorizeAppMutationVariables>; export const ChallengeDocument = gql` mutation Challenge($email: String!, $password: String!, $captchaToken: String) { - challenge(email: $email, password: $password, captchaToken: $captchaToken) { - loginToken { - ...AuthTokenFragment + challenge(email: $email, password: $password, captchaToken: $captchaToken) { + loginToken { + ...AuthTokenFragment + } + } } - } -} - ${AuthTokenFragmentFragmentDoc}`; +${AuthTokenFragmentFragmentDoc}`; export type ChallengeMutationFn = Apollo.MutationFunction<ChallengeMutation, ChallengeMutationVariables>; /** @@ -2044,19 +2110,19 @@ export type ChallengeMutationFn = Apollo.MutationFunction<ChallengeMutation, Cha * }); */ export function useChallengeMutation(baseOptions?: Apollo.MutationHookOptions<ChallengeMutation, ChallengeMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<ChallengeMutation, ChallengeMutationVariables>(ChallengeDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<ChallengeMutation, ChallengeMutationVariables>(ChallengeDocument, options); +} export type ChallengeMutationHookResult = ReturnType<typeof useChallengeMutation>; export type ChallengeMutationResult = Apollo.MutationResult<ChallengeMutation>; export type ChallengeMutationOptions = Apollo.BaseMutationOptions<ChallengeMutation, ChallengeMutationVariables>; export const EmailPasswordResetLinkDocument = gql` mutation EmailPasswordResetLink($email: String!) { - emailPasswordResetLink(email: $email) { - success - } -} - `; + emailPasswordResetLink(email: $email) { + success + } + } +`; export type EmailPasswordResetLinkMutationFn = Apollo.MutationFunction<EmailPasswordResetLinkMutation, EmailPasswordResetLinkMutationVariables>; /** @@ -2077,19 +2143,19 @@ export type EmailPasswordResetLinkMutationFn = Apollo.MutationFunction<EmailPass * }); */ export function useEmailPasswordResetLinkMutation(baseOptions?: Apollo.MutationHookOptions<EmailPasswordResetLinkMutation, EmailPasswordResetLinkMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<EmailPasswordResetLinkMutation, EmailPasswordResetLinkMutationVariables>(EmailPasswordResetLinkDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<EmailPasswordResetLinkMutation, EmailPasswordResetLinkMutationVariables>(EmailPasswordResetLinkDocument, options); +} export type EmailPasswordResetLinkMutationHookResult = ReturnType<typeof useEmailPasswordResetLinkMutation>; export type EmailPasswordResetLinkMutationResult = Apollo.MutationResult<EmailPasswordResetLinkMutation>; export type EmailPasswordResetLinkMutationOptions = Apollo.BaseMutationOptions<EmailPasswordResetLinkMutation, EmailPasswordResetLinkMutationVariables>; export const GenerateApiKeyTokenDocument = gql` mutation GenerateApiKeyToken($apiKeyId: String!, $expiresAt: String!) { - generateApiKeyToken(apiKeyId: $apiKeyId, expiresAt: $expiresAt) { - token - } -} - `; + generateApiKeyToken(apiKeyId: $apiKeyId, expiresAt: $expiresAt) { + token + } + } +`; export type GenerateApiKeyTokenMutationFn = Apollo.MutationFunction<GenerateApiKeyTokenMutation, GenerateApiKeyTokenMutationVariables>; /** @@ -2111,21 +2177,21 @@ export type GenerateApiKeyTokenMutationFn = Apollo.MutationFunction<GenerateApiK * }); */ export function useGenerateApiKeyTokenMutation(baseOptions?: Apollo.MutationHookOptions<GenerateApiKeyTokenMutation, GenerateApiKeyTokenMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<GenerateApiKeyTokenMutation, GenerateApiKeyTokenMutationVariables>(GenerateApiKeyTokenDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<GenerateApiKeyTokenMutation, GenerateApiKeyTokenMutationVariables>(GenerateApiKeyTokenDocument, options); +} export type GenerateApiKeyTokenMutationHookResult = ReturnType<typeof useGenerateApiKeyTokenMutation>; export type GenerateApiKeyTokenMutationResult = Apollo.MutationResult<GenerateApiKeyTokenMutation>; export type GenerateApiKeyTokenMutationOptions = Apollo.BaseMutationOptions<GenerateApiKeyTokenMutation, GenerateApiKeyTokenMutationVariables>; export const GenerateJwtDocument = gql` mutation GenerateJWT($workspaceId: String!) { - generateJWT(workspaceId: $workspaceId) { - tokens { - ...AuthTokensFragment + generateJWT(workspaceId: $workspaceId) { + tokens { + ...AuthTokensFragment + } + } } - } -} - ${AuthTokensFragmentFragmentDoc}`; +${AuthTokensFragmentFragmentDoc}`; export type GenerateJwtMutationFn = Apollo.MutationFunction<GenerateJwtMutation, GenerateJwtMutationVariables>; /** @@ -2146,21 +2212,21 @@ export type GenerateJwtMutationFn = Apollo.MutationFunction<GenerateJwtMutation, * }); */ export function useGenerateJwtMutation(baseOptions?: Apollo.MutationHookOptions<GenerateJwtMutation, GenerateJwtMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<GenerateJwtMutation, GenerateJwtMutationVariables>(GenerateJwtDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<GenerateJwtMutation, GenerateJwtMutationVariables>(GenerateJwtDocument, options); +} export type GenerateJwtMutationHookResult = ReturnType<typeof useGenerateJwtMutation>; export type GenerateJwtMutationResult = Apollo.MutationResult<GenerateJwtMutation>; export type GenerateJwtMutationOptions = Apollo.BaseMutationOptions<GenerateJwtMutation, GenerateJwtMutationVariables>; export const GenerateTransientTokenDocument = gql` mutation generateTransientToken { - generateTransientToken { - transientToken { - token + generateTransientToken { + transientToken { + token + } + } } - } -} - `; +`; export type GenerateTransientTokenMutationFn = Apollo.MutationFunction<GenerateTransientTokenMutation, GenerateTransientTokenMutationVariables>; /** @@ -2180,23 +2246,23 @@ export type GenerateTransientTokenMutationFn = Apollo.MutationFunction<GenerateT * }); */ export function useGenerateTransientTokenMutation(baseOptions?: Apollo.MutationHookOptions<GenerateTransientTokenMutation, GenerateTransientTokenMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<GenerateTransientTokenMutation, GenerateTransientTokenMutationVariables>(GenerateTransientTokenDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<GenerateTransientTokenMutation, GenerateTransientTokenMutationVariables>(GenerateTransientTokenDocument, options); +} export type GenerateTransientTokenMutationHookResult = ReturnType<typeof useGenerateTransientTokenMutation>; export type GenerateTransientTokenMutationResult = Apollo.MutationResult<GenerateTransientTokenMutation>; export type GenerateTransientTokenMutationOptions = Apollo.BaseMutationOptions<GenerateTransientTokenMutation, GenerateTransientTokenMutationVariables>; export const ImpersonateDocument = gql` mutation Impersonate($userId: String!) { - impersonate(userId: $userId) { - user { - ...UserQueryFragment - } - tokens { - ...AuthTokensFragment + impersonate(userId: $userId) { + user { + ...UserQueryFragment + } + tokens { + ...AuthTokensFragment + } + } } - } -} ${UserQueryFragmentFragmentDoc} ${AuthTokensFragmentFragmentDoc}`; export type ImpersonateMutationFn = Apollo.MutationFunction<ImpersonateMutation, ImpersonateMutationVariables>; @@ -2219,21 +2285,21 @@ export type ImpersonateMutationFn = Apollo.MutationFunction<ImpersonateMutation, * }); */ export function useImpersonateMutation(baseOptions?: Apollo.MutationHookOptions<ImpersonateMutation, ImpersonateMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<ImpersonateMutation, ImpersonateMutationVariables>(ImpersonateDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<ImpersonateMutation, ImpersonateMutationVariables>(ImpersonateDocument, options); +} export type ImpersonateMutationHookResult = ReturnType<typeof useImpersonateMutation>; export type ImpersonateMutationResult = Apollo.MutationResult<ImpersonateMutation>; export type ImpersonateMutationOptions = Apollo.BaseMutationOptions<ImpersonateMutation, ImpersonateMutationVariables>; export const RenewTokenDocument = gql` mutation RenewToken($appToken: String!) { - renewToken(appToken: $appToken) { - tokens { - ...AuthTokensFragment + renewToken(appToken: $appToken) { + tokens { + ...AuthTokensFragment + } + } } - } -} - ${AuthTokensFragmentFragmentDoc}`; +${AuthTokensFragmentFragmentDoc}`; export type RenewTokenMutationFn = Apollo.MutationFunction<RenewTokenMutation, RenewTokenMutationVariables>; /** @@ -2254,26 +2320,27 @@ export type RenewTokenMutationFn = Apollo.MutationFunction<RenewTokenMutation, R * }); */ export function useRenewTokenMutation(baseOptions?: Apollo.MutationHookOptions<RenewTokenMutation, RenewTokenMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<RenewTokenMutation, RenewTokenMutationVariables>(RenewTokenDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<RenewTokenMutation, RenewTokenMutationVariables>(RenewTokenDocument, options); +} export type RenewTokenMutationHookResult = ReturnType<typeof useRenewTokenMutation>; export type RenewTokenMutationResult = Apollo.MutationResult<RenewTokenMutation>; export type RenewTokenMutationOptions = Apollo.BaseMutationOptions<RenewTokenMutation, RenewTokenMutationVariables>; export const SignUpDocument = gql` - mutation SignUp($email: String!, $password: String!, $workspaceInviteHash: String, $captchaToken: String) { - signUp( - email: $email - password: $password - workspaceInviteHash: $workspaceInviteHash - captchaToken: $captchaToken - ) { - loginToken { - ...AuthTokenFragment + mutation SignUp($email: String!, $password: String!, $workspaceInviteHash: String, $workspacePersonalInviteToken: String = null, $captchaToken: String) { + signUp( + email: $email + password: $password + workspaceInviteHash: $workspaceInviteHash + workspacePersonalInviteToken: $workspacePersonalInviteToken + captchaToken: $captchaToken + ) { + loginToken { + ...AuthTokenFragment + } + } } - } -} - ${AuthTokenFragmentFragmentDoc}`; +${AuthTokenFragmentFragmentDoc}`; export type SignUpMutationFn = Apollo.MutationFunction<SignUpMutation, SignUpMutationVariables>; /** @@ -2292,27 +2359,28 @@ export type SignUpMutationFn = Apollo.MutationFunction<SignUpMutation, SignUpMut * email: // value for 'email' * password: // value for 'password' * workspaceInviteHash: // value for 'workspaceInviteHash' + * workspacePersonalInviteToken: // value for 'workspacePersonalInviteToken' * captchaToken: // value for 'captchaToken' * }, * }); */ export function useSignUpMutation(baseOptions?: Apollo.MutationHookOptions<SignUpMutation, SignUpMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<SignUpMutation, SignUpMutationVariables>(SignUpDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<SignUpMutation, SignUpMutationVariables>(SignUpDocument, options); +} export type SignUpMutationHookResult = ReturnType<typeof useSignUpMutation>; export type SignUpMutationResult = Apollo.MutationResult<SignUpMutation>; export type SignUpMutationOptions = Apollo.BaseMutationOptions<SignUpMutation, SignUpMutationVariables>; export const UpdatePasswordViaResetTokenDocument = gql` mutation UpdatePasswordViaResetToken($token: String!, $newPassword: String!) { - updatePasswordViaResetToken( - passwordResetToken: $token - newPassword: $newPassword - ) { - success - } -} - `; + updatePasswordViaResetToken( + passwordResetToken: $token + newPassword: $newPassword + ) { + success + } + } +`; export type UpdatePasswordViaResetTokenMutationFn = Apollo.MutationFunction<UpdatePasswordViaResetTokenMutation, UpdatePasswordViaResetTokenMutationVariables>; /** @@ -2334,23 +2402,23 @@ export type UpdatePasswordViaResetTokenMutationFn = Apollo.MutationFunction<Upda * }); */ export function useUpdatePasswordViaResetTokenMutation(baseOptions?: Apollo.MutationHookOptions<UpdatePasswordViaResetTokenMutation, UpdatePasswordViaResetTokenMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UpdatePasswordViaResetTokenMutation, UpdatePasswordViaResetTokenMutationVariables>(UpdatePasswordViaResetTokenDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UpdatePasswordViaResetTokenMutation, UpdatePasswordViaResetTokenMutationVariables>(UpdatePasswordViaResetTokenDocument, options); +} export type UpdatePasswordViaResetTokenMutationHookResult = ReturnType<typeof useUpdatePasswordViaResetTokenMutation>; export type UpdatePasswordViaResetTokenMutationResult = Apollo.MutationResult<UpdatePasswordViaResetTokenMutation>; export type UpdatePasswordViaResetTokenMutationOptions = Apollo.BaseMutationOptions<UpdatePasswordViaResetTokenMutation, UpdatePasswordViaResetTokenMutationVariables>; export const VerifyDocument = gql` mutation Verify($loginToken: String!) { - verify(loginToken: $loginToken) { - user { - ...UserQueryFragment - } - tokens { - ...AuthTokensFragment + verify(loginToken: $loginToken) { + user { + ...UserQueryFragment + } + tokens { + ...AuthTokensFragment + } + } } - } -} ${UserQueryFragmentFragmentDoc} ${AuthTokensFragmentFragmentDoc}`; export type VerifyMutationFn = Apollo.MutationFunction<VerifyMutation, VerifyMutationVariables>; @@ -2373,19 +2441,19 @@ export type VerifyMutationFn = Apollo.MutationFunction<VerifyMutation, VerifyMut * }); */ export function useVerifyMutation(baseOptions?: Apollo.MutationHookOptions<VerifyMutation, VerifyMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<VerifyMutation, VerifyMutationVariables>(VerifyDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<VerifyMutation, VerifyMutationVariables>(VerifyDocument, options); +} export type VerifyMutationHookResult = ReturnType<typeof useVerifyMutation>; export type VerifyMutationResult = Apollo.MutationResult<VerifyMutation>; export type VerifyMutationOptions = Apollo.BaseMutationOptions<VerifyMutation, VerifyMutationVariables>; export const CheckUserExistsDocument = gql` query CheckUserExists($email: String!, $captchaToken: String) { - checkUserExists(email: $email, captchaToken: $captchaToken) { - exists - } -} - `; + checkUserExists(email: $email, captchaToken: $captchaToken) { + exists + } + } +`; /** * __useCheckUserExistsQuery__ @@ -2405,24 +2473,24 @@ export const CheckUserExistsDocument = gql` * }); */ export function useCheckUserExistsQuery(baseOptions: Apollo.QueryHookOptions<CheckUserExistsQuery, CheckUserExistsQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<CheckUserExistsQuery, CheckUserExistsQueryVariables>(CheckUserExistsDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<CheckUserExistsQuery, CheckUserExistsQueryVariables>(CheckUserExistsDocument, options); +} export function useCheckUserExistsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<CheckUserExistsQuery, CheckUserExistsQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<CheckUserExistsQuery, CheckUserExistsQueryVariables>(CheckUserExistsDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<CheckUserExistsQuery, CheckUserExistsQueryVariables>(CheckUserExistsDocument, options); +} export type CheckUserExistsQueryHookResult = ReturnType<typeof useCheckUserExistsQuery>; export type CheckUserExistsLazyQueryHookResult = ReturnType<typeof useCheckUserExistsLazyQuery>; export type CheckUserExistsQueryResult = Apollo.QueryResult<CheckUserExistsQuery, CheckUserExistsQueryVariables>; export const ValidatePasswordResetTokenDocument = gql` query ValidatePasswordResetToken($token: String!) { - validatePasswordResetToken(passwordResetToken: $token) { - id - email - } -} - `; + validatePasswordResetToken(passwordResetToken: $token) { + id + email + } + } +`; /** * __useValidatePasswordResetTokenQuery__ @@ -2441,23 +2509,23 @@ export const ValidatePasswordResetTokenDocument = gql` * }); */ export function useValidatePasswordResetTokenQuery(baseOptions: Apollo.QueryHookOptions<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>(ValidatePasswordResetTokenDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>(ValidatePasswordResetTokenDocument, options); +} export function useValidatePasswordResetTokenLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>(ValidatePasswordResetTokenDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>(ValidatePasswordResetTokenDocument, options); +} export type ValidatePasswordResetTokenQueryHookResult = ReturnType<typeof useValidatePasswordResetTokenQuery>; export type ValidatePasswordResetTokenLazyQueryHookResult = ReturnType<typeof useValidatePasswordResetTokenLazyQuery>; export type ValidatePasswordResetTokenQueryResult = Apollo.QueryResult<ValidatePasswordResetTokenQuery, ValidatePasswordResetTokenQueryVariables>; export const BillingPortalSessionDocument = gql` query BillingPortalSession($returnUrlPath: String) { - billingPortalSession(returnUrlPath: $returnUrlPath) { - url - } -} - `; + billingPortalSession(returnUrlPath: $returnUrlPath) { + url + } + } +`; /** * __useBillingPortalSessionQuery__ @@ -2476,26 +2544,26 @@ export const BillingPortalSessionDocument = gql` * }); */ export function useBillingPortalSessionQuery(baseOptions?: Apollo.QueryHookOptions<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>(BillingPortalSessionDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>(BillingPortalSessionDocument, options); +} export function useBillingPortalSessionLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>(BillingPortalSessionDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>(BillingPortalSessionDocument, options); +} export type BillingPortalSessionQueryHookResult = ReturnType<typeof useBillingPortalSessionQuery>; export type BillingPortalSessionLazyQueryHookResult = ReturnType<typeof useBillingPortalSessionLazyQuery>; export type BillingPortalSessionQueryResult = Apollo.QueryResult<BillingPortalSessionQuery, BillingPortalSessionQueryVariables>; export const CheckoutSessionDocument = gql` mutation CheckoutSession($recurringInterval: SubscriptionInterval!, $successUrlPath: String) { - checkoutSession( - recurringInterval: $recurringInterval - successUrlPath: $successUrlPath - ) { - url - } -} - `; + checkoutSession( + recurringInterval: $recurringInterval + successUrlPath: $successUrlPath + ) { + url + } + } +`; export type CheckoutSessionMutationFn = Apollo.MutationFunction<CheckoutSessionMutation, CheckoutSessionMutationVariables>; /** @@ -2517,24 +2585,24 @@ export type CheckoutSessionMutationFn = Apollo.MutationFunction<CheckoutSessionM * }); */ export function useCheckoutSessionMutation(baseOptions?: Apollo.MutationHookOptions<CheckoutSessionMutation, CheckoutSessionMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<CheckoutSessionMutation, CheckoutSessionMutationVariables>(CheckoutSessionDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<CheckoutSessionMutation, CheckoutSessionMutationVariables>(CheckoutSessionDocument, options); +} export type CheckoutSessionMutationHookResult = ReturnType<typeof useCheckoutSessionMutation>; export type CheckoutSessionMutationResult = Apollo.MutationResult<CheckoutSessionMutation>; export type CheckoutSessionMutationOptions = Apollo.BaseMutationOptions<CheckoutSessionMutation, CheckoutSessionMutationVariables>; export const GetProductPricesDocument = gql` query GetProductPrices($product: String!) { - getProductPrices(product: $product) { - productPrices { - created - recurringInterval - stripePriceId - unitAmount + getProductPrices(product: $product) { + productPrices { + created + recurringInterval + stripePriceId + unitAmount + } + } } - } -} - `; +`; /** * __useGetProductPricesQuery__ @@ -2553,23 +2621,23 @@ export const GetProductPricesDocument = gql` * }); */ export function useGetProductPricesQuery(baseOptions: Apollo.QueryHookOptions<GetProductPricesQuery, GetProductPricesQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetProductPricesQuery, GetProductPricesQueryVariables>(GetProductPricesDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetProductPricesQuery, GetProductPricesQueryVariables>(GetProductPricesDocument, options); +} export function useGetProductPricesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetProductPricesQuery, GetProductPricesQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetProductPricesQuery, GetProductPricesQueryVariables>(GetProductPricesDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetProductPricesQuery, GetProductPricesQueryVariables>(GetProductPricesDocument, options); +} export type GetProductPricesQueryHookResult = ReturnType<typeof useGetProductPricesQuery>; export type GetProductPricesLazyQueryHookResult = ReturnType<typeof useGetProductPricesLazyQuery>; export type GetProductPricesQueryResult = Apollo.QueryResult<GetProductPricesQuery, GetProductPricesQueryVariables>; export const UpdateBillingSubscriptionDocument = gql` mutation UpdateBillingSubscription { - updateBillingSubscription { - success - } -} - `; + updateBillingSubscription { + success + } + } +`; export type UpdateBillingSubscriptionMutationFn = Apollo.MutationFunction<UpdateBillingSubscriptionMutation, UpdateBillingSubscriptionMutationVariables>; /** @@ -2589,51 +2657,48 @@ export type UpdateBillingSubscriptionMutationFn = Apollo.MutationFunction<Update * }); */ export function useUpdateBillingSubscriptionMutation(baseOptions?: Apollo.MutationHookOptions<UpdateBillingSubscriptionMutation, UpdateBillingSubscriptionMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UpdateBillingSubscriptionMutation, UpdateBillingSubscriptionMutationVariables>(UpdateBillingSubscriptionDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UpdateBillingSubscriptionMutation, UpdateBillingSubscriptionMutationVariables>(UpdateBillingSubscriptionDocument, options); +} export type UpdateBillingSubscriptionMutationHookResult = ReturnType<typeof useUpdateBillingSubscriptionMutation>; export type UpdateBillingSubscriptionMutationResult = Apollo.MutationResult<UpdateBillingSubscriptionMutation>; export type UpdateBillingSubscriptionMutationOptions = Apollo.BaseMutationOptions<UpdateBillingSubscriptionMutation, UpdateBillingSubscriptionMutationVariables>; export const GetClientConfigDocument = gql` query GetClientConfig { - clientConfig { - authProviders { - google - password - microsoft - } - billing { - isBillingEnabled - billingUrl - billingFreeTrialDurationInDays - } - signInPrefilled - signUpDisabled - debugMode - telemetry { - enabled - } - support { - supportDriver - supportFrontChatId - } - sentry { - dsn - environment - release - } - captcha { - provider - siteKey - } - api { - mutationMaximumAffectedRecords + clientConfig { + authProviders { + google + password + microsoft + } + billing { + isBillingEnabled + billingUrl + billingFreeTrialDurationInDays + } + signInPrefilled + signUpDisabled + debugMode + support { + supportDriver + supportFrontChatId + } + sentry { + dsn + environment + release + } + captcha { + provider + siteKey + } + api { + mutationMaximumAffectedRecords + } + chromeExtensionId + } } - chromeExtensionId - } -} - `; +`; /** * __useGetClientConfigQuery__ @@ -2651,23 +2716,23 @@ export const GetClientConfigDocument = gql` * }); */ export function useGetClientConfigQuery(baseOptions?: Apollo.QueryHookOptions<GetClientConfigQuery, GetClientConfigQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetClientConfigQuery, GetClientConfigQueryVariables>(GetClientConfigDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetClientConfigQuery, GetClientConfigQueryVariables>(GetClientConfigDocument, options); +} export function useGetClientConfigLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetClientConfigQuery, GetClientConfigQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetClientConfigQuery, GetClientConfigQueryVariables>(GetClientConfigDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetClientConfigQuery, GetClientConfigQueryVariables>(GetClientConfigDocument, options); +} export type GetClientConfigQueryHookResult = ReturnType<typeof useGetClientConfigQuery>; export type GetClientConfigLazyQueryHookResult = ReturnType<typeof useGetClientConfigLazyQuery>; export type GetClientConfigQueryResult = Apollo.QueryResult<GetClientConfigQuery, GetClientConfigQueryVariables>; export const SkipSyncEmailOnboardingStepDocument = gql` mutation SkipSyncEmailOnboardingStep { - skipSyncEmailOnboardingStep { - success - } -} - `; + skipSyncEmailOnboardingStep { + success + } + } +`; export type SkipSyncEmailOnboardingStepMutationFn = Apollo.MutationFunction<SkipSyncEmailOnboardingStepMutation, SkipSyncEmailOnboardingStepMutationVariables>; /** @@ -2687,21 +2752,21 @@ export type SkipSyncEmailOnboardingStepMutationFn = Apollo.MutationFunction<Skip * }); */ export function useSkipSyncEmailOnboardingStepMutation(baseOptions?: Apollo.MutationHookOptions<SkipSyncEmailOnboardingStepMutation, SkipSyncEmailOnboardingStepMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<SkipSyncEmailOnboardingStepMutation, SkipSyncEmailOnboardingStepMutationVariables>(SkipSyncEmailOnboardingStepDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<SkipSyncEmailOnboardingStepMutation, SkipSyncEmailOnboardingStepMutationVariables>(SkipSyncEmailOnboardingStepDocument, options); +} export type SkipSyncEmailOnboardingStepMutationHookResult = ReturnType<typeof useSkipSyncEmailOnboardingStepMutation>; export type SkipSyncEmailOnboardingStepMutationResult = Apollo.MutationResult<SkipSyncEmailOnboardingStepMutation>; export type SkipSyncEmailOnboardingStepMutationOptions = Apollo.BaseMutationOptions<SkipSyncEmailOnboardingStepMutation, SkipSyncEmailOnboardingStepMutationVariables>; export const GetAisqlQueryDocument = gql` query GetAISQLQuery($text: String!) { - getAISQLQuery(text: $text) { - sqlQuery - sqlQueryResult - queryFailedErrorMessage - } -} - `; + getAISQLQuery(text: $text) { + sqlQuery + sqlQueryResult + queryFailedErrorMessage + } + } +`; /** * __useGetAisqlQueryQuery__ @@ -2720,23 +2785,23 @@ export const GetAisqlQueryDocument = gql` * }); */ export function useGetAisqlQueryQuery(baseOptions: Apollo.QueryHookOptions<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>(GetAisqlQueryDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>(GetAisqlQueryDocument, options); +} export function useGetAisqlQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>(GetAisqlQueryDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>(GetAisqlQueryDocument, options); +} export type GetAisqlQueryQueryHookResult = ReturnType<typeof useGetAisqlQueryQuery>; export type GetAisqlQueryLazyQueryHookResult = ReturnType<typeof useGetAisqlQueryLazyQuery>; export type GetAisqlQueryQueryResult = Apollo.QueryResult<GetAisqlQueryQuery, GetAisqlQueryQueryVariables>; export const DeleteUserAccountDocument = gql` mutation DeleteUserAccount { - deleteUser { - id - } -} - `; + deleteUser { + id + } + } +`; export type DeleteUserAccountMutationFn = Apollo.MutationFunction<DeleteUserAccountMutation, DeleteUserAccountMutationVariables>; /** @@ -2756,17 +2821,17 @@ export type DeleteUserAccountMutationFn = Apollo.MutationFunction<DeleteUserAcco * }); */ export function useDeleteUserAccountMutation(baseOptions?: Apollo.MutationHookOptions<DeleteUserAccountMutation, DeleteUserAccountMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<DeleteUserAccountMutation, DeleteUserAccountMutationVariables>(DeleteUserAccountDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<DeleteUserAccountMutation, DeleteUserAccountMutationVariables>(DeleteUserAccountDocument, options); +} export type DeleteUserAccountMutationHookResult = ReturnType<typeof useDeleteUserAccountMutation>; export type DeleteUserAccountMutationResult = Apollo.MutationResult<DeleteUserAccountMutation>; export type DeleteUserAccountMutationOptions = Apollo.BaseMutationOptions<DeleteUserAccountMutation, DeleteUserAccountMutationVariables>; export const UploadProfilePictureDocument = gql` mutation UploadProfilePicture($file: Upload!) { - uploadProfilePicture(file: $file) -} - `; + uploadProfilePicture(file: $file) + } +`; export type UploadProfilePictureMutationFn = Apollo.MutationFunction<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>; /** @@ -2787,19 +2852,19 @@ export type UploadProfilePictureMutationFn = Apollo.MutationFunction<UploadProfi * }); */ export function useUploadProfilePictureMutation(baseOptions?: Apollo.MutationHookOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>(UploadProfilePictureDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>(UploadProfilePictureDocument, options); +} export type UploadProfilePictureMutationHookResult = ReturnType<typeof useUploadProfilePictureMutation>; export type UploadProfilePictureMutationResult = Apollo.MutationResult<UploadProfilePictureMutation>; export type UploadProfilePictureMutationOptions = Apollo.BaseMutationOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>; export const GetCurrentUserDocument = gql` query GetCurrentUser { - currentUser { - ...UserQueryFragment - } -} - ${UserQueryFragmentFragmentDoc}`; + currentUser { + ...UserQueryFragment + } + } +${UserQueryFragmentFragmentDoc}`; /** * __useGetCurrentUserQuery__ @@ -2817,23 +2882,234 @@ export const GetCurrentUserDocument = gql` * }); */ export function useGetCurrentUserQuery(baseOptions?: Apollo.QueryHookOptions<GetCurrentUserQuery, GetCurrentUserQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetCurrentUserQuery, GetCurrentUserQueryVariables>(GetCurrentUserDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetCurrentUserQuery, GetCurrentUserQueryVariables>(GetCurrentUserDocument, options); +} export function useGetCurrentUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetCurrentUserQuery, GetCurrentUserQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetCurrentUserQuery, GetCurrentUserQueryVariables>(GetCurrentUserDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetCurrentUserQuery, GetCurrentUserQueryVariables>(GetCurrentUserDocument, options); +} export type GetCurrentUserQueryHookResult = ReturnType<typeof useGetCurrentUserQuery>; export type GetCurrentUserLazyQueryHookResult = ReturnType<typeof useGetCurrentUserLazyQuery>; export type GetCurrentUserQueryResult = Apollo.QueryResult<GetCurrentUserQuery, GetCurrentUserQueryVariables>; +export const ActivateWorkflowVersionDocument = gql` + mutation ActivateWorkflowVersion($workflowVersionId: String!) { + activateWorkflowVersion(workflowVersionId: $workflowVersionId) + } +`; +export type ActivateWorkflowVersionMutationFn = Apollo.MutationFunction<ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutationVariables>; + +/** + * __useActivateWorkflowVersionMutation__ + * + * To run a mutation, you first call `useActivateWorkflowVersionMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useActivateWorkflowVersionMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [activateWorkflowVersionMutation, { data, loading, error }] = useActivateWorkflowVersionMutation({ + * variables: { + * workflowVersionId: // value for 'workflowVersionId' + * }, + * }); + */ +export function useActivateWorkflowVersionMutation(baseOptions?: Apollo.MutationHookOptions<ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutationVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutationVariables>(ActivateWorkflowVersionDocument, options); +} +export type ActivateWorkflowVersionMutationHookResult = ReturnType<typeof useActivateWorkflowVersionMutation>; +export type ActivateWorkflowVersionMutationResult = Apollo.MutationResult<ActivateWorkflowVersionMutation>; +export type ActivateWorkflowVersionMutationOptions = Apollo.BaseMutationOptions<ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutationVariables>; +export const DeactivateWorkflowVersionDocument = gql` + mutation DeactivateWorkflowVersion($workflowVersionId: String!) { + deactivateWorkflowVersion(workflowVersionId: $workflowVersionId) + } +`; +export type DeactivateWorkflowVersionMutationFn = Apollo.MutationFunction<DeactivateWorkflowVersionMutation, DeactivateWorkflowVersionMutationVariables>; + +/** + * __useDeactivateWorkflowVersionMutation__ + * + * To run a mutation, you first call `useDeactivateWorkflowVersionMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeactivateWorkflowVersionMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deactivateWorkflowVersionMutation, { data, loading, error }] = useDeactivateWorkflowVersionMutation({ + * variables: { + * workflowVersionId: // value for 'workflowVersionId' + * }, + * }); + */ +export function useDeactivateWorkflowVersionMutation(baseOptions?: Apollo.MutationHookOptions<DeactivateWorkflowVersionMutation, DeactivateWorkflowVersionMutationVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<DeactivateWorkflowVersionMutation, DeactivateWorkflowVersionMutationVariables>(DeactivateWorkflowVersionDocument, options); +} +export type DeactivateWorkflowVersionMutationHookResult = ReturnType<typeof useDeactivateWorkflowVersionMutation>; +export type DeactivateWorkflowVersionMutationResult = Apollo.MutationResult<DeactivateWorkflowVersionMutation>; +export type DeactivateWorkflowVersionMutationOptions = Apollo.BaseMutationOptions<DeactivateWorkflowVersionMutation, DeactivateWorkflowVersionMutationVariables>; +export const DeleteWorkspaceInvitationDocument = gql` + mutation DeleteWorkspaceInvitation($appTokenId: String!) { + deleteWorkspaceInvitation(appTokenId: $appTokenId) + } +`; +export type DeleteWorkspaceInvitationMutationFn = Apollo.MutationFunction<DeleteWorkspaceInvitationMutation, DeleteWorkspaceInvitationMutationVariables>; + +/** + * __useDeleteWorkspaceInvitationMutation__ + * + * To run a mutation, you first call `useDeleteWorkspaceInvitationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteWorkspaceInvitationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteWorkspaceInvitationMutation, { data, loading, error }] = useDeleteWorkspaceInvitationMutation({ + * variables: { + * appTokenId: // value for 'appTokenId' + * }, + * }); + */ +export function useDeleteWorkspaceInvitationMutation(baseOptions?: Apollo.MutationHookOptions<DeleteWorkspaceInvitationMutation, DeleteWorkspaceInvitationMutationVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<DeleteWorkspaceInvitationMutation, DeleteWorkspaceInvitationMutationVariables>(DeleteWorkspaceInvitationDocument, options); +} +export type DeleteWorkspaceInvitationMutationHookResult = ReturnType<typeof useDeleteWorkspaceInvitationMutation>; +export type DeleteWorkspaceInvitationMutationResult = Apollo.MutationResult<DeleteWorkspaceInvitationMutation>; +export type DeleteWorkspaceInvitationMutationOptions = Apollo.BaseMutationOptions<DeleteWorkspaceInvitationMutation, DeleteWorkspaceInvitationMutationVariables>; +export const ResendWorkspaceInvitationDocument = gql` + mutation ResendWorkspaceInvitation($appTokenId: String!) { + resendWorkspaceInvitation(appTokenId: $appTokenId) { + success + errors + result { + ... on WorkspaceInvitation { + id + email + expiresAt + } + } + } + } +`; +export type ResendWorkspaceInvitationMutationFn = Apollo.MutationFunction<ResendWorkspaceInvitationMutation, ResendWorkspaceInvitationMutationVariables>; + +/** + * __useResendWorkspaceInvitationMutation__ + * + * To run a mutation, you first call `useResendWorkspaceInvitationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useResendWorkspaceInvitationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [resendWorkspaceInvitationMutation, { data, loading, error }] = useResendWorkspaceInvitationMutation({ + * variables: { + * appTokenId: // value for 'appTokenId' + * }, + * }); + */ +export function useResendWorkspaceInvitationMutation(baseOptions?: Apollo.MutationHookOptions<ResendWorkspaceInvitationMutation, ResendWorkspaceInvitationMutationVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<ResendWorkspaceInvitationMutation, ResendWorkspaceInvitationMutationVariables>(ResendWorkspaceInvitationDocument, options); +} +export type ResendWorkspaceInvitationMutationHookResult = ReturnType<typeof useResendWorkspaceInvitationMutation>; +export type ResendWorkspaceInvitationMutationResult = Apollo.MutationResult<ResendWorkspaceInvitationMutation>; +export type ResendWorkspaceInvitationMutationOptions = Apollo.BaseMutationOptions<ResendWorkspaceInvitationMutation, ResendWorkspaceInvitationMutationVariables>; +export const SendInvitationsDocument = gql` + mutation SendInvitations($emails: [String!]!) { + sendInvitations(emails: $emails) { + success + errors + result { + ... on WorkspaceInvitation { + id + email + expiresAt + } + } + } + } +`; +export type SendInvitationsMutationFn = Apollo.MutationFunction<SendInvitationsMutation, SendInvitationsMutationVariables>; + +/** + * __useSendInvitationsMutation__ + * + * To run a mutation, you first call `useSendInvitationsMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useSendInvitationsMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [sendInvitationsMutation, { data, loading, error }] = useSendInvitationsMutation({ + * variables: { + * emails: // value for 'emails' + * }, + * }); + */ +export function useSendInvitationsMutation(baseOptions?: Apollo.MutationHookOptions<SendInvitationsMutation, SendInvitationsMutationVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<SendInvitationsMutation, SendInvitationsMutationVariables>(SendInvitationsDocument, options); +} +export type SendInvitationsMutationHookResult = ReturnType<typeof useSendInvitationsMutation>; +export type SendInvitationsMutationResult = Apollo.MutationResult<SendInvitationsMutation>; +export type SendInvitationsMutationOptions = Apollo.BaseMutationOptions<SendInvitationsMutation, SendInvitationsMutationVariables>; +export const GetWorkspaceInvitationsDocument = gql` + query GetWorkspaceInvitations { + findWorkspaceInvitations { + id + email + expiresAt + } + } +`; + +/** + * __useGetWorkspaceInvitationsQuery__ + * + * To run a query within a React component, call `useGetWorkspaceInvitationsQuery` and pass it any options that fit your needs. + * When your component renders, `useGetWorkspaceInvitationsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetWorkspaceInvitationsQuery({ + * variables: { + * }, + * }); + */ +export function useGetWorkspaceInvitationsQuery(baseOptions?: Apollo.QueryHookOptions<GetWorkspaceInvitationsQuery, GetWorkspaceInvitationsQueryVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetWorkspaceInvitationsQuery, GetWorkspaceInvitationsQueryVariables>(GetWorkspaceInvitationsDocument, options); +} +export function useGetWorkspaceInvitationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetWorkspaceInvitationsQuery, GetWorkspaceInvitationsQueryVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetWorkspaceInvitationsQuery, GetWorkspaceInvitationsQueryVariables>(GetWorkspaceInvitationsDocument, options); +} +export type GetWorkspaceInvitationsQueryHookResult = ReturnType<typeof useGetWorkspaceInvitationsQuery>; +export type GetWorkspaceInvitationsLazyQueryHookResult = ReturnType<typeof useGetWorkspaceInvitationsLazyQuery>; +export type GetWorkspaceInvitationsQueryResult = Apollo.QueryResult<GetWorkspaceInvitationsQuery, GetWorkspaceInvitationsQueryVariables>; export const AddUserToWorkspaceDocument = gql` mutation AddUserToWorkspace($inviteHash: String!) { - addUserToWorkspace(inviteHash: $inviteHash) { - id - } -} - `; + addUserToWorkspace(inviteHash: $inviteHash) { + id + } + } +`; export type AddUserToWorkspaceMutationFn = Apollo.MutationFunction<AddUserToWorkspaceMutation, AddUserToWorkspaceMutationVariables>; /** @@ -2854,19 +3130,52 @@ export type AddUserToWorkspaceMutationFn = Apollo.MutationFunction<AddUserToWork * }); */ export function useAddUserToWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<AddUserToWorkspaceMutation, AddUserToWorkspaceMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<AddUserToWorkspaceMutation, AddUserToWorkspaceMutationVariables>(AddUserToWorkspaceDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<AddUserToWorkspaceMutation, AddUserToWorkspaceMutationVariables>(AddUserToWorkspaceDocument, options); +} export type AddUserToWorkspaceMutationHookResult = ReturnType<typeof useAddUserToWorkspaceMutation>; export type AddUserToWorkspaceMutationResult = Apollo.MutationResult<AddUserToWorkspaceMutation>; export type AddUserToWorkspaceMutationOptions = Apollo.BaseMutationOptions<AddUserToWorkspaceMutation, AddUserToWorkspaceMutationVariables>; +export const AddUserToWorkspaceByInviteTokenDocument = gql` + mutation AddUserToWorkspaceByInviteToken($inviteToken: String!) { + addUserToWorkspaceByInviteToken(inviteToken: $inviteToken) { + id + } + } +`; +export type AddUserToWorkspaceByInviteTokenMutationFn = Apollo.MutationFunction<AddUserToWorkspaceByInviteTokenMutation, AddUserToWorkspaceByInviteTokenMutationVariables>; + +/** + * __useAddUserToWorkspaceByInviteTokenMutation__ + * + * To run a mutation, you first call `useAddUserToWorkspaceByInviteTokenMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useAddUserToWorkspaceByInviteTokenMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [addUserToWorkspaceByInviteTokenMutation, { data, loading, error }] = useAddUserToWorkspaceByInviteTokenMutation({ + * variables: { + * inviteToken: // value for 'inviteToken' + * }, + * }); + */ +export function useAddUserToWorkspaceByInviteTokenMutation(baseOptions?: Apollo.MutationHookOptions<AddUserToWorkspaceByInviteTokenMutation, AddUserToWorkspaceByInviteTokenMutationVariables>) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<AddUserToWorkspaceByInviteTokenMutation, AddUserToWorkspaceByInviteTokenMutationVariables>(AddUserToWorkspaceByInviteTokenDocument, options); +} +export type AddUserToWorkspaceByInviteTokenMutationHookResult = ReturnType<typeof useAddUserToWorkspaceByInviteTokenMutation>; +export type AddUserToWorkspaceByInviteTokenMutationResult = Apollo.MutationResult<AddUserToWorkspaceByInviteTokenMutation>; +export type AddUserToWorkspaceByInviteTokenMutationOptions = Apollo.BaseMutationOptions<AddUserToWorkspaceByInviteTokenMutation, AddUserToWorkspaceByInviteTokenMutationVariables>; export const ActivateWorkspaceDocument = gql` mutation ActivateWorkspace($input: ActivateWorkspaceInput!) { - activateWorkspace(data: $input) { - id - } -} - `; + activateWorkspace(data: $input) { + id + } + } +`; export type ActivateWorkspaceMutationFn = Apollo.MutationFunction<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>; /** @@ -2887,19 +3196,19 @@ export type ActivateWorkspaceMutationFn = Apollo.MutationFunction<ActivateWorksp * }); */ export function useActivateWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>(ActivateWorkspaceDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>(ActivateWorkspaceDocument, options); +} export type ActivateWorkspaceMutationHookResult = ReturnType<typeof useActivateWorkspaceMutation>; export type ActivateWorkspaceMutationResult = Apollo.MutationResult<ActivateWorkspaceMutation>; export type ActivateWorkspaceMutationOptions = Apollo.BaseMutationOptions<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>; export const DeleteCurrentWorkspaceDocument = gql` mutation DeleteCurrentWorkspace { - deleteCurrentWorkspace { - id - } -} - `; + deleteCurrentWorkspace { + id + } + } +`; export type DeleteCurrentWorkspaceMutationFn = Apollo.MutationFunction<DeleteCurrentWorkspaceMutation, DeleteCurrentWorkspaceMutationVariables>; /** @@ -2919,56 +3228,23 @@ export type DeleteCurrentWorkspaceMutationFn = Apollo.MutationFunction<DeleteCur * }); */ export function useDeleteCurrentWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<DeleteCurrentWorkspaceMutation, DeleteCurrentWorkspaceMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<DeleteCurrentWorkspaceMutation, DeleteCurrentWorkspaceMutationVariables>(DeleteCurrentWorkspaceDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<DeleteCurrentWorkspaceMutation, DeleteCurrentWorkspaceMutationVariables>(DeleteCurrentWorkspaceDocument, options); +} export type DeleteCurrentWorkspaceMutationHookResult = ReturnType<typeof useDeleteCurrentWorkspaceMutation>; export type DeleteCurrentWorkspaceMutationResult = Apollo.MutationResult<DeleteCurrentWorkspaceMutation>; export type DeleteCurrentWorkspaceMutationOptions = Apollo.BaseMutationOptions<DeleteCurrentWorkspaceMutation, DeleteCurrentWorkspaceMutationVariables>; -export const SendInviteLinkDocument = gql` - mutation SendInviteLink($emails: [String!]!) { - sendInviteLink(emails: $emails) { - success - } -} - `; -export type SendInviteLinkMutationFn = Apollo.MutationFunction<SendInviteLinkMutation, SendInviteLinkMutationVariables>; - -/** - * __useSendInviteLinkMutation__ - * - * To run a mutation, you first call `useSendInviteLinkMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useSendInviteLinkMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [sendInviteLinkMutation, { data, loading, error }] = useSendInviteLinkMutation({ - * variables: { - * emails: // value for 'emails' - * }, - * }); - */ -export function useSendInviteLinkMutation(baseOptions?: Apollo.MutationHookOptions<SendInviteLinkMutation, SendInviteLinkMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<SendInviteLinkMutation, SendInviteLinkMutationVariables>(SendInviteLinkDocument, options); - } -export type SendInviteLinkMutationHookResult = ReturnType<typeof useSendInviteLinkMutation>; -export type SendInviteLinkMutationResult = Apollo.MutationResult<SendInviteLinkMutation>; -export type SendInviteLinkMutationOptions = Apollo.BaseMutationOptions<SendInviteLinkMutation, SendInviteLinkMutationVariables>; export const UpdateWorkspaceDocument = gql` mutation UpdateWorkspace($input: UpdateWorkspaceInput!) { - updateWorkspace(data: $input) { - id - domainName - displayName - logo - allowImpersonation - } -} - `; + updateWorkspace(data: $input) { + id + domainName + displayName + logo + allowImpersonation + } + } +`; export type UpdateWorkspaceMutationFn = Apollo.MutationFunction<UpdateWorkspaceMutation, UpdateWorkspaceMutationVariables>; /** @@ -2989,17 +3265,17 @@ export type UpdateWorkspaceMutationFn = Apollo.MutationFunction<UpdateWorkspaceM * }); */ export function useUpdateWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<UpdateWorkspaceMutation, UpdateWorkspaceMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UpdateWorkspaceMutation, UpdateWorkspaceMutationVariables>(UpdateWorkspaceDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UpdateWorkspaceMutation, UpdateWorkspaceMutationVariables>(UpdateWorkspaceDocument, options); +} export type UpdateWorkspaceMutationHookResult = ReturnType<typeof useUpdateWorkspaceMutation>; export type UpdateWorkspaceMutationResult = Apollo.MutationResult<UpdateWorkspaceMutation>; export type UpdateWorkspaceMutationOptions = Apollo.BaseMutationOptions<UpdateWorkspaceMutation, UpdateWorkspaceMutationVariables>; export const UploadWorkspaceLogoDocument = gql` mutation UploadWorkspaceLogo($file: Upload!) { - uploadWorkspaceLogo(file: $file) -} - `; + uploadWorkspaceLogo(file: $file) + } +`; export type UploadWorkspaceLogoMutationFn = Apollo.MutationFunction<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>; /** @@ -3020,22 +3296,22 @@ export type UploadWorkspaceLogoMutationFn = Apollo.MutationFunction<UploadWorksp * }); */ export function useUploadWorkspaceLogoMutation(baseOptions?: Apollo.MutationHookOptions<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>(UploadWorkspaceLogoDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>(UploadWorkspaceLogoDocument, options); +} export type UploadWorkspaceLogoMutationHookResult = ReturnType<typeof useUploadWorkspaceLogoMutation>; export type UploadWorkspaceLogoMutationResult = Apollo.MutationResult<UploadWorkspaceLogoMutation>; export type UploadWorkspaceLogoMutationOptions = Apollo.BaseMutationOptions<UploadWorkspaceLogoMutation, UploadWorkspaceLogoMutationVariables>; export const GetWorkspaceFromInviteHashDocument = gql` query GetWorkspaceFromInviteHash($inviteHash: String!) { - findWorkspaceFromInviteHash(inviteHash: $inviteHash) { - id - displayName - logo - allowImpersonation - } -} - `; + findWorkspaceFromInviteHash(inviteHash: $inviteHash) { + id + displayName + logo + allowImpersonation + } + } +`; /** * __useGetWorkspaceFromInviteHashQuery__ @@ -3054,13 +3330,13 @@ export const GetWorkspaceFromInviteHashDocument = gql` * }); */ export function useGetWorkspaceFromInviteHashQuery(baseOptions: Apollo.QueryHookOptions<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>(GetWorkspaceFromInviteHashDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>(GetWorkspaceFromInviteHashDocument, options); +} export function useGetWorkspaceFromInviteHashLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>(GetWorkspaceFromInviteHashDocument, options); - } + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>(GetWorkspaceFromInviteHashDocument, options); +} export type GetWorkspaceFromInviteHashQueryHookResult = ReturnType<typeof useGetWorkspaceFromInviteHashQuery>; export type GetWorkspaceFromInviteHashLazyQueryHookResult = ReturnType<typeof useGetWorkspaceFromInviteHashLazyQuery>; export type GetWorkspaceFromInviteHashQueryResult = Apollo.QueryResult<GetWorkspaceFromInviteHashQuery, GetWorkspaceFromInviteHashQueryVariables>; \ No newline at end of file diff --git a/packages/twenty-front/src/hooks/usePreventOverlapCallback.ts b/packages/twenty-front/src/hooks/usePreventOverlapCallback.ts new file mode 100644 index 000000000000..0cd1c5b89845 --- /dev/null +++ b/packages/twenty-front/src/hooks/usePreventOverlapCallback.ts @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react'; +import { useDebouncedCallback } from 'use-debounce'; + +export const usePreventOverlapCallback = ( + callback: () => Promise<void>, + wait?: number, +) => { + const [isRunning, setIsRunning] = useState(false); + const [pendingRun, setPendingRun] = useState(false); + + const handleCallback = async () => { + if (isRunning) { + setPendingRun(true); + return; + } + setIsRunning(true); + try { + await callback(); + } finally { + setIsRunning(false); + } + }; + + useEffect(() => { + if (!isRunning && pendingRun) { + setPendingRun(false); + callback(); + } + }, [callback, isRunning, pendingRun, setPendingRun]); + + return useDebouncedCallback(handleCallback, wait); +}; diff --git a/packages/twenty-front/src/index.css b/packages/twenty-front/src/index.css index 2d696388b83b..808fd8917db4 100644 --- a/packages/twenty-front/src/index.css +++ b/packages/twenty-front/src/index.css @@ -12,4 +12,4 @@ html { /* https://stackoverflow.com/questions/44543157/how-to-hide-the-google-invisible-recaptcha-badge */ .grecaptcha-badge { visibility: hidden !important; -} \ No newline at end of file +} diff --git a/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts b/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts index 21915d2cdd68..9664352e7cf4 100644 --- a/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts +++ b/packages/twenty-front/src/modules/accounts/types/CalendarChannel.ts @@ -1,11 +1,39 @@ import { CalendarChannelVisibility } from '~/generated/graphql'; +export enum CalendarChannelSyncStatus { + NOT_SYNCED = 'NOT_SYNCED', + ONGOING = 'ONGOING', + ACTIVE = 'ACTIVE', + FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS', + FAILED_UNKNOWN = 'FAILED_UNKNOWN', +} + +export enum CalendarChannelSyncStage { + FULL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING', + PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING', + CALENDAR_EVENT_LIST_FETCH_ONGOING = 'CALENDAR_EVENT_LIST_FETCH_ONGOING', + CALENDAR_EVENTS_IMPORT_PENDING = 'CALENDAR_EVENTS_IMPORT_PENDING', + CALENDAR_EVENTS_IMPORT_ONGOING = 'CALENDAR_EVENTS_IMPORT_ONGOING', + FAILED = 'FAILED', +} + +export enum CalendarChannelContactAutoCreationPolicy { + AS_PARTICIPANT_AND_ORGANIZER = 'AS_PARTICIPANT_AND_ORGANIZER', + AS_PARTICIPANT = 'AS_PARTICIPANT', + AS_ORGANIZER = 'AS_ORGANIZER', + NONE = 'NONE', +} export type CalendarChannel = { id: string; handle: string; - isContactAutoCreationEnabled?: boolean; - isSyncEnabled?: boolean; + isContactAutoCreationEnabled: boolean; + contactAutoCreationPolicy: CalendarChannelContactAutoCreationPolicy; + isSyncEnabled: boolean; visibility: CalendarChannelVisibility; - syncStatus: string; + syncStatus: CalendarChannelSyncStatus; + syncStage: CalendarChannelSyncStage; + syncCursor: string; + syncStageStartedAt: Date; + throttleFailureCount: number; __typename: 'CalendarChannel'; }; diff --git a/packages/twenty-front/src/modules/accounts/types/MessageChannel.ts b/packages/twenty-front/src/modules/accounts/types/MessageChannel.ts index 33df519b4503..87d7752834f1 100644 --- a/packages/twenty-front/src/modules/accounts/types/MessageChannel.ts +++ b/packages/twenty-front/src/modules/accounts/types/MessageChannel.ts @@ -6,14 +6,35 @@ export enum MessageChannelContactAutoCreationPolicy { NONE = 'NONE', } +export enum MessageChannelSyncStatus { + NOT_SYNCED = 'NOT_SYNCED', + ONGOING = 'ONGOING', + ACTIVE = 'ACTIVE', + FAILED_INSUFFICIENT_PERMISSIONS = 'FAILED_INSUFFICIENT_PERMISSIONS', + FAILED_UNKNOWN = 'FAILED_UNKNOWN', +} + +export enum MessageChannelSyncStage { + FULL_MESSAGE_LIST_FETCH_PENDING = 'FULL_MESSAGE_LIST_FETCH_PENDING', + PARTIAL_MESSAGE_LIST_FETCH_PENDING = 'PARTIAL_MESSAGE_LIST_FETCH_PENDING', + MESSAGE_LIST_FETCH_ONGOING = 'MESSAGE_LIST_FETCH_ONGOING', + MESSAGES_IMPORT_PENDING = 'MESSAGES_IMPORT_PENDING', + MESSAGES_IMPORT_ONGOING = 'MESSAGES_IMPORT_ONGOING', + FAILED = 'FAILED', +} + export type MessageChannel = { id: string; handle: string; - contactAutoCreationPolicy?: MessageChannelContactAutoCreationPolicy; + contactAutoCreationPolicy: MessageChannelContactAutoCreationPolicy; excludeNonProfessionalEmails: boolean; excludeGroupEmails: boolean; isSyncEnabled: boolean; visibility: MessageChannelVisibility; - syncStatus: string; + syncStatus: MessageChannelSyncStatus; + syncStage: MessageChannelSyncStage; + syncCursor: string; + syncStageStartedAt: Date; + throttleFailureCount: number; __typename: 'MessageChannel'; }; diff --git a/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx b/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx index 5bc8afa2171a..360eccbbcc2a 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx @@ -63,7 +63,18 @@ export const Calendar = ({ TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE, ); - const { timelineCalendarEvents } = data?.[queryName] ?? {}; + const { timelineCalendarEvents, totalNumberOfCalendarEvents } = + data?.[queryName] ?? {}; + const hasMoreCalendarEvents = + timelineCalendarEvents && totalNumberOfCalendarEvents + ? timelineCalendarEvents?.length < totalNumberOfCalendarEvents + : false; + + const handleLastRowVisible = async () => { + if (hasMoreCalendarEvents) { + await fetchMoreRecords(); + } + }; const { calendarEventsByDayTime, @@ -134,7 +145,7 @@ export const Calendar = ({ })} <CustomResolverFetchMoreLoader loading={isFetchingMore || firstQueryLoading} - onLastRowVisible={fetchMoreRecords} + onLastRowVisible={handleLastRowVisible} /> </StyledContainer> </CalendarContext.Provider> diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx index a246ff432f31..cb9548f8bafa 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx @@ -176,7 +176,7 @@ export const CalendarEventRow = ({ : participant.displayName } placeholderColorSeed={ - participant.workspaceMemberId ?? participant.personId + participant.workspaceMemberId || participant.personId } type="rounded" /> diff --git a/packages/twenty-front/src/modules/activities/components/RichTextEditor.tsx b/packages/twenty-front/src/modules/activities/components/RichTextEditor.tsx index 32c344988140..c6842395f64f 100644 --- a/packages/twenty-front/src/modules/activities/components/RichTextEditor.tsx +++ b/packages/twenty-front/src/modules/activities/components/RichTextEditor.tsx @@ -256,10 +256,16 @@ export const RichTextEditor = ({ const handleBodyChangeDebounced = useDebouncedCallback(handleBodyChange, 500); + // See https://github.com/twentyhq/twenty/issues/6724 for explanation + const setActivityBodyDebouncedToAvoidDragBug = useDebouncedCallback( + setActivityBody, + 100, + ); + const handleEditorChange = () => { const newStringifiedBody = JSON.stringify(editor.document) ?? ''; - setActivityBody(newStringifiedBody); + setActivityBodyDebouncedToAvoidDragBug(newStringifiedBody); handleBodyChangeDebounced(newStringifiedBody); }; diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessage.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessage.tsx index 32dde14ba3bc..4f4a64b38686 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessage.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessage.tsx @@ -1,5 +1,5 @@ -import { useState } from 'react'; import styled from '@emotion/styled'; +import { useState } from 'react'; import { EmailThreadMessageBody } from '@/activities/emails/components/EmailThreadMessageBody'; import { EmailThreadMessageBodyPreview } from '@/activities/emails/components/EmailThreadMessageBodyPreview'; @@ -30,6 +30,7 @@ const StyledThreadMessageBody = styled.div` type EmailThreadMessageProps = { body: string; sentAt: string; + sender: EmailThreadMessageParticipant; participants: EmailThreadMessageParticipant[]; isExpanded?: boolean; }; @@ -37,17 +38,17 @@ type EmailThreadMessageProps = { export const EmailThreadMessage = ({ body, sentAt, + sender, participants, isExpanded = false, }: EmailThreadMessageProps) => { const [isOpen, setIsOpen] = useState(isExpanded); - const from = participants.find((participant) => participant.role === 'from'); const receivers = participants.filter( (participant) => participant.role !== 'from', ); - if (!from || receivers.length === 0) { + if (!sender || receivers.length === 0) { return null; } @@ -57,7 +58,7 @@ export const EmailThreadMessage = ({ style={{ cursor: isOpen ? 'auto' : 'pointer' }} > <StyledThreadMessageHeader onClick={() => isOpen && setIsOpen(false)}> - <EmailThreadMessageSender sender={from} sentAt={sentAt} /> + <EmailThreadMessageSender sender={sender} sentAt={sentAt} /> {isOpen && <EmailThreadMessageReceivers receivers={receivers} />} </StyledThreadMessageHeader> <StyledThreadMessageBody> diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx index e381b1bac358..bb7f8c1407f4 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadPreview.tsx @@ -1,5 +1,5 @@ -import { useRef } from 'react'; import styled from '@emotion/styled'; +import { useRef } from 'react'; import { useRecoilCallback } from 'recoil'; import { Avatar, GRAY_SCALE } from 'twenty-ui'; @@ -155,12 +155,20 @@ export const EmailThreadPreview = ({ <Avatar avatarUrl={thread?.firstParticipant?.avatarUrl} placeholder={thread.firstParticipant.displayName} + placeholderColorSeed={ + thread.firstParticipant.workspaceMemberId || + thread.firstParticipant.personId + } type="rounded" /> {thread?.lastTwoParticipants?.[0] && ( <StyledAvatar avatarUrl={thread.lastTwoParticipants[0].avatarUrl} placeholder={thread.lastTwoParticipants[0].displayName} + placeholderColorSeed={ + thread.lastTwoParticipants[0].workspaceMemberId || + thread.lastTwoParticipants[0].personId + } type="rounded" /> )} diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx index 53038755dc88..17f44524fea6 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx @@ -60,6 +60,16 @@ export const EmailThreads = ({ ); const { totalNumberOfThreads, timelineThreads } = data?.[queryName] ?? {}; + const hasMoreTimelineThreads = + timelineThreads && totalNumberOfThreads + ? timelineThreads?.length < totalNumberOfThreads + : false; + + const handleLastRowVisible = async () => { + if (hasMoreTimelineThreads) { + await fetchMoreRecords(); + } + }; if (firstQueryLoading) { return <SkeletonLoader />; @@ -108,7 +118,7 @@ export const EmailThreads = ({ )} <CustomResolverFetchMoreLoader loading={isFetchingMore || firstQueryLoading} - onLastRowVisible={fetchMoreRecords} + onLastRowVisible={handleLastRowVisible} /> </Section> </StyledContainer> diff --git a/packages/twenty-front/src/modules/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory.ts b/packages/twenty-front/src/modules/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory.ts index d141d867b223..f818332fddf4 100644 --- a/packages/twenty-front/src/modules/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory.ts +++ b/packages/twenty-front/src/modules/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory.ts @@ -47,11 +47,7 @@ export const fetchAllThreadMessagesOperationSignatureFactory: RecordGqlOperation id: true, role: true, displayName: true, - participant: { - id: true, - email: true, - name: true, - }, + handle: true, person: true, workspaceMember: true, }, diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/IntermediaryMessages.tsx b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/IntermediaryMessages.tsx index a830e8367f95..3ef96d57310e 100644 --- a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/IntermediaryMessages.tsx +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/IntermediaryMessages.tsx @@ -1,9 +1,9 @@ -import { useState } from 'react'; import styled from '@emotion/styled'; +import { useState } from 'react'; import { IconArrowsVertical } from 'twenty-ui'; import { EmailThreadMessage } from '@/activities/emails/components/EmailThreadMessage'; -import { EmailThreadMessage as EmailThreadMessageType } from '@/activities/emails/types/EmailThreadMessage'; +import { EmailThreadMessageWithSender } from '@/activities/emails/types/EmailThreadMessageWithSender'; import { Button } from '@/ui/input/button/components/Button'; const StyledButtonContainer = styled.div` @@ -14,7 +14,7 @@ const StyledButtonContainer = styled.div` export const IntermediaryMessages = ({ messages, }: { - messages: EmailThreadMessageType[]; + messages: EmailThreadMessageWithSender[]; }) => { const [areMessagesOpen, setAreMessagesOpen] = useState(false); @@ -26,6 +26,7 @@ export const IntermediaryMessages = ({ messages.map((message) => ( <EmailThreadMessage key={message.id} + sender={message.sender} participants={message.messageParticipants} body={message.text} sentAt={message.receivedAt} diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx index bd4003ce33da..42367f2f9adf 100644 --- a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerEmailThread.tsx @@ -13,33 +13,38 @@ import { Button } from '@/ui/input/button/components/Button'; import { RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID } from '@/ui/layout/right-drawer/constants/RightDrawerClickOutsideListener'; import { messageThreadState } from '@/ui/layout/right-drawer/states/messageThreadState'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { IconArrowBackUp } from 'twenty-ui'; +const StyledWrapper = styled.div` + display: flex; + flex-direction: column; + height: 100%; +`; + const StyledContainer = styled.div` box-sizing: border-box; display: flex; flex-direction: column; + flex: 1; height: 85%; - justify-content: flex-start; overflow-y: auto; - position: relative; `; -const StyledButtonContainer = styled.div` +const StyledButtonContainer = styled.div<{ isMobile: boolean }>` background: ${({ theme }) => theme.background.secondary}; - bottom: 0; + border-top: 1px solid ${({ theme }) => theme.border.color.light}; display: flex; - height: 110px; - left: 0; - padding-left: ${({ theme }) => theme.spacing(7)}; - padding-top: ${({ theme }) => theme.spacing(5)}; - position: fixed; - right: 0; + justify-content: flex-end; + height: ${({ isMobile }) => (isMobile ? '100px' : '50px')}; + padding: ${({ theme }) => theme.spacing(2)}; + width: 100%; + box-sizing: border-box; `; export const RightDrawerEmailThread = () => { const setMessageThread = useSetRecoilState(messageThreadState); - + const isMobile = useIsMobile(); const { thread, messages, @@ -50,23 +55,11 @@ export const RightDrawerEmailThread = () => { messageChannelLoading, } = useRightDrawerEmailThread(); - const visibleMessages = useMemo(() => { - return messages.filter(({ messageParticipants }) => { - const from = messageParticipants.find( - (participant) => participant.role === 'from', - ); - const receivers = messageParticipants.filter( - (participant) => participant.role !== 'from', - ); - return from && receivers.length > 0; - }); - }, [messages]); - useEffect(() => { - if (!visibleMessages[0]?.messageThread) { + if (!messages[0]?.messageThread) { return; } - setMessageThread(visibleMessages[0]?.messageThread); + setMessageThread(messages[0]?.messageThread); }); const { useRegisterClickOutsideListenerCallback } = useClickOutsideListener( @@ -88,17 +81,17 @@ export const RightDrawerEmailThread = () => { ), }); - const visibleMessagesCount = visibleMessages.length; - const is5OrMoreMessages = visibleMessagesCount >= 5; - const firstMessages = visibleMessages.slice( + const messagesCount = messages.length; + const is5OrMoreMessages = messagesCount >= 5; + const firstMessages = messages.slice( 0, - is5OrMoreMessages ? 2 : visibleMessagesCount - 1, + is5OrMoreMessages ? 2 : messagesCount - 1, ); const intermediaryMessages = is5OrMoreMessages - ? visibleMessages.slice(2, visibleMessagesCount - 1) + ? messages.slice(2, messagesCount - 1) : []; - const lastMessage = visibleMessages[visibleMessagesCount - 1]; - const subject = visibleMessages[0]?.subject; + const lastMessage = messages[messagesCount - 1]; + const subject = messages[0]?.subject; const canReply = useMemo(() => { return ( @@ -114,51 +107,55 @@ export const RightDrawerEmailThread = () => { const url = `https://mail.google.com/mail/?authuser=${connectedAccountHandle}#all/${messageThreadExternalId}`; window.open(url, '_blank'); }; - if (!thread) { + if (!thread || !messages.length) { return null; } return ( - <StyledContainer> - {threadLoading ? ( - <EmailLoader loadingText="Loading thread" /> - ) : ( - <> - <EmailThreadHeader - subject={subject} - lastMessageSentAt={lastMessage.receivedAt} - /> - {firstMessages.map((message) => ( + <StyledWrapper> + <StyledContainer> + {threadLoading ? ( + <EmailLoader loadingText="Loading thread" /> + ) : ( + <> + <EmailThreadHeader + subject={subject} + lastMessageSentAt={lastMessage.receivedAt} + /> + {firstMessages.map((message) => ( + <EmailThreadMessage + key={message.id} + sender={message.sender} + participants={message.messageParticipants} + body={message.text} + sentAt={message.receivedAt} + /> + ))} + <IntermediaryMessages messages={intermediaryMessages} /> <EmailThreadMessage - key={message.id} - participants={message.messageParticipants} - body={message.text} - sentAt={message.receivedAt} + key={lastMessage.id} + sender={lastMessage.sender} + participants={lastMessage.messageParticipants} + body={lastMessage.text} + sentAt={lastMessage.receivedAt} + isExpanded /> - ))} - <IntermediaryMessages messages={intermediaryMessages} /> - <EmailThreadMessage - key={lastMessage.id} - participants={lastMessage.messageParticipants} - body={lastMessage.text} - sentAt={lastMessage.receivedAt} - isExpanded - /> - <CustomResolverFetchMoreLoader - loading={threadLoading} - onLastRowVisible={fetchMoreMessages} - /> - </> - )} - {canReply && !messageChannelLoading ? ( - <StyledButtonContainer> + <CustomResolverFetchMoreLoader + loading={threadLoading} + onLastRowVisible={fetchMoreMessages} + /> + </> + )} + </StyledContainer> + {canReply && !messageChannelLoading && ( + <StyledButtonContainer isMobile={isMobile}> <Button onClick={handleReplyClick} - title="Reply (View in Gmail)" + title="Reply" Icon={IconArrowBackUp} disabled={!canReply} - ></Button> + /> </StyledButtonContainer> - ) : null} - </StyledContainer> + )} + </StyledWrapper> ); }; diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts index 23d004f05152..d1d67695a1c5 100644 --- a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts @@ -6,6 +6,8 @@ import { EmailThread } from '@/activities/emails/types/EmailThread'; import { EmailThreadMessage } from '@/activities/emails/types/EmailThreadMessage'; import { MessageChannel } from '@/accounts/types/MessageChannel'; +import { EmailThreadMessageParticipant } from '@/activities/emails/types/EmailThreadMessageParticipant'; +import { EmailThreadMessageWithSender } from '@/activities/emails/types/EmailThreadMessageWithSender'; import { MessageChannelMessageAssociation } from '@/activities/emails/types/MessageChannelMessageAssociation'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; @@ -13,6 +15,7 @@ import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +import { isDefined } from 'twenty-ui'; export const useRightDrawerEmailThread = () => { const viewableRecordId = useRecoilValue(viewableRecordIdState); @@ -74,6 +77,30 @@ export const useRightDrawerEmailThread = () => { } }, [messages, isMessagesFetchComplete]); + // TODO: introduce nested filters so we can retrieve the message sender directly from the message query + const { records: messageSenders } = + useFindManyRecords<EmailThreadMessageParticipant>({ + filter: { + messageId: { + in: messages.map(({ id }) => id), + }, + role: { + eq: 'from', + }, + }, + objectNameSingular: CoreObjectNameSingular.MessageParticipant, + recordGqlFields: { + id: true, + role: true, + displayName: true, + messageId: true, + handle: true, + person: true, + workspaceMember: true, + }, + skip: messages.length === 0, + }); + const { records: messageChannelMessageAssociationData } = useFindManyRecords<MessageChannelMessageAssociation>({ filter: { @@ -123,9 +150,24 @@ export const useRightDrawerEmailThread = () => { const connectedAccountHandle = messageChannelData.length > 0 ? messageChannelData[0].handle : null; + const messagesWithSender: EmailThreadMessageWithSender[] = messages + .map((message) => { + const sender = messageSenders.find( + (messageSender) => messageSender.messageId === message.id, + ); + if (!sender) { + return null; + } + return { + ...message, + sender, + }; + }) + .filter(isDefined); + return { thread, - messages, + messages: messagesWithSender, messageThreadExternalId, connectedAccountHandle, threadLoading: messagesLoading, diff --git a/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageParticipant.ts b/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageParticipant.ts index ed81fa848fba..72dfa74dfe38 100644 --- a/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageParticipant.ts +++ b/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageParticipant.ts @@ -3,9 +3,12 @@ import { Person } from '@/people/types/Person'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; export type EmailThreadMessageParticipant = { + id: string; displayName: string; handle: string; role: EmailParticipantRole; + messageId: string; person: Person; workspaceMember: WorkspaceMember; + __typename: 'EmailThreadMessageParticipant'; }; diff --git a/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageWithSender.ts b/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageWithSender.ts new file mode 100644 index 000000000000..fe6916da2451 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/types/EmailThreadMessageWithSender.ts @@ -0,0 +1,6 @@ +import { EmailThreadMessage } from '@/activities/emails/types/EmailThreadMessage'; +import { EmailThreadMessageParticipant } from '@/activities/emails/types/EmailThreadMessageParticipant'; + +export type EmailThreadMessageWithSender = EmailThreadMessage & { + sender: EmailThreadMessageParticipant; +}; diff --git a/packages/twenty-front/src/modules/activities/emails/utils/__tests__/getDisplayNameFromParticipant.test.ts b/packages/twenty-front/src/modules/activities/emails/utils/__tests__/getDisplayNameFromParticipant.test.ts index 8db46ff647b2..1c3a589c4a67 100644 --- a/packages/twenty-front/src/modules/activities/emails/utils/__tests__/getDisplayNameFromParticipant.test.ts +++ b/packages/twenty-front/src/modules/activities/emails/utils/__tests__/getDisplayNameFromParticipant.test.ts @@ -4,9 +4,12 @@ import { getDisplayNameFromParticipant } from '../getDisplayNameFromParticipant' describe('getDisplayNameFromParticipant', () => { const participantWithName: EmailThreadMessageParticipant = { + id: '2cac0ba7-0e60-46c6-86e7-e5b0bc55b7cf', + __typename: 'EmailThreadMessageParticipant', displayName: '', handle: '', role: 'from', + messageId: '638f52d1-fd55-4a2b-b0f3-9858ea3b2e91', person: { __typename: 'Person', id: '1', diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx index c31c13577bd5..2439984ceaa2 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useActivityTargetObjectRecords.test.tsx @@ -7,12 +7,10 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTargetObjectRecords'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { mockWorkspaceMembers } from '~/testing/mock-data/workspace-members'; -const mockObjectMetadataItems = getObjectMetadataItemsMock(); const cache = new InMemoryCache(); @@ -126,10 +124,8 @@ describe('useActivityTargetObjectRecords', () => { objectMetadataItemsState, ); - const { activityTargetObjectRecords } = useActivityTargetObjectRecords( - task, - CoreObjectNameSingular.Task, - ); + const { activityTargetObjectRecords } = + useActivityTargetObjectRecords(task); return { activityTargetObjectRecords, @@ -142,7 +138,7 @@ describe('useActivityTargetObjectRecords', () => { act(() => { result.current.setCurrentWorkspaceMember(mockWorkspaceMembers[0]); - result.current.setObjectMetadataItems(mockObjectMetadataItems); + result.current.setObjectMetadataItems(generatedMockObjectMetadataItems); }); const activityTargetObjectRecords = diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInDB.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInDB.test.tsx index e2db015a1a4a..1b56bc49d5da 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInDB.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useCreateActivityInDB.test.tsx @@ -26,13 +26,13 @@ const mocks: MockedResponse[] = [ mutation CreateOneTask($input: TaskCreateInput!) { createTask(data: $input) { __typename - status - assigneeId updatedAt - body createdAt dueAt id + status + body + assigneeId title } } diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx index 9b03ac5e5b61..665702704d1b 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx @@ -6,10 +6,10 @@ import { RecoilRoot, useRecoilValue, useSetRecoilState } from 'recoil'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import gql from 'graphql-tag'; import pick from 'lodash.pick'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { mockedTasks } from '~/testing/mock-data/tasks'; const mockedDate = '2024-03-15T12:00:00.000Z'; @@ -69,7 +69,7 @@ const Wrapper = ({ children }: { children: ReactNode }) => ( </RecoilRoot> ); -const mockObjectMetadataItems = getObjectMetadataItemsMock(); +const mockObjectMetadataItems = generatedMockObjectMetadataItems; describe('useOpenCreateActivityDrawer', () => { it('works as expected', async () => { diff --git a/packages/twenty-front/src/modules/activities/hooks/useActivities.ts b/packages/twenty-front/src/modules/activities/hooks/useActivities.ts index d63109339d0f..b5311a80035a 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useActivities.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useActivities.ts @@ -51,13 +51,12 @@ export const useActivities = <T extends Task | Note>({ ), ]; + const skipBecauseNoActivityTargetFound = activityIds.length === 0; + const filter: RecordGqlOperationFilter = { - id: - targetableObjects.length > 0 - ? { - in: activityIds, - } - : undefined, + id: { + in: activityIds, + }, ...activitiesFilters, }; @@ -69,7 +68,7 @@ export const useActivities = <T extends Task | Note>({ const { records: activities, loading: loadingActivities } = useFindManyRecords<Task | Note>({ - skip: skip || loadingActivityTargets, + skip: skip || loadingActivityTargets || skipBecauseNoActivityTargetFound, objectNameSingular: FIND_ACTIVITIES_OPERATION_SIGNATURE.objectNameSingular, recordGqlFields: FIND_ACTIVITIES_OPERATION_SIGNATURE.fields, diff --git a/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts b/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts index 2fe34d8c2f5e..4b8edec3a2a3 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useActivityTargetObjectRecords.ts @@ -1,4 +1,3 @@ -import { useApolloClient } from '@apollo/client'; import { useRecoilValue } from 'recoil'; import { Nullable } from 'twenty-ui'; @@ -7,46 +6,37 @@ import { Note } from '@/activities/types/Note'; import { NoteTarget } from '@/activities/types/NoteTarget'; import { Task } from '@/activities/types/Task'; import { TaskTarget } from '@/activities/types/TaskTarget'; -import { getJoinObjectNameSingular } from '@/activities/utils/getJoinObjectNameSingular'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache'; import { isDefined } from '~/utils/isDefined'; export const useActivityTargetObjectRecords = ( - activity: Task | Note, - objectNameSingular: CoreObjectNameSingular, + activity?: Task | Note, + activityTargets?: NoteTarget[] | TaskTarget[], ) => { const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - const activityTargets = - 'noteTargets' in activity && activity.noteTargets + if (!isDefined(activity) && !isDefined(activityTargets)) { + return { activityTargetObjectRecords: [] }; + } + + const targets = activityTargets + ? activityTargets + : activity && 'noteTargets' in activity && activity.noteTargets ? activity.noteTargets - : 'taskTargets' in activity && activity.taskTargets + : activity && 'taskTargets' in activity && activity.taskTargets ? activity.taskTargets : []; - const getRecordFromCache = useGetRecordFromCache({ - objectNameSingular: getJoinObjectNameSingular(objectNameSingular), - }); - - const apolloClient = useApolloClient(); - - const activityTargetObjectRecords = activityTargets + const activityTargetObjectRecords = targets .map<Nullable<ActivityTargetWithTargetRecord>>((activityTarget) => { - const activityTargetFromCache = getRecordFromCache< - NoteTarget | TaskTarget - >(activityTarget.id, apolloClient.cache); - - if (!isDefined(activityTargetFromCache)) { - throw new Error( - `Cannot find activity target ${activityTarget.id} in cache, this shouldn't happen.`, - ); + if (!isDefined(activityTarget)) { + throw new Error(`Cannot find activity target`); } const correspondingObjectMetadataItem = objectMetadataItems.find( (objectMetadataItem) => - isDefined(activityTargetFromCache[objectMetadataItem.nameSingular]) && + isDefined(activityTarget[objectMetadataItem.nameSingular]) && ![CoreObjectNameSingular.Note, CoreObjectNameSingular.Task].includes( objectMetadataItem.nameSingular as CoreObjectNameSingular, ), @@ -57,7 +47,7 @@ export const useActivityTargetObjectRecords = ( } const targetObjectRecord = - activityTargetFromCache[correspondingObjectMetadataItem.nameSingular]; + activityTarget[correspondingObjectMetadataItem.nameSingular]; if (!targetObjectRecord) { throw new Error( @@ -66,7 +56,7 @@ export const useActivityTargetObjectRecords = ( } return { - activityTarget: activityTargetFromCache ?? activityTarget, + activityTarget, targetObject: targetObjectRecord ?? undefined, targetObjectMetadataItem: correspondingObjectMetadataItem, }; diff --git a/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx b/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx index 60494d98bd20..9f56a3c0ceef 100644 --- a/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx +++ b/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetsInlineCell.tsx @@ -35,10 +35,8 @@ export const ActivityTargetsInlineCell = ({ readonly, activityObjectNameSingular, }: ActivityTargetsInlineCellProps) => { - const { activityTargetObjectRecords } = useActivityTargetObjectRecords( - activity, - activityObjectNameSingular, - ); + const { activityTargetObjectRecords } = + useActivityTargetObjectRecords(activity); const { closeInlineCell } = useInlineCell(); diff --git a/packages/twenty-front/src/modules/activities/notes/components/NoteCard.tsx b/packages/twenty-front/src/modules/activities/notes/components/NoteCard.tsx index c5c40761b4e1..22879b117a0c 100644 --- a/packages/twenty-front/src/modules/activities/notes/components/NoteCard.tsx +++ b/packages/twenty-front/src/modules/activities/notes/components/NoteCard.tsx @@ -28,8 +28,9 @@ const StyledCardDetailsContainer = styled.div` gap: ${({ theme }) => theme.spacing(2)}; height: calc(100% - 45px); justify-content: start; - padding: ${({ theme }) => theme.spacing(2)}; - width: calc(100% - ${({ theme }) => theme.spacing(4)}); + padding: ${({ theme }) => theme.spacing(4)}; + width: calc(100% - ${({ theme }) => theme.spacing(8)}); + box-sizing: border-box; `; const StyledNoteTitle = styled.div` @@ -41,7 +42,6 @@ const StyledCardContent = styled.div` align-self: stretch; color: ${({ theme }) => theme.font.color.secondary}; line-break: anywhere; - margin-top: ${({ theme }) => theme.spacing(2)}; overflow: hidden; text-overflow: ellipsis; white-space: pre-line; diff --git a/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx b/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx index 4503fd9913b3..a6e4999773bc 100644 --- a/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/components/TaskGroups.tsx @@ -91,22 +91,24 @@ export const TaskGroups = ({ ); } + const sortedTasksByStatus = Object.entries( + groupBy(tasks, ({ status }) => status), + ).toSorted(([statusA], [statusB]) => statusB.localeCompare(statusA)); + return ( <StyledContainer> - {Object.entries(groupBy(tasks, ({ status }) => status)).map( - ([status, tasksByStatus]: [string, Task[]]) => ( - <TaskList - key={status} - title={status} - tasks={tasksByStatus} - button={ - showAddButton && ( - <AddTaskButton activityTargetableObjects={targetableObjects} /> - ) - } - /> - ), - )} + {sortedTasksByStatus.map(([status, tasksByStatus]: [string, Task[]]) => ( + <TaskList + key={status} + title={status} + tasks={tasksByStatus} + button={ + showAddButton && ( + <AddTaskButton activityTargetableObjects={targetableObjects} /> + ) + } + /> + ))} </StyledContainer> ); }; diff --git a/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx b/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx index 798bb077d797..efd4323143b0 100644 --- a/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx @@ -18,13 +18,13 @@ const StyledContainer = styled.div` justify-content: space-between; border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; cursor: pointer; - display: inline-flex; + display: flex; height: ${({ theme }) => theme.spacing(12)}; min-width: calc(100% - ${({ theme }) => theme.spacing(8)}); max-width: calc(100% - ${({ theme }) => theme.spacing(8)}); padding: 0 ${({ theme }) => theme.spacing(4)}; overflow: hidden; - + max-inline-size: 60px; &:last-child { border-bottom: 0; } @@ -33,9 +33,10 @@ const StyledContainer = styled.div` const StyledTaskBody = styled.div` color: ${({ theme }) => theme.font.color.tertiary}; display: flex; - max-width: 100%; - flex: 1; + max-width: calc(80% - ${({ theme }) => theme.spacing(2)}); + text-overflow: ellipsis; overflow: hidden; + padding-bottom: ${({ theme }) => theme.spacing(0.25)}; `; const StyledTaskTitle = styled.div<{ @@ -44,10 +45,13 @@ const StyledTaskTitle = styled.div<{ color: ${({ theme }) => theme.font.color.primary}; font-weight: ${({ theme }) => theme.font.weight.medium}; padding: 0 ${({ theme }) => theme.spacing(2)}; + padding-bottom: ${({ theme }) => theme.spacing(0.25)}; text-decoration: ${({ completed }) => (completed ? 'line-through' : 'none')}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + + align-items: center; `; const StyledDueDate = styled.div<{ @@ -58,12 +62,14 @@ const StyledDueDate = styled.div<{ isPast ? theme.font.color.danger : theme.font.color.secondary}; display: flex; gap: ${({ theme }) => theme.spacing(1)}; - padding-left: ${({ theme }) => theme.spacing(2)}; + padding-left: ${({ theme }) => theme.spacing(1)}; white-space: nowrap; `; const StyledRightSideContainer = styled.div` - display: flex; + align-items: center; + display: inline-flex; + max-width: 50%; `; const StyledPlaceholder = styled.div` @@ -71,6 +77,8 @@ const StyledPlaceholder = styled.div` `; const StyledLeftSideContainer = styled.div` + align-items: center; + display: inline-flex; display: flex; flex: 1; overflow: hidden; diff --git a/packages/twenty-front/src/modules/activities/tasks/hooks/__tests__/useCompleteTask.test.tsx b/packages/twenty-front/src/modules/activities/tasks/hooks/__tests__/useCompleteTask.test.tsx index baf35a95680e..ba3e2ac53482 100644 --- a/packages/twenty-front/src/modules/activities/tasks/hooks/__tests__/useCompleteTask.test.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/hooks/__tests__/useCompleteTask.test.tsx @@ -28,20 +28,21 @@ const mocks: MockedResponse[] = [ mutation UpdateOneTask($idToUpdate: ID!, $input: TaskUpdateInput!) { updateTask(id: $idToUpdate, data: $input) { __typename - status - assigneeId updatedAt - body createdAt + deletedAt dueAt - position id - title + status + body createdBy { source workspaceMemberId name } + assigneeId + position + title } } `, @@ -53,7 +54,7 @@ const mocks: MockedResponse[] = [ result: jest.fn(() => ({ data: { updateTask: { - __typename: 'Activity', + __typename: 'Task', createdAt: '2024-03-15T07:33:14.212Z', reminderAt: null, authorId: '123', diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/components/EventRow.tsx b/packages/twenty-front/src/modules/activities/timelineActivities/components/EventRow.tsx index 902a7b728db1..e046316132df 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/components/EventRow.tsx +++ b/packages/twenty-front/src/modules/activities/timelineActivities/components/EventRow.tsx @@ -3,7 +3,8 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; import { TimelineActivityContext } from '@/activities/timelineActivities/contexts/TimelineActivityContext'; -import { useLinkedObject } from '@/activities/timelineActivities/hooks/useLinkedObject'; + +import { useLinkedObjectObjectMetadataItem } from '@/activities/timelineActivities/hooks/useLinkedObjectObjectMetadataItem'; import { EventIconDynamicComponent } from '@/activities/timelineActivities/rows/components/EventIconDynamicComponent'; import { EventRowDynamicComponent } from '@/activities/timelineActivities/rows/components/EventRowDynamicComponent'; import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity'; @@ -14,6 +15,7 @@ import { beautifyPastDateRelativeToNow } from '~/utils/date-utils'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; const StyledTimelineItemContainer = styled.div` + color: ${({ theme }) => theme.font.color.primary}; display: flex; gap: ${({ theme }) => theme.spacing(4)}; height: 'auto'; @@ -99,7 +101,7 @@ export const EventRow = ({ const { labelIdentifierValue } = useContext(TimelineActivityContext); const beautifiedCreatedAt = beautifyPastDateRelativeToNow(event.createdAt); - const linkedObjectMetadataItem = useLinkedObject( + const linkedObjectMetadataItem = useLinkedObjectObjectMetadataItem( event.linkedObjectMetadataId, ); diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/components/TimelineActivities.tsx b/packages/twenty-front/src/modules/activities/timelineActivities/components/TimelineActivities.tsx index b94921254ff9..bbda464681f9 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/components/TimelineActivities.tsx +++ b/packages/twenty-front/src/modules/activities/timelineActivities/components/TimelineActivities.tsx @@ -46,7 +46,7 @@ export const TimelineActivities = ({ const isTimelineActivitiesEmpty = !timelineActivities || timelineActivities.length === 0; - if (loading && isTimelineActivitiesEmpty) { + if (loading) { return <SkeletonLoader withSubSections />; } diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/__tests__/useTimelineActivities.test.tsx b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/__tests__/useTimelineActivities.test.tsx index e7d0da054672..894d541c888b 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/__tests__/useTimelineActivities.test.tsx +++ b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/__tests__/useTimelineActivities.test.tsx @@ -2,14 +2,18 @@ import { renderHook } from '@testing-library/react'; import { useTimelineActivities } from '@/activities/timelineActivities/hooks/useTimelineActivities'; import { ReactNode } from 'react'; -import { RecoilRoot } from 'recoil'; +import { getJestHookWrapper } from '~/testing/jest/getJestHookWrapper'; jest.mock('@/object-record/hooks/useFindManyRecords', () => ({ useFindManyRecords: jest.fn(), })); +const Wrappers = getJestHookWrapper({ + apolloMocks: [], +}); + const Wrapper = ({ children }: { children: ReactNode }) => ( - <RecoilRoot>{children}</RecoilRoot> + <Wrappers>{children}</Wrappers> ); describe('useTimelineActivities', () => { @@ -46,6 +50,7 @@ describe('useTimelineActivities', () => { updatedAt: '2024-03-22T08:28:44.830Z', }, ]; + const mockTargetableObject = { id: '1', targetObjectNameSingular: 'Opportunity', @@ -54,15 +59,28 @@ describe('useTimelineActivities', () => { const useFindManyRecordsMock = jest.requireMock( '@/object-record/hooks/useFindManyRecords', ); + useFindManyRecordsMock.useFindManyRecords.mockReturnValue({ records: mockedTimelineActivities, }); const { result } = renderHook( - () => useTimelineActivities(mockTargetableObject), + () => { + return useTimelineActivities(mockTargetableObject); + }, { wrapper: Wrapper }, ); + const wrongMockedTimelineActivities = [ + { + ...mockedTimelineActivities[0], + name: 'wrong.updated.company', + }, + ]; + expect(result.current.timelineActivities).toEqual(mockedTimelineActivities); + expect(result.current.timelineActivities).not.toEqual( + wrongMockedTimelineActivities, + ); }); }); diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObject.ts b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectObjectMetadataItem.ts similarity index 86% rename from packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObject.ts rename to packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectObjectMetadataItem.ts index b628b56907d5..9f230bef62b9 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObject.ts +++ b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectObjectMetadataItem.ts @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -export const useLinkedObject = (id: string) => { +export const useLinkedObjectObjectMetadataItem = (id: string) => { const objectMetadataItems: ObjectMetadataItem[] = useRecoilValue( objectMetadataItemsState, ); diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectsTitle.ts b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectsTitle.ts new file mode 100644 index 000000000000..2df7bc03a4c2 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useLinkedObjectsTitle.ts @@ -0,0 +1,43 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecords'; +import { isNonEmptyArray } from '@sniptt/guards'; + +export const useLinkedObjectsTitle = (linkedObjectIds: string[]) => { + const { loading } = useCombinedFindManyRecords({ + skip: !isNonEmptyArray(linkedObjectIds), + operationSignatures: [ + { + objectNameSingular: CoreObjectNameSingular.Task, + variables: { + filter: { + id: { + in: linkedObjectIds ?? [], + }, + }, + }, + fields: { + id: true, + title: true, + }, + }, + { + objectNameSingular: CoreObjectNameSingular.Note, + variables: { + filter: { + id: { + in: linkedObjectIds ?? [], + }, + }, + }, + fields: { + id: true, + title: true, + }, + }, + ], + }); + + return { + loading, + }; +}; diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useTimelineActivities.tsx b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useTimelineActivities.ts similarity index 71% rename from packages/twenty-front/src/modules/activities/timelineActivities/hooks/useTimelineActivities.tsx rename to packages/twenty-front/src/modules/activities/timelineActivities/hooks/useTimelineActivities.ts index 843586660bf3..fb65053c151c 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useTimelineActivities.tsx +++ b/packages/twenty-front/src/modules/activities/timelineActivities/hooks/useTimelineActivities.ts @@ -1,3 +1,4 @@ +import { useLinkedObjectsTitle } from '@/activities/timelineActivities/hooks/useLinkedObjectsTitle'; import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName'; @@ -19,10 +20,10 @@ export const useTimelineActivities = ( }); const { - records: TimelineActivities, - loading, + records: timelineActivities, + loading: loadingTimelineActivities, fetchMoreRecords, - } = useFindManyRecords({ + } = useFindManyRecords<TimelineActivity>({ objectNameSingular: CoreObjectNameSingular.TimelineActivity, filter: { [targetableObjectFieldIdName]: { @@ -38,8 +39,17 @@ export const useTimelineActivities = ( fetchPolicy: 'cache-and-network', }); + const activityIds = timelineActivities + .filter((timelineActivity) => timelineActivity.name.match(/note|task/i)) + .map((timelineActivity) => timelineActivity.linkedRecordId); + + const { loading: loadingLinkedObjectsTitle } = + useLinkedObjectsTitle(activityIds); + + const loading = loadingTimelineActivities || loadingLinkedObjectsTitle; + return { - timelineActivities: TimelineActivities as TimelineActivity[], + timelineActivities, loading, fetchMoreRecords, }; diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/rows/activity/components/EventRowActivity.tsx b/packages/twenty-front/src/modules/activities/timelineActivities/rows/activity/components/EventRowActivity.tsx index 30c13a7214ba..1c1f34e43ade 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/rows/activity/components/EventRowActivity.tsx +++ b/packages/twenty-front/src/modules/activities/timelineActivities/rows/activity/components/EventRowActivity.tsx @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { useRecoilState } from 'recoil'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; import { @@ -8,15 +7,21 @@ import { StyledEventRowItemColumn, } from '@/activities/timelineActivities/rows/components/EventRowDynamicComponent'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache'; +import { isNonEmptyString } from '@sniptt/guards'; type EventRowActivityProps = EventRowDynamicComponentProps; const StyledLinkedActivity = styled.span` + color: ${({ theme }) => theme.font.color.primary}; cursor: pointer; text-decoration: underline; `; +export const StyledEventRowItemText = styled.span` + color: ${({ theme }) => theme.font.color.primary}; +`; + export const EventRowActivity = ({ event, authorFullName, @@ -30,9 +35,21 @@ export const EventRowActivity = ({ throw new Error('Could not find linked record id for event'); } - const [activityInStore] = useRecoilState( - recordStoreFamilyState(event.linkedRecordId), - ); + const getActivityFromCache = useGetRecordFromCache({ + objectNameSingular, + recordGqlFields: { + id: true, + title: true, + }, + }); + + const activityInStore = getActivityFromCache(event.linkedRecordId); + + const activityTitle = isNonEmptyString(activityInStore?.title) + ? activityInStore?.title + : isNonEmptyString(event.linkedRecordCachedName) + ? event.linkedRecordCachedName + : 'Untitled'; const openActivityRightDrawer = useOpenActivityRightDrawer({ objectNameSingular, @@ -44,15 +61,11 @@ export const EventRowActivity = ({ <StyledEventRowItemAction> {`${eventAction} a related ${eventObject}`} </StyledEventRowItemAction> - {activityInStore ? ( - <StyledLinkedActivity - onClick={() => openActivityRightDrawer(event.linkedRecordId)} - > - {event.linkedRecordCachedName} - </StyledLinkedActivity> - ) : ( - <span>{event.linkedRecordCachedName}</span> - )} + <StyledLinkedActivity + onClick={() => openActivityRightDrawer(event.linkedRecordId)} + > + {activityTitle} + </StyledLinkedActivity> </> ); }; diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/rows/message/components/EventCardMessage.tsx b/packages/twenty-front/src/modules/activities/timelineActivities/rows/message/components/EventCardMessage.tsx index 134dd95ba3a7..899c0414e76b 100644 --- a/packages/twenty-front/src/modules/activities/timelineActivities/rows/message/components/EventCardMessage.tsx +++ b/packages/twenty-front/src/modules/activities/timelineActivities/rows/message/components/EventCardMessage.tsx @@ -66,6 +66,7 @@ export const EventCardMessage = ({ objectNameSingular: CoreObjectNameSingular.Message, objectRecordId: messageId, recordGqlFields: { + id: true, text: true, subject: true, direction: true, diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/types/TimelineActivityLinkedObject.ts b/packages/twenty-front/src/modules/activities/timelineActivities/types/TimelineActivityLinkedObject.ts new file mode 100644 index 000000000000..9fd28f828f43 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/timelineActivities/types/TimelineActivityLinkedObject.ts @@ -0,0 +1 @@ +export type TimelineActivityLinkedObject = 'note' | 'task'; diff --git a/packages/twenty-front/src/modules/activities/timelineActivities/utils/filterTimelineActivityByLinkedObjectTypes.ts b/packages/twenty-front/src/modules/activities/timelineActivities/utils/filterTimelineActivityByLinkedObjectTypes.ts new file mode 100644 index 000000000000..455ceca01c0a --- /dev/null +++ b/packages/twenty-front/src/modules/activities/timelineActivities/utils/filterTimelineActivityByLinkedObjectTypes.ts @@ -0,0 +1,12 @@ +import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity'; +import { TimelineActivityLinkedObject } from '@/activities/timelineActivities/types/TimelineActivityLinkedObject'; + +export const filterTimelineActivityByLinkedObjectTypes = + (linkedObjectTypes: TimelineActivityLinkedObject[]) => + (timelineActivity: TimelineActivity) => { + return linkedObjectTypes.some((linkedObjectType) => { + const linkedObjectPartInName = timelineActivity.name.split('.')[0]; + + return linkedObjectPartInName.includes(linkedObjectType); + }); + }; diff --git a/packages/twenty-front/src/modules/analytics/graphql/queries/track.ts b/packages/twenty-front/src/modules/analytics/graphql/queries/track.ts index 3aa7bba0fcf4..04a5d4487293 100644 --- a/packages/twenty-front/src/modules/analytics/graphql/queries/track.ts +++ b/packages/twenty-front/src/modules/analytics/graphql/queries/track.ts @@ -1,8 +1,8 @@ import { gql } from '@apollo/client'; export const TRACK = gql` - mutation Track($type: String!, $data: JSON!) { - track(type: $type, data: $data) { + mutation Track($type: String!, $sessionId: String!, $data: JSON!) { + track(type: $type, sessionId: $sessionId, data: $data) { success } } diff --git a/packages/twenty-front/src/modules/analytics/hooks/__tests__/useEventTracker.test.tsx b/packages/twenty-front/src/modules/analytics/hooks/__tests__/useEventTracker.test.tsx index 9b60f1ffa646..a49b85612f46 100644 --- a/packages/twenty-front/src/modules/analytics/hooks/__tests__/useEventTracker.test.tsx +++ b/packages/twenty-front/src/modules/analytics/hooks/__tests__/useEventTracker.test.tsx @@ -1,8 +1,8 @@ -import { ReactNode } from 'react'; import { gql } from '@apollo/client'; import { MockedProvider, MockedResponse } from '@apollo/client/testing'; import { expect } from '@storybook/test'; import { act, renderHook, waitFor } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; import { useEventTracker } from '../useEventTracker'; @@ -11,15 +11,23 @@ const mocks: MockedResponse[] = [ { request: { query: gql` - mutation Track($type: String!, $data: JSON!) { - track(type: $type, data: $data) { + mutation Track($action: String!, $payload: JSON!) { + track(action: $action, payload: $payload) { success } } `, variables: { - type: 'exampleType', - data: { location: { pathname: '/examplePath' } }, + action: 'exampleType', + payload: { + sessionId: 'exampleId', + pathname: '', + userAgent: '', + timeZone: '', + locale: '', + href: '', + referrer: '', + }, }, }, result: jest.fn(() => ({ @@ -43,7 +51,15 @@ const Wrapper = ({ children }: { children: ReactNode }) => ( describe('useEventTracker', () => { it('should make the call to track the event', async () => { const eventType = 'exampleType'; - const eventData = { location: { pathname: '/examplePath' } }; + const eventData = { + sessionId: 'exampleId', + pathname: '', + userAgent: '', + timeZone: '', + locale: '', + href: '', + referrer: '', + }; const { result } = renderHook(() => useEventTracker(), { wrapper: Wrapper, }); diff --git a/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts b/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts index 88d1d656740b..faaa3ea5b634 100644 --- a/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts +++ b/packages/twenty-front/src/modules/analytics/hooks/useEventTracker.ts @@ -1,32 +1,46 @@ import { useCallback } from 'react'; -import { useRecoilValue } from 'recoil'; - -import { telemetryState } from '@/client-config/states/telemetryState'; import { useTrackMutation } from '~/generated/graphql'; - -interface EventLocation { +export interface EventData { pathname: string; + userAgent: string; + timeZone: string; + locale: string; + href: string; + referrer: string; } +export const ANALYTICS_COOKIE_NAME = 'analyticsCookie'; +export const getSessionId = (): string => { + const cookie: { [key: string]: string } = {}; + document.cookie.split(';').forEach((el) => { + const [key, value] = el.split('='); + cookie[key.trim()] = value; + }); + return cookie[ANALYTICS_COOKIE_NAME]; +}; -export interface EventData { - location: EventLocation; -} +export const setSessionId = (domain?: string): void => { + const sessionId = getSessionId() || crypto.randomUUID(); + const baseCookie = `${ANALYTICS_COOKIE_NAME}=${sessionId}; Max-Age=1800; path=/; secure`; + const cookie = domain ? baseCookie + `; domain=${domain}` : baseCookie; + + document.cookie = cookie; +}; export const useEventTracker = () => { - const telemetry = useRecoilValue(telemetryState); const [createEventMutation] = useTrackMutation(); return useCallback( - (eventType: string, eventData: EventData) => { - if (telemetry.enabled) { - createEventMutation({ - variables: { - type: eventType, - data: eventData, + (eventAction: string, eventPayload: EventData) => { + createEventMutation({ + variables: { + action: eventAction, + payload: { + sessionId: getSessionId(), + ...eventPayload, }, - }); - } + }, + }); }, - [createEventMutation, telemetry], + [createEventMutation], ); }; diff --git a/packages/twenty-front/src/modules/apollo/hooks/__tests__/useApolloFactory.test.tsx b/packages/twenty-front/src/modules/apollo/hooks/__tests__/useApolloFactory.test.tsx index 59f99306a524..5e19a8309c64 100644 --- a/packages/twenty-front/src/modules/apollo/hooks/__tests__/useApolloFactory.test.tsx +++ b/packages/twenty-front/src/modules/apollo/hooks/__tests__/useApolloFactory.test.tsx @@ -1,7 +1,7 @@ -import { MemoryRouter, useLocation } from 'react-router-dom'; import { ApolloError, gql } from '@apollo/client'; import { act, renderHook } from '@testing-library/react'; import fetchMock, { enableFetchMocks } from 'jest-fetch-mock'; +import { MemoryRouter, useLocation } from 'react-router-dom'; import { RecoilRoot } from 'recoil'; import { useApolloFactory } from '../useApolloFactory'; @@ -77,8 +77,8 @@ describe('useApolloFactory', () => { await act(async () => { await result.current.factory.mutate({ mutation: gql` - mutation Track($type: String!, $data: JSON!) { - track(type: $type, data: $data) { + mutation Track($type: String!, $sessionId: String!, $data: JSON!) { + track(type: $type, sessionId: $sessionId, data: $data) { success } } diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/getRelationDefinition.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/getRelationDefinition.ts deleted file mode 100644 index a9f44909f6a3..000000000000 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/getRelationDefinition.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; -import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { RelationType } from '@/settings/data-model/types/RelationType'; -import { - FieldMetadataType, - RelationMetadataType, -} from '~/generated-metadata/graphql'; - -export const getRelationDefinition = ({ - objectMetadataItems, - fieldMetadataItemOnSourceRecord, -}: { - objectMetadataItems: ObjectMetadataItem[]; - fieldMetadataItemOnSourceRecord: FieldMetadataItem; -}) => { - if (fieldMetadataItemOnSourceRecord.type !== FieldMetadataType.Relation) { - return null; - } - - const relationMetadataItem = - fieldMetadataItemOnSourceRecord.fromRelationMetadata || - fieldMetadataItemOnSourceRecord.toRelationMetadata; - - if (!relationMetadataItem) return null; - - const relationSourceFieldMetadataItemId = - 'toFieldMetadataId' in relationMetadataItem - ? relationMetadataItem.toFieldMetadataId - : relationMetadataItem.fromFieldMetadataId; - - if (!relationSourceFieldMetadataItemId) return null; - - // TODO: precise naming, is it relationTypeFromTargetPointOfView or relationTypeFromSourcePointOfView ? - const relationType = - relationMetadataItem.relationType === RelationMetadataType.OneToMany && - fieldMetadataItemOnSourceRecord.toRelationMetadata - ? ('MANY_TO_ONE' satisfies RelationType) - : (relationMetadataItem.relationType as RelationType); - - const targetObjectMetadataNameSingular = - 'toObjectMetadata' in relationMetadataItem - ? relationMetadataItem.toObjectMetadata.nameSingular - : relationMetadataItem.fromObjectMetadata.nameSingular; - - const targetObjectMetadataItem = objectMetadataItems.find( - (item) => item.nameSingular === targetObjectMetadataNameSingular, - ); - - if (!targetObjectMetadataItem) return null; - - const fieldMetadataItemOnTargetRecord = targetObjectMetadataItem.fields.find( - (field) => field.id === relationSourceFieldMetadataItemId, - ); - - if (!fieldMetadataItemOnTargetRecord) return null; - - return { - fieldMetadataItemOnTargetRecord, - targetObjectMetadataItem, - relationType, - }; -}; diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts index 16d103532b77..535f33db4f8a 100644 --- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts +++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect.ts @@ -1,6 +1,5 @@ import { ApolloCache } from '@apollo/client'; -import { getRelationDefinition } from '@/apollo/optimistic-effect/utils/getRelationDefinition'; import { triggerAttachRelationOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerAttachRelationOptimisticEffect'; import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect'; import { triggerDetachRelationOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDetachRelationOptimisticEffect'; @@ -45,16 +44,23 @@ export const triggerUpdateRelationsOptimisticEffect = ({ return; } - const relationDefinition = getRelationDefinition({ - fieldMetadataItemOnSourceRecord, - objectMetadataItems, - }); + const relationDefinition = + fieldMetadataItemOnSourceRecord.relationDefinition; + if (!relationDefinition) { return; } - const { targetObjectMetadataItem, fieldMetadataItemOnTargetRecord } = - relationDefinition; + const { targetObjectMetadata, targetFieldMetadata } = relationDefinition; + + const fullTargetObjectMetadataItem = objectMetadataItems.find( + ({ nameSingular }) => + nameSingular === targetObjectMetadata.nameSingular, + ); + + if (!fullTargetObjectMetadataItem) { + return; + } const currentFieldValueOnSourceRecord: | RecordGqlConnection @@ -80,7 +86,7 @@ export const triggerUpdateRelationsOptimisticEffect = ({ // it's an object record connection (we can still check it though as a safeguard) const currentFieldValueOnSourceRecordIsARecordConnection = isObjectRecordConnection( - targetObjectMetadataItem.nameSingular, + targetObjectMetadata.nameSingular, currentFieldValueOnSourceRecord, ); @@ -93,7 +99,7 @@ export const triggerUpdateRelationsOptimisticEffect = ({ const updatedFieldValueOnSourceRecordIsARecordConnection = isObjectRecordConnection( - targetObjectMetadataItem.nameSingular, + targetObjectMetadata.nameSingular, updatedFieldValueOnSourceRecord, ); @@ -112,13 +118,13 @@ export const triggerUpdateRelationsOptimisticEffect = ({ // Instead of hardcoding it here const shouldCascadeDeleteTargetRecords = CORE_OBJECT_NAMES_TO_DELETE_ON_TRIGGER_RELATION_DETACH.includes( - targetObjectMetadataItem.nameSingular as CoreObjectNameSingular, + targetObjectMetadata.nameSingular as CoreObjectNameSingular, ); if (shouldCascadeDeleteTargetRecords) { triggerDeleteRecordsOptimisticEffect({ cache, - objectMetadataItem: targetObjectMetadataItem, + objectMetadataItem: fullTargetObjectMetadataItem, recordsToDelete: targetRecordsToDetachFrom, objectMetadataItems, }); @@ -128,8 +134,8 @@ export const triggerUpdateRelationsOptimisticEffect = ({ cache, sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular, sourceRecordId: currentSourceRecord.id, - fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name, - targetObjectNameSingular: targetObjectMetadataItem.nameSingular, + fieldNameOnTargetRecord: targetFieldMetadata.name, + targetObjectNameSingular: targetObjectMetadata.nameSingular, targetRecordId: targetRecordToDetachFrom.id, }); }); @@ -145,8 +151,8 @@ export const triggerUpdateRelationsOptimisticEffect = ({ cache, sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular, sourceRecordId: updatedSourceRecord.id, - fieldNameOnTargetRecord: fieldMetadataItemOnTargetRecord.name, - targetObjectNameSingular: targetObjectMetadataItem.nameSingular, + fieldNameOnTargetRecord: targetFieldMetadata.name, + targetObjectNameSingular: targetObjectMetadata.nameSingular, targetRecordId: targetRecordToAttachTo.id, }), ); diff --git a/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts b/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts index d0ba37512438..9136b83fcd04 100644 --- a/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts +++ b/packages/twenty-front/src/modules/apollo/services/__tests__/apollo.factory.test.ts @@ -41,8 +41,8 @@ const makeRequest = async () => { await client.mutate({ mutation: gql` - mutation Track($type: String!, $data: JSON!) { - track(type: $type, data: $data) { + mutation Track($type: String!, $sessionId: String!, $data: JSON!) { + track(type: $type, sessionId: $sessionId, data: $data) { success } } diff --git a/packages/twenty-front/src/modules/auth/graphql/mutations/signUp.ts b/packages/twenty-front/src/modules/auth/graphql/mutations/signUp.ts index 85285b7769e6..57499f773f7e 100644 --- a/packages/twenty-front/src/modules/auth/graphql/mutations/signUp.ts +++ b/packages/twenty-front/src/modules/auth/graphql/mutations/signUp.ts @@ -5,12 +5,14 @@ export const SIGN_UP = gql` $email: String! $password: String! $workspaceInviteHash: String + $workspacePersonalInviteToken: String = null $captchaToken: String ) { signUp( email: $email password: $password workspaceInviteHash: $workspaceInviteHash + workspacePersonalInviteToken: $workspacePersonalInviteToken captchaToken: $captchaToken ) { loginToken { diff --git a/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx b/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx index ac52204f4cc4..60e4025a814f 100644 --- a/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx +++ b/packages/twenty-front/src/modules/auth/hooks/__test__/useAuth.test.tsx @@ -1,8 +1,8 @@ -import { ReactNode } from 'react'; import { useApolloClient } from '@apollo/client'; import { MockedProvider } from '@apollo/client/testing'; import { expect } from '@storybook/test'; import { act, renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot, useRecoilValue } from 'recoil'; import { iconsState } from 'twenty-ui'; @@ -12,7 +12,6 @@ import { billingState } from '@/client-config/states/billingState'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState'; import { supportChatState } from '@/client-config/states/supportChatState'; -import { telemetryState } from '@/client-config/states/telemetryState'; import { email, mocks, password, results, token } from '../__mocks__/useAuth'; @@ -81,7 +80,6 @@ describe('useAuth', () => { const billing = useRecoilValue(billingState); const isSignInPrefilled = useRecoilValue(isSignInPrefilledState); const supportChat = useRecoilValue(supportChatState); - const telemetry = useRecoilValue(telemetryState); const isDebugMode = useRecoilValue(isDebugModeState); return { ...useAuth(), @@ -92,7 +90,6 @@ describe('useAuth', () => { billing, isSignInPrefilled, supportChat, - telemetry, isDebugMode, }, }; @@ -126,9 +123,6 @@ describe('useAuth', () => { supportDriver: 'none', supportFrontChatId: null, }); - expect(state.telemetry).toEqual({ - enabled: true, - }); expect(state.isDebugMode).toBe(false); }); diff --git a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts index 229372520c00..7a7de0807f1b 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts @@ -21,7 +21,6 @@ import { isClientConfigLoadedState } from '@/client-config/states/isClientConfig import { isDebugModeState } from '@/client-config/states/isDebugModeState'; import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState'; import { supportChatState } from '@/client-config/states/supportChatState'; -import { telemetryState } from '@/client-config/states/telemetryState'; import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; import { REACT_APP_SERVER_BASE_URL } from '~/config'; import { @@ -224,7 +223,6 @@ export const useAuth = () => { .getLoadable(isSignInPrefilledState) .getValue(); const supportChat = snapshot.getLoadable(supportChatState).getValue(); - const telemetry = snapshot.getLoadable(telemetryState).getValue(); const isDebugMode = snapshot.getLoadable(isDebugModeState).getValue(); const captchaProvider = snapshot .getLoadable(captchaProviderState) @@ -242,7 +240,6 @@ export const useAuth = () => { set(billingState, billing); set(isSignInPrefilledState, isSignInPrefilled); set(supportChatState, supportChat); - set(telemetryState, telemetry); set(isDebugModeState, isDebugMode); set(captchaProviderState, captchaProvider); set(isClientConfigLoadedState, isClientConfigLoaded); @@ -254,6 +251,7 @@ export const useAuth = () => { await client.clearStore(); sessionStorage.clear(); + localStorage.clear(); }, [client, goToRecoilSnapshot], ); @@ -263,6 +261,7 @@ export const useAuth = () => { email: string, password: string, workspaceInviteHash?: string, + workspacePersonalInviteToken?: string, captchaToken?: string, ) => { setIsVerifyPendingState(true); @@ -272,6 +271,7 @@ export const useAuth = () => { email, password, workspaceInviteHash, + workspacePersonalInviteToken, captchaToken, }, }); @@ -295,21 +295,43 @@ export const useAuth = () => { [setIsVerifyPendingState, signUp, handleVerify], ); - const handleGoogleLogin = useCallback((workspaceInviteHash?: string) => { + const buildRedirectUrl = ( + path: string, + params: { + workspacePersonalInviteToken?: string; + workspaceInviteHash?: string; + }, + ) => { const authServerUrl = REACT_APP_SERVER_BASE_URL; - window.location.href = - `${authServerUrl}/auth/google/${ - workspaceInviteHash ? '?inviteHash=' + workspaceInviteHash : '' - }` || ''; - }, []); + const url = new URL(`${authServerUrl}${path}`); + if (isDefined(params.workspaceInviteHash)) { + url.searchParams.set('inviteHash', params.workspaceInviteHash); + } + if (isDefined(params.workspacePersonalInviteToken)) { + url.searchParams.set('inviteToken', params.workspacePersonalInviteToken); + } + return url.toString(); + }; - const handleMicrosoftLogin = useCallback((workspaceInviteHash?: string) => { - const authServerUrl = REACT_APP_SERVER_BASE_URL; - window.location.href = - `${authServerUrl}/auth/microsoft/${ - workspaceInviteHash ? '?inviteHash=' + workspaceInviteHash : '' - }` || ''; - }, []); + const handleGoogleLogin = useCallback( + (params: { + workspacePersonalInviteToken?: string; + workspaceInviteHash?: string; + }) => { + window.location.href = buildRedirectUrl('/auth/google', params); + }, + [], + ); + + const handleMicrosoftLogin = useCallback( + (params: { + workspacePersonalInviteToken?: string; + workspaceInviteHash?: string; + }) => { + window.location.href = buildRedirectUrl('/auth/microsoft', params); + }, + [], + ); return { challenge: handleChallenge, diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx index 24111466a69d..48c66f54ed65 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx @@ -1,6 +1,6 @@ import { useCallback, useState } from 'react'; import { SubmitHandler, UseFormReturn } from 'react-hook-form'; -import { useParams } from 'react-router-dom'; +import { useParams, useSearchParams } from 'react-router-dom'; import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm'; import { useReadCaptchaToken } from '@/captcha/hooks/useReadCaptchaToken'; @@ -29,6 +29,9 @@ export const useSignInUp = (form: UseFormReturn<Form>) => { const isMatchingLocation = useIsMatchingLocation(); const workspaceInviteHash = useParams().workspaceInviteHash; + const [searchParams] = useSearchParams(); + const workspacePersonalInviteToken = + searchParams.get('inviteToken') ?? undefined; const [isInviteMode] = useState(() => isMatchingLocation(AppPath.Invite)); @@ -112,6 +115,7 @@ export const useSignInUp = (form: UseFormReturn<Form>) => { data.email.toLowerCase().trim(), data.password, workspaceInviteHash, + workspacePersonalInviteToken, token, ); } catch (err: any) { @@ -128,6 +132,7 @@ export const useSignInUp = (form: UseFormReturn<Form>) => { signInWithCredentials, signUpWithCredentials, workspaceInviteHash, + workspacePersonalInviteToken, enqueueSnackBar, requestFreshCaptchaToken, ], diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts index 8eb008b6f3c4..58ce165f7508 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts @@ -1,9 +1,15 @@ -import { useParams } from 'react-router-dom'; +import { useParams, useSearchParams } from 'react-router-dom'; import { useAuth } from '@/auth/hooks/useAuth'; export const useSignInWithGoogle = () => { const workspaceInviteHash = useParams().workspaceInviteHash; + const [searchParams] = useSearchParams(); + const workspacePersonalInviteToken = + searchParams.get('inviteToken') ?? undefined; const { signInWithGoogle } = useAuth(); - return { signInWithGoogle: () => signInWithGoogle(workspaceInviteHash) }; + return { + signInWithGoogle: () => + signInWithGoogle({ workspaceInviteHash, workspacePersonalInviteToken }), + }; }; diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithMicrosoft.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithMicrosoft.ts index 444bff19d31f..2f471c176c8c 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithMicrosoft.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithMicrosoft.ts @@ -1,11 +1,18 @@ -import { useParams } from 'react-router-dom'; +import { useParams, useSearchParams } from 'react-router-dom'; import { useAuth } from '@/auth/hooks/useAuth'; export const useSignInWithMicrosoft = () => { const workspaceInviteHash = useParams().workspaceInviteHash; + const [searchParams] = useSearchParams(); + const workspacePersonalInviteToken = + searchParams.get('inviteToken') ?? undefined; const { signInWithMicrosoft } = useAuth(); return { - signInWithMicrosoft: () => signInWithMicrosoft(workspaceInviteHash), + signInWithMicrosoft: () => + signInWithMicrosoft({ + workspaceInviteHash, + workspacePersonalInviteToken, + }), }; }; diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts index feee086ef7c0..a51365b98a3b 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts @@ -7,6 +7,7 @@ import { AppPath } from '@/types/AppPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { isDefaultLayoutAuthModalVisibleState } from '@/ui/layout/states/isDefaultLayoutAuthModalVisibleState'; + import { useGetWorkspaceFromInviteHashQuery } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; diff --git a/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx b/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx index 8bec4cc7dbd6..9eccbeb98e10 100644 --- a/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx +++ b/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx @@ -12,7 +12,6 @@ import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilled import { isSignUpDisabledState } from '@/client-config/states/isSignUpDisabledState'; import { sentryConfigState } from '@/client-config/states/sentryConfigState'; import { supportChatState } from '@/client-config/states/supportChatState'; -import { telemetryState } from '@/client-config/states/telemetryState'; import { useGetClientConfigQuery } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; @@ -24,7 +23,6 @@ export const ClientConfigProviderEffect = () => { const setIsSignUpDisabled = useSetRecoilState(isSignUpDisabledState); const setBilling = useSetRecoilState(billingState); - const setTelemetry = useSetRecoilState(telemetryState); const setSupportChat = useSetRecoilState(supportChatState); const setSentryConfig = useSetRecoilState(sentryConfigState); @@ -56,7 +54,6 @@ export const ClientConfigProviderEffect = () => { setIsSignUpDisabled(data?.clientConfig.signUpDisabled); setBilling(data?.clientConfig.billing); - setTelemetry(data?.clientConfig.telemetry); setSupportChat(data?.clientConfig.support); setSentryConfig({ @@ -79,7 +76,6 @@ export const ClientConfigProviderEffect = () => { setIsDebugMode, setIsSignInPrefilled, setIsSignUpDisabled, - setTelemetry, setSupportChat, setBilling, setSentryConfig, diff --git a/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts b/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts index 3143bbc5f65a..e702acefa4f1 100644 --- a/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts +++ b/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts @@ -16,9 +16,6 @@ export const GET_CLIENT_CONFIG = gql` signInPrefilled signUpDisabled debugMode - telemetry { - enabled - } support { supportDriver supportFrontChatId diff --git a/packages/twenty-front/src/modules/client-config/states/telemetryState.ts b/packages/twenty-front/src/modules/client-config/states/telemetryState.ts deleted file mode 100644 index f074ad218d5c..000000000000 --- a/packages/twenty-front/src/modules/client-config/states/telemetryState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createState } from 'twenty-ui'; - -import { Telemetry } from '~/generated/graphql'; - -export const telemetryState = createState<Telemetry>({ - key: 'telemetryState', - defaultValue: { enabled: true }, -}); diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx index 9cccd950e137..2b7d13f8c52b 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx @@ -174,7 +174,11 @@ export const CommandMenu = () => { 'firstName', 'lastName', ]), - { email: { ilike: `%${commandMenuSearch}%` } }, + ...generateILikeFiltersForCompositeFields( + commandMenuSearch, + 'emails', + ['primaryEmail'], + ), { phone: { ilike: `%${commandMenuSearch}%` } }, ]) : undefined, diff --git a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx index 506920b959a6..16c8bf7f4104 100644 --- a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx @@ -82,7 +82,9 @@ export const DefaultWithoutSearch: Story = { play: async () => { const canvas = within(document.body); - expect(await canvas.findByText('Create Task')).toBeInTheDocument(); + expect( + await canvas.findByText('Create Task', undefined, { timeout: 10000 }), + ).toBeInTheDocument(); expect(await canvas.findByText('Go to People')).toBeInTheDocument(); expect(await canvas.findByText('Go to Companies')).toBeInTheDocument(); expect(await canvas.findByText('Go to Opportunities')).toBeInTheDocument(); diff --git a/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx b/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx index 16cec36df180..5ca6eb72cd44 100644 --- a/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx +++ b/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx @@ -1,4 +1,4 @@ -import { SentryInitEffect } from '@/error-handler/components/SentryInitiEffect'; +import { SentryInitEffect } from '@/error-handler/components/SentryInitEffect'; export const ExceptionHandlerProvider: React.FC<React.PropsWithChildren> = ({ children, diff --git a/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx b/packages/twenty-front/src/modules/error-handler/components/SentryInitEffect.tsx similarity index 89% rename from packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx rename to packages/twenty-front/src/modules/error-handler/components/SentryInitEffect.tsx index 16b1ed014e48..f97336d14146 100644 --- a/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx +++ b/packages/twenty-front/src/modules/error-handler/components/SentryInitEffect.tsx @@ -1,6 +1,6 @@ -import { useEffect, useState } from 'react'; import * as Sentry from '@sentry/react'; import { isNonEmptyString } from '@sniptt/guards'; +import { useEffect, useState } from 'react'; import { useRecoilValue } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; @@ -26,14 +26,10 @@ export const SentryInitEffect = () => { release: sentryConfig?.release ?? undefined, dsn: sentryConfig?.dsn, integrations: [ - new Sentry.BrowserTracing({ - tracePropagationTargets: [ - 'localhost:3001', - REACT_APP_SERVER_BASE_URL, - ], - }), - new Sentry.Replay(), + Sentry.browserTracingIntegration({}), + Sentry.replayIntegration(), ], + tracePropagationTargets: ['localhost:3001', REACT_APP_SERVER_BASE_URL], tracesSampleRate: 1.0, replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1.0, diff --git a/packages/twenty-front/src/modules/favorites/components/Favorites.tsx b/packages/twenty-front/src/modules/favorites/components/CurrentWorkspaceMemberFavorites.tsx similarity index 83% rename from packages/twenty-front/src/modules/favorites/components/Favorites.tsx rename to packages/twenty-front/src/modules/favorites/components/CurrentWorkspaceMemberFavorites.tsx index 36d545c6f84b..c78cdd05c6fb 100644 --- a/packages/twenty-front/src/modules/favorites/components/Favorites.tsx +++ b/packages/twenty-front/src/modules/favorites/components/CurrentWorkspaceMemberFavorites.tsx @@ -11,7 +11,7 @@ import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/compo import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; -import { currentUserState } from '@/auth/states/currentUserState'; +import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { useFavorites } from '../hooks/useFavorites'; const StyledContainer = styled(NavigationDrawerSection)` @@ -34,8 +34,8 @@ const StyledNavigationDrawerItem = styled(NavigationDrawerItem)` } `; -export const Favorites = () => { - const currentUser = useRecoilValue(currentUserState); +export const CurrentWorkspaceMemberFavorites = () => { + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { favorites, handleReorderFavorite } = useFavorites(); const loading = useIsPrefetchLoading(); @@ -44,11 +44,19 @@ export const Favorites = () => { useNavigationSection('Favorites'); const isNavigationSectionOpen = useRecoilValue(isNavigationSectionOpenState); - if (loading && isDefined(currentUser)) { + if (loading && isDefined(currentWorkspaceMember)) { return <FavoritesSkeletonLoader />; } - if (!favorites || favorites.length === 0) return <></>; + const currentWorkspaceMemberFavorites = favorites.filter( + (favorite) => favorite.workspaceMemberId === currentWorkspaceMember?.id, + ); + + if ( + !currentWorkspaceMemberFavorites || + currentWorkspaceMemberFavorites.length === 0 + ) + return <></>; return ( <StyledContainer> @@ -61,7 +69,7 @@ export const Favorites = () => { onDragEnd={handleReorderFavorite} draggableItems={ <> - {favorites.map((favorite, index) => { + {currentWorkspaceMemberFavorites.map((favorite, index) => { const { id, labelIdentifier, diff --git a/packages/twenty-front/src/modules/favorites/components/WorkspaceFavorites.tsx b/packages/twenty-front/src/modules/favorites/components/WorkspaceFavorites.tsx new file mode 100644 index 000000000000..b89290526c98 --- /dev/null +++ b/packages/twenty-front/src/modules/favorites/components/WorkspaceFavorites.tsx @@ -0,0 +1,45 @@ +import { useFavorites } from '@/favorites/hooks/useFavorites'; +import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems'; +import { NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader'; +import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; +import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { View } from '@/views/types/View'; + +export const WorkspaceFavorites = () => { + const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews); + const loading = useIsPrefetchLoading(); + + const { workspaceFavorites } = useFavorites(); + + const workspaceFavoriteIds = new Set( + workspaceFavorites.map((favorite) => favorite.recordId), + ); + + const favoriteViewObjectMetadataIds = views.reduce<string[]>((acc, view) => { + if (workspaceFavoriteIds.has(view.id)) { + acc.push(view.objectMetadataId); + } + return acc; + }, []); + + const { objectMetadataItems } = useFilteredObjectMetadataItems(); + + const objectMetadataItemsToDisplay = objectMetadataItems.filter((item) => + favoriteViewObjectMetadataIds.includes(item.id), + ); + + if (loading) { + return <NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader />; + } + + return ( + <NavigationDrawerSectionForObjectMetadataItems + sectionTitle={'Workspace Favorites'} + objectMetadataItems={objectMetadataItemsToDisplay} + views={views} + isRemote={false} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts index 3956803dc55f..98813ad384c7 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts @@ -1,7 +1,6 @@ import { gql } from '@apollo/client'; import { AvatarType } from 'twenty-ui'; -import { PERSON_FRAGMENT } from '@/object-record/hooks/__mocks__/personFragment'; import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; export const mockId = '8f3b2121-f194-4ba4-9fbf-2d5a37126806'; @@ -48,36 +47,38 @@ export const initialFavorites = [ }, ]; -export const sortedFavorites = [ - { - id: '1', - recordId: '2', - position: 0, - avatarType: 'squared', - avatarUrl: undefined, - labelIdentifier: 'ABC Corp', - link: '/object/company/2', - }, - { - id: '2', - recordId: '4', - position: 1, - avatarType: 'squared', - avatarUrl: undefined, - labelIdentifier: 'Company Test', - link: '/object/company/4', - }, - { - id: '3', - position: 2, - key: '8f3b2121-f194-4ba4-9fbf-2d5a37126806', - labelIdentifier: 'favoriteLabel', - avatarUrl: 'example.com', - avatarType: 'squared', - link: 'example.com', - recordId: '1', - }, -]; +export const sortedFavorites = [ + { + "avatarType": "rounded", + "avatarUrl": "", + "id": "1", + "labelIdentifier": " ", + "link": "/object/person/1", + "position": 0, + "recordId": "1", + "workspaceMemberId": undefined, + }, + { + "avatarType": "rounded", + "avatarUrl": "", + "id": "2", + "labelIdentifier": " ", + "link": "/object/person/3", + "position": 1, + "recordId": "3", + "workspaceMemberId": undefined, + }, + { + "avatarType": "squared", + "avatarUrl": "example.com", + "id": "3", + "key": "8f3b2121-f194-4ba4-9fbf-2d5a37126806", + "labelIdentifier": "favoriteLabel", + "link": "example.com", + "position": 2, + "recordId": "1", + }, + ] export const mocks = [ { @@ -86,132 +87,155 @@ export const mocks = [ mutation CreateOneFavorite($input: FavoriteCreateInput!) { createFavorite(data: $input) { __typename + noteId taskId - myCustomObjectId - workspaceMemberId - workspaceMember { + person { __typename - userId - updatedAt - dateFormat - id - locale - avatarUrl - timeZone name { firstName lastName } - userEmail - createdAt - timeFormat - colorScheme - } - companyId - myCustomObject { - __typename - createdBy { - source - workspaceMemberId - name + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks } - position - updatedAt - name - myCustomField - id + deletedAt createdAt - } - updatedAt - id - opportunity { - __typename + updatedAt + jobTitle + intro + workPrefereance + performanceRating + xLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + city companyId - closeDate - stage + phones { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } createdBy { source workspaceMemberId name } id - updatedAt - name - createdAt - pointOfContactId - amount { - amountMicros - currencyCode - } position + emails { + primaryEmail + additionalEmails + } + avatarUrl + whatsapp { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } } - noteId - note { + task { __typename + updatedAt + createdAt + deletedAt + dueAt + id + status + body createdBy { source workspaceMemberId name } + assigneeId position - body - updatedAt - createdAt title - id } + rocketId + viewId + updatedAt + workflowId personId - task { + workspaceMemberId + note { __typename - status - assigneeId - updatedAt - body - createdAt - dueAt - position + deletedAt id - title + position + updatedAt createdBy { source workspaceMemberId name } + body + title + createdAt + } + createdAt + view { + __typename + id + type + icon + key + isCompact + kanbanFieldMetadataId + objectMetadataId + position + createdAt + deletedAt + updatedAt + name } opportunityId position - createdAt - company { + deletedAt + id + companyId + workflow { __typename + deletedAt + lastPublishedVersionId + createdAt id - visaSponsorship - createdBy { - source - workspaceMemberId - name - } - domainName { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - introVideo { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } + statuses + name position - annualRecurringRevenue { - amountMicros - currencyCode + updatedAt + } + workspaceMember { + __typename + name { + firstName + lastName } - employees - linkedinLink { + avatarUrl + userId + createdAt + timeZone + id + timeFormat + updatedAt + locale + userEmail + deletedAt + colorScheme + dateFormat + } + company { + __typename + updatedAt + domainName { primaryLinkUrl primaryLinkLabel secondaryLinks } - workPolicy + visaSponsorship address { addressStreet1 addressStreet2 @@ -222,21 +246,76 @@ export const mocks = [ addressLat addressLng } + position + employees + deletedAt + accountOwnerId + annualRecurringRevenue { + amountMicros + currencyCode + } + id name - updatedAt xLink { primaryLinkUrl primaryLinkLabel secondaryLinks } - myCustomField createdAt - accountOwnerId + createdBy { + source + workspaceMemberId + name + } + workPolicy + introVideo { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } tagline idealCustomerProfile } - person { - ${PERSON_FRAGMENT} + rocket { + __typename + createdBy { + source + workspaceMemberId + name + } + updatedAt + name + position + createdAt + id + deletedAt + } + opportunity { + __typename + createdBy { + source + workspaceMemberId + name + } + amount { + amountMicros + currencyCode + } + stage + position + closeDate + id + name + pointOfContactId + companyId + updatedAt + deletedAt + createdAt } } } @@ -286,132 +365,155 @@ export const mocks = [ ) { updateFavorite(id: $idToUpdate, data: $input) { __typename + noteId taskId - myCustomObjectId - workspaceMemberId - workspaceMember { + person { __typename - userId - updatedAt - dateFormat - id - locale - avatarUrl - timeZone name { firstName lastName } - userEmail - createdAt - timeFormat - colorScheme - } - companyId - myCustomObject { - __typename - createdBy { - source - workspaceMemberId - name + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks } - position - updatedAt - name - myCustomField - id + deletedAt createdAt - } - updatedAt - id - opportunity { - __typename + updatedAt + jobTitle + intro + workPrefereance + performanceRating + xLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + city companyId - closeDate - stage + phones { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } createdBy { source workspaceMemberId name } id - updatedAt - name - createdAt - pointOfContactId - amount { - amountMicros - currencyCode - } position + emails { + primaryEmail + additionalEmails + } + avatarUrl + whatsapp { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } } - noteId - note { + task { __typename + updatedAt + createdAt + deletedAt + dueAt + id + status + body createdBy { source workspaceMemberId name } + assigneeId position - body - updatedAt - createdAt title - id } + rocketId + viewId + updatedAt + workflowId personId - task { + workspaceMemberId + note { __typename - status - assigneeId - updatedAt - body - createdAt - dueAt - position + deletedAt id - title + position + updatedAt createdBy { source workspaceMemberId name } + body + title + createdAt + } + createdAt + view { + __typename + id + type + icon + key + isCompact + kanbanFieldMetadataId + objectMetadataId + position + createdAt + deletedAt + updatedAt + name } opportunityId position - createdAt - company { + deletedAt + id + companyId + workflow { __typename + deletedAt + lastPublishedVersionId + createdAt id - visaSponsorship - createdBy { - source - workspaceMemberId - name - } - domainName { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - introVideo { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } + statuses + name position - annualRecurringRevenue { - amountMicros - currencyCode + updatedAt + } + workspaceMember { + __typename + name { + firstName + lastName } - employees - linkedinLink { + avatarUrl + userId + createdAt + timeZone + id + timeFormat + updatedAt + locale + userEmail + deletedAt + colorScheme + dateFormat + } + company { + __typename + updatedAt + domainName { primaryLinkUrl primaryLinkLabel secondaryLinks } - workPolicy + visaSponsorship address { addressStreet1 addressStreet2 @@ -422,21 +524,76 @@ export const mocks = [ addressLat addressLng } + position + employees + deletedAt + accountOwnerId + annualRecurringRevenue { + amountMicros + currencyCode + } + id name - updatedAt xLink { primaryLinkUrl primaryLinkLabel secondaryLinks } - myCustomField createdAt - accountOwnerId + createdBy { + source + workspaceMemberId + name + } + workPolicy + introVideo { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } tagline idealCustomerProfile } - person { - ${PERSON_FRAGMENT} + rocket { + __typename + createdBy { + source + workspaceMemberId + name + } + updatedAt + name + position + createdAt + id + deletedAt + } + opportunity { + __typename + createdBy { + source + workspaceMemberId + name + } + amount { + amountMicros + currencyCode + } + stage + position + closeDate + id + name + pointOfContactId + companyId + updatedAt + deletedAt + createdAt } } } diff --git a/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx b/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx index 6a4b83b77d9b..3a30077ea285 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx +++ b/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx @@ -1,16 +1,16 @@ -import { ReactNode } from 'react'; import { MockedProvider } from '@apollo/client/testing'; import { DropResult, ResponderProvided } from '@hello-pangea/dnd'; import { act, renderHook, waitFor } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot, useSetRecoilState } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { useFavorites } from '@/favorites/hooks/useFavorites'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { favoriteId, favoriteTargetObjectRecord, @@ -29,8 +29,6 @@ jest.mock('@/object-record/hooks/useFindManyRecords', () => ({ useFindManyRecords: () => ({ records: initialFavorites }), })); -const mockObjectMetadataItems = getObjectMetadataItemsMock(); - const Wrapper = ({ children }: { children: ReactNode }) => ( <RecoilRoot> <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> @@ -51,7 +49,7 @@ describe('useFavorites', () => { setCurrentWorkspaceMember(mockWorkspaceMember); const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFavorites(); }, @@ -72,7 +70,7 @@ describe('useFavorites', () => { setCurrentWorkspaceMember(mockWorkspaceMember); const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFavorites(); }, @@ -100,7 +98,7 @@ describe('useFavorites', () => { setCurrentWorkspaceMember(mockWorkspaceMember); const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFavorites(); }, @@ -125,7 +123,7 @@ describe('useFavorites', () => { setCurrentWorkspaceMember(mockWorkspaceMember); const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFavorites(); }, diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts index 802aa3a3de26..0ca7bfc97484 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts @@ -1,9 +1,10 @@ -import { useMemo } from 'react'; import { OnDragEndResponder } from '@hello-pangea/dnd'; +import { useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { Favorite } from '@/favorites/types/Favorite'; +import { sortFavorites } from '@/favorites/utils/sort-favorites.util'; import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; @@ -13,7 +14,6 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; export const useFavorites = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); @@ -44,6 +44,15 @@ export const useFavorites = () => { }, ); + const { records: workspaceFavorites } = usePrefetchedData<Favorite>( + PrefetchKey.AllFavorites, + { + workspaceMemberId: { + eq: undefined, + }, + }, + ); + const favoriteRelationFieldMetadataItems = useMemo( () => favoriteObjectMetadataItem.fields.filter( @@ -58,43 +67,31 @@ export const useFavorites = () => { useGetObjectRecordIdentifierByNameSingular(); const favoritesSorted = useMemo(() => { - return favorites - .map((favorite) => { - for (const relationField of favoriteRelationFieldMetadataItems) { - if (isDefined(favorite[relationField.name])) { - const relationObject = favorite[relationField.name]; - - const relationObjectNameSingular = - relationField.toRelationMetadata?.fromObjectMetadata - .nameSingular ?? ''; - - const objectRecordIdentifier = - getObjectRecordIdentifierByNameSingular( - relationObject, - relationObjectNameSingular, - ); - - return { - id: favorite.id, - recordId: objectRecordIdentifier.id, - position: favorite.position, - avatarType: objectRecordIdentifier.avatarType, - avatarUrl: objectRecordIdentifier.avatarUrl, - labelIdentifier: objectRecordIdentifier.name, - link: objectRecordIdentifier.linkToShowPage, - } as Favorite; - } - } - - return favorite; - }) - .sort((a, b) => a.position - b.position); + return sortFavorites( + favorites, + favoriteRelationFieldMetadataItems, + getObjectRecordIdentifierByNameSingular, + true, + ); }, [ favoriteRelationFieldMetadataItems, favorites, getObjectRecordIdentifierByNameSingular, ]); + const workspaceFavoritesSorted = useMemo(() => { + return sortFavorites( + workspaceFavorites.filter((favorite) => favorite.viewId), + favoriteRelationFieldMetadataItems, + getObjectRecordIdentifierByNameSingular, + false, + ); + }, [ + favoriteRelationFieldMetadataItems, + getObjectRecordIdentifierByNameSingular, + workspaceFavorites, + ]); + const createFavorite = ( targetRecord: Record<string, any>, targetObjectNameSingular: string, @@ -157,6 +154,7 @@ export const useFavorites = () => { return { favorites: favoritesSorted, + workspaceFavorites: workspaceFavoritesSorted, createFavorite, handleReorderFavorite, deleteFavorite, diff --git a/packages/twenty-front/src/modules/favorites/types/Favorite.ts b/packages/twenty-front/src/modules/favorites/types/Favorite.ts index a00414137950..a0bb7289911d 100644 --- a/packages/twenty-front/src/modules/favorites/types/Favorite.ts +++ b/packages/twenty-front/src/modules/favorites/types/Favorite.ts @@ -9,5 +9,6 @@ export type Favorite = { avatarType: AvatarType; link: string; recordId: string; + workspaceMemberId: string; __typename: 'Favorite'; }; diff --git a/packages/twenty-front/src/modules/favorites/utils/sort-favorites.util.ts b/packages/twenty-front/src/modules/favorites/utils/sort-favorites.util.ts new file mode 100644 index 000000000000..aba5b0bfd6f9 --- /dev/null +++ b/packages/twenty-front/src/modules/favorites/utils/sort-favorites.util.ts @@ -0,0 +1,49 @@ +import { Favorite } from '@/favorites/types/Favorite'; +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; +import { isDefined } from 'twenty-ui'; + +export const sortFavorites = ( + favorites: Favorite[], + favoriteRelationFieldMetadataItems: FieldMetadataItem[], + getObjectRecordIdentifierByNameSingular: ( + record: any, + objectNameSingular: string, + ) => ObjectRecordIdentifier, + hasLinkToShowPage: boolean, +) => { + return favorites + .map((favorite) => { + for (const relationField of favoriteRelationFieldMetadataItems) { + if (isDefined(favorite[relationField.name])) { + const relationObject = favorite[relationField.name]; + + const relationObjectNameSingular = + relationField.relationDefinition?.targetObjectMetadata + .nameSingular ?? ''; + + const objectRecordIdentifier = + getObjectRecordIdentifierByNameSingular( + relationObject, + relationObjectNameSingular, + ); + + return { + id: favorite.id, + recordId: objectRecordIdentifier.id, + position: favorite.position, + avatarType: objectRecordIdentifier.avatarType, + avatarUrl: objectRecordIdentifier.avatarUrl, + labelIdentifier: objectRecordIdentifier.name, + link: hasLinkToShowPage + ? objectRecordIdentifier.linkToShowPage + : '', + workspaceMemberId: favorite.workspaceMemberId, + } as Favorite; + } + } + + return favorite; + }) + .sort((a, b) => a.position - b.position); +}; diff --git a/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/__stories__/KeyboardShortcutMenu.stories.tsx b/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/__stories__/KeyboardShortcutMenu.stories.tsx new file mode 100644 index 000000000000..afcb84abe27b --- /dev/null +++ b/packages/twenty-front/src/modules/keyboard-shortcut-menu/components/__stories__/KeyboardShortcutMenu.stories.tsx @@ -0,0 +1,36 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { expect, within } from '@storybook/test'; + +import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; + +import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu'; +import { useEffect } from 'react'; +import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; +import { KeyboardShortcutMenu } from '../KeyboardShortcutMenu'; + +const meta: Meta<typeof KeyboardShortcutMenu> = { + title: 'Modules/KeyboardShortcutMenu/KeyboardShortcutMenu', + component: KeyboardShortcutMenu, + decorators: [ + (Story) => { + const { openKeyboardShortcutMenu } = useKeyboardShortcutMenu(); + useEffect(() => { + openKeyboardShortcutMenu(); + }, [openKeyboardShortcutMenu]); + return <Story />; + }, + SnackBarDecorator, + ComponentWithRouterDecorator, + ], +}; + +export default meta; +type Story = StoryObj<typeof KeyboardShortcutMenu>; + +export const Default: Story = { + play: async () => { + const canvas = within(document.body); + + expect(await canvas.findByText('Keyboard shortcuts')).toBeInTheDocument(); + }, +}; diff --git a/packages/twenty-front/src/modules/localization/utils/formatDateISOStringToRelativeDate.ts b/packages/twenty-front/src/modules/localization/utils/formatDateISOStringToRelativeDate.ts new file mode 100644 index 000000000000..2bcc93a30357 --- /dev/null +++ b/packages/twenty-front/src/modules/localization/utils/formatDateISOStringToRelativeDate.ts @@ -0,0 +1,25 @@ +import { + differenceInDays, + formatDistance, + isToday, + startOfDay, +} from 'date-fns'; + +export const formatDateISOStringToRelativeDate = ( + isoDate: string, + isDayMaximumPrecision = false, +) => { + const now = new Date(); + const targetDate = new Date(isoDate); + + if (isDayMaximumPrecision && isToday(targetDate)) return 'Today'; + + const isWithin24h = Math.abs(differenceInDays(targetDate, now)) < 1; + + if (isDayMaximumPrecision || !isWithin24h) + return formatDistance(startOfDay(targetDate), startOfDay(now), { + addSuffix: true, + }); + + return formatDistance(targetDate, now, { addSuffix: true }); +}; diff --git a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx index 1dbe04bad64d..da636fe025e5 100644 --- a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx +++ b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx @@ -42,7 +42,7 @@ export const AppNavigationDrawer = ({ const drawerProps: NavigationDrawerProps = isSettingsDrawer ? { isSubMenu: true, - title: 'Settings', + title: 'Exit Settings', children: <SettingsNavigationDrawerItems />, footer: <GithubVersionLink />, } diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx index e28eb6bf83f4..88f18e97e66b 100644 --- a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx @@ -3,12 +3,14 @@ import { useSetRecoilState } from 'recoil'; import { IconSearch, IconSettings } from 'twenty-ui'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; -import { Favorites } from '@/favorites/components/Favorites'; -import { ObjectMetadataNavItems } from '@/object-metadata/components/ObjectMetadataNavItems'; +import { CurrentWorkspaceMemberFavorites } from '@/favorites/components/CurrentWorkspaceMemberFavorites'; +import { WorkspaceFavorites } from '@/favorites/components/WorkspaceFavorites'; +import { NavigationDrawerSectionForObjectMetadataItemsWrapper } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper'; import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; export const MainNavigationDrawerItems = () => { const isMobile = useIsMobile(); @@ -17,6 +19,9 @@ export const MainNavigationDrawerItems = () => { const setNavigationMemorizedUrl = useSetRecoilState( navigationMemorizedUrlState, ); + const isWorkspaceFavoriteEnabled = useIsFeatureEnabled( + 'IS_WORKSPACE_FAVORITE_ENABLED', + ); return ( <> @@ -39,10 +44,16 @@ export const MainNavigationDrawerItems = () => { </NavigationDrawerSection> )} - <Favorites /> + <CurrentWorkspaceMemberFavorites /> - <ObjectMetadataNavItems isRemote={false} /> - <ObjectMetadataNavItems isRemote={true} /> + {isWorkspaceFavoriteEnabled ? ( + <WorkspaceFavorites /> + ) : ( + <NavigationDrawerSectionForObjectMetadataItemsWrapper + isRemote={false} + /> + )} + <NavigationDrawerSectionForObjectMetadataItemsWrapper isRemote={true} /> </> ); }; diff --git a/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts b/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts index 8efee5d0c42d..1ec02c2fd071 100644 --- a/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts +++ b/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts @@ -4,16 +4,17 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { - COMPANY_OBJECT_METADATA_ID, - getObjectMetadataItemsMock, -} from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { AppPath } from '@/types/AppPath'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { mockedUserData } from '~/testing/mock-data/users'; jest.mock('@/prefetch/hooks/usePrefetchedData'); const setupMockPrefetchedData = (viewId?: string) => { + const companyObjectMetadata = generatedMockObjectMetadataItems.find( + (item) => item.nameSingular === 'company', + ); + jest.mocked(usePrefetchedData).mockReturnValue({ isDataPrefetched: true, records: viewId @@ -21,7 +22,7 @@ const setupMockPrefetchedData = (viewId?: string) => { { id: viewId, __typename: 'object', - objectMetadataId: COMPANY_OBJECT_METADATA_ID, + objectMetadataId: companyObjectMetadata?.id, }, ] : [], @@ -36,7 +37,7 @@ const renderHooks = (withCurrentUser: boolean) => { objectMetadataItemsState, ); - setObjectMetadataItems(getObjectMetadataItemsMock()); + setObjectMetadataItems(generatedMockObjectMetadataItems); if (withCurrentUser) { setCurrentUser(mockedUserData); diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx new file mode 100644 index 000000000000..ff84e7c5f221 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx @@ -0,0 +1,161 @@ +import { useLocation } from 'react-router-dom'; +import { useRecoilValue } from 'recoil'; +import { useIcons } from 'twenty-ui'; + +import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; +import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; +import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; +import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; +import { getNavigationSubItemState } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemState'; +import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; +import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews'; +import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { View } from '@/views/types/View'; + +type Section = 'CRM' | 'Scheduling' | 'Billing' | 'Custom'; + +export const NavigationDrawerSectionForObjectMetadataItems = ({ + sectionTitle, + isRemote, + views, + objectMetadataItems, +}: { + sectionTitle: string; + isRemote: boolean; + views: View[]; + objectMetadataItems: ObjectMetadataItem[]; +}) => { + const { toggleNavigationSection, isNavigationSectionOpenState } = + useNavigationSection( + 'Objects' + sectionTitle + (isRemote ? 'Remote' : 'Workspace'), + ); + const isNavigationSectionOpen = useRecoilValue(isNavigationSectionOpenState); + + const { getIcon } = useIcons(); + const currentPath = useLocation().pathname; + + const { getLastVisitedViewIdFromObjectMetadataItemId } = useLastVisitedView(); + + // Define the sections and their corresponding items + const sectionItems: Record<Section, string[]> = { + CRM: ['Companies', 'People', 'Opportunities', 'Tasks', 'Notes'], + Scheduling: ['Crews', 'Jobs'], + Billing: ['Work Orders', 'Materials', 'Services'], + Custom: [], + }; + + // Group items into sections + const categorizedItems = (Object.keys(sectionItems) as Section[]).reduce( + (acc, section) => { + if (section !== 'Custom') { + acc[section] = objectMetadataItems.filter((item) => + sectionItems[section].includes(item.labelPlural), + ); + } + return acc; + }, + {} as Record<Section, ObjectMetadataItem[]>, + ); + + // Any items not included in predefined sections are 'Custom' + categorizedItems['Custom'] = objectMetadataItems.filter( + (item) => !Object.values(sectionItems).flat().includes(item.labelPlural), + ); + + // Function to render each section + const renderSection = (section: Section) => { + const items = categorizedItems[section]; + if (items.length === 0) return null; + + return ( + <div key={section}> + <NavigationDrawerSectionTitle label={section} /> + {items + .sort((a, b) => { + // For defined sections, sort according to sectionItems order + if (section in sectionItems && section !== 'Custom') { + const indexA = sectionItems[section]?.indexOf(a.labelPlural) ?? 0; + const indexB = sectionItems[section]?.indexOf(b.labelPlural) ?? 0; + return indexA - indexB; + } + // For 'Custom', sort alphabetically + return a.labelPlural.localeCompare(b.labelPlural); + }) + .map((objectMetadataItem) => { + const objectMetadataViews = getObjectMetadataItemViews( + objectMetadataItem.id, + views, + ); + const lastVisitedViewId = + getLastVisitedViewIdFromObjectMetadataItemId( + objectMetadataItem.id, + ); + const viewId = lastVisitedViewId ?? objectMetadataViews[0]?.id; + + const navigationPath = `/objects/${objectMetadataItem.namePlural}${ + viewId ? `?view=${viewId}` : '' + }`; + + const shouldSubItemsBeDisplayed = + currentPath === `/objects/${objectMetadataItem.namePlural}` && + objectMetadataViews.length > 1; + + const sortedObjectMetadataViews = [...objectMetadataViews].sort( + (viewA, viewB) => + viewA.key === 'INDEX' ? -1 : viewA.position - viewB.position, + ); + + const selectedSubItemIndex = sortedObjectMetadataViews.findIndex( + (view) => viewId === view.id, + ); + + const subItemArrayLength = sortedObjectMetadataViews.length; + + return ( + <div key={objectMetadataItem.id}> + <NavigationDrawerItem + label={objectMetadataItem.labelPlural} + to={navigationPath} + Icon={getIcon(objectMetadataItem.icon)} + active={ + currentPath === `/objects/${objectMetadataItem.namePlural}` + } + /> + {shouldSubItemsBeDisplayed && + sortedObjectMetadataViews.map((view, index) => ( + <NavigationDrawerSubItem + label={view.name} + to={`/objects/${objectMetadataItem.namePlural}?view=${view.id}`} + active={viewId === view.id} + subItemState={getNavigationSubItemState({ + index, + arrayLength: subItemArrayLength, + selectedIndex: selectedSubItemIndex, + })} + Icon={getIcon(view.icon)} + key={view.id} + /> + ))} + </div> + ); + })} + </div> + ); + }; + + return ( + objectMetadataItems.length > 0 && ( + <NavigationDrawerSection> + <NavigationDrawerSectionTitle + label={sectionTitle} + onClick={() => toggleNavigationSection()} + /> + {isNavigationSectionOpen && + (Object.keys(categorizedItems) as Section[]).map((section) => + renderSection(section), + )} + </NavigationDrawerSection> + ) + ); +}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx new file mode 100644 index 000000000000..70e00d717330 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx @@ -0,0 +1,29 @@ +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; + +const StyledSkeletonColumn = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(1)}; + height: 76px; + padding-left: ${({ theme }) => theme.spacing(1)}; +`; + +export const NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader: React.FC = + () => { + const theme = useTheme(); + return ( + <SkeletonTheme + baseColor={theme.background.tertiary} + highlightColor={theme.background.transparent.light} + borderRadius={4} + > + <StyledSkeletonColumn> + <Skeleton width={196} height={16} /> + <Skeleton width={196} height={16} /> + <Skeleton width={196} height={16} /> + </StyledSkeletonColumn> + </SkeletonTheme> + ); + }; diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper.tsx new file mode 100644 index 000000000000..2127db1fc604 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper.tsx @@ -0,0 +1,40 @@ +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +import { currentUserState } from '@/auth/states/currentUserState'; +import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems'; +import { NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader'; +import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; +import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { View } from '@/views/types/View'; + +export const NavigationDrawerSectionForObjectMetadataItemsWrapper = ({ + isRemote, +}: { + isRemote: boolean; +}) => { + const currentUser = useRecoilValue(currentUserState); + + const { activeObjectMetadataItems } = useFilteredObjectMetadataItems(); + const filteredActiveObjectMetadataItems = activeObjectMetadataItems.filter( + (item) => (isRemote ? item.isRemote : !item.isRemote), + ); + + const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews); + const loading = useIsPrefetchLoading(); + + if (loading && isDefined(currentUser)) { + return <NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader />; + } + + return ( + <NavigationDrawerSectionForObjectMetadataItems + sectionTitle={isRemote ? 'Remote' : 'Workspace'} + objectMetadataItems={filteredActiveObjectMetadataItems} + views={views} + isRemote={isRemote} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx index b1bb3a151ad9..ecc0772b85cd 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsLoadEffect.tsx @@ -6,8 +6,8 @@ import { currentUserState } from '@/auth/states/currentUserState'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { WorkspaceActivationStatus } from '~/generated/graphql'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; @@ -16,7 +16,7 @@ export const ObjectMetadataItemsLoadEffect = () => { const currentWorkspace = useRecoilValue(currentWorkspaceState); const isLoggedIn = useIsLogged(); - const { objectMetadataItems: newObjectMetadataItems, loading } = + const { objectMetadataItems: newObjectMetadataItems } = useFindManyObjectMetadataItems({ skip: !isLoggedIn, }); @@ -29,18 +29,14 @@ export const ObjectMetadataItemsLoadEffect = () => { const toSetObjectMetadataItems = isUndefinedOrNull(currentUser) || currentWorkspace?.activationStatus !== WorkspaceActivationStatus.Active - ? getObjectMetadataItemsMock() + ? generatedMockObjectMetadataItems : newObjectMetadataItems; - if ( - !loading && - !isDeeplyEqual(objectMetadataItems, toSetObjectMetadataItems) - ) { + if (!isDeeplyEqual(objectMetadataItems, toSetObjectMetadataItems)) { setObjectMetadataItems(toSetObjectMetadataItems); } }, [ currentUser, currentWorkspace?.activationStatus, - loading, newObjectMetadataItems, objectMetadataItems, setObjectMetadataItems, diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx deleted file mode 100644 index 210dc7030a70..000000000000 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { useLocation } from 'react-router-dom'; -import { useRecoilValue } from 'recoil'; -import { useIcons } from 'twenty-ui'; - -import { ObjectMetadataNavItemsSkeletonLoader } from '@/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader'; -import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; -import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; -import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; -import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; -import { View } from '@/views/types/View'; -import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews'; - -export const ObjectMetadataNavItems = ({ isRemote }: { isRemote: boolean }) => { - const { isNavigationSectionOpenState } = useNavigationSection( - 'Objects' + (isRemote ? 'Remote' : 'Workspace'), - ); - const isNavigationSectionOpen = useRecoilValue(isNavigationSectionOpenState); - - const { activeObjectMetadataItems } = useFilteredObjectMetadataItems(); - const filteredActiveObjectMetadataItems = activeObjectMetadataItems.filter( - (item) => (isRemote ? item.isRemote : !item.isRemote), - ); - const { getIcon } = useIcons(); - const currentPath = useLocation().pathname; - - const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews); - const loading = useIsPrefetchLoading(); - - if (loading) { - return <ObjectMetadataNavItemsSkeletonLoader />; - } - - type SectionItems = { - [key: string]: string[]; - }; - - const sectionItems: SectionItems = { - CRM: ['Companies', 'People', 'Opportunities', 'Tasks', 'Notes'], - Scheduling: ['Crews', 'Jobs'], - Billing: ['Work Orders', 'Materials', 'Services'], - }; - - const categorizedItems = Object.keys(sectionItems).reduce( - (acc, section) => { - acc[section] = filteredActiveObjectMetadataItems.filter( - (item) => sectionItems[section].includes(item.labelPlural), // TS7053: Element implicitly has an any type because expression of type string can't be used to index type - ); - return acc; - }, - {} as Record<string, typeof filteredActiveObjectMetadataItems>, - ); - - const customItems = filteredActiveObjectMetadataItems.filter( - (item) => !Object.values(sectionItems).flat().includes(item.labelPlural), - ); - - const renderSection = ( - section: string, - items: typeof filteredActiveObjectMetadataItems, - ) => - items.length > 0 && ( - <div key={section}> - <NavigationDrawerSectionTitle label={section} /> - {items - .sort((a, b) => a.labelPlural.localeCompare(b.labelPlural)) - .map((item) => { - const objectMetadataViews = getObjectMetadataItemViews( - item.id, - views, - ); - const viewId = objectMetadataViews[0]?.id; - - const navigationPath = `/objects/${item.namePlural}${ - viewId ? `?view=${viewId}` : '' - }`; - - return ( - <NavigationDrawerItem - key={item.id} - label={item.labelPlural} - to={navigationPath} - active={currentPath === `/objects/${item.namePlural}`} - Icon={getIcon(item.icon)} - /> - ); - })} - </div> - ); - - return ( - <> - {isNavigationSectionOpen && ( - <> - {Object.keys(categorizedItems).map((section) => - renderSection(section, categorizedItems[section]), - )} - {customItems.length > 0 && renderSection('Custom', customItems)} - {isRemote && - renderSection('Remote', filteredActiveObjectMetadataItems)} - </> - )} - </> - ); -}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx deleted file mode 100644 index 82669d907204..000000000000 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; -import { useTheme } from '@emotion/react'; -import styled from '@emotion/styled'; - -const StyledSkeletonColumn = styled.div` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spacing(1)}; - height: 76px; - padding-left: ${({ theme }) => theme.spacing(1)}; -`; - -export const ObjectMetadataNavItemsSkeletonLoader: React.FC = () => { - const theme = useTheme(); - return ( - <SkeletonTheme - baseColor={theme.background.tertiary} - highlightColor={theme.background.transparent.light} - borderRadius={4} - > - <StyledSkeletonColumn> - <Skeleton width={196} height={16} /> - <Skeleton width={196} height={16} /> - <Skeleton width={196} height={16} /> - </StyledSkeletonColumn> - </SkeletonTheme> - ); -}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/__stories__/NavigationDrawerSectionForObjectMetadataItemsWrapper.stories.tsx b/packages/twenty-front/src/modules/object-metadata/components/__stories__/NavigationDrawerSectionForObjectMetadataItemsWrapper.stories.tsx new file mode 100644 index 000000000000..fc21940e6d6a --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/components/__stories__/NavigationDrawerSectionForObjectMetadataItemsWrapper.stories.tsx @@ -0,0 +1,44 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator'; +import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; +import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +import { NavigationDrawerSectionForObjectMetadataItemsWrapper } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper'; +import { within } from '@storybook/test'; +import { PrefetchLoadedDecorator } from '~/testing/decorators/PrefetchLoadedDecorator'; + +const meta: Meta<typeof NavigationDrawerSectionForObjectMetadataItemsWrapper> = + { + title: + 'Modules/ObjectMetadata/NavigationDrawerSectionForObjectMetadataItemsWrapper', + component: NavigationDrawerSectionForObjectMetadataItemsWrapper, + decorators: [ + IconsProviderDecorator, + ObjectMetadataItemsDecorator, + ComponentWithRouterDecorator, + ComponentWithRecoilScopeDecorator, + SnackBarDecorator, + PrefetchLoadedDecorator, + ], + parameters: { + msw: graphqlMocks, + }, + }; + +export default meta; +type Story = StoryObj< + typeof NavigationDrawerSectionForObjectMetadataItemsWrapper +>; + +export const Default: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await canvas.findByText('People', undefined, { timeout: 10000 }); + await canvas.findByText('Companies'); + await canvas.findByText('Opportunities'); + }, +}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx b/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx deleted file mode 100644 index 7e74871a5fee..000000000000 --- a/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { expect } from '@storybook/jest'; -import { Meta, StoryObj } from '@storybook/react'; -import { within } from '@storybook/test'; - -import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator'; -import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; -import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; -import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; -import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; -import { graphqlMocks } from '~/testing/graphqlMocks'; - -import { PrefetchLoadedDecorator } from '~/testing/decorators/PrefetchLoadedDecorator'; -import { ObjectMetadataNavItems } from '../ObjectMetadataNavItems'; - -const meta: Meta<typeof ObjectMetadataNavItems> = { - title: 'Modules/ObjectMetadata/ObjectMetadataNavItems', - component: ObjectMetadataNavItems, - decorators: [ - IconsProviderDecorator, - ObjectMetadataItemsDecorator, - ComponentWithRouterDecorator, - ComponentWithRecoilScopeDecorator, - SnackBarDecorator, - PrefetchLoadedDecorator, - ], - parameters: { - msw: graphqlMocks, - }, -}; - -export default meta; -type Story = StoryObj<typeof ObjectMetadataNavItems>; - -export const Default: Story = { - play: async () => { - const canvas = within(document.body); - expect(await canvas.findByText('People')).toBeInTheDocument(); - expect(await canvas.findByText('Companies')).toBeInTheDocument(); - expect(await canvas.findByText('Opportunities')).toBeInTheDocument(); - }, -}; diff --git a/packages/twenty-front/src/modules/object-metadata/constants/SortableFieldMetadataTypes.ts b/packages/twenty-front/src/modules/object-metadata/constants/SortableFieldMetadataTypes.ts index 2e7713d96fc0..282710253650 100644 --- a/packages/twenty-front/src/modules/object-metadata/constants/SortableFieldMetadataTypes.ts +++ b/packages/twenty-front/src/modules/object-metadata/constants/SortableFieldMetadataTypes.ts @@ -15,4 +15,5 @@ export const SORTABLE_FIELD_METADATA_TYPES = [ FieldMetadataType.Currency, FieldMetadataType.Actor, FieldMetadataType.Links, + FieldMetadataType.Phones, ]; diff --git a/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts b/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts index ab37d5249158..80814a64b7ec 100644 --- a/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts +++ b/packages/twenty-front/src/modules/object-metadata/graphql/mutations.ts @@ -35,6 +35,7 @@ export const CREATE_ONE_FIELD_METADATA_ITEM = gql` isNullable createdAt updatedAt + settings defaultValue options } @@ -73,6 +74,7 @@ export const UPDATE_ONE_FIELD_METADATA_ITEM = gql` isNullable createdAt updatedAt + settings } } `; @@ -136,6 +138,7 @@ export const DELETE_ONE_FIELD_METADATA_ITEM = gql` isNullable createdAt updatedAt + settings } } `; diff --git a/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts b/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts index 729e1f96bf53..a61811431d2f 100644 --- a/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts +++ b/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts @@ -39,34 +39,9 @@ export const FIND_MANY_OBJECT_METADATA_ITEMS = gql` isNullable createdAt updatedAt - fromRelationMetadata { - id - relationType - toObjectMetadata { - id - dataSourceId - nameSingular - namePlural - isSystem - isRemote - } - toFieldMetadataId - } - toRelationMetadata { - id - relationType - fromObjectMetadata { - id - dataSourceId - nameSingular - namePlural - isSystem - isRemote - } - fromFieldMetadataId - } defaultValue options + settings relationDefinition { relationId direction diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts index 0a73b0d2a42b..f3c3e93f1b2c 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts @@ -17,6 +17,7 @@ const baseFields = ` isNullable createdAt updatedAt + settings `; export const queries = { @@ -73,6 +74,7 @@ export const variables = { label: 'fieldLabel', name: 'fieldLabel', options: undefined, + settings: undefined, objectMetadataId, type: 'TEXT', }, @@ -96,6 +98,7 @@ const defaultResponseData = { isNullable: false, createdAt: '1977-09-28T13:56:55.157Z', updatedAt: '1996-10-10T08:27:57.117Z', + settings: undefined, }; const fieldRelationResponseData = { diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts index 951b2742fbef..c9324a846f95 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts @@ -39,29 +39,27 @@ export const query = gql` isNullable createdAt updatedAt - fromRelationMetadata { - id - relationType - toObjectMetadata { + relationDefinition { + relationId + direction + sourceObjectMetadata { id - dataSourceId nameSingular namePlural - isSystem } - toFieldMetadataId - } - toRelationMetadata { - id - relationType - fromObjectMetadata { + sourceFieldMetadata { + id + name + } + targetObjectMetadata { id - dataSourceId nameSingular namePlural - isSystem } - fromFieldMetadataId + targetFieldMetadata { + id + name + } } defaultValue options diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts index 19e8b6c30bac..558d2ff3034c 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts @@ -3,7 +3,7 @@ import { Nullable } from 'twenty-ui'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; describe('useColumnDefinitionsFromFieldMetadata', () => { it('should return empty definitions if no object is passed', () => { @@ -22,22 +22,24 @@ describe('useColumnDefinitionsFromFieldMetadata', () => { }); it('should return expected definitions', () => { - const mockObjectMetadataItems = getObjectMetadataItemsMock(); + const companyObjectMetadata = generatedMockObjectMetadataItems.find( + (item) => item.nameSingular === 'company', + ); const { result } = renderHook( (objectMetadataItem?: Nullable<ObjectMetadataItem>) => { return useColumnDefinitionsFromFieldMetadata(objectMetadataItem); }, { - initialProps: mockObjectMetadataItems[1], + initialProps: companyObjectMetadata, }, ); const { columnDefinitions, filterDefinitions, sortDefinitions } = result.current; - expect(columnDefinitions.length).toBe(5); - expect(filterDefinitions.length).toBe(4); - expect(sortDefinitions.length).toBe(4); + expect(columnDefinitions.length).toBe(21); + expect(filterDefinitions.length).toBe(14); + expect(sortDefinitions.length).toBe(14); }); }); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneRelationMetadataItem.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneRelationMetadataItem.test.tsx index 2d9b7f3e3f01..57692ea959d6 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneRelationMetadataItem.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useCreateOneRelationMetadataItem.test.tsx @@ -1,10 +1,10 @@ -import { ReactNode } from 'react'; import { MockedProvider } from '@apollo/client/testing'; import { act, renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; import { useCreateOneRelationMetadataItem } from '@/object-metadata/hooks/useCreateOneRelationMetadataItem'; -import { RelationMetadataType } from '~/generated/graphql'; +import { RelationDefinitionType } from '~/generated/graphql'; import { query, @@ -42,7 +42,7 @@ describe('useCreateOneRelationMetadataItem', () => { await act(async () => { const res = await result.current.createOneRelationMetadataItem({ - relationType: RelationMetadataType.OneToOne, + relationType: RelationDefinitionType.OneToOne, field: { label: 'label', }, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilteredObjectMetadataItems.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilteredObjectMetadataItems.test.tsx index c42b94fbbbe2..4d16bb6d8af9 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilteredObjectMetadataItems.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useFilteredObjectMetadataItems.test.tsx @@ -10,7 +10,7 @@ import { } from '@/object-metadata/hooks/__mocks__/useFilteredObjectMetadataItems'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const mocks = [ { @@ -34,14 +34,12 @@ const Wrapper = ({ children }: { children: ReactNode }) => ( </RecoilRoot> ); -const mockObjectMetadataItems = getObjectMetadataItemsMock(); - describe('useFilteredObjectMetadataItems', () => { it('should findActiveObjectMetadataItemBySlug', async () => { const { result } = renderHook( () => { const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFilteredObjectMetadataItems(); }, @@ -57,11 +55,35 @@ describe('useFilteredObjectMetadataItems', () => { }); }); + it('should findObjectMetadataItemBySlug', async () => { + const { result } = renderHook( + () => { + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); + setMetadataItems(generatedMockObjectMetadataItems); + + return useFilteredObjectMetadataItems(); + }, + { + wrapper: Wrapper, + }, + ); + + act(() => { + const res = result.current.findObjectMetadataItemBySlug('people'); + expect(res).toBeDefined(); + expect(res?.namePlural).toBe('people'); + }); + }); + it('should findObjectMetadataItemById', async () => { + const peopleObjectMetadata = generatedMockObjectMetadataItems.find( + (item) => item.namePlural === 'people', + ); + const { result } = renderHook( () => { const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFilteredObjectMetadataItems(); }, @@ -72,7 +94,7 @@ describe('useFilteredObjectMetadataItems', () => { act(() => { const res = result.current.findObjectMetadataItemById( - 'ff2881da-89f6-4f15-8f0a-e3f355ea3b94', + peopleObjectMetadata?.id, ); expect(res).toBeDefined(); expect(res?.namePlural).toBe('people'); @@ -83,7 +105,7 @@ describe('useFilteredObjectMetadataItems', () => { const { result } = renderHook( () => { const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFilteredObjectMetadataItems(); }, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx index 1a4c0e2cbfcc..a457bd27eff7 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetObjectRecordIdentifierByNameSingular.test.tsx @@ -3,9 +3,7 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; - -const mockObjectMetadataItems = getObjectMetadataItemsMock(); +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; describe('useGetObjectRecordIdentifierByNameSingular', () => { it('should work as expected', async () => { @@ -19,7 +17,7 @@ describe('useGetObjectRecordIdentifierByNameSingular', () => { }) => { const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useGetObjectRecordIdentifierByNameSingular()( record, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx index d92e0707f1f1..12ef572b6adf 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useGetRelationMetadata.test.tsx @@ -5,7 +5,7 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const Wrapper = ({ children }: { children: ReactNode }) => ( <RecoilRoot> @@ -15,8 +15,7 @@ const Wrapper = ({ children }: { children: ReactNode }) => ( describe('useGetRelationMetadata', () => { it('should return correct properties', async () => { - const objectMetadataItems = getObjectMetadataItemsMock(); - const objectMetadata = objectMetadataItems.find( + const objectMetadata = generatedMockObjectMetadataItems.find( (item) => item.nameSingular === 'person', )!; const fieldMetadataItem = objectMetadata.fields.find( @@ -28,7 +27,7 @@ describe('useGetRelationMetadata', () => { const setMetadataItems = useSetRecoilState(objectMetadataItemsState); useEffect(() => { - setMetadataItems(objectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); }, [setMetadataItems]); return useGetRelationMetadata(); @@ -45,9 +44,10 @@ describe('useGetRelationMetadata', () => { relationType, } = result.current({ fieldMetadataItem }) ?? {}; - const expectedRelationObjectMetadataItem = objectMetadataItems.find( - (item) => item.nameSingular === 'opportunity', - ); + const expectedRelationObjectMetadataItem = + generatedMockObjectMetadataItems.find( + (item) => item.nameSingular === 'opportunity', + ); const expectedRelationFieldMetadataItem = expectedRelationObjectMetadataItem?.fields.find( (field) => field.name === 'pointOfContact', diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItem.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItem.test.tsx index ea205704d5f1..ee757d7ff7b2 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItem.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useObjectMetadataItem.test.tsx @@ -4,6 +4,7 @@ import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const Wrapper = ({ children }: { children: ReactNode }) => ( <RecoilRoot> @@ -13,6 +14,9 @@ const Wrapper = ({ children }: { children: ReactNode }) => ( // Split into tests for each new hook describe('useObjectMetadataItem', () => { + const opportunityObjectMetadata = generatedMockObjectMetadataItems.find( + (item) => item.nameSingular === 'opportunity', + ); it('should return correct properties', async () => { const { result } = renderHook( () => useObjectMetadataItem({ objectNameSingular: 'opportunity' }), @@ -23,6 +27,6 @@ describe('useObjectMetadataItem', () => { const { objectMetadataItem } = result.current; - expect(objectMetadataItem.id).toBe('b95b3f38-9fc2-4d7e-a823-7791cf13d089'); + expect(objectMetadataItem.id).toBe(opportunityObjectMetadata?.id); }); }); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts index 75f9f5a2e489..3f39f89279cb 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts @@ -1,6 +1,6 @@ import { useDeleteOneRelationMetadataItem } from '@/object-metadata/hooks/useDeleteOneRelationMetadataItem'; -import { Field } from '~/generated/graphql'; import { FieldMetadataType } from '~/generated-metadata/graphql'; +import { Field } from '~/generated/graphql'; import { FieldMetadataItem } from '../types/FieldMetadataItem'; import { formatFieldMetadataItemInput } from '../utils/formatFieldMetadataItemInput'; @@ -18,7 +18,13 @@ export const useFieldMetadataItem = () => { const createMetadataField = ( input: Pick< Field, - 'label' | 'icon' | 'description' | 'defaultValue' | 'type' | 'options' + | 'label' + | 'icon' + | 'description' + | 'defaultValue' + | 'type' + | 'options' + | 'settings' > & { objectMetadataId: string; }, diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useFilteredObjectMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useFilteredObjectMetadataItems.ts index 2cf99ae1230c..61922bf55e0b 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useFilteredObjectMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useFilteredObjectMetadataItems.ts @@ -27,6 +27,11 @@ export const useFilteredObjectMetadataItems = () => { ({ isActive, isSystem }) => !isActive && !isSystem, ); + const findObjectMetadataItemBySlug = (slug: string) => + objectMetadataItems.find( + (objectMetadataItem) => getObjectSlug(objectMetadataItem) === slug, + ); + const findActiveObjectMetadataItemBySlug = (slug: string) => activeObjectMetadataItems.find( (activeObjectMetadataItem) => @@ -50,6 +55,7 @@ export const useFilteredObjectMetadataItems = () => { findObjectMetadataItemByNamePlural, inactiveObjectMetadataItems, objectMetadataItems, + findObjectMetadataItemBySlug, alphaSortedActiveObjectMetadataItems, }; }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useGetRelationMetadata.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useGetRelationMetadata.ts index 3217e5bae338..448bac6ef8ac 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useGetRelationMetadata.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useGetRelationMetadata.ts @@ -1,11 +1,7 @@ import { useRecoilCallback } from 'recoil'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; -import { RelationType } from '@/settings/data-model/types/RelationType'; -import { - FieldMetadataType, - RelationMetadataType, -} from '~/generated-metadata/graphql'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldMetadataItem } from '../types/FieldMetadataItem'; @@ -17,39 +13,19 @@ export const useGetRelationMetadata = () => }: { fieldMetadataItem: Pick< FieldMetadataItem, - 'fromRelationMetadata' | 'toRelationMetadata' | 'type' + 'type' | 'relationDefinition' >; }) => { if (fieldMetadataItem.type !== FieldMetadataType.Relation) return null; - const relationMetadata = - fieldMetadataItem.fromRelationMetadata || - fieldMetadataItem.toRelationMetadata; + const relationDefinition = fieldMetadataItem.relationDefinition; - if (!relationMetadata) return null; - - const relationFieldMetadataId = - 'toFieldMetadataId' in relationMetadata - ? relationMetadata.toFieldMetadataId - : relationMetadata.fromFieldMetadataId; - - if (!relationFieldMetadataId) return null; - - const relationType = - relationMetadata.relationType === RelationMetadataType.OneToMany && - fieldMetadataItem.toRelationMetadata - ? 'MANY_TO_ONE' - : (relationMetadata.relationType as RelationType); - - const relationObjectMetadataNameSingular = - 'toObjectMetadata' in relationMetadata - ? relationMetadata.toObjectMetadata.nameSingular - : relationMetadata.fromObjectMetadata.nameSingular; + if (!relationDefinition) return null; const relationObjectMetadataItem = snapshot .getLoadable( objectMetadataItemFamilySelector({ - objectName: relationObjectMetadataNameSingular, + objectName: relationDefinition.targetObjectMetadata.nameSingular, objectNameType: 'singular', }), ) @@ -59,7 +35,7 @@ export const useGetRelationMetadata = () => const relationFieldMetadataItem = relationObjectMetadataItem.fields.find( - (field) => field.id === relationFieldMetadataId, + (field) => field.id === relationDefinition.targetFieldMetadata.id, ); if (!relationFieldMetadataItem) return null; @@ -67,7 +43,7 @@ export const useGetRelationMetadata = () => return { relationFieldMetadataItem, relationObjectMetadataItem, - relationType, + relationType: relationDefinition.direction, }; }, [], diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useGetStandardObjectIcon.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useGetStandardObjectIcon.ts new file mode 100644 index 000000000000..92b014d730a7 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useGetStandardObjectIcon.ts @@ -0,0 +1,37 @@ +import { useTheme } from '@emotion/react'; +import { IconCheckbox, IconComponent, IconNotes } from 'twenty-ui'; + +export const useGetStandardObjectIcon = (objectNameSingular: string) => { + const theme = useTheme(); + + const getIconForObjectType = ( + objectType: string, + ): IconComponent | undefined => { + switch (objectType) { + case 'note': + return IconNotes; + case 'task': + return IconCheckbox; + default: + return undefined; + } + }; + + const getIconColorForObjectType = (objectType: string): string => { + switch (objectType) { + case 'note': + return theme.color.yellow; + case 'task': + return theme.color.blue; + default: + return 'currentColor'; + } + }; + + const { Icon, IconColor } = { + Icon: getIconForObjectType(objectNameSingular), + IconColor: getIconColorForObjectType(objectNameSingular), + }; + + return { Icon, IconColor }; +}; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectIsRemote.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectIsRemote.ts new file mode 100644 index 000000000000..0f3295dc5c29 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectIsRemote.ts @@ -0,0 +1,5 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; + +export const useObjectIsRemote = (objectMetadataItem: ObjectMetadataItem) => { + return objectMetadataItem.isRemote ?? false; +}; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectLabel.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectLabel.ts new file mode 100644 index 000000000000..7ef0881d6182 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectLabel.ts @@ -0,0 +1,5 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; + +export const useObjectLabel = (objectMetadataItem: ObjectMetadataItem) => { + return objectMetadataItem?.labelSingular ?? ''; +}; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts index 4d2a9bdc8250..0a8d3e8600a0 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts @@ -1,40 +1,23 @@ import { useRecoilValue } from 'recoil'; -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { isDefined } from '~/utils/isDefined'; -import { WorkspaceActivationStatus } from '~/generated/graphql'; import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier'; export const useObjectMetadataItem = ({ objectNameSingular, }: ObjectMetadataItemIdentifier) => { - const currentWorkspace = useRecoilValue(currentWorkspaceState); - - // Todo: deprecate this logic as mocked objectMetadataItems are laod in ObjectMetadataItemsLoadEffect anyway - const mockObjectMetadataItems = getObjectMetadataItemsMock(); - - let objectMetadataItem = useRecoilValue( + const objectMetadataItem = useRecoilValue( objectMetadataItemFamilySelector({ objectName: objectNameSingular, objectNameType: 'singular', }), ); - let objectMetadataItems = useRecoilValue(objectMetadataItemsState); - - if (currentWorkspace?.activationStatus !== WorkspaceActivationStatus.Active) { - objectMetadataItem = - mockObjectMetadataItems.find( - (objectMetadataItem) => - objectMetadataItem.nameSingular === objectNameSingular, - ) ?? null; - objectMetadataItems = mockObjectMetadataItems; - } + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); if (!isDefined(objectMetadataItem)) { throw new ObjectMetadataItemNotFoundError( diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts index ad9d8641b916..25208307eabd 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts @@ -2,8 +2,8 @@ import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { WorkspaceActivationStatus } from '~/generated/graphql'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { isDefined } from '~/utils/isDefined'; export const useObjectNamePluralFromSingular = ({ @@ -12,7 +12,6 @@ export const useObjectNamePluralFromSingular = ({ objectNameSingular: string; }) => { const currentWorkspace = useRecoilValue(currentWorkspaceState); - const mockObjectMetadataItems = getObjectMetadataItemsMock(); let objectMetadataItem = useRecoilValue( objectMetadataItemFamilySelector({ @@ -23,7 +22,7 @@ export const useObjectNamePluralFromSingular = ({ if (currentWorkspace?.activationStatus !== WorkspaceActivationStatus.Active) { objectMetadataItem = - mockObjectMetadataItems.find( + generatedMockObjectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.nameSingular === objectNameSingular, ) ?? null; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts index 3b4a244942d5..5a94a5191b9f 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts @@ -2,8 +2,8 @@ import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { WorkspaceActivationStatus } from '~/generated/graphql'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { isDefined } from '~/utils/isDefined'; export const useObjectNameSingularFromPlural = ({ @@ -13,8 +13,6 @@ export const useObjectNameSingularFromPlural = ({ }) => { const currentWorkspace = useRecoilValue(currentWorkspaceState); - const mockObjectMetadataItems = getObjectMetadataItemsMock(); - let objectMetadataItem = useRecoilValue( objectMetadataItemFamilySelector({ objectName: objectNamePlural, @@ -24,7 +22,7 @@ export const useObjectNameSingularFromPlural = ({ if (currentWorkspace?.activationStatus !== WorkspaceActivationStatus.Active) { objectMetadataItem = - mockObjectMetadataItems.find( + generatedMockObjectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.namePlural === objectNamePlural, ) ?? null; diff --git a/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts b/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts index 6e0d13f48ddf..dd496e70d3d2 100644 --- a/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts @@ -30,4 +30,5 @@ export enum CoreObjectNameSingular { MessageThreadSubscriber = 'messageThreadSubscriber', Workflow = 'workflow', MessageChannelMessageAssociation = 'messageChannelMessageAssociation', + WorkflowVersion = 'workflowVersion', } diff --git a/packages/twenty-front/src/modules/object-metadata/types/FieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/types/FieldMetadataItem.ts index 91b1fdd7d164..61ce60263dfc 100644 --- a/packages/twenty-front/src/modules/object-metadata/types/FieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/types/FieldMetadataItem.ts @@ -3,7 +3,6 @@ import { ThemeColor } from 'twenty-ui'; import { Field, Object as MetadataObject, - Relation, RelationDefinition, RelationDefinitionType, } from '~/generated-metadata/graphql'; @@ -18,31 +17,9 @@ export type FieldMetadataItemOption = { export type FieldMetadataItem = Omit< Field, - | '__typename' - | 'fromRelationMetadata' - | 'toRelationMetadata' - | 'defaultValue' - | 'options' - | 'settings' - | 'relationDefinition' + '__typename' | 'defaultValue' | 'options' | 'settings' | 'relationDefinition' > & { __typename?: string; - fromRelationMetadata?: - | (Pick<Relation, 'id' | 'toFieldMetadataId' | 'relationType'> & { - toObjectMetadata: Pick< - Relation['toObjectMetadata'], - 'id' | 'nameSingular' | 'namePlural' | 'isSystem' | 'isRemote' - >; - }) - | null; - toRelationMetadata?: - | (Pick<Relation, 'id' | 'fromFieldMetadataId' | 'relationType'> & { - fromObjectMetadata: Pick< - Relation['fromObjectMetadata'], - 'id' | 'nameSingular' | 'namePlural' | 'isSystem' | 'isRemote' - >; - }) - | null; defaultValue?: any; options?: FieldMetadataItemOption[] | null; relationDefinition?: { @@ -59,4 +36,7 @@ export type FieldMetadataItem = Omit< 'id' | 'nameSingular' | 'namePlural' >; } | null; + settings?: { + displayAsRelativeDate?: boolean; + }; }; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectMetadataItemBySingularName.test.ts b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectMetadataItemBySingularName.test.ts index 07e88a26f066..ea2f1d5eee19 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectMetadataItemBySingularName.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectMetadataItemBySingularName.test.ts @@ -1,14 +1,12 @@ import { getObjectMetadataItemByNameSingular } from '@/object-metadata/utils/getObjectMetadataItemBySingularName'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; - -const mockObjectMetadataItems = getObjectMetadataItemsMock(); +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; describe('getObjectMetadataItemBySingularName', () => { it('should work as expected', () => { - const firstObjectMetadataItem = mockObjectMetadataItems[0]; + const firstObjectMetadataItem = generatedMockObjectMetadataItems[0]; const foundObjectMetadataItem = getObjectMetadataItemByNameSingular({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, objectNameSingular: firstObjectMetadataItem.nameSingular, }); diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectOrderByField.test.ts b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectOrderByField.test.ts index baa61c853751..78c0e7047a4a 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectOrderByField.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectOrderByField.test.ts @@ -1,11 +1,9 @@ -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { getOrderByFieldForObjectMetadataItem } from '@/object-metadata/utils/getObjectOrderByField'; - -const mockObjectMetadataItems = getObjectMetadataItemsMock(); +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; describe('getObjectOrderByField', () => { it('should work as expected', () => { - const objectMetadataItem = mockObjectMetadataItems.find( + const objectMetadataItem = generatedMockObjectMetadataItems.find( (item) => item.nameSingular === 'person', )!; const res = getOrderByFieldForObjectMetadataItem(objectMetadataItem); diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectSlug.test.ts b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectSlug.test.ts index fdd16fdb1afa..c43c9d039e7c 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectSlug.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/getObjectSlug.test.ts @@ -1,11 +1,9 @@ -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug'; - -const mockObjectMetadataItems = getObjectMetadataItemsMock(); +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; describe('getObjectSlug', () => { it('should work as expected', () => { - const objectMetadataItem = mockObjectMetadataItems.find( + const objectMetadataItem = generatedMockObjectMetadataItems.find( (item) => item.nameSingular === 'person', )!; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/isObjectMetadataAvailableForRelation.test.ts b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/isObjectMetadataAvailableForRelation.test.ts index e2dff5d09609..caefb7feed45 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/isObjectMetadataAvailableForRelation.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/isObjectMetadataAvailableForRelation.test.ts @@ -1,11 +1,9 @@ -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation'; - -const mockObjectMetadataItems = getObjectMetadataItemsMock(); +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; describe('isObjectMetadataAvailableForRelation', () => { it('should work as expected', () => { - const objectMetadataItem = mockObjectMetadataItems.find( + const objectMetadataItem = generatedMockObjectMetadataItems.find( (item) => item.nameSingular === 'person', )!; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx index 5c996671034e..755ce29ac677 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapFieldMetadataToGraphQLQuery.test.tsx @@ -1,10 +1,8 @@ -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { mapFieldMetadataToGraphQLQuery } from '@/object-metadata/utils/mapFieldMetadataToGraphQLQuery'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { normalizeGQLField } from '~/utils/normalizeGQLField'; -const mockObjectMetadataItems = getObjectMetadataItemsMock(); - -const personObjectMetadataItem = mockObjectMetadataItems.find( +const personObjectMetadataItem = generatedMockObjectMetadataItems.find( (item) => item.nameSingular === 'person', ); @@ -15,7 +13,7 @@ if (!personObjectMetadataItem) { describe('mapFieldMetadataToGraphQLQuery', () => { it('should return fieldName if simpleValue', async () => { const res = mapFieldMetadataToGraphQLQuery({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, field: personObjectMetadataItem.fields.find( (field) => field.name === 'id', )!, @@ -24,7 +22,7 @@ describe('mapFieldMetadataToGraphQLQuery', () => { }); it('should return fieldName if composite', async () => { const res = mapFieldMetadataToGraphQLQuery({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, field: personObjectMetadataItem.fields.find( (field) => field.name === 'name', )!, @@ -40,7 +38,7 @@ describe('mapFieldMetadataToGraphQLQuery', () => { it('should return non relation subFields if relation', async () => { const res = mapFieldMetadataToGraphQLQuery({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, field: personObjectMetadataItem.fields.find( (field) => field.name === 'company', )!, @@ -96,7 +94,7 @@ idealCustomerProfile it('should return only return relation subFields that are in recordGqlFields', async () => { const res = mapFieldMetadataToGraphQLQuery({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, relationrecordFields: { accountOwner: { id: true, name: true }, people: true, @@ -184,7 +182,12 @@ xLink } id createdAt -email +city +emails +{ + primaryEmail + additionalEmails +} jobTitle name { @@ -192,6 +195,10 @@ name lastName } phone +{ + primaryPhoneNumber + primaryPhoneCountryCode +} linkedinLink { primaryLinkUrl diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx index 1da199652ee2..6e1ca8da2980 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/mapObjectMetadataToGraphQLQuery.test.tsx @@ -1,10 +1,8 @@ -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { normalizeGQLQuery } from '~/utils/normalizeGQLQuery'; -const mockObjectMetadataItems = getObjectMetadataItemsMock(); - -const personObjectMetadataItem = mockObjectMetadataItems.find( +const personObjectMetadataItem = generatedMockObjectMetadataItems.find( (item) => item.nameSingular === 'person', ); @@ -15,7 +13,7 @@ if (!personObjectMetadataItem) { describe('mapObjectMetadataToGraphQLQuery', () => { it('should query only specified recordGqlFields', async () => { const res = mapObjectMetadataToGraphQLQuery({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, objectMetadataItem: personObjectMetadataItem, recordGqlFields: { company: true, @@ -40,8 +38,16 @@ describe('mapObjectMetadataToGraphQLQuery', () => { firstName lastName } - email - phone + emails + { + primaryEmail + additionalEmails + } + phone + { + primaryPhoneNumber + primaryPhoneCountryCode + } createdAt avatarUrl jobTitle @@ -112,7 +118,7 @@ describe('mapObjectMetadataToGraphQLQuery', () => { it('should load only specified operation fields nested', async () => { const res = mapObjectMetadataToGraphQLQuery({ - objectMetadataItems: mockObjectMetadataItems, + objectMetadataItems: generatedMockObjectMetadataItems, objectMetadataItem: personObjectMetadataItem, recordGqlFields: { company: { id: true }, id: true, name: true }, }); diff --git a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition.ts b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition.ts index a579d5ce4de3..8ba9ebe23315 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition.ts @@ -1,5 +1,4 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType'; import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon'; @@ -20,17 +19,15 @@ export const formatFieldMetadataItemAsFieldDefinition = ({ labelWidth, }: FieldMetadataItemAsFieldDefinitionProps): FieldDefinition<FieldMetadata> => { const relationObjectMetadataItem = - field.toRelationMetadata?.fromObjectMetadata || - field.fromRelationMetadata?.toObjectMetadata; + field.relationDefinition?.targetObjectMetadata; const relationFieldMetadataId = - field.toRelationMetadata?.fromFieldMetadataId || - field.fromRelationMetadata?.toFieldMetadataId; + field.relationDefinition?.targetFieldMetadata.id; const fieldDefintionMetadata = { fieldName: field.name, placeHolder: field.label, - relationType: parseFieldRelationType(field), + relationType: field.relationDefinition?.direction, relationFieldMetadataId, relationObjectMetadataNameSingular: relationObjectMetadataItem?.nameSingular ?? '', @@ -40,6 +37,7 @@ export const formatFieldMetadataItemAsFieldDefinition = ({ targetFieldMetadataName: field.relationDefinition?.targetFieldMetadata?.name ?? '', options: field.options, + settings: field.settings, isNullable: field.isNullable, }; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts index 15bc319a93f3..5900beed1faa 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts @@ -5,7 +5,13 @@ export const formatFieldMetadataItemInput = ( input: Partial< Pick< FieldMetadataItem, - 'type' | 'label' | 'defaultValue' | 'icon' | 'description' | 'options' + | 'type' + | 'label' + | 'defaultValue' + | 'icon' + | 'description' + | 'options' + | 'settings' > >, ) => { @@ -18,5 +24,6 @@ export const formatFieldMetadataItemInput = ( label, name: label ? computeMetadataNameFromLabelOrThrow(label) : undefined, options: input.options, + settings: input.settings, }; }; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts index e8aef6f8ff11..7ebeb0afee26 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts @@ -24,6 +24,7 @@ export const formatFieldMetadataItemsAsFilterDefinitions = ({ if ( ![ FieldMetadataType.DateTime, + FieldMetadataType.Date, FieldMetadataType.Text, FieldMetadataType.Email, FieldMetadataType.Emails, @@ -37,6 +38,7 @@ export const formatFieldMetadataItemsAsFilterDefinitions = ({ FieldMetadataType.Currency, FieldMetadataType.Rating, FieldMetadataType.Actor, + FieldMetadataType.Phones, ].includes(field.type) ) { return acc; @@ -82,6 +84,8 @@ export const getFilterTypeFromFieldType = (fieldType: FieldMetadataType) => { return 'EMAILS'; case FieldMetadataType.Phone: return 'PHONE'; + case FieldMetadataType.Phones: + return 'PHONES'; case FieldMetadataType.Relation: return 'RELATION'; case FieldMetadataType.Select: @@ -94,6 +98,8 @@ export const getFilterTypeFromFieldType = (fieldType: FieldMetadataType) => { return 'RATING'; case FieldMetadataType.Actor: return 'ACTOR'; + case FieldMetadataType.Array: + return 'ARRAY'; default: return 'TEXT'; } diff --git a/packages/twenty-front/src/modules/object-metadata/utils/formatRelationMetadataInput.ts b/packages/twenty-front/src/modules/object-metadata/utils/formatRelationMetadataInput.ts index 32f8b1f2758b..7937900ab198 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/formatRelationMetadataInput.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/formatRelationMetadataInput.ts @@ -2,6 +2,7 @@ import { RelationType } from '@/settings/data-model/types/RelationType'; import { CreateRelationInput, Field, + RelationDefinitionType, RelationMetadataType, } from '~/generated-metadata/graphql'; @@ -24,8 +25,8 @@ export const formatRelationMetadataInput = ( // => Transform into ONE_TO_MANY and invert "from" and "to" data. const isManyToOne = input.relationType === 'MANY_TO_ONE'; const relationType = isManyToOne - ? RelationMetadataType.OneToMany - : (input.relationType as RelationMetadataType); + ? RelationDefinitionType.OneToMany + : (input.relationType as RelationDefinitionType); const { field: fromField, objectMetadataId: fromObjectMetadataId } = isManyToOne ? input.connect : input; const { field: toField, objectMetadataId: toObjectMetadataId } = isManyToOne @@ -51,7 +52,7 @@ export const formatRelationMetadataInput = ( fromLabel, fromName, fromObjectMetadataId, - relationType, + relationType: relationType as unknown as RelationMetadataType, toDescription, toIcon, toLabel, diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getLabelIdentifierFieldValue.ts b/packages/twenty-front/src/modules/object-metadata/utils/getLabelIdentifierFieldValue.ts index d63ff4c20758..001cf4ecb06b 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/getLabelIdentifierFieldValue.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/getLabelIdentifierFieldValue.ts @@ -16,14 +16,6 @@ export const getLabelIdentifierFieldValue = ( return `${record.name?.firstName ?? ''} ${record.name?.lastName ?? ''}`; } - if (objectNameSingular === CoreObjectNameSingular.NoteTarget) { - return record.note?.title ?? ''; - } - - if (objectNameSingular === CoreObjectNameSingular.TaskTarget) { - return record.task?.title ?? ''; - } - if (isDefined(labelIdentifierFieldMetadataItem?.name)) { return String(record[labelIdentifierFieldMetadataItem.name]); } diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts b/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts deleted file mode 100644 index dc86c408d6bd..000000000000 --- a/packages/twenty-front/src/modules/object-metadata/utils/getObjectMetadataItemsMock.ts +++ /dev/null @@ -1,15938 +0,0 @@ -import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; - -export const COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID = '39403bee-314b-4f14-bc91-70d500397517'; -export const COMPANY_OBJECT_METADATA_ID = 'f1231579-8e7d-4b84-9a60-41844902f2c4'; - -export const getObjectMetadataItemsMock = () => { - const mockArray = [ - { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "labelSingular": "Person", - "labelPlural": "People", - "description": "A person", - "icon": "IconUser", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "f01f1b33-0a27-49a7-b119-5f9bd58477a5", - "imageIdentifierFieldMetadataId": "ef9ff5ea-8aff-4d91-9ab6-6dc38d3eccbe", - "fields": [ - { - "__typename": "field", - "id": "102963b7-3e77-4293-a1e6-1ab59a02b663", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6697751c-3150-483b-8167-c5bc1d620c10", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject Foreign Key", - "description": null, - "icon": null, - "isCustom": true, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:10:31.391Z", - "updatedAt": "2024-08-05T17:10:31.391Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e1ecbeb4-76cb-4f9a-8829-ac0665854c69", - "type": "RELATION", - "name": "pointOfContactForOpportunities", - "label": "Linked Opportunities", - "description": "List of opportunities for which that person is the point of contact", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "3e039f55-e535-406a-8a80-185123910b7a", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "toFieldMetadataId": "dc7898b0-d2b7-4910-bedc-a6fe8eb4c41e" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "3e039f55-e535-406a-8a80-185123910b7a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e1ecbeb4-76cb-4f9a-8829-ac0665854c69", - "name": "pointOfContactForOpportunities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "dc7898b0-d2b7-4910-bedc-a6fe8eb4c41e", - "name": "pointOfContact" - } - } - }, - { - "__typename": "field", - "id": "194ff398-99f9-4cbb-b87a-e44408f9c1ed", - "type": "PHONE", - "name": "whatsapp", - "label": "Whatsapp", - "description": "Contact's Whatsapp Number", - "icon": "IconBrandWhatsapp", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:39:01.956Z", - "updatedAt": "2024-08-05T16:39:01.956Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d2729410-3db8-44b0-b88f-fa3ba9b10650", - "type": "LINKS", - "name": "linkedinLink", - "label": "Linkedin", - "description": "Contact’s Linkedin account", - "icon": "IconBrandLinkedin", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f01f1b33-0a27-49a7-b119-5f9bd58477a5", - "type": "FULL_NAME", - "name": "name", - "label": "Name", - "description": "Contact’s name", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "lastName": "''", - "firstName": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a6d4fe23-a569-4cbb-a68c-96e30a0b0d5b", - "type": "EMAIL", - "name": "email", - "label": "Email", - "description": "Contact’s Email", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "55a856ae-0a48-4ff6-874d-b630818c8cea", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Person record Position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d44bf743-b557-47d4-9341-04114fd05d52", - "type": "RELATION", - "name": "calendarEventParticipants", - "label": "Calendar Event Participants", - "description": "Calendar Event Participants", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "20d67b64-4e67-44a1-81c7-116c0c8c6368", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "a7eb211d-4481-4269-99d7-cf2183b45598" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "20d67b64-4e67-44a1-81c7-116c0c8c6368", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d44bf743-b557-47d4-9341-04114fd05d52", - "name": "calendarEventParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a7eb211d-4481-4269-99d7-cf2183b45598", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "9b018bba-687b-4850-9e0e-c192d3b5977d", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the contact", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "9a3a145b-6d06-4892-84d4-af523f40c58d", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "940d1664-b17c-4f66-820b-abfec70adaa5" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9a3a145b-6d06-4892-84d4-af523f40c58d", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "9b018bba-687b-4850-9e0e-c192d3b5977d", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "940d1664-b17c-4f66-820b-abfec70adaa5", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "4c9ba269-244f-4768-a52d-9b1ffbe3339f", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the contact", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "182b32c3-9ee9-4a65-937b-d9035ab65300", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "fc1a31f8-6e1c-4ce1-b6ff-80d1cd605e58" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "182b32c3-9ee9-4a65-937b-d9035ab65300", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4c9ba269-244f-4768-a52d-9b1ffbe3339f", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fc1a31f8-6e1c-4ce1-b6ff-80d1cd605e58", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "e41d7b2e-3e60-4741-b410-a432b1a12b77", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ef9ff5ea-8aff-4d91-9ab6-6dc38d3eccbe", - "type": "TEXT", - "name": "avatarUrl", - "label": "Avatar", - "description": "Contact’s avatar", - "icon": "IconFileUpload", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c9d4cb92-7460-4bee-8ed7-0fbdca4ba546", - "type": "TEXT", - "name": "jobTitle", - "label": "Job Title", - "description": "Contact’s job title", - "icon": "IconBriefcase", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d1fb7174-82ab-4e31-8e1c-53036d0eefe2", - "type": "LINKS", - "name": "xLink", - "label": "X", - "description": "Contact’s X/Twitter account", - "icon": "IconBrandX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ff809df8-9372-4345-9a73-393960c31950", - "type": "RATING", - "name": "performanceRating", - "label": "Performance Rating", - "description": "Person's Performance Rating", - "icon": "IconStars", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:39:01.997Z", - "updatedAt": "2024-08-05T16:39:01.997Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": [ - { - "id": "d0d6de5e-0bf5-4cdd-a599-1f8005723f6e", - "label": "1", - "value": "RATING_1", - "position": 0 - }, - { - "id": "a0c86a34-6914-43b0-a7ab-9fb4f9b9641c", - "label": "2", - "value": "RATING_2", - "position": 1 - }, - { - "id": "750dd542-0172-42da-ae00-50423f0179d3", - "label": "3", - "value": "RATING_3", - "position": 2 - }, - { - "id": "8b935586-9844-49f1-ad92-3e633d613ede", - "label": "4", - "value": "RATING_4", - "position": 3 - }, - { - "id": "eab17ee7-5aa8-40b1-a431-34438ba6b54e", - "label": "5", - "value": "RATING_5", - "position": 4 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6672a066-7a7f-44ae-bb5c-ae3a5e82d835", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Contact’s company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "0562d399-7053-4d7f-a415-cabfc889bd16", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "48dba12f-4429-4ee2-9b3a-6df97c45141d" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0562d399-7053-4d7f-a415-cabfc889bd16", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6672a066-7a7f-44ae-bb5c-ae3a5e82d835", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "48dba12f-4429-4ee2-9b3a-6df97c45141d", - "name": "people" - } - } - }, - { - "__typename": "field", - "id": "c08e6ba8-b7ef-4fa7-b199-c8e93045f8ee", - "type": "RELATION", - "name": "timelineActivities", - "label": "Events", - "description": "Events linked to the person", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "ba3d762d-8fbf-45e5-a958-136a269a396d", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "69e1ecef-09d7-4b53-826e-f440ae72d2b7" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ba3d762d-8fbf-45e5-a958-136a269a396d", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c08e6ba8-b7ef-4fa7-b199-c8e93045f8ee", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "69e1ecef-09d7-4b53-826e-f440ae72d2b7", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "1b21ef27-ba22-46ab-967e-f2d9f780bf8b", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments linked to the contact.", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "4b90ec4b-3199-4cea-9e8b-01498967bd9f", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "df6ee118-1cb0-4b2e-8668-3693d4d87ae2" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "4b90ec4b-3199-4cea-9e8b-01498967bd9f", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "1b21ef27-ba22-46ab-967e-f2d9f780bf8b", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "df6ee118-1cb0-4b2e-8668-3693d4d87ae2", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "9fbf2632-6f28-400d-86d7-3cadfbbcf7ac", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "9c2bf923-304d-47b7-beb0-286e3229f6ac", - "type": "TEXT", - "name": "phone", - "label": "Phone", - "description": "Contact’s phone number", - "icon": "IconPhone", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4cd944c2-a252-42c2-93d3-c71d71b4587d", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the contact", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "66551942-e576-4eb7-96c4-f78182f44491", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "b7caceaa-d49a-43c8-8b9b-10dc4298ade5" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "66551942-e576-4eb7-96c4-f78182f44491", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4cd944c2-a252-42c2-93d3-c71d71b4587d", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b7caceaa-d49a-43c8-8b9b-10dc4298ade5", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "c817d48c-071b-47f0-917c-5e0717678c5c", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4227c9a5-6dd3-4de0-9248-e62572afc92b", - "type": "RELATION", - "name": "messageParticipants", - "label": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "f26f3e6e-35bf-474a-9679-fbfbb009d67d", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "3779c76a-30a8-45bc-a56a-6bfc084a9b29" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "f26f3e6e-35bf-474a-9679-fbfbb009d67d", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4227c9a5-6dd3-4de0-9248-e62572afc92b", - "name": "messageParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3779c76a-30a8-45bc-a56a-6bfc084a9b29", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "14c3ddf2-a50b-40c3-9f93-6f3108c0dd72", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Contact’s company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "9048daf8-bd6f-4c83-8887-14c764ec0053", - "type": "TEXT", - "name": "intro", - "label": "Intro", - "description": "Contact's Intro", - "icon": "IconNote", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:39:01.936Z", - "updatedAt": "2024-08-05T16:39:01.936Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1c1c7ffc-3a45-4069-996a-bdfa8f46b037", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the contact", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "9d20f0c0-e37b-48ca-bc45-da16461aa547", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "2f2fc7fb-51c5-4084-8d97-13b43b49c68a" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9d20f0c0-e37b-48ca-bc45-da16461aa547", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "1c1c7ffc-3a45-4069-996a-bdfa8f46b037", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2f2fc7fb-51c5-4084-8d97-13b43b49c68a", - "name": "person" - } - } - }, - { - "__typename": "field", - "id": "f7002609-5760-4ae6-ba29-a8b9066b95de", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": null, - "icon": "IconUser", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:10:31.391Z", - "updatedAt": "2024-08-05T17:10:31.391Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "27f9741d-f967-4b75-affa-240f0f5f8d77", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "23006c79-19fe-4148-9ee4-6db039ebc6fb" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "27f9741d-f967-4b75-affa-240f0f5f8d77", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f7002609-5760-4ae6-ba29-a8b9066b95de", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "23006c79-19fe-4148-9ee4-6db039ebc6fb", - "name": "people" - } - } - }, - { - "__typename": "field", - "id": "fdcffad9-a55c-4a74-9d3e-e0052cb3454e", - "type": "MULTI_SELECT", - "name": "workPrefereance", - "label": "Work Preference", - "description": "Person's Work Preference", - "icon": "IconHome", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:39:01.977Z", - "updatedAt": "2024-08-05T16:39:01.977Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": [ - { - "id": "05ae5e3e-80bb-4a89-8539-de88f875384e", - "color": "green", - "label": "On-Site", - "value": "ON_SITE", - "position": 0 - }, - { - "id": "fa7fb51a-3c52-48db-ac7c-ba23daed31cc", - "color": "turquoise", - "label": "Hybrid", - "value": "HYBRID", - "position": 1 - }, - { - "id": "c29d7f0e-f82b-4bff-973a-5081f6d60a39", - "color": "sky", - "label": "Remote Work", - "value": "REMOTE_WORK", - "position": 2 - } - ], - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "note", - "namePlural": "notes", - "labelSingular": "Note", - "labelPlural": "Notes", - "description": "A note", - "icon": "IconNotes", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "2be5c772-b9f3-4851-9d9e-8990f81c475e", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "6c2c95b9-8e58-4956-a796-926fec68c67a", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "854f4b18-7f4a-458a-b4b8-47ab09478625", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Note record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "eb26a816-6dbd-4128-9a5f-fe92dd63ba55", - "type": "RICH_TEXT", - "name": "body", - "label": "Body", - "description": "Note body", - "icon": "IconFilePencil", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "383d3f90-d691-4487-a13d-e80c50fb756e", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the note.", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "bc6b24e6-9fcd-43fd-a2ba-c12f5d022132", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "99599532-c0e9-4d62-b4a6-89866e0374be" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bc6b24e6-9fcd-43fd-a2ba-c12f5d022132", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "383d3f90-d691-4487-a13d-e80c50fb756e", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "99599532-c0e9-4d62-b4a6-89866e0374be", - "name": "note" - } - } - }, - { - "__typename": "field", - "id": "a723f071-bc95-4a94-84d5-0f5904d88ea7", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ff8e5043-6168-4c65-984d-ef4d28eb76ce", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the note", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "a39ebd92-e37e-46d7-b545-aed1945476f2", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "b4b7114a-8536-438a-8d13-917eae164506" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a39ebd92-e37e-46d7-b545-aed1945476f2", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ff8e5043-6168-4c65-984d-ef4d28eb76ce", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b4b7114a-8536-438a-8d13-917eae164506", - "name": "note" - } - } - }, - { - "__typename": "field", - "id": "143a13af-842b-4f5d-913c-648472fbfc28", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "38a2a378-bac0-4c4d-bf05-7f9ff995b860", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Note attachments", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "ac29383b-d63e-4c0e-b28a-1abc03ab2b5a", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "e985e32a-532f-4259-828f-cac80c5fc3b8" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ac29383b-d63e-4c0e-b28a-1abc03ab2b5a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "38a2a378-bac0-4c4d-bf05-7f9ff995b860", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e985e32a-532f-4259-828f-cac80c5fc3b8", - "name": "note" - } - } - }, - { - "__typename": "field", - "id": "d6d5a326-5a21-46a6-96b5-c70549f8f937", - "type": "RELATION", - "name": "noteTargets", - "label": "Targets", - "description": "Note targets", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "72daf099-f592-4521-8a4e-febd67309f47", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "b8d93efe-14da-47a2-bb24-96ae2d037b59" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "72daf099-f592-4521-8a4e-febd67309f47", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d6d5a326-5a21-46a6-96b5-c70549f8f937", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b8d93efe-14da-47a2-bb24-96ae2d037b59", - "name": "note" - } - } - }, - { - "__typename": "field", - "id": "2be5c772-b9f3-4851-9d9e-8990f81c475e", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Note title", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0baad27f-ac7b-48a3-b0a7-f2eb9613b2c6", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "message", - "namePlural": "messages", - "labelSingular": "Message", - "labelPlural": "Messages", - "description": "Message", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "314263a0-4be7-4b22-bac1-37c8df91bdb2", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "938b8c3d-af73-43e7-acf9-ac634186d3aa", - "type": "DATE_TIME", - "name": "receivedAt", - "label": "Received At", - "description": "The date the message was received", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2e91d365-c35a-446e-b019-bdf7e51d7d79", - "type": "RELATION", - "name": "messageThread", - "label": "Message Thread Id", - "description": "Message Thread Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "01efe0bd-eda8-494a-b7ea-b4813dcf0b5a", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageThread", - "namePlural": "messageThreads", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "11a2bd26-4856-4ab2-916d-86a07beaccd3" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "01efe0bd-eda8-494a-b7ea-b4813dcf0b5a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "nameSingular": "message", - "namePlural": "messages" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2e91d365-c35a-446e-b019-bdf7e51d7d79", - "name": "messageThread" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "11a2bd26-4856-4ab2-916d-86a07beaccd3", - "name": "messages" - } - } - }, - { - "__typename": "field", - "id": "5291bbf6-1c32-47fe-8164-ebd6dca187ad", - "type": "RELATION", - "name": "messageParticipants", - "label": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "099ebe85-572a-4f77-b077-475f97c0d54c", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "2efee208-73da-4ca1-ba73-19763d507611" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "099ebe85-572a-4f77-b077-475f97c0d54c", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "nameSingular": "message", - "namePlural": "messages" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5291bbf6-1c32-47fe-8164-ebd6dca187ad", - "name": "messageParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2efee208-73da-4ca1-ba73-19763d507611", - "name": "message" - } - } - }, - { - "__typename": "field", - "id": "232561ae-1e5f-4cde-a093-53597948a567", - "type": "SELECT", - "name": "direction", - "label": "Direction", - "description": "Message Direction", - "icon": "IconDirection", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'INCOMING'", - "options": [ - { - "id": "14216544-33d1-47d0-99a9-717763d49c0f", - "color": "green", - "label": "Incoming", - "value": "INCOMING", - "position": 0 - }, - { - "id": "f1b89e48-1107-45a2-b54a-31a75e76b9b2", - "color": "blue", - "label": "Outgoing", - "value": "OUTGOING", - "position": 1 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c31a967f-0c76-4a07-9299-01ac653b3807", - "type": "TEXT", - "name": "headerMessageId", - "label": "Header message Id", - "description": "Message id from the message header", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "055e1afd-6445-4747-b489-0bb412c42e1e", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "314263a0-4be7-4b22-bac1-37c8df91bdb2", - "type": "TEXT", - "name": "subject", - "label": "Subject", - "description": "Subject", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c9419522-6ce4-48d6-bad8-8d71336ca964", - "type": "UUID", - "name": "messageThreadId", - "label": "Message Thread Id id (foreign key)", - "description": "Message Thread Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "cb6eb250-d255-4446-88f3-bc6b7dd20800", - "type": "RELATION", - "name": "messageChannelMessageAssociations", - "label": "Message Channel Association", - "description": "Messages from the channel.", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "3d3b5a91-f7b7-4c50-98d2-093be343711c", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "6e2131e3-b688-4b61-99bf-f0b50f100a5f" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "3d3b5a91-f7b7-4c50-98d2-093be343711c", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "nameSingular": "message", - "namePlural": "messages" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "cb6eb250-d255-4446-88f3-bc6b7dd20800", - "name": "messageChannelMessageAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6e2131e3-b688-4b61-99bf-f0b50f100a5f", - "name": "message" - } - } - }, - { - "__typename": "field", - "id": "367b2c39-dca7-48cb-b04a-8dd4e5e489af", - "type": "TEXT", - "name": "text", - "label": "Text", - "description": "Text", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c2c61dcb-08ee-4761-b5d6-53b44fda1431", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "41cf0d75-84f4-4063-a428-d699a731b080", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "f3189217-0595-44ad-a51c-6145a2f7c6ba", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "apiKey", - "namePlural": "apiKeys", - "labelSingular": "Api Key", - "labelPlural": "Api Keys", - "description": "An api key", - "icon": "IconRobot", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "13406939-4334-4820-ada4-3197dedc51b0", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "6a350a28-c036-4018-8caa-97128d74c3d9", - "type": "DATE_TIME", - "name": "revokedAt", - "label": "Revocation date", - "description": "ApiKey revocation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "22031e60-824f-4458-b265-bcae66ae8555", - "type": "DATE_TIME", - "name": "expiresAt", - "label": "Expiration date", - "description": "ApiKey expiration date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "eff85403-ee56-4b40-9d6c-d57197318bd2", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "13406939-4334-4820-ada4-3197dedc51b0", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "ApiKey name", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "75eccaec-4a93-4b74-a844-89b89ca98598", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7f3deab6-000a-40e4-b513-8658642168cd", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "labelSingular": "Company", - "labelPlural": "Companies", - "description": "A company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "2599d01d-02ee-4d55-9063-35c67cc81a0f", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "b229e842-ca29-4c1a-ba74-e69be1f357ac", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "65ed4460-c5b9-4634-bdc1-80f59515a2f6", - "type": "BOOLEAN", - "name": "visaSponsorship", - "label": "Visa Sponsorship", - "description": "Company's Visa Sponsorship Policy", - "icon": "IconBrandVisa", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:39:01.913Z", - "updatedAt": "2024-08-05T16:39:01.913Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": false, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a7c771af-639a-4f01-b1fa-3b245c3d4e92", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6cc3a88a-be92-47c7-9f17-8d726bb7f8b6", - "type": "LINKS", - "name": "domainName", - "label": "Domain Name", - "description": "The company website URL. We use this url to fetch the company icon", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ec77df7f-a933-4415-a515-8b4938c9f125", - "type": "LINKS", - "name": "introVideo", - "label": "Intro Video", - "description": "Company's Intro Video", - "icon": "IconVideo", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:39:01.865Z", - "updatedAt": "2024-08-05T16:39:01.865Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3ece1b4d-c052-4b32-bd2a-ba0f8c8b6f3e", - "type": "RELATION", - "name": "accountOwner", - "label": "Account Owner", - "description": "Your team member responsible for managing the company account", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "0896a728-e2cf-4032-9af2-a471645e9697", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "de44f939-76d9-4c1a-96aa-7c5a646f2045" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0896a728-e2cf-4032-9af2-a471645e9697", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3ece1b4d-c052-4b32-bd2a-ba0f8c8b6f3e", - "name": "accountOwner" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "de44f939-76d9-4c1a-96aa-7c5a646f2045", - "name": "accountOwnerForCompanies" - } - } - }, - { - "__typename": "field", - "id": "c06142b8-52a9-4b0b-93f6-99e2b5b67ab8", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the company", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "c542c9e0-b4b6-4073-aae6-66299868e9fb", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "979ea933-d8a1-4db6-8c29-5c747a690326" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c542c9e0-b4b6-4073-aae6-66299868e9fb", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c06142b8-52a9-4b0b-93f6-99e2b5b67ab8", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "979ea933-d8a1-4db6-8c29-5c747a690326", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "b08f7cc5-f0c9-4ab1-a2bd-2733ab95d97b", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Company record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f0c8cde4-5a5d-4a6f-8273-94396a60f918", - "type": "CURRENCY", - "name": "annualRecurringRevenue", - "label": "ARR", - "description": "Annual Recurring Revenue: The actual or estimated annual revenue of the company", - "icon": "IconMoneybag", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "amountMicros": null, - "currencyCode": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5e24424a-db05-468b-bd45-7cab4059be3a", - "type": "NUMBER", - "name": "employees", - "label": "Employees", - "description": "Number of employees in the company", - "icon": "IconUsers", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "63261a95-39ac-4826-bc8b-7fc0fd21a8ad", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the company", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "d420db15-3060-4760-afd0-8485c76e53b4", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "cb654210-43c9-4ff7-95ee-8250c1d80e8d" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d420db15-3060-4760-afd0-8485c76e53b4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "63261a95-39ac-4826-bc8b-7fc0fd21a8ad", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "cb654210-43c9-4ff7-95ee-8250c1d80e8d", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "cb47633a-1b44-41b9-8bce-16e28616c2ad", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the company", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "f80bfd64-c33d-4488-bc49-1635e092ea3f", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "1e4e3b2b-113f-4af3-aed8-94b03785a626" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "f80bfd64-c33d-4488-bc49-1635e092ea3f", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "cb47633a-1b44-41b9-8bce-16e28616c2ad", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "1e4e3b2b-113f-4af3-aed8-94b03785a626", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "c132d454-299e-4885-89b0-de5b824e43e2", - "type": "LINKS", - "name": "linkedinLink", - "label": "Linkedin", - "description": "The company Linkedin account", - "icon": "IconBrandLinkedin", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "64f76ec9-3fae-4a61-b30f-7c646f4fe33d", - "type": "MULTI_SELECT", - "name": "workPolicy", - "label": "Work Policy", - "description": "Company's Work Policy", - "icon": "IconHome", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:39:01.888Z", - "updatedAt": "2024-08-05T16:39:01.888Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": [ - { - "id": "2a832e12-073e-4b58-bb71-9f68c00cabda", - "color": "green", - "label": "On-Site", - "value": "ON_SITE", - "position": 0 - }, - { - "id": "231423db-f097-4410-8efc-95bc19f9e87f", - "color": "turquoise", - "label": "Hybrid", - "value": "HYBRID", - "position": 1 - }, - { - "id": "db436d25-f1e3-45aa-9f81-7a5ef84a50ef", - "color": "sky", - "label": "Remote Work", - "value": "REMOTE_WORK", - "position": 2 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "79452277-0e6e-4dc5-b972-470c29bd6d12", - "type": "ADDRESS", - "name": "address", - "label": "Address", - "description": "Address of the company", - "icon": "IconMap", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "addressLat": null, - "addressLng": null, - "addressCity": "''", - "addressState": "''", - "addressCountry": "''", - "addressStreet1": "''", - "addressStreet2": "''", - "addressPostcode": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2599d01d-02ee-4d55-9063-35c67cc81a0f", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "The company name", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4cbb077e-ccce-4892-8fc0-9b9238d7a009", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3a2bd134-5b31-4bde-a64f-d5244a8e6271", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments linked to the company", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "be6051cd-703c-4539-89ed-e643784bad26", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "6496b8e0-2d8f-493e-8973-fcba2aa84b59" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "be6051cd-703c-4539-89ed-e643784bad26", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3a2bd134-5b31-4bde-a64f-d5244a8e6271", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6496b8e0-2d8f-493e-8973-fcba2aa84b59", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "1ce2452b-75a2-4989-ad48-f6f696fe1a38", - "type": "LINKS", - "name": "xLink", - "label": "X", - "description": "The company Twitter/X account", - "icon": "IconBrandX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "48dba12f-4429-4ee2-9b3a-6df97c45141d", - "type": "RELATION", - "name": "people", - "label": "People", - "description": "People linked to the company.", - "icon": "IconUsers", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "0562d399-7053-4d7f-a415-cabfc889bd16", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "toFieldMetadataId": "6672a066-7a7f-44ae-bb5c-ae3a5e82d835" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0562d399-7053-4d7f-a415-cabfc889bd16", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "48dba12f-4429-4ee2-9b3a-6df97c45141d", - "name": "people" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6672a066-7a7f-44ae-bb5c-ae3a5e82d835", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "a49c82ff-0483-4acc-9e67-16e121daa11f", - "type": "TEXT", - "name": "myCustomField", - "label": "myCustomField", - "description": null, - "icon": "IconUsers", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T17:09:37.502Z", - "updatedAt": "2024-08-05T17:09:37.502Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0f2127dd-9364-4a9e-a66f-a866eb629d8b", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4d74b886-b359-4c4c-a2c0-692edc8a3273", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the company", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "2ed70c2c-b17a-4ed1-9f35-b570139440fa", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "10150d34-2f00-4642-8a9d-6b0b6ab72562" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2ed70c2c-b17a-4ed1-9f35-b570139440fa", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4d74b886-b359-4c4c-a2c0-692edc8a3273", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "10150d34-2f00-4642-8a9d-6b0b6ab72562", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "cbd94612-00a2-4efd-8869-93f945e93076", - "type": "RELATION", - "name": "opportunities", - "label": "Opportunities", - "description": "Opportunities linked to the company.", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "67d4ff08-f5e6-4382-8996-67fdc2d02125", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "toFieldMetadataId": "28b61c8a-8437-4770-9b12-f3d0e591bee8" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "67d4ff08-f5e6-4382-8996-67fdc2d02125", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "cbd94612-00a2-4efd-8869-93f945e93076", - "name": "opportunities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "28b61c8a-8437-4770-9b12-f3d0e591bee8", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "ae74690d-94d5-4860-928f-4ed8ea36be1d", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the company", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "31819eaa-5847-4207-b4a3-0ecffefd9332", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "69b1d954-1ed3-4bf9-b9e1-b886a00953b4" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "31819eaa-5847-4207-b4a3-0ecffefd9332", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ae74690d-94d5-4860-928f-4ed8ea36be1d", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "69b1d954-1ed3-4bf9-b9e1-b886a00953b4", - "name": "company" - } - } - }, - { - "__typename": "field", - "id": "abc8bbb4-cc34-428b-a182-b032c2b3c7ff", - "type": "UUID", - "name": "accountOwnerId", - "label": "Account Owner id (foreign key)", - "description": "Your team member responsible for managing the company account id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "9bbd039b-40e0-4742-879e-0be3cf9b12b7", - "type": "TEXT", - "name": "tagline", - "label": "Tagline", - "description": "Company's Tagline", - "icon": "IconAdCircle", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:39:01.834Z", - "updatedAt": "2024-08-05T16:39:01.834Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f90f1fda-258f-4b52-af93-9f157e2ed187", - "type": "BOOLEAN", - "name": "idealCustomerProfile", - "label": "ICP", - "description": "Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you", - "icon": "IconTarget", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": false, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "ee025446-440d-49ae-8d0e-ad30b6309840", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "viewField", - "namePlural": "viewFields", - "labelSingular": "View Field", - "labelPlural": "View Fields", - "description": "(System) View Fields", - "icon": "IconTag", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "440d28bb-2d5f-4624-8fdd-5476ac84baa5", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "2c466c0c-926a-4722-846c-3bd89c2751da", - "type": "BOOLEAN", - "name": "isVisible", - "label": "Visible", - "description": "View Field visibility", - "icon": "IconEye", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6725c7ad-a704-436a-be67-a4612bc48e37", - "type": "RELATION", - "name": "view", - "label": "View", - "description": "View Field related view", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "57d32129-b126-417e-98a8-7f1217b29dea", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "view", - "namePlural": "views", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "6ea01d0e-340e-40e4-a029-89a7cbc07291" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "57d32129-b126-417e-98a8-7f1217b29dea", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ee025446-440d-49ae-8d0e-ad30b6309840", - "nameSingular": "viewField", - "namePlural": "viewFields" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6725c7ad-a704-436a-be67-a4612bc48e37", - "name": "view" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "nameSingular": "view", - "namePlural": "views" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6ea01d0e-340e-40e4-a029-89a7cbc07291", - "name": "viewFields" - } - } - }, - { - "__typename": "field", - "id": "21015789-4b34-4a98-8669-1ceb7e408d0c", - "type": "UUID", - "name": "viewId", - "label": "View id (foreign key)", - "description": "View Field related view id foreign key", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4ce74348-740e-49e4-b13f-05a7810fc021", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "be8726a0-5584-4e78-82b8-4be201cd8870", - "type": "UUID", - "name": "fieldMetadataId", - "label": "Field Metadata Id", - "description": "View Field target field", - "icon": "IconTag", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6a582800-ad4d-4a5b-ac51-9a4a28f7b348", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "619cb257-468c-4496-8db7-3d119013b5a8", - "type": "NUMBER", - "name": "size", - "label": "Size", - "description": "View Field size", - "icon": "IconEye", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": 0, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c82925e9-c98a-497d-9d70-c39158402171", - "type": "NUMBER", - "name": "position", - "label": "Position", - "description": "View Field position", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": 0, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "440d28bb-2d5f-4624-8fdd-5476ac84baa5", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "e0bf07c5-4729-46ab-aa15-480f26999477", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "webhook", - "namePlural": "webhooks", - "labelSingular": "Webhook", - "labelPlural": "Webhooks", - "description": "A webhook", - "icon": "IconRobot", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "1b437ef4-0bcf-4a8d-9ebf-f25ffccb3d54", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "1b437ef4-0bcf-4a8d-9ebf-f25ffccb3d54", - "type": "TEXT", - "name": "targetUrl", - "label": "Target Url", - "description": "Webhook target url", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b3ce5dca-00ec-4ea3-ae2a-4f08cac53a3b", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e11a3ed9-2576-4bca-bc8d-4559b247f466", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "670a4724-178c-44b4-94a6-30e11f015cb0", - "type": "TEXT", - "name": "operation", - "label": "Operation", - "description": "Webhook operation", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a3d5bfcd-ed28-4dcb-a650-c474de21ec58", - "type": "TEXT", - "name": "description", - "label": "Description", - "description": null, - "icon": "IconInfo", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7ab0a589-fe02-4e80-8ae9-4ea51d3b8907", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "labelSingular": "Favorite", - "labelPlural": "Favorites", - "description": "A favorite", - "icon": "IconHeart", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "18c9dce6-51cb-4326-890f-156a3e19a88d", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "3d4cd287-7435-4574-aedd-09f6f5b34afb", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "Favorite task id foreign key", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3214e46b-3728-42ea-bdcc-dc8d0d15e64c", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject ID (foreign key)", - "description": "Favorite myCustomObject id foreign key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.167Z", - "updatedAt": "2024-08-05T17:09:54.167Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b5845911-ec5b-4032-a60e-bcdbd1a6b1f2", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Favorite workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "407a2cbc-6c15-41dd-942c-5322d273bec3", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Favorite workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "b0f40da3-1fda-4803-be21-14a2755bc834", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "f537669a-4524-4dfc-91d3-79438e2a481e" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "b0f40da3-1fda-4803-be21-14a2755bc834", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "407a2cbc-6c15-41dd-942c-5322d273bec3", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f537669a-4524-4dfc-91d3-79438e2a481e", - "name": "favorites" - } - } - }, - { - "__typename": "field", - "id": "9c99e6fc-aed4-44f6-a231-1d1ce3f218ab", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Favorite company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "87c2dd65-2c54-4184-9a19-0bdce7781a3f", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": "Favorite myCustomObject", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.168Z", - "updatedAt": "2024-08-05T17:09:54.168Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "143c2257-721f-46eb-8114-987a70979146", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "c475ebbc-f86b-4956-9d67-d0bb62062408" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "143c2257-721f-46eb-8114-987a70979146", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "87c2dd65-2c54-4184-9a19-0bdce7781a3f", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c475ebbc-f86b-4956-9d67-d0bb62062408", - "name": "favorites" - } - } - }, - { - "__typename": "field", - "id": "0c955466-cf7a-43b5-a0c5-4703b9703193", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "18c9dce6-51cb-4326-890f-156a3e19a88d", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3464f1ce-34d3-4bf1-ac74-072bf750cc5c", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "Favorite opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "c1110f68-bbc9-4dbf-aae4-c6e5e2569240", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "a1a7bb38-6f6c-4bdb-803f-804cdd97cb77" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c1110f68-bbc9-4dbf-aae4-c6e5e2569240", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3464f1ce-34d3-4bf1-ac74-072bf750cc5c", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a1a7bb38-6f6c-4bdb-803f-804cdd97cb77", - "name": "favorites" - } - } - }, - { - "__typename": "field", - "id": "9520f201-9dec-4e48-ba68-4fb9f2a4c662", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "Favorite note id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b4b7114a-8536-438a-8d13-917eae164506", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "Favorite note", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "a39ebd92-e37e-46d7-b545-aed1945476f2", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "ff8e5043-6168-4c65-984d-ef4d28eb76ce" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a39ebd92-e37e-46d7-b545-aed1945476f2", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b4b7114a-8536-438a-8d13-917eae164506", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ff8e5043-6168-4c65-984d-ef4d28eb76ce", - "name": "favorites" - } - } - }, - { - "__typename": "field", - "id": "4f2c079a-0221-47e9-ab92-68f529726424", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Favorite person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e7201f19-bfa7-42e1-9550-7c848a842ecc", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "Favorite task", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "32b10a0d-0ca4-4027-be9e-ab8d8be608d1", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "80fe7004-903e-4bdd-985d-9ef7e6acd793" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "32b10a0d-0ca4-4027-be9e-ab8d8be608d1", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e7201f19-bfa7-42e1-9550-7c848a842ecc", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "80fe7004-903e-4bdd-985d-9ef7e6acd793", - "name": "favorites" - } - } - }, - { - "__typename": "field", - "id": "ce728fc3-01f7-4e2b-b71c-05ed44b50836", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "Favorite opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "674ead9c-88e9-481c-b5b3-dec4a450d67e", - "type": "NUMBER", - "name": "position", - "label": "Position", - "description": "Favorite position", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": 0, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5966af59-a371-42a3-85de-1b9a8e9768c9", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "69b1d954-1ed3-4bf9-b9e1-b886a00953b4", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Favorite company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "31819eaa-5847-4207-b4a3-0ecffefd9332", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "ae74690d-94d5-4860-928f-4ed8ea36be1d" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "31819eaa-5847-4207-b4a3-0ecffefd9332", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "69b1d954-1ed3-4bf9-b9e1-b886a00953b4", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ae74690d-94d5-4860-928f-4ed8ea36be1d", - "name": "favorites" - } - } - }, - { - "__typename": "field", - "id": "b7caceaa-d49a-43c8-8b9b-10dc4298ade5", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Favorite person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "66551942-e576-4eb7-96c4-f78182f44491", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "4cd944c2-a252-42c2-93d3-c71d71b4587d" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "66551942-e576-4eb7-96c4-f78182f44491", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b7caceaa-d49a-43c8-8b9b-10dc4298ade5", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4cd944c2-a252-42c2-93d3-c71d71b4587d", - "name": "favorites" - } - } - } - ] - }, - { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "labelSingular": "Message Channel Message Association", - "labelPlural": "Message Channel Message Associations", - "description": "Message Synced with a Message Channel", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "f3df53cf-dad8-4880-9b06-cd24188c77e5", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "53f2d078-7fd1-4ba7-bae7-e58398dd2d6e", - "type": "UUID", - "name": "messageThreadId", - "label": "Message Thread Id id (foreign key)", - "description": "Message Thread Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "70a1610d-08ea-44eb-a453-02c1749e6e0c", - "type": "UUID", - "name": "messageId", - "label": "Message Id id (foreign key)", - "description": "Message Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "930b7926-639c-43c1-85ba-4c185a9ad5d3", - "type": "RELATION", - "name": "messageThread", - "label": "Message Thread Id", - "description": "Message Thread Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "6be1cb67-30fe-41b3-8695-09cf6cbef18a", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageThread", - "namePlural": "messageThreads", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "bfa74ef1-b2d8-4720-a9bd-3084ceb005f3" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "6be1cb67-30fe-41b3-8695-09cf6cbef18a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "930b7926-639c-43c1-85ba-4c185a9ad5d3", - "name": "messageThread" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "bfa74ef1-b2d8-4720-a9bd-3084ceb005f3", - "name": "messageChannelMessageAssociations" - } - } - }, - { - "__typename": "field", - "id": "aa5c5146-05fc-4f48-a90a-1570bdc91ed9", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "470b0e39-1f5b-45e3-a092-c0f247539933", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6e2131e3-b688-4b61-99bf-f0b50f100a5f", - "type": "RELATION", - "name": "message", - "label": "Message Id", - "description": "Message Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "3d3b5a91-f7b7-4c50-98d2-093be343711c", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "message", - "namePlural": "messages", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "cb6eb250-d255-4446-88f3-bc6b7dd20800" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "3d3b5a91-f7b7-4c50-98d2-093be343711c", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6e2131e3-b688-4b61-99bf-f0b50f100a5f", - "name": "message" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "nameSingular": "message", - "namePlural": "messages" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "cb6eb250-d255-4446-88f3-bc6b7dd20800", - "name": "messageChannelMessageAssociations" - } - } - }, - { - "__typename": "field", - "id": "621d12d5-80e5-4d0e-9c93-2433ff447dda", - "type": "UUID", - "name": "messageChannelId", - "label": "Message Channel Id id (foreign key)", - "description": "Message Channel Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ec0e8151-40a6-4695-a3bd-68794b26ea40", - "type": "TEXT", - "name": "messageExternalId", - "label": "Message External Id", - "description": "Message id from the messaging provider", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f3df53cf-dad8-4880-9b06-cd24188c77e5", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f2561dd5-c695-4635-816c-27175470b285", - "type": "RELATION", - "name": "messageChannel", - "label": "Message Channel Id", - "description": "Message Channel Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "e420b731-e1e1-425a-ac7a-488d37d1958b", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannel", - "namePlural": "messageChannels", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "2682d5c3-f05e-4c5c-87eb-bb1a6c0c37bb" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e420b731-e1e1-425a-ac7a-488d37d1958b", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f2561dd5-c695-4635-816c-27175470b285", - "name": "messageChannel" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2682d5c3-f05e-4c5c-87eb-bb1a6c0c37bb", - "name": "messageChannelMessageAssociations" - } - } - }, - { - "__typename": "field", - "id": "b93119d3-d244-42a4-8d7d-8c312f683f55", - "type": "TEXT", - "name": "messageThreadExternalId", - "label": "Thread External Id", - "description": "Thread id from the messaging provider", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activity", - "namePlural": "activities", - "labelSingular": "Activity", - "labelPlural": "Activities", - "description": "An activity", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "7690dd7a-0c0d-444a-845a-2ea9ea4fa54d", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "beac3449-af10-43a2-9abb-276a798df3de", - "type": "RELATION", - "name": "author", - "label": "Author", - "description": "Activity author", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "6d4e8025-7ee9-4079-ae80-b18de7b5ff4e", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "5e889b07-de1e-47f0-aeb9-301a684bd6a4" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "6d4e8025-7ee9-4079-ae80-b18de7b5ff4e", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "beac3449-af10-43a2-9abb-276a798df3de", - "name": "author" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5e889b07-de1e-47f0-aeb9-301a684bd6a4", - "name": "authoredActivities" - } - } - }, - { - "__typename": "field", - "id": "9045116d-0fed-433c-80a4-f4296db72ae5", - "type": "RELATION", - "name": "comments", - "label": "Comments", - "description": "Activity comments", - "icon": "IconComment", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "00b07eda-840c-4a91-a8f7-365c008a2ea1", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "comment", - "namePlural": "comments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "88c3a2b9-b59a-413a-b2d3-44b151185929" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "00b07eda-840c-4a91-a8f7-365c008a2ea1", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "9045116d-0fed-433c-80a4-f4296db72ae5", - "name": "comments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "nameSingular": "comment", - "namePlural": "comments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "88c3a2b9-b59a-413a-b2d3-44b151185929", - "name": "activity" - } - } - }, - { - "__typename": "field", - "id": "bec64b6b-d141-45fe-a166-4f5d9ae578ce", - "type": "UUID", - "name": "authorId", - "label": "Author id (foreign key)", - "description": "Activity author id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6e363f5f-737c-4b94-b5ce-5fe034330f47", - "type": "TEXT", - "name": "body", - "label": "Body", - "description": "Activity body", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "605e8c91-456d-4a53-906c-df02d6425362", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d8477f91-7cb2-4455-b2c3-911dcb4c464f", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "8958f22c-ba22-42f5-8db9-11ea3df92c5b", - "type": "UUID", - "name": "assigneeId", - "label": "Assignee id (foreign key)", - "description": "Activity assignee id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "41f8fd90-2de9-402f-8b37-fb023d318de2", - "type": "RELATION", - "name": "activityTargets", - "label": "Targets", - "description": "Activity targets", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "16017cba-688e-4483-a258-9cef3999cbbf", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "aa1c7e04-31c1-4b62-8451-6b32926cab47" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "16017cba-688e-4483-a258-9cef3999cbbf", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "41f8fd90-2de9-402f-8b37-fb023d318de2", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "aa1c7e04-31c1-4b62-8451-6b32926cab47", - "name": "activity" - } - } - }, - { - "__typename": "field", - "id": "ea9aa19c-22d8-4b72-83ff-78d9653c27c4", - "type": "RELATION", - "name": "assignee", - "label": "Assignee", - "description": "Activity assignee", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "cf9ac76a-9f22-4252-a00a-63cc45fcabc4", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "a147a0df-eb28-4259-a304-0460f92adf30" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "cf9ac76a-9f22-4252-a00a-63cc45fcabc4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ea9aa19c-22d8-4b72-83ff-78d9653c27c4", - "name": "assignee" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a147a0df-eb28-4259-a304-0460f92adf30", - "name": "assignedActivities" - } - } - }, - { - "__typename": "field", - "id": "7690dd7a-0c0d-444a-845a-2ea9ea4fa54d", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Activity title", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "918033d1-237e-45fd-960f-3fa4f0e45292", - "type": "DATE_TIME", - "name": "reminderAt", - "label": "Reminder Date", - "description": "Activity reminder date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5c749bc8-9331-4744-8697-a03a4ad46a3d", - "type": "TEXT", - "name": "type", - "label": "Type", - "description": "Activity type", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'Note'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7b24a2df-8118-4dea-862b-ec21e5a12e47", - "type": "DATE_TIME", - "name": "completedAt", - "label": "Completion Date", - "description": "Activity completion date", - "icon": "IconCheck", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "29a1593e-7704-4e43-ae88-507b1ff0febb", - "type": "DATE_TIME", - "name": "dueAt", - "label": "Due Date", - "description": "Activity due date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d9f1711b-a8b1-48ee-9f81-503bbf945b87", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Activity attachments", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "23518310-2443-4907-8ac6-b77bf340d99d", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "394c0644-d8bd-44a8-82c9-6e2a4c9aa19c" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "23518310-2443-4907-8ac6-b77bf340d99d", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d9f1711b-a8b1-48ee-9f81-503bbf945b87", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "394c0644-d8bd-44a8-82c9-6e2a4c9aa19c", - "name": "activity" - } - } - }, - { - "__typename": "field", - "id": "2d969fc8-07b3-470e-8bb5-b6e78fbfb22a", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageThread", - "namePlural": "messageThreads", - "labelSingular": "Message Thread", - "labelPlural": "Message Threads", - "description": "Message Thread", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "260b37ba-7451-488f-ae65-a7143aa694e8", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "f05ccb65-325b-4bef-b946-695e598092b5", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "bfa74ef1-b2d8-4720-a9bd-3084ceb005f3", - "type": "RELATION", - "name": "messageChannelMessageAssociations", - "label": "Message Channel Association", - "description": "Messages from the channel", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "6be1cb67-30fe-41b3-8695-09cf6cbef18a", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "930b7926-639c-43c1-85ba-4c185a9ad5d3" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "6be1cb67-30fe-41b3-8695-09cf6cbef18a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "bfa74ef1-b2d8-4720-a9bd-3084ceb005f3", - "name": "messageChannelMessageAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "930b7926-639c-43c1-85ba-4c185a9ad5d3", - "name": "messageThread" - } - } - }, - { - "__typename": "field", - "id": "463d59e6-add9-494a-a88f-a280329fb16e", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "260b37ba-7451-488f-ae65-a7143aa694e8", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "11a2bd26-4856-4ab2-916d-86a07beaccd3", - "type": "RELATION", - "name": "messages", - "label": "Messages", - "description": "Messages from the thread.", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "01efe0bd-eda8-494a-b7ea-b4813dcf0b5a", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "message", - "namePlural": "messages", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "2e91d365-c35a-446e-b019-bdf7e51d7d79" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "01efe0bd-eda8-494a-b7ea-b4813dcf0b5a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "c62f3148-1b8d-4fa3-ac29-8a20585bcee9", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "11a2bd26-4856-4ab2-916d-86a07beaccd3", - "name": "messages" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "nameSingular": "message", - "namePlural": "messages" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2e91d365-c35a-446e-b019-bdf7e51d7d79", - "name": "messageThread" - } - } - } - ] - }, - { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "labelSingular": "Note Target", - "labelPlural": "Note Targets", - "description": "A note target", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "96b428bf-6cda-44ec-a774-764075c44326", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "c60efe10-abb9-4c1f-8a27-e97884770401", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "NoteTarget person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "96b428bf-6cda-44ec-a774-764075c44326", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e1b3d8bb-787a-4f2c-a6b0-5384f7ce19fe", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f4814caa-d470-415b-83e0-015903b68bca", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject ID (foreign key)", - "description": "NoteTarget myCustomObject id foreign key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.176Z", - "updatedAt": "2024-08-05T17:09:54.176Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e884eac3-4cbd-40af-970e-a34b409c0acd", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": "NoteTarget myCustomObject", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.177Z", - "updatedAt": "2024-08-05T17:09:54.177Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "4f4d3969-913b-478c-a41d-9daffc9b2255", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "87631266-4a85-4c49-82d1-90d1805c3de6" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "4f4d3969-913b-478c-a41d-9daffc9b2255", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e884eac3-4cbd-40af-970e-a34b409c0acd", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "87631266-4a85-4c49-82d1-90d1805c3de6", - "name": "noteTargets" - } - } - }, - { - "__typename": "field", - "id": "6267cb8e-04e2-48ce-a479-3108b2bf1801", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c4946aa0-9c73-4daf-af28-85fff088525c", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "NoteTarget opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b8d93efe-14da-47a2-bb24-96ae2d037b59", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "NoteTarget note", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "72daf099-f592-4521-8a4e-febd67309f47", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "d6d5a326-5a21-46a6-96b5-c70549f8f937" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "72daf099-f592-4521-8a4e-febd67309f47", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b8d93efe-14da-47a2-bb24-96ae2d037b59", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d6d5a326-5a21-46a6-96b5-c70549f8f937", - "name": "noteTargets" - } - } - }, - { - "__typename": "field", - "id": "18504863-6684-44f8-afa6-12e2eae7f428", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "NoteTarget company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "459cd941-1db8-4e61-af0e-35812736cfd1", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "NoteTarget opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "a0fa9159-85ab-47c5-bdac-46f7acbb78a7", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "8ee18f64-937c-489b-893c-80bc44f9c105" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a0fa9159-85ab-47c5-bdac-46f7acbb78a7", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "459cd941-1db8-4e61-af0e-35812736cfd1", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "8ee18f64-937c-489b-893c-80bc44f9c105", - "name": "noteTargets" - } - } - }, - { - "__typename": "field", - "id": "cb654210-43c9-4ff7-95ee-8250c1d80e8d", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "NoteTarget company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "d420db15-3060-4760-afd0-8485c76e53b4", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "63261a95-39ac-4826-bc8b-7fc0fd21a8ad" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d420db15-3060-4760-afd0-8485c76e53b4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "cb654210-43c9-4ff7-95ee-8250c1d80e8d", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "63261a95-39ac-4826-bc8b-7fc0fd21a8ad", - "name": "noteTargets" - } - } - }, - { - "__typename": "field", - "id": "2d7a63c8-3a4f-4e20-aa73-f417ee714632", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "NoteTarget note id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2f2fc7fb-51c5-4084-8d97-13b43b49c68a", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "NoteTarget person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "9d20f0c0-e37b-48ca-bc45-da16461aa547", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "1c1c7ffc-3a45-4069-996a-bdfa8f46b037" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9d20f0c0-e37b-48ca-bc45-da16461aa547", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2f2fc7fb-51c5-4084-8d97-13b43b49c68a", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "1c1c7ffc-3a45-4069-996a-bdfa8f46b037", - "name": "noteTargets" - } - } - } - ] - }, - { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "labelSingular": "Opportunity", - "labelPlural": "Opportunities", - "description": "An opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "945ed2b8-974b-47cd-a40e-63dd1130919e", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "40cdd413-5239-4887-b5e6-eb32eb1d95e3", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the opportunity", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "e594dda4-55fc-46ba-8108-5f672a5b1301", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "705e4379-9ba2-4853-b267-c86dad461dd7" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e594dda4-55fc-46ba-8108-5f672a5b1301", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "40cdd413-5239-4887-b5e6-eb32eb1d95e3", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "705e4379-9ba2-4853-b267-c86dad461dd7", - "name": "opportunity" - } - } - }, - { - "__typename": "field", - "id": "8ee18f64-937c-489b-893c-80bc44f9c105", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the opportunity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "a0fa9159-85ab-47c5-bdac-46f7acbb78a7", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "459cd941-1db8-4e61-af0e-35812736cfd1" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a0fa9159-85ab-47c5-bdac-46f7acbb78a7", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "8ee18f64-937c-489b-893c-80bc44f9c105", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "459cd941-1db8-4e61-af0e-35812736cfd1", - "name": "opportunity" - } - } - }, - { - "__typename": "field", - "id": "b32abba8-6801-4bf2-8c62-748fb0f2c224", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Opportunity company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a1a7bb38-6f6c-4bdb-803f-804cdd97cb77", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the opportunity", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "c1110f68-bbc9-4dbf-aae4-c6e5e2569240", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "3464f1ce-34d3-4bf1-ac74-072bf750cc5c" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c1110f68-bbc9-4dbf-aae4-c6e5e2569240", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a1a7bb38-6f6c-4bdb-803f-804cdd97cb77", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3464f1ce-34d3-4bf1-ac74-072bf750cc5c", - "name": "opportunity" - } - } - }, - { - "__typename": "field", - "id": "b32af3b6-330f-405b-b9ce-6156797f836a", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments linked to the opportunity", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "0ee1046a-3f9f-477e-8811-5d29021eca38", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "31bbc876-619d-4444-b954-9b6c66343314" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0ee1046a-3f9f-477e-8811-5d29021eca38", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b32af3b6-330f-405b-b9ce-6156797f836a", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "31bbc876-619d-4444-b954-9b6c66343314", - "name": "opportunity" - } - } - }, - { - "__typename": "field", - "id": "59d9b42a-aedf-4bd4-89bb-79416d1c45ba", - "type": "DATE_TIME", - "name": "closeDate", - "label": "Close date", - "description": "Opportunity close date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "23598371-f3eb-4dc3-9254-c8150639fa2d", - "type": "SELECT", - "name": "stage", - "label": "Stage", - "description": "Opportunity stage", - "icon": "IconProgressCheck", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'NEW'", - "options": [ - { - "id": "20e58665-2b7c-464b-b25e-6ed2f27cc94a", - "color": "red", - "label": "New", - "value": "NEW", - "position": 0 - }, - { - "id": "9c2a17fd-65ad-4b55-82e1-eaf62da947ee", - "color": "purple", - "label": "Screening", - "value": "SCREENING", - "position": 1 - }, - { - "id": "a0e93b94-c12f-433d-9971-2e7a6d55881b", - "color": "sky", - "label": "Meeting", - "value": "MEETING", - "position": 2 - }, - { - "id": "7c510ced-cbea-4e39-98a0-35b449a1ac28", - "color": "turquoise", - "label": "Proposal", - "value": "PROPOSAL", - "position": 3 - }, - { - "id": "ff6973c2-a8eb-4e37-b742-259ea74893dd", - "color": "yellow", - "label": "Customer", - "value": "CUSTOMER", - "position": 4 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f1e9a8ea-6c0a-4bf4-acef-86d0855ac9ae", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f28ff3e4-c792-4f94-84d2-4df0572d29cb", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "64c6f5b9-63c4-4079-bd72-b54bf2b0c1ae", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "71341870-4e4d-4399-ab74-8f277047664e", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the opportunity", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "d2a53784-3664-49ab-983e-5ad5bf15dbd0", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "997b0618-d3f7-4e5c-8c8e-2ba1bad10549" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d2a53784-3664-49ab-983e-5ad5bf15dbd0", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "71341870-4e4d-4399-ab74-8f277047664e", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "997b0618-d3f7-4e5c-8c8e-2ba1bad10549", - "name": "opportunity" - } - } - }, - { - "__typename": "field", - "id": "713c39d7-63e2-4b0e-bd5c-d240b840255e", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the opportunity.", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "61e4edee-13d4-4edd-9101-b9dc5ea5506a", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "2c3baa6b-7ffe-470e-bd9d-0532e2bce3ac" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "61e4edee-13d4-4edd-9101-b9dc5ea5506a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "713c39d7-63e2-4b0e-bd5c-d240b840255e", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2c3baa6b-7ffe-470e-bd9d-0532e2bce3ac", - "name": "opportunity" - } - } - }, - { - "__typename": "field", - "id": "945ed2b8-974b-47cd-a40e-63dd1130919e", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "The opportunity name", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "eeeecdec-299d-4ac1-8475-180b9de43351", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "28b61c8a-8437-4770-9b12-f3d0e591bee8", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Opportunity company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "67d4ff08-f5e6-4382-8996-67fdc2d02125", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "cbd94612-00a2-4efd-8869-93f945e93076" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "67d4ff08-f5e6-4382-8996-67fdc2d02125", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "28b61c8a-8437-4770-9b12-f3d0e591bee8", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "cbd94612-00a2-4efd-8869-93f945e93076", - "name": "opportunities" - } - } - }, - { - "__typename": "field", - "id": "dc7898b0-d2b7-4910-bedc-a6fe8eb4c41e", - "type": "RELATION", - "name": "pointOfContact", - "label": "Point of Contact", - "description": "Opportunity point of contact", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "3e039f55-e535-406a-8a80-185123910b7a", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "e1ecbeb4-76cb-4f9a-8829-ac0665854c69" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "3e039f55-e535-406a-8a80-185123910b7a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "dc7898b0-d2b7-4910-bedc-a6fe8eb4c41e", - "name": "pointOfContact" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e1ecbeb4-76cb-4f9a-8829-ac0665854c69", - "name": "pointOfContactForOpportunities" - } - } - }, - { - "__typename": "field", - "id": "35f32ceb-5f9c-4106-84e1-a480e015fb6f", - "type": "UUID", - "name": "pointOfContactId", - "label": "Point of Contact id (foreign key)", - "description": "Opportunity point of contact id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d4fdbcc2-9de3-4ec8-a3d2-6126f01cd930", - "type": "CURRENCY", - "name": "amount", - "label": "Amount", - "description": "Opportunity amount", - "icon": "IconCurrencyDollar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "amountMicros": null, - "currencyCode": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6fe0ff62-8159-4a5f-b0cd-2ca1dfcf5fb7", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Opportunity record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "labelSingular": "Message Participant", - "labelPlural": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "3ad8eb5c-c148-43f4-89b9-3152b77854e5", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "a7036ff9-a86d-4290-9f2a-cc360c86fe1e", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "94c22c13-b00a-4f60-b2d2-f34b9efe6aa2", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "dd7ee456-52bf-4335-bee9-7ba18a1e9a09" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "94c22c13-b00a-4f60-b2d2-f34b9efe6aa2", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a7036ff9-a86d-4290-9f2a-cc360c86fe1e", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "dd7ee456-52bf-4335-bee9-7ba18a1e9a09", - "name": "messageParticipants" - } - } - }, - { - "__typename": "field", - "id": "3779c76a-30a8-45bc-a56a-6bfc084a9b29", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "f26f3e6e-35bf-474a-9679-fbfbb009d67d", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "4227c9a5-6dd3-4de0-9248-e62572afc92b" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "f26f3e6e-35bf-474a-9679-fbfbb009d67d", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3779c76a-30a8-45bc-a56a-6bfc084a9b29", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4227c9a5-6dd3-4de0-9248-e62572afc92b", - "name": "messageParticipants" - } - } - }, - { - "__typename": "field", - "id": "2efee208-73da-4ca1-ba73-19763d507611", - "type": "RELATION", - "name": "message", - "label": "Message", - "description": "Message", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "099ebe85-572a-4f77-b077-475f97c0d54c", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "message", - "namePlural": "messages", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "5291bbf6-1c32-47fe-8164-ebd6dca187ad" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "099ebe85-572a-4f77-b077-475f97c0d54c", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2efee208-73da-4ca1-ba73-19763d507611", - "name": "message" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f5a97cba-781d-4665-9dea-0eda6d687a99", - "nameSingular": "message", - "namePlural": "messages" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5291bbf6-1c32-47fe-8164-ebd6dca187ad", - "name": "messageParticipants" - } - } - }, - { - "__typename": "field", - "id": "199bc901-b741-42c5-85dd-4869ce61c879", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e218128f-4d7f-4aa8-9dd2-28849b6c538b", - "type": "TEXT", - "name": "displayName", - "label": "Display Name", - "description": "Display Name", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "71f33a61-2df2-4e23-bdd4-175e572e87ed", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "25cbd116-0230-46f6-88a7-4943ac810ec7", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3ad8eb5c-c148-43f4-89b9-3152b77854e5", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0e8a37ac-fd49-4d07-9695-7a156b5469b7", - "type": "SELECT", - "name": "role", - "label": "Role", - "description": "Role", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'from'", - "options": [ - { - "id": "333b63f9-8a5a-4532-ac53-c03b300fc23e", - "color": "green", - "label": "From", - "value": "from", - "position": 0 - }, - { - "id": "0e980644-befb-4f91-91db-b566c8ff5533", - "color": "blue", - "label": "To", - "value": "to", - "position": 1 - }, - { - "id": "662e29a9-43bd-40ad-a4b7-e728cc2489f0", - "color": "orange", - "label": "Cc", - "value": "cc", - "position": 2 - }, - { - "id": "c3405807-634e-4195-bc58-5d4f0eae8b29", - "color": "red", - "label": "Bcc", - "value": "bcc", - "position": 3 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "dd20415d-fb86-40b6-99bb-25b128d81776", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6c0f1e3e-8aea-4e5d-9298-089a0a3dd0de", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4bef8eac-ecb2-4de2-af0e-7c9e1fca1f06", - "type": "UUID", - "name": "messageId", - "label": "Message id (foreign key)", - "description": "Message id foreign key", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "labelSingular": "Attachment", - "labelPlural": "Attachments", - "description": "An attachment", - "icon": "IconFileImport", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "13649d8b-94c8-40ce-9dbb-9c7ab32a2ed8", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "e985e32a-532f-4259-828f-cac80c5fc3b8", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "Attachment note", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "ac29383b-d63e-4c0e-b28a-1abc03ab2b5a", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "38a2a378-bac0-4c4d-bf05-7f9ff995b860" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ac29383b-d63e-4c0e-b28a-1abc03ab2b5a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e985e32a-532f-4259-828f-cac80c5fc3b8", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "38a2a378-bac0-4c4d-bf05-7f9ff995b860", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "2352488a-4c22-42ac-9645-2ef1cedc80b5", - "type": "UUID", - "name": "activityId", - "label": "Activity id (foreign key)", - "description": "Attachment activity id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c2ace3e1-07b9-4073-b27d-023586dfc0d2", - "type": "TEXT", - "name": "type", - "label": "Type", - "description": "Attachment type", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "df6ee118-1cb0-4b2e-8668-3693d4d87ae2", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Attachment person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "4b90ec4b-3199-4cea-9e8b-01498967bd9f", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "1b21ef27-ba22-46ab-967e-f2d9f780bf8b" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "4b90ec4b-3199-4cea-9e8b-01498967bd9f", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "df6ee118-1cb0-4b2e-8668-3693d4d87ae2", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "1b21ef27-ba22-46ab-967e-f2d9f780bf8b", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "53d23be1-1b1f-4782-900c-3501e5ff1e96", - "type": "TEXT", - "name": "fullPath", - "label": "Full path", - "description": "Attachment full path", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "41623677-7310-44a0-80a2-4a19880bccd1", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "Attachment opportunity id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0f978508-2e4a-4bc6-bbaf-87ad6acbe08a", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "Attachment task", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "aeca7339-1ff5-45cb-b9f4-d8bd9ec572d9", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "7e719850-091f-4876-87b0-4eb5fd9847af" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "aeca7339-1ff5-45cb-b9f4-d8bd9ec572d9", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0f978508-2e4a-4bc6-bbaf-87ad6acbe08a", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "7e719850-091f-4876-87b0-4eb5fd9847af", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "263a372a-3df9-4c57-9e5b-80db73c7b56e", - "type": "UUID", - "name": "authorId", - "label": "Author id (foreign key)", - "description": "Attachment author id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b86a10c8-fc7f-436a-8b05-7b6c618357a7", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d9a522cf-9b09-496d-b5be-a57589c42bc5", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3d2bbb4e-e908-4bc5-97d7-a152dd7652bf", - "type": "RELATION", - "name": "author", - "label": "Author", - "description": "Attachment author", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "c86299f2-7210-4c89-a2ab-29e17f21edc8", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "1b2d1e2c-290d-4a0e-adf9-192e5fac103c" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c86299f2-7210-4c89-a2ab-29e17f21edc8", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3d2bbb4e-e908-4bc5-97d7-a152dd7652bf", - "name": "author" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "1b2d1e2c-290d-4a0e-adf9-192e5fac103c", - "name": "authoredAttachments" - } - } - }, - { - "__typename": "field", - "id": "31bbc876-619d-4444-b954-9b6c66343314", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "Attachment opportunity", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "0ee1046a-3f9f-477e-8811-5d29021eca38", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "b32af3b6-330f-405b-b9ce-6156797f836a" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0ee1046a-3f9f-477e-8811-5d29021eca38", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "31bbc876-619d-4444-b954-9b6c66343314", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b32af3b6-330f-405b-b9ce-6156797f836a", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "3ec97541-3618-453f-b498-e2a0b2d7aee4", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "Attachment note id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2e1b103b-a75b-4ebc-8219-4b59027bd3fd", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": "Attachment myCustomObject", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.173Z", - "updatedAt": "2024-08-05T17:09:54.173Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "bd914a9e-b1f8-43c6-af60-3afe46518988", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "a4580aee-6fb4-4b5d-87c0-daf24745ca13" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bd914a9e-b1f8-43c6-af60-3afe46518988", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2e1b103b-a75b-4ebc-8219-4b59027bd3fd", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a4580aee-6fb4-4b5d-87c0-daf24745ca13", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "c538c173-a98b-4019-b956-ab997255a429", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "13649d8b-94c8-40ce-9dbb-9c7ab32a2ed8", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "Attachment name", - "icon": "IconFileUpload", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "fffa8f0c-6e71-42fa-8127-50c27909efe2", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "Attachment task id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6496b8e0-2d8f-493e-8973-fcba2aa84b59", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Attachment company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "be6051cd-703c-4539-89ed-e643784bad26", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "3a2bd134-5b31-4bde-a64f-d5244a8e6271" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "be6051cd-703c-4539-89ed-e643784bad26", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6496b8e0-2d8f-493e-8973-fcba2aa84b59", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3a2bd134-5b31-4bde-a64f-d5244a8e6271", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "827ed149-e80e-4d73-a687-23e005e20670", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Attachment person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "352954a9-daf9-4d56-9360-51587debc379", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject ID (foreign key)", - "description": "Attachment myCustomObject id foreign key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.172Z", - "updatedAt": "2024-08-05T17:09:54.172Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "394c0644-d8bd-44a8-82c9-6e2a4c9aa19c", - "type": "RELATION", - "name": "activity", - "label": "Activity", - "description": "Attachment activity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "23518310-2443-4907-8ac6-b77bf340d99d", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "d9f1711b-a8b1-48ee-9f81-503bbf945b87" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "23518310-2443-4907-8ac6-b77bf340d99d", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "394c0644-d8bd-44a8-82c9-6e2a4c9aa19c", - "name": "activity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d9f1711b-a8b1-48ee-9f81-503bbf945b87", - "name": "attachments" - } - } - }, - { - "__typename": "field", - "id": "86007c49-92a3-4b62-aa0a-5d6418675b0a", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Attachment company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "task", - "namePlural": "tasks", - "labelSingular": "Task", - "labelPlural": "Tasks", - "description": "A task", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "3a9c10bc-f466-42e3-aa9d-203c8a946955", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "4e474cea-2549-45bc-9c60-4eecff56a186", - "type": "SELECT", - "name": "status", - "label": "Status", - "description": "Task status", - "icon": "IconCheck", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'TODO'", - "options": [ - { - "id": "d6af8120-3e3d-49ba-b6ac-3089e3446b6c", - "color": "sky", - "label": "To do", - "value": "TODO", - "position": 0 - }, - { - "id": "0d66033b-96f3-4128-8182-a25751a50ce2", - "color": "purple", - "label": "In progress", - "value": "IN_PROGESS", - "position": 1 - }, - { - "id": "8e897afd-d233-4943-92c3-89e8979faa9c", - "color": "green", - "label": "Done", - "value": "DONE", - "position": 1 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "53347f0d-658a-45b0-91b5-2088adbeaaf0", - "type": "RELATION", - "name": "assignee", - "label": "Assignee", - "description": "Task assignee", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "5527b9f6-55ec-4efd-b244-03e91b01e91b", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "fefca31b-ba53-4860-b04e-5b9944587693" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5527b9f6-55ec-4efd-b244-03e91b01e91b", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "53347f0d-658a-45b0-91b5-2088adbeaaf0", - "name": "assignee" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fefca31b-ba53-4860-b04e-5b9944587693", - "name": "assignedTasks" - } - } - }, - { - "__typename": "field", - "id": "9233de38-fac9-4df0-bb13-d68c14389a59", - "type": "UUID", - "name": "assigneeId", - "label": "Assignee id (foreign key)", - "description": "Task assignee id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "886d752e-cc9d-43c5-8e73-ee99943ae04c", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7f33f6b1-1c59-4860-ba51-ed0bc3356f06", - "type": "RICH_TEXT", - "name": "body", - "label": "Body", - "description": "Task body", - "icon": "IconFilePencil", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "90f8da4c-865b-4ebe-ae5c-d4377081d8d5", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c7759c16-3319-40b2-873d-84e3d4a1d3ad", - "type": "DATE_TIME", - "name": "dueAt", - "label": "Due Date", - "description": "Task due date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a6c74223-e44c-4677-bde7-e3e06c28fe01", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Task record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7e719850-091f-4876-87b0-4eb5fd9847af", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Task attachments", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "aeca7339-1ff5-45cb-b9f4-d8bd9ec572d9", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "0f978508-2e4a-4bc6-bbaf-87ad6acbe08a" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "aeca7339-1ff5-45cb-b9f4-d8bd9ec572d9", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "7e719850-091f-4876-87b0-4eb5fd9847af", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0f978508-2e4a-4bc6-bbaf-87ad6acbe08a", - "name": "task" - } - } - }, - { - "__typename": "field", - "id": "f1ed6bba-53bc-4f9c-ac40-504a9ff5bade", - "type": "RELATION", - "name": "taskTargets", - "label": "Targets", - "description": "Task targets", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "85f92b6a-bc71-4da4-ba4e-7b0685a05fde", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "31d8d648-5118-4b59-8c1e-876e83bf85f3" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "85f92b6a-bc71-4da4-ba4e-7b0685a05fde", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f1ed6bba-53bc-4f9c-ac40-504a9ff5bade", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "31d8d648-5118-4b59-8c1e-876e83bf85f3", - "name": "task" - } - } - }, - { - "__typename": "field", - "id": "e10938b5-0a72-48b3-8fb1-4984d1bd651b", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "80fe7004-903e-4bdd-985d-9ef7e6acd793", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the task", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "32b10a0d-0ca4-4027-be9e-ab8d8be608d1", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "e7201f19-bfa7-42e1-9550-7c848a842ecc" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "32b10a0d-0ca4-4027-be9e-ab8d8be608d1", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "80fe7004-903e-4bdd-985d-9ef7e6acd793", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e7201f19-bfa7-42e1-9550-7c848a842ecc", - "name": "task" - } - } - }, - { - "__typename": "field", - "id": "3a9c10bc-f466-42e3-aa9d-203c8a946955", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Task title", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "49cf9eb7-53bc-4347-93f5-daec9c219cfa", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the task.", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "9f7f6a7c-072e-4818-8077-d0d0c9601cb0", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "6ea41d58-7eae-4434-bb2f-9a1b2c30dba3" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9f7f6a7c-072e-4818-8077-d0d0c9601cb0", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "49cf9eb7-53bc-4347-93f5-daec9c219cfa", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6ea41d58-7eae-4434-bb2f-9a1b2c30dba3", - "name": "task" - } - } - }, - { - "__typename": "field", - "id": "504f6d88-cdaa-4e7f-beda-14d7e8adf203", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "labelSingular": "Timeline Activity", - "labelPlural": "Timeline Activities", - "description": "Aggregated / filtered event to be displayed on the timeline", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "13cff5d9-b6d4-4eaa-82d3-31c98395deca", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "13cff5d9-b6d4-4eaa-82d3-31c98395deca", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "99599532-c0e9-4d62-b4a6-89866e0374be", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "Event note", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "bc6b24e6-9fcd-43fd-a2ba-c12f5d022132", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "383d3f90-d691-4487-a13d-e80c50fb756e" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bc6b24e6-9fcd-43fd-a2ba-c12f5d022132", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "99599532-c0e9-4d62-b4a6-89866e0374be", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f62992f2-80ef-477c-ae60-fc7a862b0f4a", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "383d3f90-d691-4487-a13d-e80c50fb756e", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "b148030f-e465-4961-9c94-d096dc332bf7", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e86bb958-5af5-4e89-8104-925159a41d79", - "type": "TEXT", - "name": "name", - "label": "Event name", - "description": "Event name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a866ea59-2ff6-4a55-816f-f19927ff742e", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "Event task id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "136cece0-793d-4274-9cc4-f03d5aea0ce0", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject ID (foreign key)", - "description": "Timeline Activity myCustomObject id foreign key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.152Z", - "updatedAt": "2024-08-05T17:09:54.152Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6c46473c-5baa-4795-8eed-3b0649cc9ef0", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "Event opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "dba195e2-63d6-42ca-94aa-42c87b4306ea", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Event workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "170c6f88-63b3-41ff-9e5d-044968a062a4", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "4ae17923-dd16-45c7-9df3-8cee92584a52" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "170c6f88-63b3-41ff-9e5d-044968a062a4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "dba195e2-63d6-42ca-94aa-42c87b4306ea", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4ae17923-dd16-45c7-9df3-8cee92584a52", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "a4101adc-223b-4fa3-a375-b5e49e5a05eb", - "type": "UUID", - "name": "linkedRecordId", - "label": "Linked Record id", - "description": "Linked Record id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "da41fbb2-1e52-416b-be9c-32242ae63e33", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "69e1ecef-09d7-4b53-826e-f440ae72d2b7", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Event person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "ba3d762d-8fbf-45e5-a958-136a269a396d", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "c08e6ba8-b7ef-4fa7-b199-c8e93045f8ee" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ba3d762d-8fbf-45e5-a958-136a269a396d", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "69e1ecef-09d7-4b53-826e-f440ae72d2b7", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c08e6ba8-b7ef-4fa7-b199-c8e93045f8ee", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "6ea41d58-7eae-4434-bb2f-9a1b2c30dba3", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "Event task", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "9f7f6a7c-072e-4818-8077-d0d0c9601cb0", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "49cf9eb7-53bc-4347-93f5-daec9c219cfa" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9f7f6a7c-072e-4818-8077-d0d0c9601cb0", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6ea41d58-7eae-4434-bb2f-9a1b2c30dba3", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "49cf9eb7-53bc-4347-93f5-daec9c219cfa", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "979ea933-d8a1-4db6-8c29-5c747a690326", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Event company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "c542c9e0-b4b6-4073-aae6-66299868e9fb", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "c06142b8-52a9-4b0b-93f6-99e2b5b67ab8" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c542c9e0-b4b6-4073-aae6-66299868e9fb", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "979ea933-d8a1-4db6-8c29-5c747a690326", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c06142b8-52a9-4b0b-93f6-99e2b5b67ab8", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "55701d3c-1710-4f70-ae03-25690249dddf", - "type": "RAW_JSON", - "name": "properties", - "label": "Event details", - "description": "Json value for event details", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ff438247-19b7-4ea6-a00e-1f66b4caa523", - "type": "UUID", - "name": "linkedObjectMetadataId", - "label": "Linked Object Metadata Id", - "description": "inked Object Metadata Id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "faacecdd-08e4-4d9a-b64d-abbac4d5320e", - "type": "TEXT", - "name": "linkedRecordCachedName", - "label": "Linked Record cached name", - "description": "Cached record name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2a612f5a-c6c8-4e82-9368-2ba6f458b4f2", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Event company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "8d4a2a2f-a04f-4cd4-add6-8a417220306e", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "Event note id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e7e04af7-a0a2-4999-9265-e9bafcd0197c", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": "Timeline Activity myCustomObject", - "icon": "IconTimeline", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.153Z", - "updatedAt": "2024-08-05T17:09:54.153Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "e143276e-7f4a-46e8-bf0f-61111f36d4fd", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "e7cd7adb-152e-4d19-b2ba-d1b66bc40e79" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e143276e-7f4a-46e8-bf0f-61111f36d4fd", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e7e04af7-a0a2-4999-9265-e9bafcd0197c", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e7cd7adb-152e-4d19-b2ba-d1b66bc40e79", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "a5a11b28-dc40-42b1-b160-f95e36f25682", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Event person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5494a528-2d5c-402b-b5b0-30b0d30852a1", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Event workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2c3baa6b-7ffe-470e-bd9d-0532e2bce3ac", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "Event opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "61e4edee-13d4-4edd-9101-b9dc5ea5506a", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "713c39d7-63e2-4b0e-bd5c-d240b840255e" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "61e4edee-13d4-4edd-9101-b9dc5ea5506a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2c3baa6b-7ffe-470e-bd9d-0532e2bce3ac", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "713c39d7-63e2-4b0e-bd5c-d240b840255e", - "name": "timelineActivities" - } - } - }, - { - "__typename": "field", - "id": "2371abba-e2a8-42c1-96cf-127f2fd2fddc", - "type": "DATE_TIME", - "name": "happensAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "labelSingular": "Connected Account", - "labelPlural": "Connected Accounts", - "description": "A connected account", - "icon": "IconAt", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "6a63f624-b6fe-4b46-ab94-6d9e327dedf8", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "6b464b10-e402-4862-887c-eccc38af9145", - "type": "UUID", - "name": "accountOwnerId", - "label": "Account Owner id (foreign key)", - "description": "Account Owner id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b392b533-9e94-4c00-8dfd-5183c6a544df", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b6b3881a-852b-42dd-bfe0-65eab4dbcb0a", - "type": "TEXT", - "name": "provider", - "label": "provider", - "description": "The account provider", - "icon": "IconSettings", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7e0a02a3-6d2f-4064-a2fa-e13da62c0e6f", - "type": "TEXT", - "name": "refreshToken", - "label": "Refresh Token", - "description": "Messaging provider refresh token", - "icon": "IconKey", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "55a55985-3e1d-4db6-b0ac-3585d72b69ed", - "type": "RELATION", - "name": "messageChannels", - "label": "Message Channels", - "description": "Message Channels", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "1a74fdd8-63d4-407f-9d25-7e2e6c4d271c", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannel", - "namePlural": "messageChannels", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "252a6670-31ea-4b7a-a75f-09c44f4822be" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1a74fdd8-63d4-407f-9d25-7e2e6c4d271c", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "55a55985-3e1d-4db6-b0ac-3585d72b69ed", - "name": "messageChannels" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "252a6670-31ea-4b7a-a75f-09c44f4822be", - "name": "connectedAccount" - } - } - }, - { - "__typename": "field", - "id": "ff264a3b-dcfa-4a94-aa6b-3416456ca567", - "type": "TEXT", - "name": "handleAliases", - "label": "Handle Aliases", - "description": "Handle Aliases", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "793ca9eb-06ac-433a-b0c3-d62139cbd71c", - "type": "RELATION", - "name": "calendarChannels", - "label": "Calendar Channels", - "description": "Calendar Channels", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "69dde225-0e12-4df6-ab55-d870d6dec717", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "f7f4925d-e186-4fe6-80f5-1ddd1ae5bf22" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "69dde225-0e12-4df6-ab55-d870d6dec717", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "793ca9eb-06ac-433a-b0c3-d62139cbd71c", - "name": "calendarChannels" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f7f4925d-e186-4fe6-80f5-1ddd1ae5bf22", - "name": "connectedAccount" - } - } - }, - { - "__typename": "field", - "id": "044bb29e-1cea-455e-8cd4-76c3aecfe9c5", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6a63f624-b6fe-4b46-ab94-6d9e327dedf8", - "type": "TEXT", - "name": "handle", - "label": "handle", - "description": "The account handle (email, username, phone number, etc.)", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "02ff8c81-8978-4dae-b719-2efed251c95d", - "type": "TEXT", - "name": "accessToken", - "label": "Access Token", - "description": "Messaging provider access token", - "icon": "IconKey", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "8c36e0eb-108e-4797-97a1-b9b5ea096180", - "type": "RELATION", - "name": "accountOwner", - "label": "Account Owner", - "description": "Account Owner", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "9a65de46-ef09-429f-b7ba-31cb8a8c7038", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "4d977e6a-4d0e-4bca-b743-9bc3df1744d6" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9a65de46-ef09-429f-b7ba-31cb8a8c7038", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "8c36e0eb-108e-4797-97a1-b9b5ea096180", - "name": "accountOwner" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4d977e6a-4d0e-4bca-b743-9bc3df1744d6", - "name": "connectedAccounts" - } - } - }, - { - "__typename": "field", - "id": "7aa3c042-1267-4ff7-9dcf-51bf6dafb96d", - "type": "DATE_TIME", - "name": "authFailedAt", - "label": "Auth failed at", - "description": "Auth failed at", - "icon": "IconX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "608ca34b-405b-4b6e-8eaa-7183c45f9b13", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "46ffb6c5-a7fc-4035-bf98-e02f06d67059", - "type": "TEXT", - "name": "lastSyncHistoryId", - "label": "Last sync history ID", - "description": "Last sync history ID", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "view", - "namePlural": "views", - "labelSingular": "View", - "labelPlural": "Views", - "description": "(System) Views", - "icon": "IconLayoutCollage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "1558d329-6983-48af-a136-e5b10f9edd3a", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "fa6d3625-a637-421d-97f6-354c92915ff1", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4a7f5e32-8c16-43fe-a20b-0847e8002a8a", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0d2e0bfe-fe67-4df4-af4f-49722ba4bf96", - "type": "RELATION", - "name": "viewFilters", - "label": "View Filters", - "description": "View Filters", - "icon": "IconFilterBolt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "bd7a6047-3eb5-413e-9315-bb28533c4aed", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "666caea5-3c1e-4847-9fd9-2d8c1d08eabb", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "viewFilter", - "namePlural": "viewFilters", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "c56cc7db-9e19-470e-9d6d-2b7180fb0fb7" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bd7a6047-3eb5-413e-9315-bb28533c4aed", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "nameSingular": "view", - "namePlural": "views" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0d2e0bfe-fe67-4df4-af4f-49722ba4bf96", - "name": "viewFilters" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "666caea5-3c1e-4847-9fd9-2d8c1d08eabb", - "nameSingular": "viewFilter", - "namePlural": "viewFilters" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c56cc7db-9e19-470e-9d6d-2b7180fb0fb7", - "name": "view" - } - } - }, - { - "__typename": "field", - "id": "4c25b9f8-40e3-4889-ab95-551cd9fdfbb6", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0e220989-7171-4776-9045-4cea28effd86", - "type": "TEXT", - "name": "type", - "label": "Type", - "description": "View type", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'table'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1a7b73fc-a1b3-41e1-8971-e11bc73421cf", - "type": "BOOLEAN", - "name": "isCompact", - "label": "Compact View", - "description": "Describes if the view is in compact mode", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": false, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "d8c8b4c5-d58c-4990-9c43-65d8c070d629", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "View position", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6ea01d0e-340e-40e4-a029-89a7cbc07291", - "type": "RELATION", - "name": "viewFields", - "label": "View Fields", - "description": "View Fields", - "icon": "IconTag", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "57d32129-b126-417e-98a8-7f1217b29dea", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "ee025446-440d-49ae-8d0e-ad30b6309840", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "viewField", - "namePlural": "viewFields", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "6725c7ad-a704-436a-be67-a4612bc48e37" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "57d32129-b126-417e-98a8-7f1217b29dea", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "nameSingular": "view", - "namePlural": "views" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6ea01d0e-340e-40e4-a029-89a7cbc07291", - "name": "viewFields" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ee025446-440d-49ae-8d0e-ad30b6309840", - "nameSingular": "viewField", - "namePlural": "viewFields" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6725c7ad-a704-436a-be67-a4612bc48e37", - "name": "view" - } - } - }, - { - "__typename": "field", - "id": "737edb22-8d06-4d16-aac0-4eda04062485", - "type": "TEXT", - "name": "kanbanFieldMetadataId", - "label": "kanbanfieldMetadataId", - "description": "View Kanban column field", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1558d329-6983-48af-a136-e5b10f9edd3a", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "View name", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "8b65e9c3-764d-4569-9d47-0e9146b27802", - "type": "TEXT", - "name": "icon", - "label": "Icon", - "description": "View icon", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b6cb0290-080b-4bab-867a-6d32122d24ad", - "type": "SELECT", - "name": "key", - "label": "Key", - "description": "View key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'INDEX'", - "options": [ - { - "id": "54770bee-85b8-48db-87e9-9ba47fde5b27", - "color": "red", - "label": "Index", - "value": "INDEX", - "position": 0 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "df99390b-b681-4c2b-ba91-8279f0bf0707", - "type": "UUID", - "name": "objectMetadataId", - "label": "Object Metadata Id", - "description": "View target object", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4abadd14-56cd-48e4-8013-7b46de4ffe22", - "type": "RELATION", - "name": "viewSorts", - "label": "View Sorts", - "description": "View Sorts", - "icon": "IconArrowsSort", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "53abf7c2-810d-478b-bb2d-689f31322d67", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "1b5e63b9-9fc3-485d-86ff-de70ff17a665", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "viewSort", - "namePlural": "viewSorts", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "673fb6fb-5123-4336-9b4b-e4b268c1cffe" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "53abf7c2-810d-478b-bb2d-689f31322d67", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "nameSingular": "view", - "namePlural": "views" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4abadd14-56cd-48e4-8013-7b46de4ffe22", - "name": "viewSorts" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1b5e63b9-9fc3-485d-86ff-de70ff17a665", - "nameSingular": "viewSort", - "namePlural": "viewSorts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "673fb6fb-5123-4336-9b4b-e4b268c1cffe", - "name": "view" - } - } - } - ] - }, - { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "labelSingular": "Task Target", - "labelPlural": "Task Targets", - "description": "An task target", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "4d792e46-cd2f-4db4-a348-50f1adbf0ebf", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "85958c6a-882f-4304-947c-45a44fb73585", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "TaskTarget task id foreign key", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "90e006e0-f7b9-49da-acd5-7c36a85e5d53", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "TaskTarget opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "cd786729-40e1-4829-a6ee-9e4bf2e0a04f", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4d792e46-cd2f-4db4-a348-50f1adbf0ebf", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e0094c52-055f-4f11-9334-927f01ac586f", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "TaskTarget person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ea500914-d6c5-45d6-90ef-40c9912c98c2", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "TaskTarget company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "fc1a31f8-6e1c-4ce1-b6ff-80d1cd605e58", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "TaskTarget person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "182b32c3-9ee9-4a65-937b-d9035ab65300", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "4c9ba269-244f-4768-a52d-9b1ffbe3339f" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "182b32c3-9ee9-4a65-937b-d9035ab65300", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fc1a31f8-6e1c-4ce1-b6ff-80d1cd605e58", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4c9ba269-244f-4768-a52d-9b1ffbe3339f", - "name": "taskTargets" - } - } - }, - { - "__typename": "field", - "id": "0cfef76e-8309-4946-bfad-0a400d2327b9", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7c6ab6b0-9978-456b-bb7c-c7c1dc454e3d", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": "TaskTarget myCustomObject", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.181Z", - "updatedAt": "2024-08-05T17:09:54.181Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "3f2b2bab-8411-41b7-a87b-06dd0007eab4", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "90dd4b06-8b21-4411-9f38-b95968a1d4e1" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "3f2b2bab-8411-41b7-a87b-06dd0007eab4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "7c6ab6b0-9978-456b-bb7c-c7c1dc454e3d", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "90dd4b06-8b21-4411-9f38-b95968a1d4e1", - "name": "taskTargets" - } - } - }, - { - "__typename": "field", - "id": "705e4379-9ba2-4853-b267-c86dad461dd7", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "TaskTarget opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "e594dda4-55fc-46ba-8108-5f672a5b1301", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "40cdd413-5239-4887-b5e6-eb32eb1d95e3" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e594dda4-55fc-46ba-8108-5f672a5b1301", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "705e4379-9ba2-4853-b267-c86dad461dd7", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "40cdd413-5239-4887-b5e6-eb32eb1d95e3", - "name": "taskTargets" - } - } - }, - { - "__typename": "field", - "id": "31d8d648-5118-4b59-8c1e-876e83bf85f3", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "TaskTarget task", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "85f92b6a-bc71-4da4-ba4e-7b0685a05fde", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "f1ed6bba-53bc-4f9c-ac40-504a9ff5bade" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "85f92b6a-bc71-4da4-ba4e-7b0685a05fde", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "31d8d648-5118-4b59-8c1e-876e83bf85f3", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f1ed6bba-53bc-4f9c-ac40-504a9ff5bade", - "name": "taskTargets" - } - } - }, - { - "__typename": "field", - "id": "f6566665-bc44-4d92-9e6a-7405e8f505cb", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject ID (foreign key)", - "description": "TaskTarget myCustomObject id foreign key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.180Z", - "updatedAt": "2024-08-05T17:09:54.180Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1e4e3b2b-113f-4af3-aed8-94b03785a626", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "TaskTarget company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "f80bfd64-c33d-4488-bc49-1635e092ea3f", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "cb47633a-1b44-41b9-8bce-16e28616c2ad" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "f80bfd64-c33d-4488-bc49-1635e092ea3f", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "1e4e3b2b-113f-4af3-aed8-94b03785a626", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "cb47633a-1b44-41b9-8bce-16e28616c2ad", - "name": "taskTargets" - } - } - } - ] - }, - { - "__typename": "object", - "id": "666caea5-3c1e-4847-9fd9-2d8c1d08eabb", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "viewFilter", - "namePlural": "viewFilters", - "labelSingular": "View Filter", - "labelPlural": "View Filters", - "description": "(System) View Filters", - "icon": "IconFilterBolt", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "5a3d73f8-918d-49f5-a890-aac2b3163ed2", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "2d97f9a5-4f5b-45d0-aabd-843c7f2ed19b", - "type": "TEXT", - "name": "operand", - "label": "Operand", - "description": "View Filter operand", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'Contains'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "40f77e70-c43b-4f16-8a20-beb0aafd77a0", - "type": "TEXT", - "name": "displayValue", - "label": "Display Value", - "description": "View Filter Display Value", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c56cc7db-9e19-470e-9d6d-2b7180fb0fb7", - "type": "RELATION", - "name": "view", - "label": "View", - "description": "View Filter related view", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "bd7a6047-3eb5-413e-9315-bb28533c4aed", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "view", - "namePlural": "views", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "0d2e0bfe-fe67-4df4-af4f-49722ba4bf96" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bd7a6047-3eb5-413e-9315-bb28533c4aed", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "666caea5-3c1e-4847-9fd9-2d8c1d08eabb", - "nameSingular": "viewFilter", - "namePlural": "viewFilters" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c56cc7db-9e19-470e-9d6d-2b7180fb0fb7", - "name": "view" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "nameSingular": "view", - "namePlural": "views" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0d2e0bfe-fe67-4df4-af4f-49722ba4bf96", - "name": "viewFilters" - } - } - }, - { - "__typename": "field", - "id": "5a3d73f8-918d-49f5-a890-aac2b3163ed2", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f2f27130-bc36-4a22-96eb-a7a3a0aee6c5", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "97ecc896-e994-4822-8758-6f06de23b1d5", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1927b1c6-5531-43f4-9c3d-078aeeedbafc", - "type": "TEXT", - "name": "value", - "label": "Value", - "description": "View Filter value", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6e257f21-2577-46eb-81e1-30b6280411ce", - "type": "UUID", - "name": "viewId", - "label": "View id (foreign key)", - "description": "View Filter related view id foreign key", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "97920c5b-939b-489f-9132-15522c8b2f25", - "type": "UUID", - "name": "fieldMetadataId", - "label": "Field Metadata Id", - "description": "View Filter target field", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "labelSingular": "Activity Target", - "labelPlural": "Activity Targets", - "description": "An activity target", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "ba72ff28-333c-4a4e-a9a7-97625ae1a899", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "aa1c7e04-31c1-4b62-8451-6b32926cab47", - "type": "RELATION", - "name": "activity", - "label": "Activity", - "description": "ActivityTarget activity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "16017cba-688e-4483-a258-9cef3999cbbf", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "41f8fd90-2de9-402f-8b37-fb023d318de2" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "16017cba-688e-4483-a258-9cef3999cbbf", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "aa1c7e04-31c1-4b62-8451-6b32926cab47", - "name": "activity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "41f8fd90-2de9-402f-8b37-fb023d318de2", - "name": "activityTargets" - } - } - }, - { - "__typename": "field", - "id": "702bc8dc-83d5-4367-82e9-a221dcf05687", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "ActivityTarget company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a2e154ce-eb15-4d30-adcf-f8b6f969b007", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "ActivityTarget opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "997b0618-d3f7-4e5c-8c8e-2ba1bad10549", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "ActivityTarget opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "d2a53784-3664-49ab-983e-5ad5bf15dbd0", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "71341870-4e4d-4399-ab74-8f277047664e" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d2a53784-3664-49ab-983e-5ad5bf15dbd0", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "997b0618-d3f7-4e5c-8c8e-2ba1bad10549", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b95b3f38-9fc2-4d7e-a823-7791cf13d089", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "71341870-4e4d-4399-ab74-8f277047664e", - "name": "activityTargets" - } - } - }, - { - "__typename": "field", - "id": "0dbe65bc-b07e-4359-a7ab-c70cdf95dcf7", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "29b26108-6f7e-4424-b430-de1b54a9629a", - "type": "UUID", - "name": "myCustomObjectId", - "label": "myCustomObject ID (foreign key)", - "description": "ActivityTarget myCustomObject id foreign key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.160Z", - "updatedAt": "2024-08-05T17:09:54.160Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f522e7f8-7e9c-4fde-9e8a-1ddd5fa40063", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "ActivityTarget person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5032f1f4-d2ae-46de-bff6-b596a73c0d8c", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ba72ff28-333c-4a4e-a9a7-97625ae1a899", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "10150d34-2f00-4642-8a9d-6b0b6ab72562", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "ActivityTarget company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "2ed70c2c-b17a-4ed1-9f35-b570139440fa", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "4d74b886-b359-4c4c-a2c0-692edc8a3273" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2ed70c2c-b17a-4ed1-9f35-b570139440fa", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "10150d34-2f00-4642-8a9d-6b0b6ab72562", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4d74b886-b359-4c4c-a2c0-692edc8a3273", - "name": "activityTargets" - } - } - }, - { - "__typename": "field", - "id": "940d1664-b17c-4f66-820b-abfec70adaa5", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "ActivityTarget person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "9a3a145b-6d06-4892-84d4-af523f40c58d", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "9b018bba-687b-4850-9e0e-c192d3b5977d" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9a3a145b-6d06-4892-84d4-af523f40c58d", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "940d1664-b17c-4f66-820b-abfec70adaa5", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "9b018bba-687b-4850-9e0e-c192d3b5977d", - "name": "activityTargets" - } - } - }, - { - "__typename": "field", - "id": "d20eb128-2dd6-49e2-ac71-9d8991bc22fb", - "type": "RELATION", - "name": "myCustomObject", - "label": "myCustomObject", - "description": "ActivityTarget myCustomObject", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.161Z", - "updatedAt": "2024-08-05T17:09:54.161Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "1271db29-f60e-4cf2-83cb-b31f62211850", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "7e079b54-1abf-486d-850e-5a5d32fed77b" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1271db29-f60e-4cf2-83cb-b31f62211850", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d20eb128-2dd6-49e2-ac71-9d8991bc22fb", - "name": "myCustomObject" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "7e079b54-1abf-486d-850e-5a5d32fed77b", - "name": "activityTargets" - } - } - }, - { - "__typename": "field", - "id": "23a39b63-86cb-46da-b4a1-a49317ad06f5", - "type": "UUID", - "name": "activityId", - "label": "Activity id (foreign key)", - "description": "ActivityTarget activity id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations", - "labelSingular": "Calendar Channel Event Association", - "labelPlural": "Calendar Channel Event Associations", - "description": "Calendar Channel Event Associations", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "5966ae0a-06c2-4f9e-92e7-e908b4afbcbc", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "94180d42-50ed-48a0-a62b-e00f1a6f4753", - "type": "RELATION", - "name": "calendarChannel", - "label": "Channel ID", - "description": "Channel ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "876e63a4-ce57-4852-b1b7-5659021ea34c", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "0751ede9-2493-4079-b976-14b98a4eb971" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "876e63a4-ce57-4852-b1b7-5659021ea34c", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "94180d42-50ed-48a0-a62b-e00f1a6f4753", - "name": "calendarChannel" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0751ede9-2493-4079-b976-14b98a4eb971", - "name": "calendarChannelEventAssociations" - } - } - }, - { - "__typename": "field", - "id": "c9dfb626-58e2-4aab-986c-4839dc7f5e0b", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2baeedd7-34a0-4d07-ab4c-5e6995213ec5", - "type": "RELATION", - "name": "calendarEvent", - "label": "Event ID", - "description": "Event ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "09476064-1403-4948-84c2-d87a02a022ca", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "46421d40-86ab-4f44-aee4-862320bf7534" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "09476064-1403-4948-84c2-d87a02a022ca", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2baeedd7-34a0-4d07-ab4c-5e6995213ec5", - "name": "calendarEvent" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "46421d40-86ab-4f44-aee4-862320bf7534", - "name": "calendarChannelEventAssociations" - } - } - }, - { - "__typename": "field", - "id": "a00a384b-ab25-4dc5-a778-25d9b9cb8ffd", - "type": "UUID", - "name": "calendarEventId", - "label": "Event ID id (foreign key)", - "description": "Event ID id foreign key", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "fea76c39-2d44-4d78-b346-eec8a9d55102", - "type": "TEXT", - "name": "eventExternalId", - "label": "Event external ID", - "description": "Event external ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5966ae0a-06c2-4f9e-92e7-e908b4afbcbc", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6bec724b-ce56-4ebb-82fb-f2c79c4ef360", - "type": "UUID", - "name": "calendarChannelId", - "label": "Channel ID id (foreign key)", - "description": "Channel ID id foreign key", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "00171466-dba6-4b35-81a5-e37a9d4ea659", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects", - "labelSingular": "myCustomObject", - "labelPlural": "myCustomObjects", - "description": null, - "icon": "IconListNumbers", - "isCustom": true, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "labelIdentifierFieldMetadataId": null, - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "c475ebbc-f86b-4956-9d67-d0bb62062408", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites tied to the myCustomObject", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.168Z", - "updatedAt": "2024-08-05T17:09:54.168Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "143c2257-721f-46eb-8114-987a70979146", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "87c2dd65-2c54-4184-9a19-0bdce7781a3f" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "143c2257-721f-46eb-8114-987a70979146", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c475ebbc-f86b-4956-9d67-d0bb62062408", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "87c2dd65-2c54-4184-9a19-0bdce7781a3f", - "name": "myCustomObject" - } - } - }, - { - "__typename": "field", - "id": "7e079b54-1abf-486d-850e-5a5d32fed77b", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the myCustomObject", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.161Z", - "updatedAt": "2024-08-05T17:09:54.161Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "1271db29-f60e-4cf2-83cb-b31f62211850", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "d20eb128-2dd6-49e2-ac71-9d8991bc22fb" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1271db29-f60e-4cf2-83cb-b31f62211850", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "7e079b54-1abf-486d-850e-5a5d32fed77b", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "648268ca-94bf-418e-853c-56d0f51472b3", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d20eb128-2dd6-49e2-ac71-9d8991bc22fb", - "name": "myCustomObject" - } - } - }, - { - "__typename": "field", - "id": "90dd4b06-8b21-4411-9f38-b95968a1d4e1", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the myCustomObject", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.181Z", - "updatedAt": "2024-08-05T17:09:54.181Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "3f2b2bab-8411-41b7-a87b-06dd0007eab4", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "7c6ab6b0-9978-456b-bb7c-c7c1dc454e3d" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "3f2b2bab-8411-41b7-a87b-06dd0007eab4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "90dd4b06-8b21-4411-9f38-b95968a1d4e1", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "77d124cc-049a-44f9-ab59-56e3dd55bb69", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "7c6ab6b0-9978-456b-bb7c-c7c1dc454e3d", - "name": "myCustomObject" - } - } - }, - { - "__typename": "field", - "id": "13b6535d-d523-4e2b-9ba4-90630173388a", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "9d9aa060-cdfd-4e01-80fc-92549f025a9d", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5842b56f-0029-4205-9ee2-d90bc51f25e5", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "87631266-4a85-4c49-82d1-90d1805c3de6", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the myCustomObject", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.177Z", - "updatedAt": "2024-08-05T17:09:54.177Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "4f4d3969-913b-478c-a41d-9daffc9b2255", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "e884eac3-4cbd-40af-970e-a34b409c0acd" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "4f4d3969-913b-478c-a41d-9daffc9b2255", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "87631266-4a85-4c49-82d1-90d1805c3de6", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "bd4e44a0-4b0d-4392-b0c9-d6c8684e3d44", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e884eac3-4cbd-40af-970e-a34b409c0acd", - "name": "myCustomObject" - } - } - }, - { - "__typename": "field", - "id": "7dd8ba1c-17d8-491b-bc6d-1bf024b38eee", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "Name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'Untitled'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c2a859ac-2667-4f12-8cbd-6cc55e45664f", - "type": "TEXT", - "name": "myCustomField", - "label": "myCustomField", - "description": null, - "icon": "IconUsers", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T17:10:03.185Z", - "updatedAt": "2024-08-05T17:10:03.185Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a4580aee-6fb4-4b5d-87c0-daf24745ca13", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments tied to the myCustomObject", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.173Z", - "updatedAt": "2024-08-05T17:09:54.173Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "bd914a9e-b1f8-43c6-af60-3afe46518988", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "2e1b103b-a75b-4ebc-8219-4b59027bd3fd" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bd914a9e-b1f8-43c6-af60-3afe46518988", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a4580aee-6fb4-4b5d-87c0-daf24745ca13", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2e1b103b-a75b-4ebc-8219-4b59027bd3fd", - "name": "myCustomObject" - } - } - }, - { - "__typename": "field", - "id": "6e5b1581-2e88-44e4-ac0c-2143cc92ad19", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e7cd7adb-152e-4d19-b2ba-d1b66bc40e79", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities tied to the myCustomObject", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T17:09:54.153Z", - "updatedAt": "2024-08-05T17:09:54.153Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "e143276e-7f4a-46e8-bf0f-61111f36d4fd", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "e7e04af7-a0a2-4999-9265-e9bafcd0197c" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e143276e-7f4a-46e8-bf0f-61111f36d4fd", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e7cd7adb-152e-4d19-b2ba-d1b66bc40e79", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e7e04af7-a0a2-4999-9265-e9bafcd0197c", - "name": "myCustomObject" - } - } - }, - { - "__typename": "field", - "id": "dbf144b7-885d-40ae-af3e-3efdb424fe26", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T17:09:54.141Z", - "updatedAt": "2024-08-05T17:09:54.141Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "23006c79-19fe-4148-9ee4-6db039ebc6fb", - "type": "RELATION", - "name": "people", - "label": "people", - "description": null, - "icon": "IconUsers", - "isCustom": true, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T17:10:31.391Z", - "updatedAt": "2024-08-05T17:10:31.391Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "27f9741d-f967-4b75-affa-240f0f5f8d77", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "toFieldMetadataId": "f7002609-5760-4ae6-ba29-a8b9066b95de" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "27f9741d-f967-4b75-affa-240f0f5f8d77", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "56dffccc-daf8-4c49-8919-f19787f07846", - "nameSingular": "myCustomObject", - "namePlural": "myCustomObjects" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "23006c79-19fe-4148-9ee4-6db039ebc6fb", - "name": "people" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f7002609-5760-4ae6-ba29-a8b9066b95de", - "name": "myCustomObject" - } - } - } - ] - }, - { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels", - "labelSingular": "Calendar Channel", - "labelPlural": "Calendar Channels", - "description": "Calendar Channels", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "fc64465a-ab08-4df8-93e2-a19e758e54d8", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "26d457d6-8f93-4813-88fa-78704b780644", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "895be714-df44-4d95-8860-a40ab37bf61d", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "11816da4-27dd-475c-ae34-c578b21d1072", - "type": "DATE_TIME", - "name": "syncStageStartedAt", - "label": "Sync stage started at", - "description": "Sync stage started at", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "17cc8c28-aa8d-43a0-9c11-ccfc43300d57", - "type": "BOOLEAN", - "name": "isContactAutoCreationEnabled", - "label": "Is Contact Auto Creation Enabled", - "description": "Is Contact Auto Creation Enabled", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "bb8528d4-eb52-469b-a87a-895e41fce448", - "type": "NUMBER", - "name": "throttleFailureCount", - "label": "Throttle Failure Count", - "description": "Throttle Failure Count", - "icon": "IconX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": 0, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "cc4fbb8e-3d27-461c-be5e-3b55c3d059d0", - "type": "BOOLEAN", - "name": "isSyncEnabled", - "label": "Is Sync Enabled", - "description": "Is Sync Enabled", - "icon": "IconRefresh", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "fc64465a-ab08-4df8-93e2-a19e758e54d8", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0751ede9-2493-4079-b976-14b98a4eb971", - "type": "RELATION", - "name": "calendarChannelEventAssociations", - "label": "Calendar Channel Event Associations", - "description": "Calendar Channel Event Associations", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "876e63a4-ce57-4852-b1b7-5659021ea34c", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "94180d42-50ed-48a0-a62b-e00f1a6f4753" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "876e63a4-ce57-4852-b1b7-5659021ea34c", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0751ede9-2493-4079-b976-14b98a4eb971", - "name": "calendarChannelEventAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "94180d42-50ed-48a0-a62b-e00f1a6f4753", - "name": "calendarChannel" - } - } - }, - { - "__typename": "field", - "id": "ce4b8d97-0dbc-4e35-b07d-9b76b78b0805", - "type": "SELECT", - "name": "visibility", - "label": "Visibility", - "description": "Visibility", - "icon": "IconEyeglass", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'SHARE_EVERYTHING'", - "options": [ - { - "id": "b6afdf8e-219c-4fa4-b493-2ef201cf08ae", - "color": "green", - "label": "Metadata", - "value": "METADATA", - "position": 0 - }, - { - "id": "1005e275-acda-4842-9b5f-202a82d7eef9", - "color": "orange", - "label": "Share Everything", - "value": "SHARE_EVERYTHING", - "position": 1 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f7f4925d-e186-4fe6-80f5-1ddd1ae5bf22", - "type": "RELATION", - "name": "connectedAccount", - "label": "Connected Account", - "description": "Connected Account", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "69dde225-0e12-4df6-ab55-d870d6dec717", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "793ca9eb-06ac-433a-b0c3-d62139cbd71c" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "69dde225-0e12-4df6-ab55-d870d6dec717", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "3f89df71-38d5-46f4-818f-076a5ee77e48", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f7f4925d-e186-4fe6-80f5-1ddd1ae5bf22", - "name": "connectedAccount" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "793ca9eb-06ac-433a-b0c3-d62139cbd71c", - "name": "calendarChannels" - } - } - }, - { - "__typename": "field", - "id": "fb9fa3ad-8a76-4b35-9e3d-2d70e0bd9b43", - "type": "TEXT", - "name": "syncCursor", - "label": "Sync Cursor", - "description": "Sync Cursor. Used for syncing events from the calendar provider", - "icon": "IconReload", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "cc894f79-0ce0-4534-8874-f6f7b38bcfe8", - "type": "SELECT", - "name": "contactAutoCreationPolicy", - "label": "Contact auto creation policy", - "description": "Automatically create records for people you participated with in an event.", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'AS_PARTICIPANT_AND_ORGANIZER'", - "options": [ - { - "id": "479dcab1-99b1-49db-a398-c838657d694c", - "color": "green", - "label": "As Participant and Organizer", - "value": "AS_PARTICIPANT_AND_ORGANIZER", - "position": 0 - }, - { - "id": "8736e812-170f-46ff-ace4-e16a58a6426d", - "color": "orange", - "label": "As Participant", - "value": "AS_PARTICIPANT", - "position": 1 - }, - { - "id": "afffd87a-0025-4c0e-bd88-6808da2a6d4c", - "color": "blue", - "label": "As Organizer", - "value": "AS_ORGANIZER", - "position": 2 - }, - { - "id": "45145a84-a014-436a-bf88-a174e6da5352", - "color": "red", - "label": "None", - "value": "NONE", - "position": 3 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "87dda3f9-e513-44c1-87f3-1c2b322368e6", - "type": "UUID", - "name": "connectedAccountId", - "label": "Connected Account id (foreign key)", - "description": "Connected Account id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "465d2623-1abb-4587-878c-4752cacf5fc9", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2a2b8f04-c432-4a96-9eb2-7b824b68dfc6", - "type": "SELECT", - "name": "syncStage", - "label": "Sync stage", - "description": "Sync stage", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING'", - "options": [ - { - "id": "37376ca4-6926-4128-9395-9cd599d1dc56", - "color": "blue", - "label": "Full calendar event list fetch pending", - "value": "FULL_CALENDAR_EVENT_LIST_FETCH_PENDING", - "position": 0 - }, - { - "id": "0ee03d31-3ffc-4b2d-9e8d-0eea0179bf04", - "color": "blue", - "label": "Partial calendar event list fetch pending", - "value": "PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING", - "position": 1 - }, - { - "id": "aaa2d5b7-c930-4672-b381-8759b53c3c12", - "color": "orange", - "label": "Calendar event list fetch ongoing", - "value": "CALENDAR_EVENT_LIST_FETCH_ONGOING", - "position": 2 - }, - { - "id": "940eeb35-e2f6-44ca-9b81-cd682b9f4d32", - "color": "blue", - "label": "Calendar events import pending", - "value": "CALENDAR_EVENTS_IMPORT_PENDING", - "position": 3 - }, - { - "id": "ff49a7d8-b7ee-4804-85a3-b0b1641681f2", - "color": "orange", - "label": "Calendar events import ongoing", - "value": "CALENDAR_EVENTS_IMPORT_ONGOING", - "position": 4 - }, - { - "id": "10e8fafb-a086-491e-a6b5-b33bb11e757b", - "color": "red", - "label": "Failed", - "value": "FAILED", - "position": 5 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "335172ff-f683-4cd4-96d0-3120d505ee7e", - "type": "SELECT", - "name": "syncStatus", - "label": "Sync status", - "description": "Sync status", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": [ - { - "id": "427be75a-3309-4ac7-ad9f-6315829ec1de", - "color": "yellow", - "label": "Ongoing", - "value": "ONGOING", - "position": 1 - }, - { - "id": "5caefabb-b384-4d23-84cf-569ae417e0e9", - "color": "blue", - "label": "Not Synced", - "value": "NOT_SYNCED", - "position": 2 - }, - { - "id": "34d49c7c-ea37-4293-ab2c-1d1e68bb0e09", - "color": "green", - "label": "Active", - "value": "ACTIVE", - "position": 3 - }, - { - "id": "b7ed2a50-b048-4f30-b7f8-b586a7e8deef", - "color": "red", - "label": "Failed Insufficient Permissions", - "value": "FAILED_INSUFFICIENT_PERMISSIONS", - "position": 4 - }, - { - "id": "73e4ce2f-f208-482f-b054-85ecb9cbfb9c", - "color": "red", - "label": "Failed Unknown", - "value": "FAILED_UNKNOWN", - "position": 5 - } - ], - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "comment", - "namePlural": "comments", - "labelSingular": "Comment", - "labelPlural": "Comments", - "description": "A comment", - "icon": "IconMessageCircle", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "95c741f7-cf0f-403e-9664-83a052f3934c", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "209c9e5d-c82d-4d30-8fb1-1f7bc70d74ec", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "95c741f7-cf0f-403e-9664-83a052f3934c", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e2400fef-dfb4-4ec8-b83f-705b923b7b00", - "type": "UUID", - "name": "authorId", - "label": "Author id (foreign key)", - "description": "Comment author id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7e3e4ebe-fc63-47c6-b21d-0934b2842806", - "type": "TEXT", - "name": "body", - "label": "Body", - "description": "Comment body", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "239d39c7-de84-462e-b99c-c7e9c1b99d8a", - "type": "UUID", - "name": "activityId", - "label": "Activity id (foreign key)", - "description": "Comment activity id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5a74f15a-2abd-4631-b324-575dd0a81b14", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1a7fec45-dd33-43a0-9302-5b0b9052d2f0", - "type": "RELATION", - "name": "author", - "label": "Author", - "description": "Comment author", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "4917f689-5cc2-4716-b4ab-6906aef009b3", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "12d19915-891e-4a4e-8c42-49a12639264f" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "4917f689-5cc2-4716-b4ab-6906aef009b3", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "nameSingular": "comment", - "namePlural": "comments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "1a7fec45-dd33-43a0-9302-5b0b9052d2f0", - "name": "author" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "12d19915-891e-4a4e-8c42-49a12639264f", - "name": "authoredComments" - } - } - }, - { - "__typename": "field", - "id": "88c3a2b9-b59a-413a-b2d3-44b151185929", - "type": "RELATION", - "name": "activity", - "label": "Activity", - "description": "Comment activity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "00b07eda-840c-4a91-a8f7-365c008a2ea1", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "9045116d-0fed-433c-80a4-f4296db72ae5" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "00b07eda-840c-4a91-a8f7-365c008a2ea1", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "nameSingular": "comment", - "namePlural": "comments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "88c3a2b9-b59a-413a-b2d3-44b151185929", - "name": "activity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "9045116d-0fed-433c-80a4-f4296db72ae5", - "name": "comments" - } - } - } - ] - }, - { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents", - "labelSingular": "Calendar event", - "labelPlural": "Calendar events", - "description": "Calendar events", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "c84c6690-4785-4487-a164-75b35fa6b5ed", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "2563cdaf-19b2-4ca7-bea7-d233228ac87b", - "type": "TEXT", - "name": "description", - "label": "Description", - "description": "Description", - "icon": "IconFileDescription", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f67e0a42-d909-4029-b740-ed4ba6fef8d2", - "type": "BOOLEAN", - "name": "isCanceled", - "label": "Is canceled", - "description": "Is canceled", - "icon": "IconCalendarCancel", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": false, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "21f11229-c9a8-4d90-8f78-8803296de422", - "type": "DATE_TIME", - "name": "endsAt", - "label": "End Date", - "description": "End Date", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "3f88228c-6666-4c18-b4c3-2355e9fb74fd", - "type": "TEXT", - "name": "iCalUID", - "label": "iCal UID", - "description": "iCal UID", - "icon": "IconKey", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b9ff2603-b060-47f7-8b74-367411c97043", - "type": "DATE_TIME", - "name": "externalCreatedAt", - "label": "Creation DateTime", - "description": "Creation DateTime", - "icon": "IconCalendarPlus", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "65f9e0fd-c875-43e0-9988-94dcd1105951", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e4b6323e-2faa-472a-b369-394b7682f7f1", - "type": "BOOLEAN", - "name": "isFullDay", - "label": "Is Full Day", - "description": "Is Full Day", - "icon": "Icon24Hours", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": false, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "eec86c3b-f7ac-4066-ae3e-f7add17f1f97", - "type": "TEXT", - "name": "location", - "label": "Location", - "description": "Location", - "icon": "IconMapPin", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "46421d40-86ab-4f44-aee4-862320bf7534", - "type": "RELATION", - "name": "calendarChannelEventAssociations", - "label": "Calendar Channel Event Associations", - "description": "Calendar Channel Event Associations", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "09476064-1403-4948-84c2-d87a02a022ca", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "2baeedd7-34a0-4d07-ab4c-5e6995213ec5" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "09476064-1403-4948-84c2-d87a02a022ca", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "46421d40-86ab-4f44-aee4-862320bf7534", - "name": "calendarChannelEventAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "5b55de69-76d8-4170-94d3-ff85ee7640ca", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2baeedd7-34a0-4d07-ab4c-5e6995213ec5", - "name": "calendarEvent" - } - } - }, - { - "__typename": "field", - "id": "c84c6690-4785-4487-a164-75b35fa6b5ed", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Title", - "icon": "IconH1", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "26107044-238f-49dc-89ce-179b46450864", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "57f8f510-2486-47cf-aa05-b10c14f3cc43", - "type": "LINKS", - "name": "conferenceLink", - "label": "Meet Link", - "description": "Meet Link", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "75f5a937-b2c8-4225-bbd6-c8b575e2dd25", - "type": "DATE_TIME", - "name": "startsAt", - "label": "Start Date", - "description": "Start Date", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e286138c-24c0-49d9-8f51-41d47f7958cd", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "849a0245-051d-4dac-8ecf-f35462912b3f", - "type": "DATE_TIME", - "name": "externalUpdatedAt", - "label": "Update DateTime", - "description": "Update DateTime", - "icon": "IconCalendarCog", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c9a2189f-abb1-4166-9d1d-f870f0e32b3e", - "type": "RELATION", - "name": "calendarEventParticipants", - "label": "Event Participants", - "description": "Event Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "28688620-c3df-463d-a655-ad6435f6215b", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "9ae2ccf9-1390-4861-a771-324ab4310f33" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "28688620-c3df-463d-a655-ad6435f6215b", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c9a2189f-abb1-4166-9d1d-f870f0e32b3e", - "name": "calendarEventParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "9ae2ccf9-1390-4861-a771-324ab4310f33", - "name": "calendarEvent" - } - } - }, - { - "__typename": "field", - "id": "cb31cbcb-b866-46d9-aeda-4b4aacd32e6e", - "type": "TEXT", - "name": "conferenceSolution", - "label": "Conference Solution", - "description": "Conference Solution", - "icon": "IconScreenShare", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c1a46da5-904c-4883-8cf1-730ecd860a18", - "type": "TEXT", - "name": "recurringEventExternalId", - "label": "Recurring Event ID", - "description": "Recurring Event ID", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannel", - "namePlural": "messageChannels", - "labelSingular": "Message Channel", - "labelPlural": "Message Channels", - "description": "Message Channels", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "ee88f9a9-318c-44ce-ba9e-3d64c740e090", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "47b231aa-01e2-49e0-bafb-d2b63a153265", - "type": "NUMBER", - "name": "throttleFailureCount", - "label": "Throttle Failure Count", - "description": "Throttle Failure Count", - "icon": "IconX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": 0, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "2821a085-4008-4b66-a99d-f3c2e1557967", - "type": "SELECT", - "name": "type", - "label": "Type", - "description": "Channel Type", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'email'", - "options": [ - { - "id": "08b1d086-9a6f-4343-8f13-2201c1310f5e", - "color": "green", - "label": "Email", - "value": "email", - "position": 0 - }, - { - "id": "2cef0d80-3db0-4793-b849-650cca4d5021", - "color": "blue", - "label": "SMS", - "value": "sms", - "position": 1 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b4d39140-3163-4a87-98fe-bb9e8cc137d8", - "type": "DATE_TIME", - "name": "syncStageStartedAt", - "label": "Sync stage started at", - "description": "Sync stage started at", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6485d1ba-0c12-4843-bef8-2ecd53074e7d", - "type": "UUID", - "name": "connectedAccountId", - "label": "Connected Account id (foreign key)", - "description": "Connected Account id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "608b0c0a-a828-44e8-9491-e58507090911", - "type": "SELECT", - "name": "syncStatus", - "label": "Sync status", - "description": "Sync status", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": [ - { - "id": "3b0b0655-df75-40cc-b2a3-5b0a44d4e89e", - "color": "yellow", - "label": "Ongoing", - "value": "ONGOING", - "position": 1 - }, - { - "id": "668d19e4-a5f7-471b-aa2d-5b9ee0bd38a4", - "color": "blue", - "label": "Not Synced", - "value": "NOT_SYNCED", - "position": 2 - }, - { - "id": "5d0b907a-0f0d-48ef-971e-6da5c8c6cb08", - "color": "green", - "label": "Active", - "value": "ACTIVE", - "position": 3 - }, - { - "id": "919a86ec-634a-4d12-8a70-0da59eed2ed7", - "color": "red", - "label": "Failed Insufficient Permissions", - "value": "FAILED_INSUFFICIENT_PERMISSIONS", - "position": 4 - }, - { - "id": "360e055a-314f-4e1f-b1a3-bde1cb3a3743", - "color": "red", - "label": "Failed Unknown", - "value": "FAILED_UNKNOWN", - "position": 5 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "898058fb-b487-4300-a3d7-a9f5d7efc928", - "type": "TEXT", - "name": "syncCursor", - "label": "Last sync cursor", - "description": "Last sync cursor", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ee851ccd-e643-40aa-9553-bb0487d4b4b9", - "type": "BOOLEAN", - "name": "isContactAutoCreationEnabled", - "label": "Is Contact Auto Creation Enabled", - "description": "Is Contact Auto Creation Enabled", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "60c85385-7576-4f68-a3a3-4539f9a79f14", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7dc2ea04-202c-4f02-a302-6438d5100423", - "type": "SELECT", - "name": "visibility", - "label": "Visibility", - "description": "Visibility", - "icon": "IconEyeglass", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'SHARE_EVERYTHING'", - "options": [ - { - "id": "30bf3541-7afe-4a39-a070-79b85f6de6ce", - "color": "green", - "label": "Metadata", - "value": "METADATA", - "position": 0 - }, - { - "id": "edb11f69-2cda-4959-9fd2-0629f8d9d4c5", - "color": "blue", - "label": "Subject", - "value": "SUBJECT", - "position": 1 - }, - { - "id": "5728b6b0-59fc-4def-ae0a-6aa261a18ad9", - "color": "orange", - "label": "Share Everything", - "value": "SHARE_EVERYTHING", - "position": 2 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1987d97a-4dd3-4d12-a991-8e514f6999ca", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ee88f9a9-318c-44ce-ba9e-3d64c740e090", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6a84ba01-5f11-40bf-99e4-a5a7e9a8dadb", - "type": "DATE_TIME", - "name": "syncedAt", - "label": "Last sync date", - "description": "Last sync date", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "252a6670-31ea-4b7a-a75f-09c44f4822be", - "type": "RELATION", - "name": "connectedAccount", - "label": "Connected Account", - "description": "Connected Account", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "1a74fdd8-63d4-407f-9d25-7e2e6c4d271c", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "55a55985-3e1d-4db6-b0ac-3585d72b69ed" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1a74fdd8-63d4-407f-9d25-7e2e6c4d271c", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "252a6670-31ea-4b7a-a75f-09c44f4822be", - "name": "connectedAccount" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "55a55985-3e1d-4db6-b0ac-3585d72b69ed", - "name": "messageChannels" - } - } - }, - { - "__typename": "field", - "id": "2682d5c3-f05e-4c5c-87eb-bb1a6c0c37bb", - "type": "RELATION", - "name": "messageChannelMessageAssociations", - "label": "Message Channel Association", - "description": "Messages from the channel.", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "e420b731-e1e1-425a-ac7a-488d37d1958b", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "f2561dd5-c695-4635-816c-27175470b285" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e420b731-e1e1-425a-ac7a-488d37d1958b", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "219d7acf-5934-44dc-8789-62ade666cb43", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2682d5c3-f05e-4c5c-87eb-bb1a6c0c37bb", - "name": "messageChannelMessageAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d0f0efa4-9f44-4812-96f9-d91ee933a5e8", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f2561dd5-c695-4635-816c-27175470b285", - "name": "messageChannel" - } - } - }, - { - "__typename": "field", - "id": "6484b400-3a26-4e67-94d4-f286e758d32d", - "type": "SELECT", - "name": "syncStage", - "label": "Sync stage", - "description": "Sync stage", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'FULL_MESSAGE_LIST_FETCH_PENDING'", - "options": [ - { - "id": "542073b7-5d8d-456a-9f97-c4318c965ee1", - "color": "blue", - "label": "Full messages list fetch pending", - "value": "FULL_MESSAGE_LIST_FETCH_PENDING", - "position": 0 - }, - { - "id": "9b6e03b6-7f79-4af9-adc6-be179c7e12ba", - "color": "blue", - "label": "Partial messages list fetch pending", - "value": "PARTIAL_MESSAGE_LIST_FETCH_PENDING", - "position": 1 - }, - { - "id": "1e551bc2-cc65-4b02-9538-3964763ed964", - "color": "orange", - "label": "Messages list fetch ongoing", - "value": "MESSAGE_LIST_FETCH_ONGOING", - "position": 2 - }, - { - "id": "d9fb2786-ccbb-4c26-a8e8-efa09cec9779", - "color": "blue", - "label": "Messages import pending", - "value": "MESSAGES_IMPORT_PENDING", - "position": 3 - }, - { - "id": "a0c3a8c3-be71-4b7e-9fbd-79e9d564e033", - "color": "orange", - "label": "Messages import ongoing", - "value": "MESSAGES_IMPORT_ONGOING", - "position": 4 - }, - { - "id": "0bea2ea8-99cf-4a04-80a7-197022bab014", - "color": "red", - "label": "Failed", - "value": "FAILED", - "position": 5 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5d8b9142-82f7-44cc-931b-457a7895c864", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "53050215-3982-4ed7-857f-6089bb66e63e", - "type": "BOOLEAN", - "name": "excludeGroupEmails", - "label": "Exclude group emails", - "description": "Exclude group emails", - "icon": "IconUsersGroup", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "95465535-60f1-4a23-8c0d-0e3c98b986da", - "type": "BOOLEAN", - "name": "excludeNonProfessionalEmails", - "label": "Exclude non professional emails", - "description": "Exclude non professional emails", - "icon": "IconBriefcase", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "71179534-e47a-4f19-916e-adad2e0360c8", - "type": "SELECT", - "name": "contactAutoCreationPolicy", - "label": "Contact auto creation policy", - "description": "Automatically create People records when receiving or sending emails", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'SENT'", - "options": [ - { - "id": "61e4a068-f941-4951-940b-4534b55036e5", - "color": "green", - "label": "Sent and Received", - "value": "SENT_AND_RECEIVED", - "position": 0 - }, - { - "id": "8922afcf-f166-48cd-bdbe-1fc29cbc9d83", - "color": "blue", - "label": "Sent", - "value": "SENT", - "position": 1 - }, - { - "id": "e992588f-fb3c-483c-9bd8-3798c944246b", - "color": "red", - "label": "None", - "value": "NONE", - "position": 2 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "697a053e-b751-469e-a46a-c1d9ca189ed0", - "type": "BOOLEAN", - "name": "isSyncEnabled", - "label": "Is Sync Enabled", - "description": "Is Sync Enabled", - "icon": "IconRefresh", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": true, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "labelSingular": "Calendar event participant", - "labelPlural": "Calendar event participants", - "description": "Calendar event participants", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "40ddb08c-2b24-429b-8c38-538aa6793d9e", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "57c875cf-6453-4e41-9bd5-3c804464de3b", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Workspace Member id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "cc3faae7-be01-435f-aafb-835e0f7cd8e4", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "00b58d77-0409-4fb0-a6b4-7a4b4f4ec71b", - "type": "UUID", - "name": "calendarEventId", - "label": "Event ID id (foreign key)", - "description": "Event ID id foreign key", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "40ddb08c-2b24-429b-8c38-538aa6793d9e", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b2982cd8-c796-4718-b74b-298b46d19841", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Workspace Member", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "67aaa999-8332-43ba-8830-76bf48d53cf2", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "6623a9d7-e137-4709-a592-02ae76e5bfd7" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "67aaa999-8332-43ba-8830-76bf48d53cf2", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b2982cd8-c796-4718-b74b-298b46d19841", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6623a9d7-e137-4709-a592-02ae76e5bfd7", - "name": "calendarEventParticipants" - } - } - }, - { - "__typename": "field", - "id": "00578ebe-8d35-4f34-8f67-02485d704025", - "type": "SELECT", - "name": "responseStatus", - "label": "Response Status", - "description": "Response Status", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'NEEDS_ACTION'", - "options": [ - { - "id": "fd0a498b-4600-41c1-9a96-cebe90c41a55", - "color": "orange", - "label": "Needs Action", - "value": "NEEDS_ACTION", - "position": 0 - }, - { - "id": "81a5956c-b7d4-45a2-afde-0f956ce68aee", - "color": "red", - "label": "Declined", - "value": "DECLINED", - "position": 1 - }, - { - "id": "4adf3c41-f7a4-4614-8226-0ce0918c0503", - "color": "yellow", - "label": "Tentative", - "value": "TENTATIVE", - "position": 2 - }, - { - "id": "23c5a1c2-1d16-40ce-a747-660be35bd518", - "color": "green", - "label": "Accepted", - "value": "ACCEPTED", - "position": 3 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "da6e6808-841d-4079-b050-a2d59e7b1a37", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "bd330d82-e102-43ed-88fe-caf5abe486f4", - "type": "TEXT", - "name": "displayName", - "label": "Display Name", - "description": "Display Name", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6cf6873a-af1e-46ab-aacd-80b2254b0239", - "type": "BOOLEAN", - "name": "isOrganizer", - "label": "Is Organizer", - "description": "Is Organizer", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": false, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "61840181-5ec1-4e0f-a133-b705d19a38ff", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "9ae2ccf9-1390-4861-a771-324ab4310f33", - "type": "RELATION", - "name": "calendarEvent", - "label": "Event ID", - "description": "Event ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "28688620-c3df-463d-a655-ad6435f6215b", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "c9a2189f-abb1-4166-9d1d-f870f0e32b3e" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "28688620-c3df-463d-a655-ad6435f6215b", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "9ae2ccf9-1390-4861-a771-324ab4310f33", - "name": "calendarEvent" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "37d40c3f-e106-4348-af22-201659bbd8a6", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c9a2189f-abb1-4166-9d1d-f870f0e32b3e", - "name": "calendarEventParticipants" - } - } - }, - { - "__typename": "field", - "id": "a7eb211d-4481-4269-99d7-cf2183b45598", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "20d67b64-4e67-44a1-81c7-116c0c8c6368", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - }, - "fromFieldMetadataId": "d44bf743-b557-47d4-9341-04114fd05d52" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "20d67b64-4e67-44a1-81c7-116c0c8c6368", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a7eb211d-4481-4269-99d7-cf2183b45598", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ff2881da-89f6-4f15-8f0a-e3f355ea3b94", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d44bf743-b557-47d4-9341-04114fd05d52", - "name": "calendarEventParticipants" - } - } - }, - { - "__typename": "field", - "id": "eb0946e3-084e-477f-8aba-3c88ed29cf3b", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "labelSingular": "Workspace Member", - "labelPlural": "Workspace Members", - "description": "A workspace member", - "icon": "IconUserCircle", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "db603745-ca4c-4a32-bb0d-d475216111d9", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "b97b813e-dc34-4c16-b7d3-7dee169c3f11", - "type": "UUID", - "name": "userId", - "label": "User Id", - "description": "Associated User Id", - "icon": "IconCircleUsers", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "12d19915-891e-4a4e-8c42-49a12639264f", - "type": "RELATION", - "name": "authoredComments", - "label": "Authored comments", - "description": "Authored comments", - "icon": "IconComment", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "4917f689-5cc2-4716-b4ab-6906aef009b3", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "comment", - "namePlural": "comments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "1a7fec45-dd33-43a0-9302-5b0b9052d2f0" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "4917f689-5cc2-4716-b4ab-6906aef009b3", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "12d19915-891e-4a4e-8c42-49a12639264f", - "name": "authoredComments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "3af96291-b873-402f-bd90-f4731984c8dd", - "nameSingular": "comment", - "namePlural": "comments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "1a7fec45-dd33-43a0-9302-5b0b9052d2f0", - "name": "author" - } - } - }, - { - "__typename": "field", - "id": "5e889b07-de1e-47f0-aeb9-301a684bd6a4", - "type": "RELATION", - "name": "authoredActivities", - "label": "Authored activities", - "description": "Activities created by the workspace member", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "6d4e8025-7ee9-4079-ae80-b18de7b5ff4e", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "beac3449-af10-43a2-9abb-276a798df3de" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "6d4e8025-7ee9-4079-ae80-b18de7b5ff4e", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5e889b07-de1e-47f0-aeb9-301a684bd6a4", - "name": "authoredActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "beac3449-af10-43a2-9abb-276a798df3de", - "name": "author" - } - } - }, - { - "__typename": "field", - "id": "dd7ee456-52bf-4335-bee9-7ba18a1e9a09", - "type": "RELATION", - "name": "messageParticipants", - "label": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "94c22c13-b00a-4f60-b2d2-f34b9efe6aa2", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "a7036ff9-a86d-4290-9f2a-cc360c86fe1e" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "94c22c13-b00a-4f60-b2d2-f34b9efe6aa2", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "dd7ee456-52bf-4335-bee9-7ba18a1e9a09", - "name": "messageParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b889efa2-e58a-471c-b258-3c5ef2fa09e9", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a7036ff9-a86d-4290-9f2a-cc360c86fe1e", - "name": "workspaceMember" - } - } - }, - { - "__typename": "field", - "id": "de44f939-76d9-4c1a-96aa-7c5a646f2045", - "type": "RELATION", - "name": "accountOwnerForCompanies", - "label": "Account Owner For Companies", - "description": "Account owner for companies", - "icon": "IconBriefcase", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "0896a728-e2cf-4032-9af2-a471645e9697", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - }, - "toFieldMetadataId": "3ece1b4d-c052-4b32-bd2a-ba0f8c8b6f3e" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0896a728-e2cf-4032-9af2-a471645e9697", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "de44f939-76d9-4c1a-96aa-7c5a646f2045", - "name": "accountOwnerForCompanies" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "f1231579-8e7d-4b84-9a60-41844902f2c4", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3ece1b4d-c052-4b32-bd2a-ba0f8c8b6f3e", - "name": "accountOwner" - } - } - }, - { - "__typename": "field", - "id": "45b45740-d6cd-476c-af07-f6ed323953b6", - "type": "RELATION", - "name": "auditLogs", - "label": "Audit Logs", - "description": "Audit Logs linked to the workspace member", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "025cb05b-3bdb-4418-8a07-8b7a8c22dbc1", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "189129d8-8037-4edf-9c91-63001ab52370", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "auditLog", - "namePlural": "auditLogs", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "0e09a491-d3bd-4a23-9c50-cda32acbc7ef" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "025cb05b-3bdb-4418-8a07-8b7a8c22dbc1", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "45b45740-d6cd-476c-af07-f6ed323953b6", - "name": "auditLogs" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "189129d8-8037-4edf-9c91-63001ab52370", - "nameSingular": "auditLog", - "namePlural": "auditLogs" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0e09a491-d3bd-4a23-9c50-cda32acbc7ef", - "name": "workspaceMember" - } - } - }, - { - "__typename": "field", - "id": "956a552e-b573-4d31-afd4-b65cb8f2b4b8", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "1b2d1e2c-290d-4a0e-adf9-192e5fac103c", - "type": "RELATION", - "name": "authoredAttachments", - "label": "Authored attachments", - "description": "Attachments created by the workspace member", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "c86299f2-7210-4c89-a2ab-29e17f21edc8", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "3d2bbb4e-e908-4bc5-97d7-a152dd7652bf" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c86299f2-7210-4c89-a2ab-29e17f21edc8", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "1b2d1e2c-290d-4a0e-adf9-192e5fac103c", - "name": "authoredAttachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "9a53b4e1-bce2-4160-8ce3-028e14b2abb7", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3d2bbb4e-e908-4bc5-97d7-a152dd7652bf", - "name": "author" - } - } - }, - { - "__typename": "field", - "id": "89b50259-5ed6-4504-9c89-3f4457dc43a6", - "type": "RELATION", - "name": "blocklist", - "label": "Blocklist", - "description": "Blocklisted handles", - "icon": "IconForbid2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "d9eb657a-f97b-4cec-af79-0e113d47279b", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "033ae6fd-c59e-475e-ba93-bbc1b2b185a5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "blocklist", - "namePlural": "blocklists", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "597169c3-ad77-4a48-8a2a-94b7cc155e25" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d9eb657a-f97b-4cec-af79-0e113d47279b", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "89b50259-5ed6-4504-9c89-3f4457dc43a6", - "name": "blocklist" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "033ae6fd-c59e-475e-ba93-bbc1b2b185a5", - "nameSingular": "blocklist", - "namePlural": "blocklists" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "597169c3-ad77-4a48-8a2a-94b7cc155e25", - "name": "workspaceMember" - } - } - }, - { - "__typename": "field", - "id": "aa2d23d6-1303-4347-b252-48dd9f9bd52b", - "type": "SELECT", - "name": "dateFormat", - "label": "Date format", - "description": "User's preferred date format", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'SYSTEM'", - "options": [ - { - "id": "6a0b0a55-082b-4d1e-ac29-2d423a05744c", - "color": "turquoise", - "label": "System", - "value": "SYSTEM", - "position": 0 - }, - { - "id": "eee2180b-4f0e-41ef-9a6a-2e2938322270", - "color": "red", - "label": "Month First", - "value": "MONTH_FIRST", - "position": 1 - }, - { - "id": "4cbf15d8-a63c-4615-ad5d-74e798199ffd", - "color": "purple", - "label": "Day First", - "value": "DAY_FIRST", - "position": 2 - }, - { - "id": "c391f77e-7728-4369-ad35-60a1d84ee49e", - "color": "sky", - "label": "Year First", - "value": "YEAR_FIRST", - "position": 3 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "95db483c-ff8c-430f-a995-de4f96fff94b", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "ddadaf73-086d-4453-b631-5e16afce87b5", - "type": "TEXT", - "name": "locale", - "label": "Language", - "description": "Preferred language", - "icon": "IconLanguage", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'en'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6623a9d7-e137-4709-a592-02ae76e5bfd7", - "type": "RELATION", - "name": "calendarEventParticipants", - "label": "Calendar Event Participants", - "description": "Calendar Event Participants", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "67aaa999-8332-43ba-8830-76bf48d53cf2", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "b2982cd8-c796-4718-b74b-298b46d19841" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "67aaa999-8332-43ba-8830-76bf48d53cf2", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6623a9d7-e137-4709-a592-02ae76e5bfd7", - "name": "calendarEventParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2128a43e-af47-44bf-b7e9-5d00ddd27a99", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b2982cd8-c796-4718-b74b-298b46d19841", - "name": "workspaceMember" - } - } - }, - { - "__typename": "field", - "id": "7b895d3d-e6df-4b0e-8497-28d91431de59", - "type": "TEXT", - "name": "avatarUrl", - "label": "Avatar Url", - "description": "Workspace member avatar", - "icon": "IconFileUpload", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4d977e6a-4d0e-4bca-b743-9bc3df1744d6", - "type": "RELATION", - "name": "connectedAccounts", - "label": "Connected accounts", - "description": "Connected accounts", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "9a65de46-ef09-429f-b7ba-31cb8a8c7038", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "8c36e0eb-108e-4797-97a1-b9b5ea096180" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "9a65de46-ef09-429f-b7ba-31cb8a8c7038", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4d977e6a-4d0e-4bca-b743-9bc3df1744d6", - "name": "connectedAccounts" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "90e63030-f26d-46c8-b27a-13686b717538", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "8c36e0eb-108e-4797-97a1-b9b5ea096180", - "name": "accountOwner" - } - } - }, - { - "__typename": "field", - "id": "156aa42f-667a-46aa-9aea-ff8472f28509", - "type": "TEXT", - "name": "timeZone", - "label": "Time zone", - "description": "User time zone", - "icon": "IconTimezone", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'system'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "fefca31b-ba53-4860-b04e-5b9944587693", - "type": "RELATION", - "name": "assignedTasks", - "label": "Assigned tasks", - "description": "Tasks assigned to the workspace member", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "5527b9f6-55ec-4efd-b244-03e91b01e91b", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - }, - "toFieldMetadataId": "53347f0d-658a-45b0-91b5-2088adbeaaf0" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5527b9f6-55ec-4efd-b244-03e91b01e91b", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fefca31b-ba53-4860-b04e-5b9944587693", - "name": "assignedTasks" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "99f8caa6-263c-4690-8dc0-eb7645304cf5", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "53347f0d-658a-45b0-91b5-2088adbeaaf0", - "name": "assignee" - } - } - }, - { - "__typename": "field", - "id": "db603745-ca4c-4a32-bb0d-d475216111d9", - "type": "FULL_NAME", - "name": "name", - "label": "Name", - "description": "Workspace member name", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": { - "lastName": "''", - "firstName": "''" - }, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "83def86f-9dbd-4606-a7a1-844c1d0f3080", - "type": "TEXT", - "name": "userEmail", - "label": "User Email", - "description": "Related user email address", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a147a0df-eb28-4259-a304-0460f92adf30", - "type": "RELATION", - "name": "assignedActivities", - "label": "Assigned activities", - "description": "Activities assigned to the workspace member", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "cf9ac76a-9f22-4252-a00a-63cc45fcabc4", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "ea9aa19c-22d8-4b72-83ff-78d9653c27c4" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "cf9ac76a-9f22-4252-a00a-63cc45fcabc4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a147a0df-eb28-4259-a304-0460f92adf30", - "name": "assignedActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "cf6f8138-3445-4a36-b137-41ebb8f2e3dc", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ea9aa19c-22d8-4b72-83ff-78d9653c27c4", - "name": "assignee" - } - } - }, - { - "__typename": "field", - "id": "56975f55-db1f-464f-b03e-2ecadb8b59cd", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f537669a-4524-4dfc-91d3-79438e2a481e", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the workspace member", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "b0f40da3-1fda-4803-be21-14a2755bc834", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "407a2cbc-6c15-41dd-942c-5322d273bec3" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "b0f40da3-1fda-4803-be21-14a2755bc834", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f537669a-4524-4dfc-91d3-79438e2a481e", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d19be8c8-2cf4-4c29-80ae-0d1841dc11c1", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "407a2cbc-6c15-41dd-942c-5322d273bec3", - "name": "workspaceMember" - } - } - }, - { - "__typename": "field", - "id": "f1374fe7-1b98-4868-96b0-63d64996e397", - "type": "SELECT", - "name": "timeFormat", - "label": "Time format", - "description": "User's preferred time format", - "icon": "IconClock2", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'SYSTEM'", - "options": [ - { - "id": "91233e08-341a-4dfd-bb89-450a4f40c579", - "color": "sky", - "label": "System", - "value": "SYSTEM", - "position": 0 - }, - { - "id": "9e680299-7bee-432a-9e65-dfa9ad270769", - "color": "red", - "label": "24HRS", - "value": "HOUR_24", - "position": 1 - }, - { - "id": "c1d9ba3d-291b-4636-9909-14e41a5812db", - "color": "purple", - "label": "12HRS", - "value": "HOUR_12", - "position": 2 - } - ], - "relationDefinition": null - }, - { - "__typename": "field", - "id": "6c5481e3-b9a4-4298-b011-14dfc7ed3be4", - "type": "TEXT", - "name": "colorScheme", - "label": "Color Scheme", - "description": "Preferred color scheme", - "icon": "IconColorSwatch", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'Light'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "4ae17923-dd16-45c7-9df3-8cee92584a52", - "type": "RELATION", - "name": "timelineActivities", - "label": "Events", - "description": "Events linked to the workspace member", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": { - "__typename": "relation", - "id": "170c6f88-63b3-41ff-9e5d-044968a062a4", - "relationType": "ONE_TO_MANY", - "toObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - }, - "toFieldMetadataId": "dba195e2-63d6-42ca-94aa-42c87b4306ea" - }, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "170c6f88-63b3-41ff-9e5d-044968a062a4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4ae17923-dd16-45c7-9df3-8cee92584a52", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "94ef21ab-5eca-4c80-b378-2a207dcca2e4", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "dba195e2-63d6-42ca-94aa-42c87b4306ea", - "name": "workspaceMember" - } - } - } - ] - }, - { - "__typename": "object", - "id": "1b5e63b9-9fc3-485d-86ff-de70ff17a665", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "viewSort", - "namePlural": "viewSorts", - "labelSingular": "View Sort", - "labelPlural": "View Sorts", - "description": "(System) View Sorts", - "icon": "IconArrowsSort", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "35329333-5b6c-4160-8a2a-48ff1f40c500", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "14b9ac38-97c5-44f9-b4f5-a6bbc18dd87c", - "type": "TEXT", - "name": "direction", - "label": "Direction", - "description": "View Sort direction", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "'asc'", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "673fb6fb-5123-4336-9b4b-e4b268c1cffe", - "type": "RELATION", - "name": "view", - "label": "View", - "description": "View Sort related view", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "53abf7c2-810d-478b-bb2d-689f31322d67", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "view", - "namePlural": "views", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "4abadd14-56cd-48e4-8013-7b46de4ffe22" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "53abf7c2-810d-478b-bb2d-689f31322d67", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1b5e63b9-9fc3-485d-86ff-de70ff17a665", - "nameSingular": "viewSort", - "namePlural": "viewSorts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "673fb6fb-5123-4336-9b4b-e4b268c1cffe", - "name": "view" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "90df20e5-c655-474f-bb98-b423652e36df", - "nameSingular": "view", - "namePlural": "views" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4abadd14-56cd-48e4-8013-7b46de4ffe22", - "name": "viewSorts" - } - } - }, - { - "__typename": "field", - "id": "75ec0934-d5bf-4a0a-9b18-cadb0a56e489", - "type": "UUID", - "name": "fieldMetadataId", - "label": "Field Metadata Id", - "description": "View Sort target field", - "icon": "IconTag", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "35329333-5b6c-4160-8a2a-48ff1f40c500", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "a5baa6c5-3cf2-4f2d-a7ff-b5d7176a1498", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "bdfdc845-c48e-4671-b07b-579ad800408f", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "e9572e7f-c327-4da6-93c0-64bf5a465de4", - "type": "UUID", - "name": "viewId", - "label": "View id (foreign key)", - "description": "View Sort related view id foreign key", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "189129d8-8037-4edf-9c91-63001ab52370", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "auditLog", - "namePlural": "auditLogs", - "labelSingular": "Audit Log", - "labelPlural": "Audit Logs", - "description": "An audit log of actions performed in the system", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "8407e296-b80d-4bcb-9e33-8bf9bf942625", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "3cc5ffd0-17da-42f6-87bb-2021b3ad41e3", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "78632f28-cdfa-4f91-a019-de3d7b711d4d", - "type": "RAW_JSON", - "name": "context", - "label": "Event context", - "description": "Json object to provide context (user, device, workspace, etc.)", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "b706c04a-686d-45a4-b2a0-f28fb8e743fa", - "type": "TEXT", - "name": "objectMetadataId", - "label": "Object metadata id", - "description": "Object metadata id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "fadfc339-188a-4563-a502-478e72ce09c3", - "type": "TEXT", - "name": "objectName", - "label": "Object name", - "description": "Object name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "f90ab65b-1171-4c1e-9603-7b744058c317", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "5e4525b9-5a43-414e-ad35-f1eb19858a27", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "522226c1-3446-423c-b6a6-44776f59b076", - "type": "RAW_JSON", - "name": "properties", - "label": "Event details", - "description": "Json value for event details", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "0e09a491-d3bd-4a23-9c50-cda32acbc7ef", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Event workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "025cb05b-3bdb-4418-8a07-8b7a8c22dbc1", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "45b45740-d6cd-476c-af07-f6ed323953b6" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "025cb05b-3bdb-4418-8a07-8b7a8c22dbc1", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "189129d8-8037-4edf-9c91-63001ab52370", - "nameSingular": "auditLog", - "namePlural": "auditLogs" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0e09a491-d3bd-4a23-9c50-cda32acbc7ef", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "45b45740-d6cd-476c-af07-f6ed323953b6", - "name": "auditLogs" - } - } - }, - { - "__typename": "field", - "id": "8407e296-b80d-4bcb-9e33-8bf9bf942625", - "type": "TEXT", - "name": "name", - "label": "Event name", - "description": "Event name/type", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "9d2e7f7f-d1a9-4f42-bfe9-437fe0e72088", - "type": "UUID", - "name": "recordId", - "label": "Record id", - "description": "Record id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "7d8d0023-c979-4c93-850e-7fce90b500ae", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Event workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - } - ] - }, - { - "__typename": "object", - "id": "033ae6fd-c59e-475e-ba93-bbc1b2b185a5", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "blocklist", - "namePlural": "blocklists", - "labelSingular": "Blocklist", - "labelPlural": "Blocklists", - "description": "Blocklist", - "icon": "IconForbid2", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "labelIdentifierFieldMetadataId": "231e4111-5613-4925-97e4-6c84bcee60b7", - "imageIdentifierFieldMetadataId": null, - "fields": [ - { - "__typename": "field", - "id": "2b4e97a1-b598-47f4-83ab-4ec184dac6ed", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "54603149-fda9-4d0b-87eb-0c093c297599", - "type": "UUID", - "name": "workspaceMemberId", - "label": "WorkspaceMember id (foreign key)", - "description": "WorkspaceMember id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": null, - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "597169c3-ad77-4a48-8a2a-94b7cc155e25", - "type": "RELATION", - "name": "workspaceMember", - "label": "WorkspaceMember", - "description": "WorkspaceMember", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": { - "__typename": "relation", - "id": "d9eb657a-f97b-4cec-af79-0e113d47279b", - "relationType": "ONE_TO_MANY", - "fromObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "dataSourceId": "9af88cea-baa2-4c00-bc22-c55cfbcd7e3c", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - }, - "fromFieldMetadataId": "89b50259-5ed6-4504-9c89-3f4457dc43a6" - }, - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d9eb657a-f97b-4cec-af79-0e113d47279b", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "033ae6fd-c59e-475e-ba93-bbc1b2b185a5", - "nameSingular": "blocklist", - "namePlural": "blocklists" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "597169c3-ad77-4a48-8a2a-94b7cc155e25", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1e9ad365-ccb9-4dec-b42f-13b6e86477e3", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "89b50259-5ed6-4504-9c89-3f4457dc43a6", - "name": "blocklist" - } - } - }, - { - "__typename": "field", - "id": "231e4111-5613-4925-97e4-6c84bcee60b7", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "''", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "88c47801-89ed-43ee-8b0d-172eccef5445", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Last update", - "description": "Last time the record was changed", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "now", - "options": null, - "relationDefinition": null - }, - { - "__typename": "field", - "id": "c1f89a93-80b6-4601-a330-8d9f7d5ef894", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-05T16:38:57.285Z", - "updatedAt": "2024-08-05T16:38:57.285Z", - "fromRelationMetadata": null, - "toRelationMetadata": null, - "defaultValue": "uuid", - "options": null, - "relationDefinition": null - } - ] - } - ]; - - // Todo fix typing here (the backend is not in sync with the frontend) - return mockArray as ObjectMetadataItem[]; -}; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getOrderByForFieldMetadataType.ts b/packages/twenty-front/src/modules/object-metadata/utils/getOrderByForFieldMetadataType.ts index 1803bc9c5db8..4bb814db1571 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/getOrderByForFieldMetadataType.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/getOrderByForFieldMetadataType.ts @@ -4,6 +4,7 @@ import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordG import { FieldEmailsValue, FieldLinksValue, + FieldPhonesValue, } from '@/object-record/record-field/types/FieldMetadata'; import { OrderBy } from '@/types/OrderBy'; import { FieldMetadataType } from '~/generated-metadata/graphql'; @@ -54,6 +55,14 @@ export const getOrderByForFieldMetadataType = ( } satisfies { [key in keyof FieldEmailsValue]?: OrderBy }, }, ]; + case FieldMetadataType.Phones: + return [ + { + [field.name]: { + primaryPhoneNumber: direction ?? 'AscNullsLast', + } satisfies { [key in keyof FieldPhonesValue]?: OrderBy }, + }, + ]; default: return [ { diff --git a/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts b/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts index 9984d62ffdcf..d379313a0496 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts @@ -4,7 +4,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery'; import { FieldMetadataType, - RelationMetadataType, + RelationDefinitionType, } from '~/generated-metadata/graphql'; import { FieldMetadataItem } from '../types/FieldMetadataItem'; @@ -17,10 +17,7 @@ export const mapFieldMetadataToGraphQLQuery = ({ computeReferences = false, }: { objectMetadataItems: ObjectMetadataItem[]; - field: Pick< - FieldMetadataItem, - 'name' | 'type' | 'toRelationMetadata' | 'fromRelationMetadata' - >; + field: Pick<FieldMetadataItem, 'name' | 'type' | 'relationDefinition'>; relationrecordFields?: Record<string, any>; computeReferences?: boolean; }): any => { @@ -41,6 +38,7 @@ export const mapFieldMetadataToGraphQLQuery = ({ FieldMetadataType.Position, FieldMetadataType.RawJson, FieldMetadataType.RichText, + FieldMetadataType.Array, ].includes(fieldType); if (fieldIsSimpleValue) { @@ -49,12 +47,12 @@ export const mapFieldMetadataToGraphQLQuery = ({ if ( fieldType === FieldMetadataType.Relation && - field.toRelationMetadata?.relationType === RelationMetadataType.OneToMany + field.relationDefinition?.direction === RelationDefinitionType.ManyToOne ) { const relationMetadataItem = objectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.id === - (field.toRelationMetadata as any)?.fromObjectMetadata?.id, + field.relationDefinition?.targetObjectMetadata.id, ); if (isUndefined(relationMetadataItem)) { @@ -73,12 +71,12 @@ ${mapObjectMetadataToGraphQLQuery({ if ( fieldType === FieldMetadataType.Relation && - field.fromRelationMetadata?.relationType === RelationMetadataType.OneToMany + field.relationDefinition?.direction === RelationDefinitionType.OneToMany ) { const relationMetadataItem = objectMetadataItems.find( (objectMetadataItem) => objectMetadataItem.id === - (field.fromRelationMetadata as any)?.toObjectMetadata?.id, + field.relationDefinition?.targetObjectMetadata.id, ); if (isUndefined(relationMetadataItem)) { @@ -164,5 +162,14 @@ ${mapObjectMetadataToGraphQLQuery({ }`; } + if (fieldType === FieldMetadataType.Phones) { + return `${field.name} + { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + }`; + } + return ''; }; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts b/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts deleted file mode 100644 index 8540a7cfcef6..000000000000 --- a/packages/twenty-front/src/modules/object-metadata/utils/parseFieldRelationType.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; -import { FieldDefinitionRelationType } from '@/object-record/record-field/types/FieldDefinition'; -import { - FieldMetadataType, - RelationMetadataType, -} from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; - -export const parseFieldRelationType = ( - field: FieldMetadataItem | undefined, -): FieldDefinitionRelationType | undefined => { - if (!field || field.type !== FieldMetadataType.Relation) return; - - const config: Record< - RelationMetadataType, - { from: FieldDefinitionRelationType; to: FieldDefinitionRelationType } - > = { - [RelationMetadataType.ManyToMany]: { - from: 'FROM_MANY_OBJECTS', - to: 'TO_MANY_OBJECTS', - }, - [RelationMetadataType.OneToMany]: { - from: 'FROM_MANY_OBJECTS', - to: 'TO_ONE_OBJECT', - }, - [RelationMetadataType.ManyToOne]: { - from: 'TO_ONE_OBJECT', - to: 'FROM_MANY_OBJECTS', - }, - [RelationMetadataType.OneToOne]: { - from: 'FROM_ONE_OBJECT', - to: 'TO_ONE_OBJECT', - }, - }; - - if ( - isDefined(field.fromRelationMetadata) && - field.fromRelationMetadata.relationType in config - ) { - return config[field.fromRelationMetadata.relationType].from; - } - - if ( - isDefined(field.toRelationMetadata) && - field.toRelationMetadata.relationType in config - ) { - return config[field.toRelationMetadata.relationType].to; - } - - throw new Error( - `Cannot determine field relation type for field : ${JSON.stringify( - field, - )}.`, - ); -}; diff --git a/packages/twenty-front/src/modules/object-metadata/validation-schemas/fieldMetadataItemSchema.ts b/packages/twenty-front/src/modules/object-metadata/validation-schemas/fieldMetadataItemSchema.ts index ce60af2269f9..18fc5722a1a2 100644 --- a/packages/twenty-front/src/modules/object-metadata/validation-schemas/fieldMetadataItemSchema.ts +++ b/packages/twenty-front/src/modules/object-metadata/validation-schemas/fieldMetadataItemSchema.ts @@ -6,7 +6,6 @@ import { metadataLabelSchema } from '@/object-metadata/validation-schemas/metada import { FieldMetadataType, RelationDefinitionType, - RelationMetadataType, } from '~/generated-metadata/graphql'; import { camelCaseStringSchema } from '~/utils/validation-schemas/camelCaseStringSchema'; @@ -16,24 +15,6 @@ export const fieldMetadataItemSchema = (existingLabels?: string[]) => { createdAt: z.string().datetime(), defaultValue: z.any().optional(), description: z.string().trim().nullable().optional(), - fromRelationMetadata: z - .object({ - __typename: z.literal('relation').optional(), - id: z.string().uuid(), - relationType: z.nativeEnum(RelationMetadataType), - toFieldMetadataId: z.string().uuid(), - toObjectMetadata: z.object({ - __typename: z.literal('object').optional(), - dataSourceId: z.string().uuid(), - id: z.string().uuid(), - isRemote: z.boolean(), - isSystem: z.boolean(), - namePlural: z.string().trim().min(1), - nameSingular: z.string().trim().min(1), - }), - }) - .nullable() - .optional(), icon: z.string().startsWith('Icon').trim().nullable(), id: z.string().uuid(), isActive: z.boolean(), @@ -54,6 +35,7 @@ export const fieldMetadataItemSchema = (existingLabels?: string[]) => { ) .nullable() .optional(), + settings: z.any().optional(), relationDefinition: z .object({ __typename: z.literal('RelationDefinition').optional(), @@ -84,24 +66,6 @@ export const fieldMetadataItemSchema = (existingLabels?: string[]) => { }) .nullable() .optional(), - toRelationMetadata: z - .object({ - __typename: z.literal('relation').optional(), - id: z.string().uuid(), - relationType: z.nativeEnum(RelationMetadataType), - fromFieldMetadataId: z.string().uuid(), - fromObjectMetadata: z.object({ - __typename: z.literal('object').optional(), - id: z.string().uuid(), - dataSourceId: z.string().uuid(), - isRemote: z.boolean(), - isSystem: z.boolean(), - namePlural: z.string().trim().min(1), - nameSingular: z.string().trim().min(1), - }), - }) - .nullable() - .optional(), type: z.nativeEnum(FieldMetadataType), updatedAt: z.string().datetime(), }) satisfies z.ZodType<FieldMetadataItem>; diff --git a/packages/twenty-front/src/modules/object-metadata/validation-schemas/selectOptionsSchema.ts b/packages/twenty-front/src/modules/object-metadata/validation-schemas/selectOptionsSchema.ts index ff767cdd5493..3893306c87ce 100644 --- a/packages/twenty-front/src/modules/object-metadata/validation-schemas/selectOptionsSchema.ts +++ b/packages/twenty-front/src/modules/object-metadata/validation-schemas/selectOptionsSchema.ts @@ -2,7 +2,6 @@ import { themeColorSchema } from 'twenty-ui'; import { z } from 'zod'; import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem'; -import { getOptionValueFromLabel } from '@/settings/data-model/fields/forms/select/utils/getOptionValueFromLabel'; import { computeOptionValueFromLabelOrThrow } from '~/pages/settings/data-model/utils/compute-option-value-from-label.utils'; const selectOptionSchema = z @@ -13,9 +12,6 @@ const selectOptionSchema = z position: z.number(), value: z.string(), }) - .refine((option) => option.value === getOptionValueFromLabel(option.label), { - message: 'Value does not match label', - }) .refine( (option) => { try { diff --git a/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx b/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx index db5e7aabd015..16b207dbe12f 100644 --- a/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx +++ b/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx @@ -4,6 +4,7 @@ import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage'; import { useRecordChipData } from '@/object-record/hooks/useRecordChipData'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink'; +import { MouseEvent } from 'react'; export type RecordChipProps = { objectNameSingular: string; @@ -23,8 +24,15 @@ export const RecordChip = ({ record, }); + const handleClick = (e: MouseEvent<HTMLAnchorElement>) => { + e.stopPropagation(); + }; + return ( - <UndecoratedLink to={getLinkToShowPage(objectNameSingular, record)}> + <UndecoratedLink + onClick={handleClick} + to={getLinkToShowPage(objectNameSingular, record)} + > <AvatarChip placeholderColorSeed={record.id} name={recordChipData.name} diff --git a/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts b/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts index 38038ee0562e..72573ea2133e 100644 --- a/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts +++ b/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts @@ -98,6 +98,11 @@ export type EmailsFilter = { primaryEmail?: StringFilter; }; +export type PhonesFilter = { + primaryPhoneNumber?: StringFilter; + primaryPhoneCountryCode?: StringFilter; +}; + export type LeafFilter = | UUIDFilter | StringFilter @@ -110,6 +115,7 @@ export type LeafFilter = | AddressFilter | LinksFilter | ActorFilter + | PhonesFilter | undefined; export type AndObjectRecordFilter = { diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragment.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragment.ts index 2f0fdfcee60b..8a2b3f08567d 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragment.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragment.ts @@ -1,37 +1,48 @@ export const PERSON_FRAGMENT = ` __typename - updatedAt - myCustomObjectId - whatsapp - linkedinLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } name { firstName lastName } - email - position - createdBy { - source - workspaceMemberId - name + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks } - avatarUrl + deletedAt + createdAt + updatedAt jobTitle + intro + workPrefereance + performanceRating xLink { primaryLinkUrl primaryLinkLabel secondaryLinks } - performanceRating - createdAt - phone - id city companyId - intro - workPrefereance + phones { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } + createdBy { + source + workspaceMemberId + name + } + id + position + emails { + primaryEmail + additionalEmails + } + avatarUrl + whatsapp { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } ` diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts index 74f789878076..f36762b3bcef 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts @@ -35,7 +35,10 @@ export const responseData = { firstName: '', lastName: '', }, - phone: '', + phones: { + primaryPhoneCountryCode: '', + primaryPhoneNumber: '', + }, linkedinLink: { primaryLinkUrl: '', primaryLinkLabel: '', diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts index faf2a80f894a..4753898533af 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts @@ -40,7 +40,10 @@ export const responseData = { firstName: '', lastName: '', }, - phone: '', + phones: { + primaryPhoneCountryCode: '', + primaryPhoneNumber: '', + }, linkedinLink: { primaryLinkUrl: '', primaryLinkLabel: '', diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts index e1cd100fc548..15bb27bc76b1 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts @@ -17,13 +17,12 @@ const basePerson = { secondaryLinks: null, }, createdAt: '', - email: '', + city: '', jobTitle: '', name: { firstName: '', lastName: '', }, - phone: '', linkedinLink: { primaryLinkUrl: '', primaryLinkLabel: '', diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFetchAllRecordIds.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFetchAllRecordIds.test.tsx index fc32df77ebb0..02095502e9ed 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFetchAllRecordIds.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFetchAllRecordIds.test.tsx @@ -4,7 +4,6 @@ import { ReactNode, useEffect } from 'react'; import { RecoilRoot, useRecoilState } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { mockPageSize, peopleMockWithIdsOnly, @@ -18,6 +17,7 @@ import { } from '@/object-record/hooks/__mocks__/useFetchAllRecordIds'; import { useFetchAllRecordIds } from '@/object-record/hooks/useFetchAllRecordIds'; import { SnackBarManagerScopeInternalContext } from '@/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const mocks = [ { @@ -75,7 +75,7 @@ describe('useFetchAllRecordIds', () => { ); useEffect(() => { - setObjectMetadataItems(getObjectMetadataItemsMock()); + setObjectMetadataItems(generatedMockObjectMetadataItems); }, [setObjectMetadataItems]); return useFetchAllRecordIds({ diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx index 6b7d71c18b5d..d86769f1d219 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx @@ -5,7 +5,6 @@ import { RecoilRoot, useSetRecoilState } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { query, responseData, @@ -13,6 +12,7 @@ import { } from '@/object-record/hooks/__mocks__/useFindManyRecords'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const mocks = [ { @@ -65,11 +65,9 @@ describe('useFindManyRecords', () => { locale: 'en', }); - const mockObjectMetadataItems = getObjectMetadataItemsMock(); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFindManyRecords({ objectNameSingular: 'person', diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx index 6d29107a3204..feb33c81b30a 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx @@ -1,11 +1,11 @@ -import { ReactNode } from 'react'; import { expect } from '@storybook/test'; import { renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery'; import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const Wrapper = ({ children }: { children: ReactNode }) => ( <RecoilRoot> @@ -18,7 +18,7 @@ describe('useGenerateFindManyRecordsForMultipleMetadataItemsQuery', () => { const { result } = renderHook( () => { return useGenerateCombinedFindManyRecordsQuery({ - operationSignatures: getObjectMetadataItemsMock() + operationSignatures: generatedMockObjectMetadataItems .slice(0, 2) .map((item) => ({ objectNameSingular: item.nameSingular, diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx index 0ccd92897a89..eb6e7048d316 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx @@ -1,6 +1,6 @@ -import { ReactNode } from 'react'; import { MockedProvider } from '@apollo/client/testing'; import { act, renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; import { @@ -11,8 +11,17 @@ import { import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; const person = { id: '36abbb63-34ed-4a16-89f5-f549ac55d0f9' }; -const update = { name: { firstName: 'John', lastName: 'Doe' } }; -const updatePerson = { ...person, ...responseData, ...update }; +const update = { + name: { + firstName: 'John', + lastName: 'Doe', + }, +}; +const updatePerson = { + ...person, + ...responseData, + ...update, +}; const mocks = [ { diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts index 6524374c5efe..08f4d092a135 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts @@ -6,7 +6,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache'; import { DEFAULT_MUTATION_BATCH_SIZE } from '@/object-record/constants/DefaultMutationBatchSize'; -import { useDestroyManyRecordsMutation } from '@/object-record/hooks/useDestroyManyRecordMutation'; +import { useDestroyManyRecordsMutation } from '@/object-record/hooks/useDestroyManyRecordsMutation'; import { getDestroyManyRecordsMutationResponseField } from '@/object-record/utils/getDestroyManyRecordsMutationResponseField'; import { useRecoilValue } from 'recoil'; import { isDefined } from '~/utils/isDefined'; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecordsMutation.ts similarity index 100% rename from packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecordMutation.ts rename to packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecordsMutation.ts diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecord.ts new file mode 100644 index 000000000000..fc5d75d0a42f --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecord.ts @@ -0,0 +1,84 @@ +import { useApolloClient } from '@apollo/client'; +import { useCallback } from 'react'; + +import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDeleteRecordsOptimisticEffect'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; +import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache'; +import { useDestroyOneRecordMutation } from '@/object-record/hooks/useDestroyOneRecordMutation'; +import { getDestroyOneRecordMutationResponseField } from '@/object-record/utils/getDestroyOneRecordMutationResponseField'; +import { capitalize } from '~/utils/string/capitalize'; + +type useDestroyOneRecordProps = { + objectNameSingular: string; + refetchFindManyQuery?: boolean; +}; + +export const useDestroyOneRecord = ({ + objectNameSingular, +}: useDestroyOneRecordProps) => { + const apolloClient = useApolloClient(); + + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular, + }); + + const getRecordFromCache = useGetRecordFromCache({ + objectNameSingular, + }); + + const { destroyOneRecordMutation } = useDestroyOneRecordMutation({ + objectNameSingular, + }); + + const { objectMetadataItems } = useObjectMetadataItems(); + + const mutationResponseField = + getDestroyOneRecordMutationResponseField(objectNameSingular); + + const destroyOneRecord = useCallback( + async (idToDestroy: string) => { + const deletedRecord = await apolloClient.mutate({ + mutation: destroyOneRecordMutation, + variables: { idToDestroy }, + optimisticResponse: { + [mutationResponseField]: { + __typename: capitalize(objectNameSingular), + id: idToDestroy, + }, + }, + update: (cache, { data }) => { + const record = data?.[mutationResponseField]; + + if (!record) return; + + const cachedRecord = getRecordFromCache(record.id, cache); + + if (!cachedRecord) return; + + triggerDeleteRecordsOptimisticEffect({ + cache, + objectMetadataItem, + recordsToDelete: [cachedRecord], + objectMetadataItems, + }); + }, + }); + + return deletedRecord.data?.[mutationResponseField] ?? null; + }, + [ + apolloClient, + destroyOneRecordMutation, + getRecordFromCache, + mutationResponseField, + objectMetadataItem, + objectNameSingular, + objectMetadataItems, + ], + ); + + return { + destroyOneRecord, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecordMutation.ts new file mode 100644 index 000000000000..c6a6fb680de0 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/useDestroyOneRecordMutation.ts @@ -0,0 +1,39 @@ +import gql from 'graphql-tag'; + +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation'; +import { getDestroyOneRecordMutationResponseField } from '@/object-record/utils/getDestroyOneRecordMutationResponseField'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; +import { capitalize } from '~/utils/string/capitalize'; + +export const useDestroyOneRecordMutation = ({ + objectNameSingular, +}: { + objectNameSingular: string; +}) => { + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular, + }); + + if (isUndefinedOrNull(objectMetadataItem)) { + return { destroyOneRecordMutation: EMPTY_MUTATION }; + } + + const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular); + + const mutationResponseField = getDestroyOneRecordMutationResponseField( + objectMetadataItem.nameSingular, + ); + + const destroyOneRecordMutation = gql` + mutation DestroyOne${capitalizedObjectName}($idToDestroy: ID!) { + ${mutationResponseField}(id: $idToDestroy) { + id + } + } + `; + + return { + destroyOneRecordMutation, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts index 95385c377722..b147b5535f71 100644 --- a/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/multiple-objects/hooks/useCombinedFindManyRecords.ts @@ -11,13 +11,13 @@ export const useCombinedFindManyRecords = ({ skip = false, }: { operationSignatures: RecordGqlOperationSignature[]; - skip: boolean; + skip?: boolean; }) => { const findManyQuery = useGenerateCombinedFindManyRecordsQuery({ operationSignatures, }); - const { data } = useQuery<MultiObjectRecordQueryResult>( + const { data, loading } = useQuery<MultiObjectRecordQueryResult>( findManyQuery ?? EMPTY_QUERY, { skip, @@ -35,5 +35,6 @@ export const useCombinedFindManyRecords = ({ return { result: resultWithoutConnection, + loading, }; }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx index 885a6c8eb840..b88f421c9857 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx @@ -2,6 +2,7 @@ import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdow import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; +import { useCallback } from 'react'; import { MultipleFiltersButton } from './MultipleFiltersButton'; import { MultipleFiltersDropdownContent } from './MultipleFiltersDropdownContent'; @@ -13,12 +14,18 @@ type MultipleFiltersDropdownButtonProps = { export const MultipleFiltersDropdownButton = ({ hotkeyScope, }: MultipleFiltersDropdownButtonProps) => { - const { resetFilter } = useFilterDropdown(); + const { resetFilter, setIsObjectFilterDropdownOperandSelectUnfolded } = + useFilterDropdown(); + + const handleDropdownClose = useCallback(() => { + resetFilter(); + setIsObjectFilterDropdownOperandSelectUnfolded(false); + }, [resetFilter, setIsObjectFilterDropdownOperandSelectUnfolded]); return ( <Dropdown dropdownId={OBJECT_FILTER_DROPDOWN_ID} - onClose={resetFilter} + onClose={handleDropdownClose} clickableComponent={<MultipleFiltersButton />} dropdownComponents={<MultipleFiltersDropdownContent />} dropdownHotkeyScope={hotkeyScope} diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx index 91e31b5671ef..da02a28a6731 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx @@ -1,11 +1,9 @@ -import { useRecoilValue } from 'recoil'; - +import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput'; import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; -import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; - -import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput'; +import styled from '@emotion/styled'; +import { useRecoilValue } from 'recoil'; import { MultipleFiltersDropdownFilterOnFilterChangedEffect } from './MultipleFiltersDropdownFilterOnFilterChangedEffect'; import { ObjectFilterDropdownDateInput } from './ObjectFilterDropdownDateInput'; import { ObjectFilterDropdownFilterSelect } from './ObjectFilterDropdownFilterSelect'; @@ -16,6 +14,21 @@ import { ObjectFilterDropdownOptionSelect } from './ObjectFilterDropdownOptionSe import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect'; import { ObjectFilterDropdownTextSearchInput } from './ObjectFilterDropdownTextSearchInput'; +const StyledContainer = styled.div` + position: relative; +`; + +const StyledOperandSelectContainer = styled.div` + background: ${({ theme }) => theme.background.secondary}; + box-shadow: ${({ theme }) => theme.boxShadow.light}; + border-radius: ${({ theme }) => theme.border.radius.md}; + left: 10px; + position: absolute; + top: 10px; + width: 100%; + z-index: 1000; +`; + type MultipleFiltersDropdownContentProps = { filterDropdownId?: string; }; @@ -24,83 +37,97 @@ export const MultipleFiltersDropdownContent = ({ filterDropdownId, }: MultipleFiltersDropdownContentProps) => { const { - isObjectFilterDropdownOperandSelectUnfoldedState, filterDefinitionUsedInDropdownState, selectedOperandInDropdownState, + isObjectFilterDropdownOperandSelectUnfoldedState, } = useFilterDropdown({ filterDropdownId }); const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue( isObjectFilterDropdownOperandSelectUnfoldedState, ); + const filterDefinitionUsedInDropdown = useRecoilValue( filterDefinitionUsedInDropdownState, ); + const selectedOperandInDropdown = useRecoilValue( selectedOperandInDropdownState, ); - const isEmptyOperand = + + const isConfigurable = selectedOperandInDropdown && - [ViewFilterOperand.IsEmpty, ViewFilterOperand.IsNotEmpty].includes( - selectedOperandInDropdown, - ); + [ + ViewFilterOperand.Is, + ViewFilterOperand.IsNotNull, + ViewFilterOperand.IsNot, + ViewFilterOperand.LessThan, + ViewFilterOperand.GreaterThan, + ViewFilterOperand.IsBefore, + ViewFilterOperand.IsAfter, + ViewFilterOperand.Contains, + ViewFilterOperand.DoesNotContain, + ViewFilterOperand.IsRelative, + ].includes(selectedOperandInDropdown); return ( - <> + <StyledContainer> {!filterDefinitionUsedInDropdown ? ( <ObjectFilterDropdownFilterSelect /> - ) : isObjectFilterDropdownOperandSelectUnfolded ? ( - <ObjectFilterDropdownOperandSelect /> - ) : isEmptyOperand ? ( - <ObjectFilterDropdownOperandButton /> ) : ( - selectedOperandInDropdown && ( - <> - <ObjectFilterDropdownOperandButton /> - <DropdownMenuSeparator /> - {[ - 'TEXT', - 'EMAIL', - 'EMAILS', - 'PHONE', - 'FULL_NAME', - 'LINK', - 'LINKS', - 'ADDRESS', - 'ACTOR', - ].includes(filterDefinitionUsedInDropdown.type) && ( - <ObjectFilterDropdownTextSearchInput /> - )} - {['NUMBER', 'CURRENCY'].includes( - filterDefinitionUsedInDropdown.type, - ) && <ObjectFilterDropdownNumberInput />} - {filterDefinitionUsedInDropdown.type === 'RATING' && ( - <ObjectFilterDropdownRatingInput /> - )} - {filterDefinitionUsedInDropdown.type === 'DATE_TIME' && ( - <ObjectFilterDropdownDateInput /> - )} - {filterDefinitionUsedInDropdown.type === 'RELATION' && ( - <> - <ObjectFilterDropdownSearchInput /> - <DropdownMenuSeparator /> - <ObjectFilterDropdownRecordSelect /> - </> - )} - {filterDefinitionUsedInDropdown.type === 'SELECT' && ( - <> - <ObjectFilterDropdownSearchInput /> - <DropdownMenuSeparator /> - <ObjectFilterDropdownOptionSelect /> - </> - )} - </> - ) + <> + <ObjectFilterDropdownOperandButton /> + {isObjectFilterDropdownOperandSelectUnfolded && ( + <StyledOperandSelectContainer> + <ObjectFilterDropdownOperandSelect /> + </StyledOperandSelectContainer> + )} + {isConfigurable && selectedOperandInDropdown && ( + <> + {[ + 'TEXT', + 'EMAIL', + 'EMAILS', + 'PHONE', + 'FULL_NAME', + 'LINK', + 'LINKS', + 'ADDRESS', + 'ACTOR', + 'ARRAY', + 'PHONES', + ].includes(filterDefinitionUsedInDropdown.type) && ( + <ObjectFilterDropdownTextSearchInput /> + )} + {['NUMBER', 'CURRENCY'].includes( + filterDefinitionUsedInDropdown.type, + ) && <ObjectFilterDropdownNumberInput />} + {filterDefinitionUsedInDropdown.type === 'RATING' && ( + <ObjectFilterDropdownRatingInput /> + )} + {['DATE_TIME', 'DATE'].includes( + filterDefinitionUsedInDropdown.type, + ) && <ObjectFilterDropdownDateInput />} + {filterDefinitionUsedInDropdown.type === 'RELATION' && ( + <> + <ObjectFilterDropdownSearchInput /> + <ObjectFilterDropdownRecordSelect /> + </> + )} + {filterDefinitionUsedInDropdown.type === 'SELECT' && ( + <> + <ObjectFilterDropdownSearchInput /> + <ObjectFilterDropdownOptionSelect /> + </> + )} + </> + )} + </> )} <MultipleFiltersDropdownFilterOnFilterChangedEffect filterDefinitionUsedInDropdownType={ filterDefinitionUsedInDropdown?.type } /> - </> + </StyledContainer> ); }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownFilterOnFilterChangedEffect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownFilterOnFilterChangedEffect.tsx index 477e74d34a55..c70ff89521c5 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownFilterOnFilterChangedEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownFilterOnFilterChangedEffect.tsx @@ -11,6 +11,7 @@ export const MultipleFiltersDropdownFilterOnFilterChangedEffect = ({ useEffect(() => { switch (filterDefinitionUsedInDropdownType) { + case 'DATE': case 'DATE_TIME': setDropdownWidth(280); break; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx index 3b5672783714..9abc6b7842a1 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx @@ -1,9 +1,8 @@ -import { useRecoilValue } from 'recoil'; - -import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton'; import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton'; @@ -16,12 +15,9 @@ export const ObjectFilterDropdownButton = ({ filterDropdownId, hotkeyScope, }: ObjectFilterDropdownButtonProps) => { - const { availableFilterDefinitionsState } = useFilterDropdown({ - filterDropdownId: filterDropdownId, - }); - - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, + filterDropdownId, ); const hasOnlyOneEntityFilter = diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx index 0a463a229d5d..3961f28c836b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx @@ -2,10 +2,19 @@ import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue'; import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { computeVariableDateViewFilterValue } from '@/views/utils/view-filter-value/computeVariableDateViewFilterValue'; +import { + VariableDateViewFilterValueDirection, + VariableDateViewFilterValueUnit, +} from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; +import { resolveFilterValue } from '@/views/utils/view-filter-value/resolveFilterValue'; import { useState } from 'react'; +import { isDefined } from 'twenty-ui'; import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; export const ObjectFilterDropdownDateInput = () => { const { @@ -23,35 +32,93 @@ export const ObjectFilterDropdownDateInput = () => { selectedOperandInDropdownState, ); - const selectedFilter = useRecoilValue(selectedFilterState); + const selectedFilter = useRecoilValue(selectedFilterState) as + | (Filter & { definition: { type: 'DATE' | 'DATE_TIME' } }) + | null + | undefined; + + const initialFilterValue = selectedFilter + ? resolveFilterValue(selectedFilter) + : null; const [internalDate, setInternalDate] = useState<Date | null>( - selectedFilter?.value ? new Date(selectedFilter.value) : new Date(), + initialFilterValue instanceof Date ? initialFilterValue : null, ); - const handleChange = (date: Date | null) => { - setInternalDate(date); + + const isDateTimeInput = + filterDefinitionUsedInDropdown?.type === FieldMetadataType.DateTime; + + const handleAbsoluteDateChange = (newDate: Date | null) => { + setInternalDate(newDate); if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; selectFilter?.({ id: selectedFilter?.id ? selectedFilter.id : v4(), fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, - value: isDefined(date) ? date.toISOString() : '', + value: newDate?.toISOString() ?? '', operand: selectedOperandInDropdown, - displayValue: isDefined(date) ? date.toLocaleString() : '', + displayValue: isDefined(newDate) + ? isDateTimeInput + ? newDate.toLocaleString() + : newDate.toLocaleDateString() + : '', definition: filterDefinitionUsedInDropdown, }); setIsObjectFilterDropdownUnfolded(false); }; + const handleRelativeDateChange = ( + relativeDate: { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; + } | null, + ) => { + if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; + + const value = relativeDate + ? computeVariableDateViewFilterValue( + relativeDate.direction, + relativeDate.amount, + relativeDate.unit, + ) + : ''; + + selectFilter?.({ + id: selectedFilter?.id ? selectedFilter.id : v4(), + fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, + value, + operand: selectedOperandInDropdown, + displayValue: getRelativeDateDisplayValue(relativeDate), + definition: filterDefinitionUsedInDropdown, + }); + + setIsObjectFilterDropdownUnfolded(false); + }; + + const isRelativeOperand = + selectedOperandInDropdown === ViewFilterOperand.IsRelative; + + const resolvedValue = selectedFilter + ? resolveFilterValue(selectedFilter) + : null; + + const relativeDate = + resolvedValue && !(resolvedValue instanceof Date) + ? resolvedValue + : undefined; + return ( <InternalDatePicker + relativeDate={relativeDate} + highlightedDateRange={relativeDate} + isRelative={isRelativeOperand} date={internalDate} - onChange={handleChange} - onMouseSelect={handleChange} - isDateTimeInput={ - filterDefinitionUsedInDropdown?.type === FieldMetadataType.DateTime - } + onChange={handleAbsoluteDateChange} + onRelativeDateChange={handleRelativeDateChange} + onMouseSelect={handleAbsoluteDateChange} + isDateTimeInput={isDateTimeInput} /> ); }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx index bf123401f40c..59ee04d92518 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx @@ -1,15 +1,18 @@ -import { useState } from 'react'; import styled from '@emotion/styled'; -import { useRecoilValue } from 'recoil'; -import { useIcons } from 'twenty-ui'; +import { useState } from 'react'; -import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; -import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; -import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; -import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; +import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem'; +import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; +import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter'; +import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope'; +import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem'; +import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; +import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { isDefined } from 'twenty-ui'; export const StyledInput = styled.input` background: transparent; @@ -39,20 +42,38 @@ export const StyledInput = styled.input` export const ObjectFilterDropdownFilterSelect = () => { const [searchText, setSearchText] = useState(''); - const { - setFilterDefinitionUsedInDropdown, - setSelectedOperandInDropdown, - setObjectFilterDropdownSearchInput, - availableFilterDefinitionsState, - } = useFilterDropdown(); - - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, + ); + + const sortedAvailableFilterDefinitions = [...availableFilterDefinitions] + .sort((a, b) => a.label.localeCompare(b.label)) + .filter((item) => + item.label.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()), + ); + + const selectableListItemIds = sortedAvailableFilterDefinitions.map( + (item) => item.fieldMetadataId, ); - const { getIcon } = useIcons(); + const { selectFilter } = useSelectFilter(); + + const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID); + + const handleEnter = (itemId: string) => { + const selectedFilterDefinition = sortedAvailableFilterDefinitions.find( + (item) => item.fieldMetadataId === itemId, + ); + + if (!isDefined(selectedFilterDefinition)) { + return; + } + + resetSelectedItem(); - const setHotkeyScope = useSetHotkeyScope(); + selectFilter({ filterDefinition: selectedFilterDefinition }); + }; return ( <> @@ -64,39 +85,27 @@ export const ObjectFilterDropdownFilterSelect = () => { setSearchText(event.target.value) } /> - <DropdownMenuItemsContainer> - {[...availableFilterDefinitions] - .sort((a, b) => a.label.localeCompare(b.label)) - .filter((item) => - item.label - .toLocaleLowerCase() - .includes(searchText.toLocaleLowerCase()), - ) - .map((availableFilterDefinition, index) => ( - <MenuItem - key={`select-filter-${index}`} - testId={`select-filter-${index}`} - onClick={() => { - setFilterDefinitionUsedInDropdown(availableFilterDefinition); - - if ( - availableFilterDefinition.type === 'RELATION' || - availableFilterDefinition.type === 'SELECT' - ) { - setHotkeyScope(RelationPickerHotkeyScope.RelationPicker); - } - - setSelectedOperandInDropdown( - getOperandsForFilterType(availableFilterDefinition.type)?.[0], - ); - - setObjectFilterDropdownSearchInput(''); - }} - LeftIcon={getIcon(availableFilterDefinition.iconName)} - text={availableFilterDefinition.label} - /> - ))} - </DropdownMenuItemsContainer> + <SelectableList + hotkeyScope={FiltersHotkeyScope.ObjectFilterDropdownButton} + selectableItemIdArray={selectableListItemIds} + selectableListId={OBJECT_FILTER_DROPDOWN_ID} + onEnter={handleEnter} + > + <DropdownMenuItemsContainer> + {sortedAvailableFilterDefinitions.map( + (availableFilterDefinition, index) => ( + <SelectableItem + itemId={availableFilterDefinition.fieldMetadataId} + > + <ObjectFilterDropdownFilterSelectMenuItem + key={`select-filter-${index}`} + filterDefinition={availableFilterDefinition} + /> + </SelectableItem> + ), + )} + </DropdownMenuItemsContainer> + </SelectableList> </> ); }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx new file mode 100644 index 000000000000..eb04750c9b8c --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx @@ -0,0 +1,43 @@ +import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; +import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter'; +import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; +import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect'; +import { useRecoilValue } from 'recoil'; +import { useIcons } from 'twenty-ui'; + +export type ObjectFilterDropdownFilterSelectMenuItemProps = { + filterDefinition: FilterDefinition; +}; + +export const ObjectFilterDropdownFilterSelectMenuItem = ({ + filterDefinition, +}: ObjectFilterDropdownFilterSelectMenuItemProps) => { + const { selectFilter } = useSelectFilter(); + + const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList( + OBJECT_FILTER_DROPDOWN_ID, + ); + + const isSelectedItem = useRecoilValue( + isSelectedItemIdSelector(filterDefinition.fieldMetadataId), + ); + + const { getIcon } = useIcons(); + + const handleClick = () => { + resetSelectedItem(); + + selectFilter({ filterDefinition }); + }; + + return ( + <MenuItemSelect + selected={false} + hovered={isSelectedItem} + onClick={handleClick} + LeftIcon={getIcon(filterDefinition.iconName)} + text={filterDefinition.label} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx index 4aa675ec3539..3931c76547e1 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx @@ -10,19 +10,11 @@ export const ObjectFilterDropdownOperandButton = () => { const { selectedOperandInDropdownState, setIsObjectFilterDropdownOperandSelectUnfolded, - isObjectFilterDropdownOperandSelectUnfoldedState, } = useFilterDropdown(); const selectedOperandInDropdown = useRecoilValue( selectedOperandInDropdownState, ); - const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue( - isObjectFilterDropdownOperandSelectUnfoldedState, - ); - - if (isObjectFilterDropdownOperandSelectUnfolded) { - return null; - } return ( <DropdownMenuHeader diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx index 5f500b916461..c710d8f23334 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx @@ -2,12 +2,12 @@ import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; -import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { isDefined } from '~/utils/isDefined'; +import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; import { getOperandLabel } from '../utils/getOperandLabel'; import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; @@ -36,22 +36,25 @@ export const ObjectFilterDropdownOperandSelect = () => { ); const handleOperandChange = (newOperand: ViewFilterOperand) => { - const isEmptyOperand = [ + const isValuelessOperand = [ ViewFilterOperand.IsEmpty, ViewFilterOperand.IsNotEmpty, + ViewFilterOperand.IsInPast, + ViewFilterOperand.IsInFuture, + ViewFilterOperand.IsToday, ].includes(newOperand); setSelectedOperandInDropdown(newOperand); setIsObjectFilterDropdownOperandSelectUnfolded(false); - if (isEmptyOperand) { + if (isValuelessOperand && isDefined(filterDefinitionUsedInDropdown)) { selectFilter?.({ id: v4(), fieldMetadataId: filterDefinitionUsedInDropdown?.fieldMetadataId ?? '', displayValue: '', operand: newOperand, value: '', - definition: filterDefinitionUsedInDropdown as FilterDefinition, + definition: filterDefinitionUsedInDropdown, }); return; } @@ -60,12 +63,19 @@ export const ObjectFilterDropdownOperandSelect = () => { isDefined(filterDefinitionUsedInDropdown) && isDefined(selectedFilter) ) { + const { value, displayValue } = getInitialFilterValue( + filterDefinitionUsedInDropdown.type, + newOperand, + selectedFilter.value, + selectedFilter.displayValue, + ); + selectFilter?.({ id: selectedFilter.id ? selectedFilter.id : v4(), fieldMetadataId: selectedFilter.fieldMetadataId, - displayValue: selectedFilter.displayValue, + displayValue, operand: newOperand, - value: selectedFilter.value, + value, definition: filterDefinitionUsedInDropdown, }); } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx index 9ced7ee64e8a..213f828cfa0b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx @@ -41,7 +41,7 @@ export const ObjectFilterDropdownOptionSelect = () => { selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, }); - const { handleResetSelectedPosition } = useSelectableList( + const { resetSelectedItem } = useSelectableList( MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, ); @@ -90,10 +90,10 @@ export const ObjectFilterDropdownOptionSelect = () => { [Key.Escape], () => { closeDropdown(); - handleResetSelectedPosition(); + resetSelectedItem(); }, RelationPickerHotkeyScope.RelationPicker, - [closeDropdown, handleResetSelectedPosition], + [closeDropdown, resetSelectedItem], ); const handleMultipleOptionSelectChange = ( @@ -137,7 +137,7 @@ export const ObjectFilterDropdownOptionSelect = () => { value: newFilterValue, }); } - handleResetSelectedPosition(); + resetSelectedItem(); }; const optionsInDropdown = selectableOptions?.filter((option) => diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx index 7546dc51c2fe..ddaaf2e6ad92 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx @@ -7,7 +7,7 @@ import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types import { MultipleRecordSelectDropdown } from '@/object-record/select/components/MultipleRecordSelectDropdown'; import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect'; import { SelectableRecord } from '@/object-record/select/types/SelectableRecord'; -import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; +import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { isDefined } from '~/utils/isDefined'; @@ -17,6 +17,7 @@ export const MAX_RECORDS_TO_DISPLAY = 3; type ObjectFilterDropdownRecordSelectProps = { viewComponentId?: string; }; + export const ObjectFilterDropdownRecordSelect = ({ viewComponentId, }: ObjectFilterDropdownRecordSelectProps) => { @@ -31,7 +32,9 @@ export const ObjectFilterDropdownRecordSelect = ({ emptyFilterButKeepDefinition, } = useFilterDropdown(); - const { removeCombinedViewFilter } = useCombinedViewFilters(viewComponentId); + const { deleteCombinedViewFilter } = + useDeleteCombinedViewFilters(viewComponentId); + const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(viewComponentId); @@ -78,7 +81,7 @@ export const ObjectFilterDropdownRecordSelect = ({ if (newSelectedRecordIds.length === 0) { emptyFilterButKeepDefinition(); - removeCombinedViewFilter(fieldId); + deleteCombinedViewFilter(fieldId); return; } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx index 5f57a990d365..ddfb5125b9dc 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx @@ -1,5 +1,5 @@ -import React from 'react'; import { useTheme } from '@emotion/react'; +import React from 'react'; import { useRecoilValue } from 'recoil'; import { IconChevronDown } from 'twenty-ui'; @@ -11,8 +11,9 @@ import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/Styl import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; - import { GenericEntityFilterChip } from './GenericEntityFilterChip'; import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect'; import { ObjectFilterDropdownSearchInput } from './ObjectFilterDropdownSearchInput'; @@ -25,14 +26,13 @@ export const SingleEntityObjectFilterDropdownButton = ({ hotkeyScope: HotkeyScope; }) => { const { - availableFilterDefinitionsState, selectedFilterState, setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, } = useFilterDropdown(); - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, ); const selectedFilter = useRecoilValue(selectedFilterState); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx new file mode 100644 index 000000000000..b97deda7b578 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx @@ -0,0 +1,125 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { TaskGroups } from '@/activities/tasks/components/TaskGroups'; +import { MultipleFiltersDropdownButton } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton'; +import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { within } from '@storybook/test'; +import { ComponentDecorator } from 'twenty-ui'; +import { FieldMetadataType } from '~/generated/graphql'; +import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; + +const meta: Meta<typeof MultipleFiltersDropdownButton> = { + title: + 'Modules/ObjectRecord/ObjectFilterDropdown/MultipleFiltersDropdownButton', + component: MultipleFiltersDropdownButton, + decorators: [ + (Story) => { + const instanceId = 'entity-tasks-filter-scope'; + const setAvailableFilterDefinitions = useSetRecoilComponentStateV2( + availableFilterDefinitionsComponentState, + instanceId, + ); + + setAvailableFilterDefinitions([ + { + fieldMetadataId: '1', + iconName: 'IconUser', + label: 'Text', + type: FieldMetadataType.Text, + }, + { + fieldMetadataId: '2', + iconName: 'Icon123', + label: 'Email', + type: FieldMetadataType.Email, + }, + { + fieldMetadataId: '3', + iconName: 'IconNumber', + label: 'Number', + type: FieldMetadataType.Number, + }, + { + fieldMetadataId: '3', + iconName: 'IconCalendar', + label: 'Date', + type: FieldMetadataType.DateTime, + }, + ]); + return ( + <ViewComponentInstanceContext.Provider value={{ instanceId }}> + <ObjectFilterDropdownScope filterScopeId={instanceId}> + <Story /> + </ObjectFilterDropdownScope> + </ViewComponentInstanceContext.Provider> + ); + }, + ObjectMetadataItemsDecorator, + SnackBarDecorator, + ComponentDecorator, + IconsProviderDecorator, + ], + args: { + hotkeyScope: { + scope: 'object-filter-dropdown', + }, + }, +}; + +export default meta; +type Story = StoryObj<typeof TaskGroups>; + +export const Default: Story = { + play: async () => { + const canvas = within(document.body); + + const filterButton = await canvas.findByText('Filter'); + + filterButton.click(); + + const textFilter = await canvas.findByText('Text'); + + textFilter.click(); + + const operatorDropdown = await canvas.findByText('Contains'); + + operatorDropdown.click(); + + const containsOption = await canvas.findByText("Doesn't contain"); + + containsOption.click(); + }, +}; + +export const Date: Story = { + play: async () => { + const canvas = within(document.body); + + const filterButton = await canvas.findByText('Filter'); + + filterButton.click(); + + const dateFilter = await canvas.findByText('Date'); + + dateFilter.click(); + }, +}; + +export const Number: Story = { + play: async () => { + const canvas = within(document.body); + + const filterButton = await canvas.findByText('Filter'); + + filterButton.click(); + + const dateFilter = await canvas.findByText('Number'); + + dateFilter.click(); + }, +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx index 91aed0b40adc..b69584cb39d7 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx @@ -6,6 +6,8 @@ import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/ import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; const filterDropdownId = 'filterDropdownId'; @@ -35,11 +37,13 @@ describe('useFilterDropdown', () => { it('should set availableFilterDefinitions', async () => { const { result } = renderHook(() => { useFilterDropdown({ filterDropdownId }); - const { availableFilterDefinitionsState } = - useFilterDropdownStates(filterDropdownId); const [availableFilterDefinitions, setAvailableFilterDefinitions] = - useRecoilState(availableFilterDefinitionsState); + useRecoilComponentStateV2( + availableFilterDefinitionsComponentState, + filterDropdownId, + ); + return { availableFilterDefinitions, setAvailableFilterDefinitions }; }, renderHookConfig); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts index 8325af5e8085..b09d33a38396 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts @@ -18,7 +18,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { ); const { - availableFilterDefinitionsState, filterDefinitionUsedInDropdownState, objectFilterDropdownSearchInputState, objectFilterDropdownSelectedRecordIdsState, @@ -73,9 +72,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { ], ); - const setAvailableFilterDefinitions = useSetRecoilState( - availableFilterDefinitionsState, - ); const setSelectedFilter = useSetRecoilState(selectedFilterState); const setSelectedOperandInDropdown = useSetRecoilState( selectedOperandInDropdownState, @@ -106,7 +102,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { resetFilter, setSelectedFilter, setSelectedOperandInDropdown, - setAvailableFilterDefinitions, setFilterDefinitionUsedInDropdown, setObjectFilterDropdownSearchInput, // setObjectFilterDropdownSelectedEntityId, @@ -116,7 +111,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { setIsObjectFilterDropdownUnfolded, setOnFilterSelect, emptyFilterButKeepDefinition, - availableFilterDefinitionsState, filterDefinitionUsedInDropdownState, objectFilterDropdownSearchInputState, // objectFilterDropdownSelectedEntityIdState, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts index 82888840c7b7..8d9e5f1d08bd 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdownStates.ts @@ -8,14 +8,8 @@ import { onFilterSelectComponentState } from '@/object-record/object-filter-drop import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; -import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; export const useFilterDropdownStates = (scopeId: string) => { - const availableFilterDefinitionsState = extractComponentState( - availableFilterDefinitionsComponentState, - scopeId, - ); - const filterDefinitionUsedInDropdownState = extractComponentState( filterDefinitionUsedInDropdownComponentState, scopeId, @@ -63,7 +57,6 @@ export const useFilterDropdownStates = (scopeId: string) => { ); return { - availableFilterDefinitionsState, filterDefinitionUsedInDropdownState, objectFilterDropdownSearchInputState, objectFilterDropdownSelectedRecordIdsState, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts new file mode 100644 index 000000000000..005135444a9e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts @@ -0,0 +1,59 @@ +import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; +import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; +import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; +import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType'; +import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { v4 } from 'uuid'; + +type SelectFilterParams = { + filterDefinition: FilterDefinition; +}; + +export const useSelectFilter = () => { + const { + setFilterDefinitionUsedInDropdown, + setSelectedOperandInDropdown, + setObjectFilterDropdownSearchInput, + selectFilter: filterDropdownSelectFilter, + } = useFilterDropdown(); + + const setHotkeyScope = useSetHotkeyScope(); + + const selectFilter = ({ filterDefinition }: SelectFilterParams) => { + setFilterDefinitionUsedInDropdown(filterDefinition); + + if ( + filterDefinition.type === 'RELATION' || + filterDefinition.type === 'SELECT' + ) { + setHotkeyScope(RelationPickerHotkeyScope.RelationPicker); + } + + setSelectedOperandInDropdown( + getOperandsForFilterType(filterDefinition.type)?.[0], + ); + + const { value, displayValue } = getInitialFilterValue( + filterDefinition.type, + getOperandsForFilterType(filterDefinition.type)?.[0], + ); + + if (value !== '') { + filterDropdownSelectFilter({ + id: v4(), + fieldMetadataId: filterDefinition.fieldMetadataId, + displayValue, + operand: getOperandsForFilterType(filterDefinition.type)?.[0], + value, + definition: filterDefinition, + }); + } + + setObjectFilterDropdownSearchInput(''); + }; + + return { + selectFilter, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext.ts index 1c29844bd5f6..be81417c1ca9 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type ObjectFilterDropdownScopeInternalContextProps = ComponentStateKey; +type ObjectFilterDropdownScopeInternalContextProps = RecoilComponentStateKey; export const ObjectFilterDropdownScopeInternalContext = createScopeInternalContext<ObjectFilterDropdownScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/Filter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/Filter.ts index 52ed99ac5531..4d2eddb8756e 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/Filter.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/Filter.ts @@ -1,5 +1,4 @@ import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; - import { FilterDefinition } from './FilterDefinition'; export type Filter = { diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts index 875148acf06b..1803a88a54e4 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts @@ -1,6 +1,7 @@ export type FilterType = | 'TEXT' | 'PHONE' + | 'PHONES' | 'EMAIL' | 'EMAILS' | 'DATE_TIME' @@ -15,4 +16,5 @@ export type FilterType = | 'SELECT' | 'RATING' | 'MULTI_SELECT' - | 'ACTOR'; + | 'ACTOR' + | 'ARRAY'; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/__tests__/getOperandsForFilterType.test.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/__tests__/getOperandsForFilterType.test.tsx index 7b4b9516e7f4..a06f8455d1f4 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/__tests__/getOperandsForFilterType.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/__tests__/getOperandsForFilterType.test.tsx @@ -19,6 +19,16 @@ describe('getOperandsForFilterType', () => { ViewFilterOperand.LessThan, ]; + const dateOperands = [ + ViewFilterOperand.Is, + ViewFilterOperand.IsRelative, + ViewFilterOperand.IsInPast, + ViewFilterOperand.IsInFuture, + ViewFilterOperand.IsToday, + ViewFilterOperand.IsBefore, + ViewFilterOperand.IsAfter, + ]; + const relationOperand = [ViewFilterOperand.Is, ViewFilterOperand.IsNot]; const testCases = [ @@ -31,7 +41,8 @@ describe('getOperandsForFilterType', () => { ['ACTOR', [...containsOperands, ...emptyOperands]], ['CURRENCY', [...numberOperands, ...emptyOperands]], ['NUMBER', [...numberOperands, ...emptyOperands]], - ['DATE_TIME', [...numberOperands, ...emptyOperands]], + ['DATE', [...dateOperands, ...emptyOperands]], + ['DATE_TIME', [...dateOperands, ...emptyOperands]], ['RELATION', [...relationOperand, ...emptyOperands]], [undefined, []], [null, []], diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getInitialFilterValue.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getInitialFilterValue.ts new file mode 100644 index 000000000000..3076bef96d03 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getInitialFilterValue.ts @@ -0,0 +1,42 @@ +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { z } from 'zod'; + +export const getInitialFilterValue = ( + newType: FilterType, + newOperand: ViewFilterOperand, + oldValue?: string, + oldDisplayValue?: string, +): Pick<Filter, 'value' | 'displayValue'> | Record<string, never> => { + switch (newType) { + case 'DATE': + case 'DATE_TIME': { + const activeDatePickerOperands = [ + ViewFilterOperand.IsBefore, + ViewFilterOperand.Is, + ViewFilterOperand.IsAfter, + ]; + + if (activeDatePickerOperands.includes(newOperand)) { + const date = z.coerce.date().safeParse(oldValue).data ?? new Date(); + const value = date.toISOString(); + const displayValue = + newType === 'DATE' + ? date.toLocaleString() + : date.toLocaleDateString(); + + return { value, displayValue }; + } + + if (newOperand === ViewFilterOperand.IsRelative) { + return { value: '', displayValue: '' }; + } + break; + } + } + return { + value: oldValue ?? '', + displayValue: oldDisplayValue ?? '', + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandLabel.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandLabel.ts index 9c9e297ef960..b68049b51750 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandLabel.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandLabel.ts @@ -12,6 +12,10 @@ export const getOperandLabel = ( return 'Greater than'; case ViewFilterOperand.LessThan: return 'Less than'; + case ViewFilterOperand.IsBefore: + return 'Is before'; + case ViewFilterOperand.IsAfter: + return 'Is after'; case ViewFilterOperand.Is: return 'Is'; case ViewFilterOperand.IsNot: @@ -22,6 +26,14 @@ export const getOperandLabel = ( return 'Is empty'; case ViewFilterOperand.IsNotEmpty: return 'Is not empty'; + case ViewFilterOperand.IsRelative: + return 'Is relative'; + case ViewFilterOperand.IsInPast: + return 'Is in past'; + case ViewFilterOperand.IsInFuture: + return 'Is in future'; + case ViewFilterOperand.IsToday: + return 'Is today'; default: return ''; } @@ -47,6 +59,16 @@ export const getOperandLabelShort = ( return '\u00A0> '; case ViewFilterOperand.LessThan: return '\u00A0< '; + case ViewFilterOperand.IsBefore: + return '\u00A0< '; + case ViewFilterOperand.IsAfter: + return '\u00A0> '; + case ViewFilterOperand.IsInPast: + return ': Past'; + case ViewFilterOperand.IsInFuture: + return ': Future'; + case ViewFilterOperand.IsToday: + return ': Today'; default: return ': '; } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts index 8265e54a9fe3..d1066e2a5491 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts @@ -22,6 +22,8 @@ export const getOperandsForFilterType = ( case 'LINK': case 'LINKS': case 'ACTOR': + case 'ARRAY': + case 'PHONES': return [ ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain, @@ -29,13 +31,23 @@ export const getOperandsForFilterType = ( ]; case 'CURRENCY': case 'NUMBER': - case 'DATE_TIME': - case 'DATE': return [ ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan, ...emptyOperands, ]; + case 'DATE_TIME': + case 'DATE': + return [ + ViewFilterOperand.Is, + ViewFilterOperand.IsRelative, + ViewFilterOperand.IsInPast, + ViewFilterOperand.IsInFuture, + ViewFilterOperand.IsToday, + ViewFilterOperand.IsBefore, + ViewFilterOperand.IsAfter, + ...emptyOperands, + ]; case 'RATING': return [ ViewFilterOperand.Is, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue.ts new file mode 100644 index 000000000000..fb59e540180b --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue.ts @@ -0,0 +1,28 @@ +import { + VariableDateViewFilterValueDirection, + VariableDateViewFilterValueUnit, +} from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; +import { plural } from 'pluralize'; +import { capitalize } from '~/utils/string/capitalize'; +export const getRelativeDateDisplayValue = ( + relativeDate: { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; + } | null, +) => { + if (!relativeDate) return ''; + const { direction, amount, unit } = relativeDate; + + const directionStr = capitalize(direction.toLowerCase()); + const amountStr = direction === 'THIS' ? '' : amount; + const unitStr = amount + ? amount > 1 + ? plural(unit.toLowerCase()) + : unit.toLowerCase() + : undefined; + + return [directionStr, amountStr, unitStr] + .filter((item) => item !== undefined) + .join(' '); +}; diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx index 35869601c988..dbbc8d829745 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx @@ -39,6 +39,21 @@ export const StyledInput = styled.input` } `; +const StyledContainer = styled.div` + position: relative; +`; + +const StyledSelectedSortDirectionContainer = styled.div` + background: ${({ theme }) => theme.background.secondary}; + box-shadow: ${({ theme }) => theme.boxShadow.light}; + border-radius: ${({ theme }) => theme.border.radius.md}; + left: 10px; + position: absolute; + top: 10px; + width: 100%; + z-index: 1000; +`; + export type ObjectSortDropdownButtonProps = { sortDropdownId: string; hotkeyScope: HotkeyScope; @@ -95,60 +110,61 @@ export const ObjectSortDropdownButton = ({ } dropdownComponents={ <> - {isSortDirectionMenuUnfolded ? ( - <DropdownMenuItemsContainer> - {SORT_DIRECTIONS.map((sortOrder, index) => ( - <MenuItem - key={index} - onClick={() => { - setSelectedSortDirection(sortOrder); - setIsSortDirectionMenuUnfolded(false); - }} - text={sortOrder === 'asc' ? 'Ascending' : 'Descending'} - /> - ))} - </DropdownMenuItemsContainer> - ) : ( - <> - <DropdownMenuHeader - EndIcon={IconChevronDown} - onClick={() => setIsSortDirectionMenuUnfolded(true)} - > - {selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'} - </DropdownMenuHeader> - <StyledInput - autoFocus - value={objectSortDropdownSearchInput} - placeholder="Search fields" - onChange={(event) => - setObjectSortDropdownSearchInput(event.target.value) - } - /> + {isSortDirectionMenuUnfolded && ( + <StyledSelectedSortDirectionContainer> <DropdownMenuItemsContainer> - {[...availableSortDefinitions] - .sort((a, b) => a.label.localeCompare(b.label)) - .filter((item) => - item.label - .toLocaleLowerCase() - .includes( - objectSortDropdownSearchInput.toLocaleLowerCase(), - ), - ) - .map((availableSortDefinition, index) => ( - <MenuItem - testId={`select-sort-${index}`} - key={index} - onClick={() => { - setObjectSortDropdownSearchInput(''); - handleAddSort(availableSortDefinition); - }} - LeftIcon={getIcon(availableSortDefinition.iconName)} - text={availableSortDefinition.label} - /> - ))} + {SORT_DIRECTIONS.map((sortOrder, index) => ( + <MenuItem + key={index} + onClick={() => { + setSelectedSortDirection(sortOrder); + setIsSortDirectionMenuUnfolded(false); + }} + text={sortOrder === 'asc' ? 'Ascending' : 'Descending'} + /> + ))} </DropdownMenuItemsContainer> - </> + </StyledSelectedSortDirectionContainer> )} + <StyledContainer> + <DropdownMenuHeader + EndIcon={IconChevronDown} + onClick={() => setIsSortDirectionMenuUnfolded(true)} + > + {selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'} + </DropdownMenuHeader> + <StyledInput + autoFocus + value={objectSortDropdownSearchInput} + placeholder="Search fields" + onChange={(event) => + setObjectSortDropdownSearchInput(event.target.value) + } + /> + <DropdownMenuItemsContainer> + {[...availableSortDefinitions] + .sort((a, b) => a.label.localeCompare(b.label)) + .filter((item) => + item.label + .toLocaleLowerCase() + .includes( + objectSortDropdownSearchInput.toLocaleLowerCase(), + ), + ) + .map((availableSortDefinition, index) => ( + <MenuItem + testId={`select-sort-${index}`} + key={index} + onClick={() => { + setObjectSortDropdownSearchInput(''); + handleAddSort(availableSortDefinition); + }} + LeftIcon={getIcon(availableSortDefinition.iconName)} + text={availableSortDefinition.label} + /> + ))} + </DropdownMenuItemsContainer> + </StyledContainer> </> } onClose={handleDropdownButtonClose} diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx index 6bf6ddf0d53e..64de66d8950a 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/__tests__/useSortDropdown.test.tsx @@ -6,6 +6,8 @@ import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useS import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates'; import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; const Wrapper = ({ children }: { children: React.ReactNode }) => ( <RecoilRoot>{children}</RecoilRoot> @@ -24,11 +26,13 @@ describe('useSortDropdown', () => { it('should set availableSortDefinitions', async () => { const { result } = renderHook(() => { useSortDropdown({ sortDropdownId }); - const { availableSortDefinitionsState } = - useSortDropdownStates(sortDropdownId); + // TODO: verify this instance id works const [availableSortDefinitions, setAvailableSortDefinitions] = - useRecoilState(availableSortDefinitionsState); + useRecoilComponentStateV2( + availableSortDefinitionsComponentState, + sortDropdownId, + ); return { availableSortDefinitions, diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useObjectSortDropdown.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useObjectSortDropdown.ts index 4a797a259a4d..2cbe44c58a2a 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useObjectSortDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useObjectSortDropdown.ts @@ -7,6 +7,8 @@ import selectedSortDirectionState from '@/object-record/object-sort-dropdown/sta import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; import { OBJECT_SORT_DROPDOWN_ID, VIEW_SORT_DROPDOWN_ID, @@ -41,7 +43,6 @@ export const useObjectSortDropdown = () => { }; const { - availableSortDefinitionsState, onSortSelectState, isSortSelectedState, objectSortDropdownSearchInputState, @@ -52,8 +53,10 @@ export const useObjectSortDropdown = () => { }); const isSortSelected = useRecoilValue(isSortSelectedState); - const availableSortDefinitions = useRecoilValue( - availableSortDefinitionsState, + + const availableSortDefinitions = useRecoilComponentValueV2( + availableSortDefinitionsComponentState, + VIEW_SORT_DROPDOWN_ID, ); const onSortSelect = useRecoilValue(onSortSelectState); diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts index 44373f1fa430..3a857e28ca10 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdown.ts @@ -14,8 +14,8 @@ export const useSortDropdown = (props?: UseSortProps) => { ObjectSortDropdownScopeInternalContext, props?.sortDropdownId, ); + const { - availableSortDefinitionsState, isSortSelectedState, onSortSelectState, objectSortDropdownSearchInputState, @@ -35,7 +35,6 @@ export const useSortDropdown = (props?: UseSortProps) => { return { scopeId, - availableSortDefinitionsState, isSortSelectedState, onSortSelectState, objectSortDropdownSearchInputState, diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts index b36788076b69..40eb5623e677 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/hooks/useSortDropdownStates.ts @@ -2,14 +2,8 @@ import { isSortSelectedComponentState } from '@/object-record/object-sort-dropdo import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState'; import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; -import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; export const useSortDropdownStates = (scopeId: string) => { - const availableSortDefinitionsState = extractComponentState( - availableSortDefinitionsComponentState, - scopeId, - ); - const isSortSelectedState = extractComponentState( isSortSelectedComponentState, scopeId, @@ -26,7 +20,6 @@ export const useSortDropdownStates = (scopeId: string) => { ); return { - availableSortDefinitionsState, isSortSelectedState, onSortSelectState, objectSortDropdownSearchInputState, diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext.ts index 8454813f3d87..35a7798bc54e 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext.ts @@ -1,9 +1,9 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; import { Sort } from '../../types/Sort'; -type ObjectSortDropdownScopeInternalContextProps = ComponentStateKey & { +type ObjectSortDropdownScopeInternalContextProps = RecoilComponentStateKey & { onSortSelect?: (sort: Sort) => void; }; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx index 8d968c8dd5b2..4bfb9f2557fc 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx @@ -1,9 +1,3 @@ -import styled from '@emotion/styled'; -import { ReactNode, useContext, useState } from 'react'; -import { useInView } from 'react-intersection-observer'; -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; -import { AvatarChipVariant, IconEye } from 'twenty-ui'; - import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates'; import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext'; @@ -15,15 +9,24 @@ import { import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon'; import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell'; +import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode'; import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope'; import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Checkbox, CheckboxVariant } from '@/ui/input/components/Checkbox'; +import { TextInput } from '@/ui/input/components/TextInput'; import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/contextMenuIsOpenState'; import { contextMenuPositionState } from '@/ui/navigation/context-menu/states/contextMenuPositionState'; import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut'; import { RecordBoardScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts'; +import styled from '@emotion/styled'; +import { ReactNode, useContext, useState } from 'react'; +import { useInView } from 'react-intersection-observer'; +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; +import { AvatarChipVariant, IconEye } from 'twenty-ui'; +import { useAddNewCard } from '../../record-board-column/hooks/useAddNewCard'; const StyledBoardCard = styled.div<{ selected: boolean }>` background-color: ${({ theme, selected }) => @@ -61,6 +64,14 @@ const StyledBoardCard = styled.div<{ selected: boolean }>` } `; +const StyledTextInput = styled(TextInput)` + backdrop-filter: blur(12px) saturate(200%) contrast(50%) brightness(130%); + background: ${({ theme }) => theme.background.primary}; + box-shadow: ${({ theme }) => theme.boxShadow.strong}; + width: ${({ theme }) => theme.spacing(53)}; + border-radius: ${({ theme }) => theme.border.radius.sm}; +`; + const StyledBoardCardWrapper = styled.div` padding-bottom: ${({ theme }) => theme.spacing(2)}; width: 100%; @@ -83,7 +94,6 @@ export const StyledBoardCardHeader = styled.div<{ img { height: ${({ theme }) => theme.icon.size.md}px; - margin-right: ${({ theme }) => theme.spacing(2)}; object-fit: cover; width: ${({ theme }) => theme.icon.size.md}px; } @@ -131,7 +141,21 @@ const StyledRecordInlineCellPlaceholder = styled.div` height: 24px; `; -export const RecordBoardCard = () => { +const StyledRecordInlineCell = styled(RecordInlineCell)` + height: 24px; +`; + +export const RecordBoardCard = ({ + isCreating = false, + onCreateSuccess, + position, +}: { + isCreating?: boolean; + onCreateSuccess?: () => void; + position?: 'first' | 'last'; +}) => { + const [newLabelValue, setNewLabelValue] = useState(''); + const { handleBlur, handleInputEnter } = useAddNewCard(); const { recordId } = useContext(RecordBoardCardContext); const { updateOneRecord, objectMetadataItem } = useContext(RecordBoardContext); @@ -140,7 +164,6 @@ export const RecordBoardCard = () => { isRecordBoardCardSelectedFamilyState, visibleFieldDefinitionsState, } = useRecordBoardStates(); - const isCompactModeActive = useRecoilValue(isCompactModeActiveState); const [isCardInCompactMode, setIsCardInCompactMode] = useState(true); @@ -206,66 +229,106 @@ export const RecordBoardCard = () => { rootMargin: '1000px', }); - if (!record) { - return null; - } - const visibleFieldDefinitionsFiltered = visibleFieldDefinitions.filter( (boardField) => !boardField.isLabelIdentifier, ); + const labelIdentifierField = visibleFieldDefinitions.find( + (field) => field.isLabelIdentifier, + ); + return ( <StyledBoardCardWrapper onContextMenu={handleContextMenu}> - <RecordValueSetterEffect recordId={recordId} /> + {!isCreating && <RecordValueSetterEffect recordId={recordId} />} <StyledBoardCard ref={cardRef} selected={isCurrentCardSelected} onMouseLeave={onMouseLeaveBoard} onClick={() => { - setIsCurrentCardSelected(!isCurrentCardSelected); + if (!isCreating) { + setIsCurrentCardSelected(!isCurrentCardSelected); + } }} > <StyledBoardCardHeader showCompactView={isCompactModeActive}> - <RecordIdentifierChip - objectNameSingular={objectMetadataItem.nameSingular} - record={record} - variant={AvatarChipVariant.Transparent} - /> - {isCompactModeActive && ( - <StyledCompactIconContainer className="compact-icon-container"> - <LightIconButton - Icon={IconEye} - accent="tertiary" - onClick={(e) => { - e.stopPropagation(); - setIsCardInCompactMode(false); - }} + {isCreating && position !== undefined ? ( + <RecordInlineCellEditMode> + <StyledTextInput + autoFocus + value={newLabelValue} + onInputEnter={() => + handleInputEnter( + labelIdentifierField?.label ?? '', + newLabelValue, + position, + onCreateSuccess, + ) + } + onBlur={() => + handleBlur( + labelIdentifierField?.label ?? '', + newLabelValue, + position, + onCreateSuccess, + ) + } + onChange={(text: string) => setNewLabelValue(text)} + placeholder={labelIdentifierField?.label} /> - </StyledCompactIconContainer> - )} - <StyledCheckboxContainer className="checkbox-container"> - <Checkbox - hoverable - checked={isCurrentCardSelected} - onChange={() => setIsCurrentCardSelected(!isCurrentCardSelected)} - variant={CheckboxVariant.Secondary} + </RecordInlineCellEditMode> + ) : ( + <RecordIdentifierChip + objectNameSingular={objectMetadataItem.nameSingular} + record={record as ObjectRecord} + variant={AvatarChipVariant.Transparent} /> - </StyledCheckboxContainer> + )} + + {!isCreating && ( + <> + {isCompactModeActive && ( + <StyledCompactIconContainer className="compact-icon-container"> + <LightIconButton + Icon={IconEye} + accent="tertiary" + onClick={(e) => { + e.stopPropagation(); + setIsCardInCompactMode(false); + }} + /> + </StyledCompactIconContainer> + )} + + <StyledCheckboxContainer className="checkbox-container"> + <Checkbox + hoverable + checked={isCurrentCardSelected} + onChange={() => + setIsCurrentCardSelected(!isCurrentCardSelected) + } + variant={CheckboxVariant.Secondary} + /> + </StyledCheckboxContainer> + </> + )} </StyledBoardCardHeader> - <StyledBoardCardBody> - <AnimatedEaseInOut - isOpen={!isCardInCompactMode || !isCompactModeActive} - initial={false} - > + + <AnimatedEaseInOut + isOpen={!isCardInCompactMode || !isCompactModeActive} + initial={false} + > + <StyledBoardCardBody> {visibleFieldDefinitionsFiltered.map((fieldDefinition) => ( <PreventSelectOnClickContainer key={fieldDefinition.fieldMetadataId} > <FieldContext.Provider value={{ - recordId, + recordId: isCreating ? '' : recordId, maxWidth: 156, - recoilScopeId: recordId + fieldDefinition.fieldMetadataId, + recoilScopeId: + (isCreating ? 'new' : recordId) + + fieldDefinition.fieldMetadataId, isLabelIdentifier: false, fieldDefinition: { disableTooltip: false, @@ -285,15 +348,15 @@ export const RecordBoardCard = () => { }} > {inView ? ( - <RecordInlineCell /> + <StyledRecordInlineCell /> ) : ( <StyledRecordInlineCellPlaceholder /> )} </FieldContext.Provider> </PreventSelectOnClickContainer> ))} - </AnimatedEaseInOut> - </StyledBoardCardBody> + </StyledBoardCardBody> + </AnimatedEaseInOut> </StyledBoardCard> </StyledBoardCardWrapper> ); diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx index 79c786df1225..93a41e91043f 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer.tsx @@ -1,6 +1,6 @@ -import React, { useContext } from 'react'; import styled from '@emotion/styled'; import { Draggable, DroppableProvided } from '@hello-pangea/dnd'; +import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; @@ -110,7 +110,7 @@ export const RecordBoardColumnCardsContainer = ({ CoreObjectNameSingular.Opportunity ? ( <RecordBoardColumnNewOpportunityButton /> ) : ( - <RecordBoardColumnNewButton /> + <RecordBoardColumnNewButton columnId={columnDefinition.id} /> )} </StyledNewButtonContainer> </div> diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx index a730766c5ad3..1b07479660ce 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeader.tsx @@ -4,10 +4,11 @@ import { IconDotsVertical, IconPlus, Tag } from 'twenty-ui'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; +import { RecordBoardCard } from '@/object-record/record-board/record-board-card/components/RecordBoardCard'; import { RecordBoardColumnDropdownMenu } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnDropdownMenu'; import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; -import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard'; import { useAddNewOpportunity } from '@/object-record/record-board/record-board-column/hooks/useAddNewOpportunity'; +import { useColumnNewCardActions } from '@/object-record/record-board/record-board-column/hooks/useColumnNewCardActions'; import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope'; import { RecordBoardColumnDefinitionType } from '@/object-record/record-board/types/RecordBoardColumnDefinition'; import { SingleEntitySelect } from '@/object-record/relation-picker/components/SingleEntitySelect'; @@ -94,16 +95,16 @@ export const RecordBoardColumnHeader = () => { handleCancel, handleEntitySelect, } = useAddNewOpportunity('first'); - const { handleAddNewCardClick } = useAddNewCard('first'); + + const { newRecord, handleNewButtonClick, handleCreateSuccess } = + useColumnNewCardActions(columnDefinition.id); const isOpportunity = objectMetadataItem.nameSingular === CoreObjectNameSingular.Opportunity; const handleClick = isOpportunity ? handleAddNewOpportunityClick - : () => { - handleAddNewCardClick(); - }; + : () => handleNewButtonClick('first'); return ( <> @@ -164,6 +165,13 @@ export const RecordBoardColumnHeader = () => { stageId={columnDefinition.id} /> )} + {newRecord?.isCreating && newRecord.position === 'first' && ( + <RecordBoardCard + isCreating={true} + onCreateSuccess={() => handleCreateSuccess('first')} + position="first" + /> + )} {isCreatingCard && ( <SingleEntitySelect disableBackgroundBlur diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewButton.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewButton.tsx index c12e0c492374..6c116ede2025 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewButton.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnNewButton.tsx @@ -1,10 +1,10 @@ +import { RecordBoardCard } from '@/object-record/record-board/record-board-card/components/RecordBoardCard'; +import { useColumnNewCardActions } from '@/object-record/record-board/record-board-column/hooks/useColumnNewCardActions'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { IconPlus } from 'twenty-ui'; -import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard'; - -const StyledButton = styled.button` +const StyledNewButton = styled.button` align-items: center; align-self: baseline; background-color: ${({ theme }) => theme.background.primary}; @@ -15,19 +15,35 @@ const StyledButton = styled.button` display: flex; gap: ${({ theme }) => theme.spacing(1)}; padding: ${({ theme }) => theme.spacing(1)}; - &:hover { background-color: ${({ theme }) => theme.background.tertiary}; } `; -export const RecordBoardColumnNewButton = () => { +export const RecordBoardColumnNewButton = ({ + columnId, +}: { + columnId: string; +}) => { const theme = useTheme(); - const { handleAddNewCardClick } = useAddNewCard('last'); + + const { newRecord, handleNewButtonClick, handleCreateSuccess } = + useColumnNewCardActions(columnId); + + if (newRecord.isCreating && newRecord.position === 'last') { + return ( + <RecordBoardCard + isCreating={true} + onCreateSuccess={() => handleCreateSuccess('last')} + position="last" + /> + ); + } + return ( - <StyledButton onClick={handleAddNewCardClick}> + <StyledNewButton onClick={() => handleNewButtonClick('last')}> <IconPlus size={theme.icon.size.md} /> New - </StyledButton> + </StyledNewButton> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts index 24cb1e158548..cbc3d2e6b981 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewCard.ts @@ -1,20 +1,135 @@ import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; -import { useContext } from 'react'; +import { recordBoardNewRecordByColumnIdSelector } from '@/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector'; +import { useCallback, useContext } from 'react'; +import { useRecoilCallback } from 'recoil'; +import { v4 as uuidv4 } from 'uuid'; -export const useAddNewCard = (position: string) => { - const { columnDefinition } = useContext(RecordBoardColumnContext); +export const useAddNewCard = () => { + const columnContext = useContext(RecordBoardColumnContext); const { createOneRecord, selectFieldMetadataItem } = useContext(RecordBoardContext); - const handleAddNewCardClick = () => { - createOneRecord({ - [selectFieldMetadataItem.name]: columnDefinition.value, - position: position, - }); + const getColumnDefinitionId = useCallback( + (columnId?: string) => { + const columnDefinitionId = columnId || columnContext?.columnDefinition.id; + if (!columnDefinitionId) { + throw new Error('Column ID is required'); + } + return columnDefinitionId; + }, + [columnContext], + ); + + const addNewCard = useCallback( + (set: any, columnDefinitionId: string, position: 'first' | 'last') => { + set( + recordBoardNewRecordByColumnIdSelector({ + familyKey: columnDefinitionId, + scopeId: columnDefinitionId, + }), + { + id: uuidv4(), + columnId: columnDefinitionId, + isCreating: true, + position, + }, + ); + }, + [], + ); + + const createRecord = useCallback( + ( + labelIdentifier: string, + labelValue: string, + position: 'first' | 'last', + ) => { + if (labelValue !== '') { + createOneRecord({ + [selectFieldMetadataItem.name]: columnContext?.columnDefinition.value, + position, + [labelIdentifier.toLowerCase()]: labelValue, + }); + } + }, + [createOneRecord, columnContext, selectFieldMetadataItem], + ); + + const handleAddNewCardClick = useRecoilCallback( + ({ set }) => + ( + labelIdentifier: string, + labelValue: string, + position: 'first' | 'last', + columnId?: string, + ): void => { + const columnDefinitionId = getColumnDefinitionId(columnId); + addNewCard(set, columnDefinitionId, position); + createRecord(labelIdentifier, labelValue, position); + }, + [addNewCard, createRecord, getColumnDefinitionId], + ); + + const handleCreateSuccess = useRecoilCallback( + ({ set }) => + (position: 'first' | 'last', columnId?: string): void => { + const columnDefinitionId = getColumnDefinitionId(columnId); + set( + recordBoardNewRecordByColumnIdSelector({ + familyKey: columnDefinitionId, + scopeId: columnDefinitionId, + }), + { + id: '', + columnId: columnDefinitionId, + isCreating: false, + position, + }, + ); + }, + [getColumnDefinitionId], + ); + + const handleCreate = ( + labelIdentifier: string, + labelValue: string, + position: 'first' | 'last', + onCreateSuccess?: () => void, + ) => { + if (labelValue.trim() !== '' && position !== undefined) { + handleAddNewCardClick(labelIdentifier, labelValue.trim(), position); + onCreateSuccess?.(); + } + }; + + const handleBlur = ( + labelIdentifier: string, + labelValue: string, + position: 'first' | 'last', + onCreateSuccess?: () => void, + ) => { + if (labelValue.trim() === '') { + onCreateSuccess?.(); + } else { + handleCreate(labelIdentifier, labelValue, position, onCreateSuccess); + } + }; + + const handleInputEnter = ( + labelIdentifier: string, + labelValue: string, + position: 'first' | 'last', + onCreateSuccess?: () => void, + ) => { + handleCreate(labelIdentifier, labelValue, position, onCreateSuccess); }; return { handleAddNewCardClick, + handleCreateSuccess, + handleCreate, + handleBlur, + handleInputEnter, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewOpportunity.ts b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewOpportunity.ts index 230eedb281fb..d5ce6341646d 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewOpportunity.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useAddNewOpportunity.ts @@ -1,5 +1,6 @@ import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; +import { useIsOpportunitiesCompanyFieldDisabled } from '@/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled'; import { useEntitySelectSearch } from '@/object-record/relation-picker/hooks/useEntitySelectSearch'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; @@ -20,21 +21,19 @@ export const useAddNewOpportunity = (position: string) => { const { resetSearchFilter } = useEntitySelectSearch({ relationPickerScopeId: 'relation-picker', }); - + const { isOpportunitiesCompanyFieldDisabled } = + useIsOpportunitiesCompanyFieldDisabled(); const handleEntitySelect = useCallback( (company?: EntityForSelect) => { setIsCreatingCard(false); goBackToPreviousHotkeyScope(); resetSearchFilter(); - - if (company !== undefined) { - createOneRecord({ - name: company.name, - companyId: company.id, - position: position, - [selectFieldMetadataItem.name]: columnDefinition.value, - }); - } + createOneRecord({ + name: company?.name, + companyId: company?.id, + position: position, + [selectFieldMetadataItem.name]: columnDefinition.value, + }); }, [ columnDefinition, @@ -47,11 +46,19 @@ export const useAddNewOpportunity = (position: string) => { ); const handleAddNewOpportunityClick = useCallback(() => { - setIsCreatingCard(true); + if (isOpportunitiesCompanyFieldDisabled) { + handleEntitySelect(); + } else { + setIsCreatingCard(true); + } setHotkeyScopeAndMemorizePreviousScope( RelationPickerHotkeyScope.RelationPicker, ); - }, [setHotkeyScopeAndMemorizePreviousScope]); + }, [ + setHotkeyScopeAndMemorizePreviousScope, + isOpportunitiesCompanyFieldDisabled, + handleEntitySelect, + ]); const handleCancel = useCallback(() => { resetSearchFilter(); diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useColumnNewCardActions.ts b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useColumnNewCardActions.ts new file mode 100644 index 000000000000..8fd3ab2f4ad2 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useColumnNewCardActions.ts @@ -0,0 +1,38 @@ +import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates'; +import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard'; +import { recordBoardNewRecordByColumnIdSelector } from '@/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector'; +import { useRecoilValue } from 'recoil'; + +export const useColumnNewCardActions = (columnId: string) => { + const { visibleFieldDefinitionsState } = useRecordBoardStates(); + const visibleFieldDefinitions = useRecoilValue( + visibleFieldDefinitionsState(), + ); + const labelIdentifierField = visibleFieldDefinitions.find( + (field) => field.isLabelIdentifier, + ); + + const { handleAddNewCardClick, handleCreateSuccess } = useAddNewCard(); + + const newRecord = useRecoilValue( + recordBoardNewRecordByColumnIdSelector({ + familyKey: columnId, + scopeId: columnId, + }), + ); + + const handleNewButtonClick = (position: 'first' | 'last') => { + handleAddNewCardClick( + labelIdentifierField?.label ?? '', + '', + position, + columnId, + ); + }; + + return { + newRecord, + handleNewButtonClick, + handleCreateSuccess, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled.ts b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled.ts new file mode 100644 index 000000000000..f2895e81990d --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled.ts @@ -0,0 +1,17 @@ +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; + +export const useIsOpportunitiesCompanyFieldDisabled = () => { + const { objectMetadataItem: opportunityMetadataItem } = useObjectMetadataItem( + { + objectNameSingular: CoreObjectNameSingular.Opportunity, + }, + ); + const isOpportunitiesCompanyFieldDisabled = + !opportunityMetadataItem.fields.find( + (field) => field.name === CoreObjectNameSingular.Company, + )?.isActive || false; + return { + isOpportunitiesCompanyFieldDisabled, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts index 22aeae0edc3b..44ac1e08e1b8 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext.ts @@ -2,9 +2,9 @@ import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/ import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type RecordBoardScopeInternalContextProps = ComponentStateKey & { +type RecordBoardScopeInternalContextProps = RecoilComponentStateKey & { onFieldsChange: (fields: FieldDefinition<FieldMetadata>[]) => void; onColumnsChange: (column: RecordBoardColumnDefinition[]) => void; }; diff --git a/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts b/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts new file mode 100644 index 000000000000..bc362d973c70 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-board/states/recordBoardNewRecordByColumnIdComponentFamilyState.ts @@ -0,0 +1,19 @@ +import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; + +export type NewCard = { + id: string; + columnId: string; + isCreating: boolean; + position: 'first' | 'last'; +}; + +export const recordBoardNewRecordByColumnIdComponentFamilyState = + createComponentFamilyState<NewCard, string>({ + key: 'recordBoardNewRecordByColumnIdComponentFamilyState', + defaultValue: { + id: '', + columnId: '', + isCreating: false, + position: 'last', + }, + }); diff --git a/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector.ts b/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector.ts new file mode 100644 index 000000000000..122daffa3af1 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector.ts @@ -0,0 +1,31 @@ +import { createComponentFamilySelector } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelector'; +import { + NewCard, + recordBoardNewRecordByColumnIdComponentFamilyState, +} from '../recordBoardNewRecordByColumnIdComponentFamilyState'; + +export const recordBoardNewRecordByColumnIdSelector = + createComponentFamilySelector<NewCard, string>({ + key: 'recordBoardNewRecordByColumnIdSelector', + get: + ({ familyKey, scopeId }: { familyKey: string; scopeId: string }) => + ({ get }) => { + return get( + recordBoardNewRecordByColumnIdComponentFamilyState({ + familyKey, + scopeId, + }), + ) as NewCard; + }, + set: + ({ familyKey, scopeId }: { familyKey: string; scopeId: string }) => + ({ set }, newValue) => { + set( + recordBoardNewRecordByColumnIdComponentFamilyState({ + familyKey, + scopeId, + }), + newValue as NewCard, + ); + }, + }); diff --git a/packages/twenty-front/src/modules/object-record/record-field/__mocks__/fieldDefinitions.ts b/packages/twenty-front/src/modules/object-record/record-field/__mocks__/fieldDefinitions.ts index 3a3b49e69f28..e688a2a64544 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/__mocks__/fieldDefinitions.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/__mocks__/fieldDefinitions.ts @@ -72,11 +72,11 @@ export const linkFieldDefinition: FieldDefinition<FieldLinkMetadata> = { }, }; -const phoneFieldMetadataItem = mockedPersonObjectMetadataItem.fields?.find( - ({ name }) => name === 'phone', +const phonesFieldMetadataItem = mockedPersonObjectMetadataItem.fields?.find( + ({ name }) => name === 'phones', ); -export const phoneFieldDefinition = formatFieldMetadataItemAsFieldDefinition({ - field: phoneFieldMetadataItem!, +export const phonesFieldDefinition = formatFieldMetadataItemAsFieldDefinition({ + field: phonesFieldMetadataItem!, objectMetadataItem: mockedPersonObjectMetadataItem, }); diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx index 613eeb72f071..781ac98a650f 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx @@ -1,18 +1,22 @@ import { useContext } from 'react'; import { ActorFieldDisplay } from '@/object-record/record-field/meta-types/display/components/ActorFieldDisplay'; +import { ArrayFieldDisplay } from '@/object-record/record-field/meta-types/display/components/ArrayFieldDisplay'; import { BooleanFieldDisplay } from '@/object-record/record-field/meta-types/display/components/BooleanFieldDisplay'; import { EmailsFieldDisplay } from '@/object-record/record-field/meta-types/display/components/EmailsFieldDisplay'; import { LinksFieldDisplay } from '@/object-record/record-field/meta-types/display/components/LinksFieldDisplay'; +import { PhonesFieldDisplay } from '@/object-record/record-field/meta-types/display/components/PhonesFieldDisplay'; import { RatingFieldDisplay } from '@/object-record/record-field/meta-types/display/components/RatingFieldDisplay'; import { RelationFromManyFieldDisplay } from '@/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay'; import { RichTextFieldDisplay } from '@/object-record/record-field/meta-types/display/components/RichTextFieldDisplay'; import { isFieldIdentifierDisplay } from '@/object-record/record-field/meta-types/display/utils/isFieldIdentifierDisplay'; import { isFieldActor } from '@/object-record/record-field/types/guards/isFieldActor'; +import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray'; import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean'; import { isFieldDisplayedAsPhone } from '@/object-record/record-field/types/guards/isFieldDisplayedAsPhone'; import { isFieldEmails } from '@/object-record/record-field/types/guards/isFieldEmails'; import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; import { isFieldRating } from '@/object-record/record-field/types/guards/isFieldRating'; import { isFieldRelationFromManyObjects } from '@/object-record/record-field/types/guards/isFieldRelationFromManyObjects'; import { isFieldRelationToOneObject } from '@/object-record/record-field/types/guards/isFieldRelationToOneObject'; @@ -102,7 +106,11 @@ export const FieldDisplay = () => { <RichTextFieldDisplay /> ) : isFieldActor(fieldDefinition) ? ( <ActorFieldDisplay /> + ) : isFieldArray(fieldDefinition) ? ( + <ArrayFieldDisplay /> ) : isFieldEmails(fieldDefinition) ? ( <EmailsFieldDisplay /> + ) : isFieldPhones(fieldDefinition) ? ( + <PhonesFieldDisplay /> ) : null; }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx index 16555c0d1cf8..144a24a8b8b0 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx @@ -6,6 +6,7 @@ import { EmailsFieldInput } from '@/object-record/record-field/meta-types/input/ import { FullNameFieldInput } from '@/object-record/record-field/meta-types/input/components/FullNameFieldInput'; import { LinksFieldInput } from '@/object-record/record-field/meta-types/input/components/LinksFieldInput'; import { MultiSelectFieldInput } from '@/object-record/record-field/meta-types/input/components/MultiSelectFieldInput'; +import { PhonesFieldInput } from '@/object-record/record-field/meta-types/input/components/PhonesFieldInput'; import { RawJsonFieldInput } from '@/object-record/record-field/meta-types/input/components/RawJsonFieldInput'; import { RelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/components/RelationFromManyFieldInput'; import { SelectFieldInput } from '@/object-record/record-field/meta-types/input/components/SelectFieldInput'; @@ -16,13 +17,16 @@ import { isFieldEmails } from '@/object-record/record-field/types/guards/isField import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName'; import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks'; import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; import { isFieldRelationFromManyObjects } from '@/object-record/record-field/types/guards/isFieldRelationFromManyObjects'; import { isFieldRelationToOneObject } from '@/object-record/record-field/types/guards/isFieldRelationToOneObject'; import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId'; +import { ArrayFieldInput } from '@/object-record/record-field/meta-types/input/components/ArrayFieldInput'; import { RichTextFieldInput } from '@/object-record/record-field/meta-types/input/components/RichTextFieldInput'; +import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray'; import { isFieldRichText } from '@/object-record/record-field/types/guards/isFieldRichText'; import { FieldContext } from '../contexts/FieldContext'; import { BooleanFieldInput } from '../meta-types/input/components/BooleanFieldInput'; @@ -89,6 +93,8 @@ export const FieldInput = ({ onTab={onTab} onShiftTab={onShiftTab} /> + ) : isFieldPhones(fieldDefinition) ? ( + <PhonesFieldInput onCancel={onCancel} /> ) : isFieldText(fieldDefinition) ? ( <TextFieldInput onEnter={onEnter} @@ -183,6 +189,8 @@ export const FieldInput = ({ /> ) : isFieldRichText(fieldDefinition) ? ( <RichTextFieldInput /> + ) : isFieldArray(fieldDefinition) ? ( + <ArrayFieldInput onCancel={onCancel} /> ) : ( <></> )} diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useGetButtonIcon.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useGetButtonIcon.test.tsx index 8237c4ace637..e7c147a580cc 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useGetButtonIcon.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useGetButtonIcon.test.tsx @@ -1,10 +1,10 @@ -import { ReactNode } from 'react'; import { renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; import { IconPencil } from 'twenty-ui'; import { - phoneFieldDefinition, + phonesFieldDefinition, relationFieldDefinition, } from '@/object-record/record-field/__mocks__/fieldDefinitions'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; @@ -29,7 +29,7 @@ const getWrapper = </FieldContext.Provider> ); -const PhoneWrapper = getWrapper(phoneFieldDefinition); +const PhoneWrapper = getWrapper(phonesFieldDefinition); const RelationWrapper = getWrapper(relationFieldDefinition); describe('useGetButtonIcon', () => { diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldEmpty.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldEmpty.test.tsx index 02881a761474..0e32c1da8731 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldEmpty.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldEmpty.test.tsx @@ -1,8 +1,8 @@ -import { ReactNode } from 'react'; import { act, renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot, useSetRecoilState } from 'recoil'; -import { phoneFieldDefinition } from '@/object-record/record-field/__mocks__/fieldDefinitions'; +import { phonesFieldDefinition } from '@/object-record/record-field/__mocks__/fieldDefinitions'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { useIsFieldEmpty } from '@/object-record/record-field/hooks/useIsFieldEmpty'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; @@ -12,7 +12,7 @@ const recordId = 'recordId'; const Wrapper = ({ children }: { children: ReactNode }) => ( <FieldContext.Provider value={{ - fieldDefinition: phoneFieldDefinition, + fieldDefinition: phonesFieldDefinition, recordId, hotkeyScope: 'hotkeyScope', isLabelIdentifier: false, diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldInputOnly.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldInputOnly.test.tsx index 50e39ac55cd9..0d9d62368f3d 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldInputOnly.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldInputOnly.test.tsx @@ -3,7 +3,7 @@ import { ReactNode } from 'react'; import { RecoilRoot } from 'recoil'; import { - phoneFieldDefinition, + phonesFieldDefinition, ratingFieldDefinition, } from '@/object-record/record-field/__mocks__/fieldDefinitions'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; @@ -29,7 +29,7 @@ const getWrapper = ); const RatingWrapper = getWrapper(ratingFieldDefinition); -const PhoneWrapper = getWrapper(phoneFieldDefinition); +const PhoneWrapper = getWrapper(phonesFieldDefinition); describe('useIsFieldInputOnly', () => { it('should return true', () => { diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldReadOnly.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldReadOnly.test.tsx index 2baa6c2d34d8..f51cf795f861 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldReadOnly.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useIsFieldReadOnly.test.tsx @@ -4,7 +4,7 @@ import { RecoilRoot } from 'recoil'; import { actorFieldDefinition, - phoneFieldDefinition, + phonesFieldDefinition, } from '@/object-record/record-field/__mocks__/fieldDefinitions'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { useIsFieldReadOnly } from '@/object-record/record-field/hooks/useIsFieldReadOnly'; @@ -29,7 +29,7 @@ const getWrapper = ); const ActorWrapper = getWrapper(actorFieldDefinition); -const PhoneWrapper = getWrapper(phoneFieldDefinition); +const PhoneWrapper = getWrapper(phonesFieldDefinition); describe('useIsFieldReadOnly', () => { it('should return true', () => { diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/usePersistField.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/usePersistField.test.tsx index 6583c23d9d88..2e8756c2e8f0 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/usePersistField.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/usePersistField.test.tsx @@ -8,7 +8,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { PERSON_FRAGMENT } from '@/object-record/hooks/__mocks__/personFragment'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { - phoneFieldDefinition, + phonesFieldDefinition, relationFieldDefinition, } from '@/object-record/record-field/__mocks__/fieldDefinitions'; import { @@ -33,7 +33,16 @@ const mocks: MockedResponse[] = [ { request: { query, - variables: { idToUpdate: 'recordId', input: { phone: '+1 123 456' } }, + variables: { + idToUpdate: 'recordId', + input: { + phones: { + primaryPhoneNumber: '123 456', + primaryPhoneCountryCode: '+1', + additionalPhones: [], + }, + }, + }, }, result: jest.fn(() => ({ data: { @@ -98,7 +107,7 @@ const getWrapper = ); }; -const PhoneWrapper = getWrapper(phoneFieldDefinition); +const PhoneWrapper = getWrapper(phonesFieldDefinition); const RelationWrapper = getWrapper(relationFieldDefinition); describe('usePersistField', () => { @@ -118,7 +127,11 @@ describe('usePersistField', () => { ); act(() => { - result.current.persistField('+1 123 456'); + result.current.persistField({ + primaryPhoneNumber: '123 456', + primaryPhoneCountryCode: '+1', + additionalPhones: [], + }); }); await waitFor(() => { diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx index 4747c76bef90..86a2037c5d2c 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/__tests__/useToggleEditOnlyInput.test.tsx @@ -26,35 +26,13 @@ const mocks: MockedResponse[] = [ ) { updateCompany(id: $idToUpdate, data: $input) { __typename - id - visaSponsorship - createdBy { - source - workspaceMemberId - name - } + updatedAt domainName { primaryLinkUrl primaryLinkLabel secondaryLinks } - introVideo { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - position - annualRecurringRevenue { - amountMicros - currencyCode - } - employees - linkedinLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - workPolicy + visaSponsorship address { addressStreet1 addressStreet2 @@ -65,16 +43,38 @@ const mocks: MockedResponse[] = [ addressLat addressLng } + position + employees + deletedAt + accountOwnerId + annualRecurringRevenue { + amountMicros + currencyCode + } + id name - updatedAt xLink { primaryLinkUrl primaryLinkLabel secondaryLinks } - myCustomField createdAt - accountOwnerId + createdBy { + source + workspaceMemberId + name + } + workPolicy + introVideo { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } tagline idealCustomerProfile } diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/useInitDraftValueV2.ts b/packages/twenty-front/src/modules/object-record/record-field/hooks/useInitDraftValueV2.ts index 5c7f8fb2dadc..f3847113fbd7 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/useInitDraftValueV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/useInitDraftValueV2.ts @@ -27,7 +27,7 @@ export const useInitDraftValueV2 = <FieldValue>() => { const recordFieldInputScopeId = `${getRecordFieldInputId( recordId, fieldDefinition?.metadata?.fieldName, - )}-scope`; + )}`; const getDraftValueSelector = extractComponentSelector< FieldInputDraftValue<FieldValue> | undefined diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts b/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts index cc33c79a6216..0aa155a868c9 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts @@ -15,6 +15,8 @@ import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldL import { isFieldLinksValue } from '@/object-record/record-field/types/guards/isFieldLinksValue'; import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; +import { isFieldPhonesValue } from '@/object-record/record-field/types/guards/isFieldPhonesValue'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue'; import { isFieldRelationToOneObject } from '@/object-record/record-field/types/guards/isFieldRelationToOneObject'; @@ -24,6 +26,8 @@ import { isFieldSelectValue } from '@/object-record/record-field/types/guards/is import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; +import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray'; +import { isFieldArrayValue } from '@/object-record/record-field/types/guards/isFieldArrayValue'; import { FieldContext } from '../contexts/FieldContext'; import { isFieldBoolean } from '../types/guards/isFieldBoolean'; import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue'; @@ -104,6 +108,9 @@ export const usePersistField = () => { const fieldIsPhone = isFieldPhone(fieldDefinition) && isFieldPhoneValue(valueToPersist); + const fieldIsPhones = + isFieldPhones(fieldDefinition) && isFieldPhonesValue(valueToPersist); + const fieldIsSelect = isFieldSelect(fieldDefinition) && isFieldSelectValue(valueToPersist); @@ -119,6 +126,9 @@ export const usePersistField = () => { isFieldRawJson(fieldDefinition) && isFieldRawJsonValue(valueToPersist); + const fieldIsArray = + isFieldArray(fieldDefinition) && isFieldArrayValue(valueToPersist); + const isValuePersistable = fieldIsRelationToOneObject || fieldIsText || @@ -130,6 +140,7 @@ export const usePersistField = () => { fieldIsDateTime || fieldIsDate || fieldIsPhone || + fieldIsPhones || fieldIsLink || fieldIsLinks || fieldIsCurrency || @@ -137,7 +148,8 @@ export const usePersistField = () => { fieldIsSelect || fieldIsMultiSelect || fieldIsAddress || - fieldIsRawJson; + fieldIsRawJson || + fieldIsArray; if (isValuePersistable) { const fieldName = fieldDefinition.metadata.fieldName; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ArrayFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ArrayFieldDisplay.tsx new file mode 100644 index 000000000000..195d3bb87c1f --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ArrayFieldDisplay.tsx @@ -0,0 +1,34 @@ +import { THEME_COMMON } from 'twenty-ui'; + +import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus'; +import { useArrayFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useArrayFieldDisplay'; +import { ArrayDisplay } from '@/ui/field/display/components/ArrayDisplay'; +import styled from '@emotion/styled'; + +const spacing1 = THEME_COMMON.spacing(1); + +const StyledContainer = styled.div` + align-items: center; + display: flex; + flex-wrap: wrap; + gap: ${spacing1}; + justify-content: flex-start; + max-width: 100%; + overflow: hidden; +`; + +export const ArrayFieldDisplay = () => { + const { fieldValue } = useArrayFieldDisplay(); + + const { isFocused } = useFieldFocus(); + + if (!Array.isArray(fieldValue)) { + return <></>; + } + + return ( + <StyledContainer> + <ArrayDisplay value={fieldValue} isFocused={isFocused} /> + </StyledContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateFieldDisplay.tsx index 05b88fd267ec..86039881b0e4 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateFieldDisplay.tsx @@ -2,7 +2,15 @@ import { useDateFieldDisplay } from '@/object-record/record-field/meta-types/hoo import { DateDisplay } from '@/ui/field/display/components/DateDisplay'; export const DateFieldDisplay = () => { - const { fieldValue } = useDateFieldDisplay(); + const { fieldValue, fieldDefinition } = useDateFieldDisplay(); - return <DateDisplay value={fieldValue} />; + const displayAsRelativeDate = + fieldDefinition.metadata?.settings?.displayAsRelativeDate; + + return ( + <DateDisplay + value={fieldValue} + displayAsRelativeDate={displayAsRelativeDate} + /> + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateTimeFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateTimeFieldDisplay.tsx index 03ffc92d395b..9d67dff920d3 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateTimeFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/DateTimeFieldDisplay.tsx @@ -2,7 +2,15 @@ import { useDateTimeFieldDisplay } from '@/object-record/record-field/meta-types import { DateTimeDisplay } from '@/ui/field/display/components/DateTimeDisplay'; export const DateTimeFieldDisplay = () => { - const { fieldValue } = useDateTimeFieldDisplay(); + const { fieldValue, fieldDefinition } = useDateTimeFieldDisplay(); - return <DateTimeDisplay value={fieldValue} />; + const displayAsRelativeDate = + fieldDefinition.metadata?.settings?.displayAsRelativeDate; + + return ( + <DateTimeDisplay + value={fieldValue} + displayAsRelativeDate={displayAsRelativeDate} + /> + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhonesFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhonesFieldDisplay.tsx new file mode 100644 index 000000000000..5a7925c3238d --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/PhonesFieldDisplay.tsx @@ -0,0 +1,11 @@ +import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus'; +import { usePhonesFieldDisplay } from '@/object-record/record-field/meta-types/hooks/usePhonesFieldDisplay'; +import { PhonesDisplay } from '@/ui/field/display/components/PhonesDisplay'; + +export const PhonesFieldDisplay = () => { + const { fieldValue } = usePhonesFieldDisplay(); + + const { isFocused } = useFieldFocus(); + + return <PhonesDisplay value={fieldValue} isFocused={isFocused} />; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx index adfaea988958..48e83e11cc06 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/RelationFromManyFieldDisplay.tsx @@ -1,30 +1,91 @@ +import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTargetObjectRecords'; +import { NoteTarget } from '@/activities/types/NoteTarget'; +import { TaskTarget } from '@/activities/types/TaskTarget'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { RecordChip } from '@/object-record/components/RecordChip'; import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus'; import { useRelationFromManyFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useRelationFromManyFieldDisplay'; import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList'; +import { isNull } from '@sniptt/guards'; export const RelationFromManyFieldDisplay = () => { const { fieldValue, fieldDefinition } = useRelationFromManyFieldDisplay(); const { isFocused } = useFieldFocus(); + const { fieldName, objectMetadataNameSingular } = fieldDefinition.metadata; + const relationObjectNameSingular = fieldDefinition?.metadata.relationObjectMetadataNameSingular; + const { activityTargetObjectRecords } = useActivityTargetObjectRecords( + undefined, + fieldValue as NoteTarget[] | TaskTarget[], + ); + if (!fieldValue || !relationObjectNameSingular) { return null; } - return ( - <ExpandableList isChipCountDisplayed={isFocused}> - {fieldValue.map((record) => { - return ( - <RecordChip - key={record.id} - objectNameSingular={relationObjectNameSingular} - record={record} - /> - ); - })} - </ExpandableList> - ); + const isRelationFromActivityTargets = + (fieldName === 'noteTargets' && + objectMetadataNameSingular === CoreObjectNameSingular.Note) || + (fieldName === 'taskTargets' && + objectMetadataNameSingular === CoreObjectNameSingular.Task); + + const isRelationFromManyActivities = + (fieldName === 'noteTargets' && + objectMetadataNameSingular !== CoreObjectNameSingular.Note) || + (fieldName === 'taskTargets' && + objectMetadataNameSingular !== CoreObjectNameSingular.Task); + + if (isRelationFromManyActivities) { + const objectNameSingular = + fieldName === 'noteTargets' + ? CoreObjectNameSingular.Note + : CoreObjectNameSingular.Task; + + const relationFieldName = fieldName === 'noteTargets' ? 'note' : 'task'; + + return ( + <ExpandableList isChipCountDisplayed={isFocused}> + {fieldValue + .filter((record) => !isNull(record[relationFieldName])) + .map((record) => ( + <RecordChip + key={record.id} + objectNameSingular={objectNameSingular} + record={record[relationFieldName]} + /> + ))} + </ExpandableList> + ); + } else if (isRelationFromActivityTargets) { + return ( + <ExpandableList isChipCountDisplayed={isFocused}> + {activityTargetObjectRecords + .filter((record) => !isNull(record.targetObject)) + .map((record) => ( + <RecordChip + key={record.targetObject.id} + objectNameSingular={record.targetObjectMetadataItem.nameSingular} + record={record.targetObject} + /> + ))} + </ExpandableList> + ); + } else { + return ( + <ExpandableList isChipCountDisplayed={isFocused}> + {fieldValue + .filter((record) => !isNull(record)) + .map((record) => ( + <RecordChip + key={record.id} + objectNameSingular={relationObjectNameSingular} + record={record} + /> + ))} + </ExpandableList> + ); + } }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RatingFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RatingFieldDisplay.perf.stories.tsx index bf769c6474bd..3c31dc6d5682 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RatingFieldDisplay.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RatingFieldDisplay.perf.stories.tsx @@ -29,6 +29,6 @@ export const Default: Story = {}; export const Performance = getProfilingStory({ componentName: 'RatingFieldDisplay', averageThresholdInMs: 0.5, - numberOfRuns: 50, - numberOfTestsPerRun: 100, + numberOfRuns: 30, + numberOfTestsPerRun: 50, }); diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx index 96054d36a118..2c6b1977a80e 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/__stories__/perf/RelationFromManyFieldDisplay.perf.stories.tsx @@ -1,5 +1,5 @@ -import { useEffect } from 'react'; import { Meta, StoryObj } from '@storybook/react'; +import { useEffect } from 'react'; import { useSetRecoilState } from 'recoil'; import { ComponentDecorator } from 'twenty-ui'; @@ -94,9 +94,10 @@ type Story = StoryObj<typeof RelationFromManyFieldDisplay>; export const Default: Story = {}; +// TODO: optimize this component once we have morph many export const Performance = getProfilingStory({ componentName: 'RelationFromManyFieldDisplay', - averageThresholdInMs: 0.5, + averageThresholdInMs: 1, numberOfRuns: 20, numberOfTestsPerRun: 100, }); diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayField.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayField.ts new file mode 100644 index 000000000000..7178d7affeef --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayField.ts @@ -0,0 +1,44 @@ +import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; +import { usePersistField } from '@/object-record/record-field/hooks/usePersistField'; +import { FieldArrayValue } from '@/object-record/record-field/types/FieldMetadata'; +import { assertFieldMetadata } from '@/object-record/record-field/types/guards/assertFieldMetadata'; +import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray'; +import { arraySchema } from '@/object-record/record-field/types/guards/isFieldArrayValue'; +import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; +import { useContext } from 'react'; +import { useRecoilState } from 'recoil'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +export const useArrayField = () => { + const { recordId, fieldDefinition, hotkeyScope } = useContext(FieldContext); + + assertFieldMetadata(FieldMetadataType.Array, isFieldArray, fieldDefinition); + + const fieldName = fieldDefinition.metadata.fieldName; + + const [fieldValue, setFieldValue] = useRecoilState<FieldArrayValue>( + recordStoreFamilySelector({ + recordId, + fieldName, + }), + ); + + const persistField = usePersistField(); + + const persistArrayField = (nextValue: string[]) => { + if (!nextValue) persistField(null); + + try { + persistField(arraySchema.parse(nextValue)); + } catch { + return; + } + }; + + return { + fieldValue, + setFieldValue, + persistArrayField, + hotkeyScope, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayFieldDisplay.ts new file mode 100644 index 000000000000..e735febebba6 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useArrayFieldDisplay.ts @@ -0,0 +1,24 @@ +import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; +import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; +import { + FieldArrayMetadata, + FieldArrayValue, +} from '@/object-record/record-field/types/FieldMetadata'; +import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; +import { useContext } from 'react'; + +export const useArrayFieldDisplay = () => { + const { recordId, fieldDefinition } = useContext(FieldContext); + + const { fieldName } = fieldDefinition.metadata; + + const fieldValue = useRecordFieldValue<FieldArrayValue | undefined>( + recordId, + fieldName, + ); + + return { + fieldDefinition: fieldDefinition as FieldDefinition<FieldArrayMetadata>, + fieldValue, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateFieldDisplay.ts index 3f7e5407f64c..2e400704d9bb 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateFieldDisplay.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateFieldDisplay.ts @@ -2,6 +2,8 @@ import { useContext } from 'react'; import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; +import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; +import { FieldDateMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { FieldContext } from '../../contexts/FieldContext'; export const useDateFieldDisplay = () => { @@ -16,7 +18,10 @@ export const useDateFieldDisplay = () => { ); return { - fieldDefinition, + // TODO: we have to use this because we removed the assertion that would have otherwise narrowed the type because + // it impacts performance. We should find a way to assert the type in a way that doesn't impact performance. + // Maybe a level above ? + fieldDefinition: fieldDefinition as FieldDefinition<FieldDateMetadata>, fieldValue, hotkeyScope, clearable, diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateTimeFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateTimeFieldDisplay.ts index bc41e36a47f0..412271428fa4 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateTimeFieldDisplay.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useDateTimeFieldDisplay.ts @@ -2,6 +2,8 @@ import { useContext } from 'react'; import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; +import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; +import { FieldDateTimeMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { FieldContext } from '../../contexts/FieldContext'; export const useDateTimeFieldDisplay = () => { @@ -16,7 +18,7 @@ export const useDateTimeFieldDisplay = () => { ); return { - fieldDefinition, + fieldDefinition: fieldDefinition as FieldDefinition<FieldDateTimeMetadata>, fieldValue, hotkeyScope, clearable, diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesField.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesField.ts new file mode 100644 index 000000000000..109f1e5fb41b --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesField.ts @@ -0,0 +1,53 @@ +import { useContext } from 'react'; +import { useRecoilState, useRecoilValue } from 'recoil'; + +import { usePersistField } from '@/object-record/record-field/hooks/usePersistField'; +import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput'; +import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; +import { phonesSchema } from '@/object-record/record-field/types/guards/isFieldPhonesValue'; +import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +import { FieldContext } from '../../contexts/FieldContext'; +import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; + +export const usePhonesField = () => { + const { recordId, fieldDefinition, hotkeyScope } = useContext(FieldContext); + + assertFieldMetadata(FieldMetadataType.Phones, isFieldPhones, fieldDefinition); + + const fieldName = fieldDefinition.metadata.fieldName; + + const [fieldValue, setFieldValue] = useRecoilState<FieldPhonesValue>( + recordStoreFamilySelector({ + recordId, + fieldName: fieldName, + }), + ); + + const { setDraftValue, getDraftValueSelector } = + useRecordFieldInput<FieldPhonesValue>(`${recordId}-${fieldName}`); + + const draftValue = useRecoilValue(getDraftValueSelector()); + + const persistField = usePersistField(); + + const persistPhonesField = (nextValue: FieldPhonesValue) => { + try { + persistField(phonesSchema.parse(nextValue)); + } catch { + return; + } + }; + + return { + fieldDefinition, + fieldValue, + draftValue, + setDraftValue, + setFieldValue, + hotkeyScope, + persistPhonesField, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesFieldDisplay.ts new file mode 100644 index 000000000000..e1b33157854e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/usePhonesFieldDisplay.ts @@ -0,0 +1,22 @@ +import { useContext } from 'react'; + +import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata'; +import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; + +import { FieldContext } from '../../contexts/FieldContext'; + +export const usePhonesFieldDisplay = () => { + const { recordId, fieldDefinition } = useContext(FieldContext); + + const fieldName = fieldDefinition.metadata.fieldName; + + const fieldValue = useRecordFieldValue<FieldPhonesValue | undefined>( + recordId, + fieldName, + ); + + return { + fieldDefinition, + fieldValue, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldInput.tsx new file mode 100644 index 000000000000..2353f7d2fcfb --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldInput.tsx @@ -0,0 +1,39 @@ +import { useArrayField } from '@/object-record/record-field/meta-types/hooks/useArrayField'; +import { ArrayFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/ArrayFieldMenuItem'; +import { MultiItemFieldInput } from '@/object-record/record-field/meta-types/input/components/MultiItemFieldInput'; +import { useMemo } from 'react'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +type ArrayFieldInputProps = { + onCancel?: () => void; +}; + +export const ArrayFieldInput = ({ onCancel }: ArrayFieldInputProps) => { + const { persistArrayField, hotkeyScope, fieldValue } = useArrayField(); + + const arrayItems = useMemo<Array<string>>( + () => (Array.isArray(fieldValue) ? fieldValue : []), + [fieldValue], + ); + + return ( + <MultiItemFieldInput + hotkeyScope={hotkeyScope} + newItemLabel="Add Item" + items={arrayItems} + onPersist={persistArrayField} + onCancel={onCancel} + placeholder="Enter value" + fieldMetadataType={FieldMetadataType.Array} + renderItem={({ value, index, handleEdit, handleDelete }) => ( + <ArrayFieldMenuItem + key={index} + dropdownId={`${hotkeyScope}-array-${index}`} + value={value} + onEdit={handleEdit} + onDelete={handleDelete} + /> + )} + ></MultiItemFieldInput> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldMenuItem.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldMenuItem.tsx new file mode 100644 index 000000000000..cfe06add3ceb --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/ArrayFieldMenuItem.tsx @@ -0,0 +1,27 @@ +import { MultiItemFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/MultiItemFieldMenuItem'; +import { ArrayDisplay } from '@/ui/field/display/components/ArrayDisplay'; + +type ArrayFieldMenuItemProps = { + dropdownId: string; + onEdit?: () => void; + onDelete?: () => void; + value: string; +}; + +export const ArrayFieldMenuItem = ({ + dropdownId, + onEdit, + onDelete, + value, +}: ArrayFieldMenuItemProps) => { + return ( + <MultiItemFieldMenuItem + dropdownId={dropdownId} + value={value} + onEdit={onEdit} + onDelete={onDelete} + DisplayComponent={() => <ArrayDisplay value={[value]} isInputDisplay />} + hasPrimaryButton={false} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/EmailsFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/EmailsFieldInput.tsx index c3d90e7b1bbb..02ce963192b0 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/EmailsFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/EmailsFieldInput.tsx @@ -2,6 +2,7 @@ import { useEmailsField } from '@/object-record/record-field/meta-types/hooks/us import { EmailsFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/EmailsFieldMenuItem'; import { useMemo } from 'react'; import { isDefined } from 'twenty-ui'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { MultiItemFieldInput } from './MultiItemFieldInput'; type EmailsFieldInputProps = { @@ -34,6 +35,7 @@ export const EmailsFieldInput = ({ onCancel }: EmailsFieldInputProps) => { onPersist={handlePersistEmails} onCancel={onCancel} placeholder="Email" + fieldMetadataType={FieldMetadataType.Emails} renderItem={({ value: email, index, diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx index e7f40c461a1c..c8d7a5f52793 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx @@ -3,8 +3,7 @@ import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleT import { DoubleTextInput } from '@/ui/field/input/components/DoubleTextInput'; import { FieldInputOverlay } from '@/ui/field/input/components/FieldInputOverlay'; -import { usePersistField } from '../../../hooks/usePersistField'; - +import { isDoubleTextFieldEmpty } from '@/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty'; import { FieldInputEvent } from './DateTimeFieldInput'; const FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS = @@ -28,46 +27,55 @@ export const FullNameFieldInput = ({ onTab, onShiftTab, }: FullNameFieldInputProps) => { - const { hotkeyScope, draftValue, setDraftValue } = useFullNameField(); - - const persistField = usePersistField(); + const { hotkeyScope, draftValue, setDraftValue, persistFullNameField } = + useFullNameField(); const convertToFullName = (newDoubleText: FieldDoubleText) => { return { - firstName: newDoubleText.firstValue, - lastName: newDoubleText.secondValue, + firstName: newDoubleText.firstValue.trim(), + lastName: newDoubleText.secondValue.trim(), }; }; + const getRequiredDraftValueFromDoubleText = ( + newDoubleText: FieldDoubleText, + ) => { + return isDoubleTextFieldEmpty(newDoubleText) + ? undefined + : convertToFullName(newDoubleText); + }; + const handleEnter = (newDoubleText: FieldDoubleText) => { - onEnter?.(() => persistField(convertToFullName(newDoubleText))); + onEnter?.(() => persistFullNameField(convertToFullName(newDoubleText))); }; const handleEscape = (newDoubleText: FieldDoubleText) => { - onEscape?.(() => persistField(convertToFullName(newDoubleText))); + onEscape?.(() => persistFullNameField(convertToFullName(newDoubleText))); }; const handleClickOutside = ( event: MouseEvent | TouchEvent, newDoubleText: FieldDoubleText, ) => { - onClickOutside?.(() => persistField(convertToFullName(newDoubleText))); + onClickOutside?.(() => + persistFullNameField(convertToFullName(newDoubleText)), + ); }; const handleTab = (newDoubleText: FieldDoubleText) => { - onTab?.(() => persistField(convertToFullName(newDoubleText))); + onTab?.(() => persistFullNameField(convertToFullName(newDoubleText))); }; const handleShiftTab = (newDoubleText: FieldDoubleText) => { - onShiftTab?.(() => persistField(convertToFullName(newDoubleText))); + onShiftTab?.(() => persistFullNameField(convertToFullName(newDoubleText))); }; const handleChange = (newDoubleText: FieldDoubleText) => { - setDraftValue(convertToFullName(newDoubleText)); + setDraftValue(getRequiredDraftValueFromDoubleText(newDoubleText)); }; const handlePaste = (newDoubleText: FieldDoubleText) => { - setDraftValue(convertToFullName(newDoubleText)); + setDraftValue(getRequiredDraftValueFromDoubleText(newDoubleText)); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx index 66ed0055d8f0..c205039450f0 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldInput.tsx @@ -2,6 +2,7 @@ import { useLinksField } from '@/object-record/record-field/meta-types/hooks/use import { LinksFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/LinksFieldMenuItem'; import { useMemo } from 'react'; import { isDefined } from 'twenty-ui'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { absoluteUrlSchema } from '~/utils/validation-schemas/absoluteUrlSchema'; import { MultiItemFieldInput } from './MultiItemFieldInput'; @@ -47,6 +48,7 @@ export const LinksFieldInput = ({ onCancel }: LinksFieldInputProps) => { onPersist={handlePersistLinks} onCancel={onCancel} placeholder="URL" + fieldMetadataType={FieldMetadataType.Links} validateInput={(input) => absoluteUrlSchema.safeParse(input).success} formatInput={(input) => ({ url: input, label: '' })} renderItem={({ diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldInput.tsx index b223abfcff13..a73e49498805 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldInput.tsx @@ -1,16 +1,21 @@ import styled from '@emotion/styled'; -import { useRef, useState } from 'react'; +import React, { useRef, useState } from 'react'; import { Key } from 'ts-key-enum'; import { IconCheck, IconPlus } from 'twenty-ui'; +import { PhoneRecord } from '@/object-record/record-field/types/FieldMetadata'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; -import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; +import { + DropdownMenuInput, + DropdownMenuInputProps, +} from '@/ui/layout/dropdown/components/DropdownMenuInput'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { moveArrayItem } from '~/utils/array/moveArrayItem'; import { toSpliced } from '~/utils/array/toSpliced'; @@ -35,8 +40,12 @@ type MultiItemFieldInputProps<T> = { handleDelete: () => void; }) => React.ReactNode; hotkeyScope: string; + newItemLabel?: string; + fieldMetadataType: FieldMetadataType; + renderInput?: DropdownMenuInputProps['renderInput']; }; +// Todo: the API of this component does not look healthy: we have renderInput, renderItem, formatInput, ... export const MultiItemFieldInput = <T,>({ items, onPersist, @@ -46,9 +55,11 @@ export const MultiItemFieldInput = <T,>({ formatInput, renderItem, hotkeyScope, + newItemLabel, + fieldMetadataType, + renderInput, }: MultiItemFieldInputProps<T>) => { const containerRef = useRef<HTMLDivElement>(null); - const handleDropdownClose = () => { onCancel?.(); }; @@ -71,8 +82,25 @@ export const MultiItemFieldInput = <T,>({ }; const handleEditButtonClick = (index: number) => { + let item; + switch (fieldMetadataType) { + case FieldMetadataType.Links: + item = items[index] as { label: string; url: string }; + setInputValue(item.url || ''); + break; + case FieldMetadataType.Phones: + item = items[index] as PhoneRecord; + setInputValue(item.countryCode + item.number); + break; + case FieldMetadataType.Emails: + item = items[index] as string; + setInputValue(item); + break; + default: + throw new Error(`Unsupported field type: ${fieldMetadataType}`); + } + setItemToEditIndex(index); - setInputValue((items[index] as unknown as string) || ''); setIsInputDisplayed(true); }; @@ -132,6 +160,16 @@ export const MultiItemFieldInput = <T,>({ placeholder={placeholder} value={inputValue} hotkeyScope={hotkeyScope} + renderInput={ + renderInput + ? (props) => + renderInput({ + ...props, + onChange: (newValue) => + setInputValue(newValue as unknown as string), + }) + : undefined + } onChange={(event) => setInputValue(event.target.value)} onEnter={handleSubmitInput} rightComponent={ @@ -146,7 +184,7 @@ export const MultiItemFieldInput = <T,>({ <MenuItem onClick={handleAddButtonClick} LeftIcon={IconPlus} - text={`Add ${placeholder}`} + text={newItemLabel || `Add ${placeholder}`} /> </DropdownMenuItemsContainer> )} diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldMenuItem.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldMenuItem.tsx index 95fcf4e5a943..383b471217f9 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldMenuItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiItemFieldMenuItem.tsx @@ -21,6 +21,7 @@ type MultiItemFieldMenuItemProps<T> = { onSetAsPrimary?: () => void; onDelete?: () => void; DisplayComponent: React.ComponentType<{ value: T }>; + hasPrimaryButton?: boolean; }; const StyledIconBookmark = styled(IconBookmark)` @@ -37,6 +38,7 @@ export const MultiItemFieldMenuItem = <T,>({ onSetAsPrimary, onDelete, DisplayComponent, + hasPrimaryButton = true, }: MultiItemFieldMenuItemProps<T>) => { const [isHovered, setIsHovered] = useState(false); const { isDropdownOpen, closeDropdown } = useDropdown(dropdownId); @@ -74,7 +76,7 @@ export const MultiItemFieldMenuItem = <T,>({ clickableComponent={iconButton} dropdownComponents={ <DropdownMenuItemsContainer> - {!isPrimary && ( + {hasPrimaryButton && !isPrimary && ( <MenuItem LeftIcon={IconBookmarkPlus} text="Set as Primary" diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx index c6134f911a2d..7ebe1951edb6 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx @@ -16,6 +16,7 @@ import { MenuItemMultiSelectTag } from '@/ui/navigation/menu-item/components/Men import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { isDefined } from '~/utils/isDefined'; +import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; const StyledRelationPickerContainer = styled.div` left: -1px; @@ -33,7 +34,7 @@ export const MultiSelectFieldInput = ({ const { selectedItemIdState } = useSelectableListStates({ selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, }); - const { handleResetSelectedPosition } = useSelectableList( + const { resetSelectedItem } = useSelectableList( MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, ); const { persistField, fieldDefinition, fieldValues, hotkeyScope } = @@ -46,7 +47,9 @@ export const MultiSelectFieldInput = ({ fieldValues?.includes(option.value), ); - const optionsInDropDown = fieldDefinition.metadata.options; + const filteredOptionsInDropDown = fieldDefinition.metadata.options.filter( + (option) => option.label.toLowerCase().includes(searchFilter.toLowerCase()), + ); const formatNewSelectedOptions = (value: string) => { const selectedOptionsValues = selectedOptions.map( @@ -65,10 +68,10 @@ export const MultiSelectFieldInput = ({ Key.Escape, () => { onCancel?.(); - handleResetSelectedPosition(); + resetSelectedItem(); }, hotkeyScope, - [onCancel, handleResetSelectedPosition], + [onCancel, resetSelectedItem], ); useListenClickOutside({ @@ -83,11 +86,11 @@ export const MultiSelectFieldInput = ({ if (weAreNotInAnHTMLInput && isDefined(onCancel)) { onCancel(); } - handleResetSelectedPosition(); + resetSelectedItem(); }, }); - const optionIds = optionsInDropDown.map((option) => option.value); + const optionIds = filteredOptionsInDropDown.map((option) => option.value); return ( <SelectableList @@ -95,7 +98,7 @@ export const MultiSelectFieldInput = ({ selectableItemIdArray={optionIds} hotkeyScope={hotkeyScope} onEnter={(itemId) => { - const option = optionsInDropDown.find( + const option = filteredOptionsInDropDown.find( (option) => option.value === itemId, ); if (isDefined(option)) { @@ -107,12 +110,16 @@ export const MultiSelectFieldInput = ({ <DropdownMenu data-select-disable> <DropdownMenuSearchInput value={searchFilter} - onChange={(event) => setSearchFilter(event.currentTarget.value)} + onChange={(event) => + setSearchFilter( + turnIntoEmptyStringIfWhitespacesOnly(event.currentTarget.value), + ) + } autoFocus /> <DropdownMenuSeparator /> <DropdownMenuItemsContainer hasMaxHeight> - {optionsInDropDown.map((option) => { + {filteredOptionsInDropDown.map((option) => { return ( <MenuItemMultiSelectTag key={option.value} diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/NumberFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/NumberFieldInput.tsx index 336aefc99945..d5fead466f64 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/NumberFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/NumberFieldInput.tsx @@ -60,7 +60,7 @@ export const NumberFieldInput = ({ <TextInput placeholder={fieldDefinition.metadata.placeHolder} autoFocus - value={draftValue ?? ''} + value={draftValue?.toString() ?? ''} onClickOutside={handleClickOutside} onEnter={handleEnter} onEscape={handleEscape} diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldInput.tsx new file mode 100644 index 000000000000..6667acf2031f --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldInput.tsx @@ -0,0 +1,134 @@ +import { usePhonesField } from '@/object-record/record-field/meta-types/hooks/usePhonesField'; +import { PhonesFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem'; +import styled from '@emotion/styled'; +import { E164Number, parsePhoneNumber } from 'libphonenumber-js'; +import { useMemo } from 'react'; +import ReactPhoneNumberInput from 'react-phone-number-input'; +import 'react-phone-number-input/style.css'; +import { isDefined, TEXT_INPUT_STYLE } from 'twenty-ui'; + +import { MultiItemFieldInput } from './MultiItemFieldInput'; + +import { PhoneCountryPickerDropdownButton } from '@/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownButton'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +const StyledCustomPhoneInput = styled(ReactPhoneNumberInput)` + font-family: ${({ theme }) => theme.font.family}; + height: 32px; + ${TEXT_INPUT_STYLE} + padding: 0; + + .PhoneInputInput { + background: none; + border: none; + color: ${({ theme }) => theme.font.color.primary}; + + &::placeholder, + &::-webkit-input-placeholder { + color: ${({ theme }) => theme.font.color.light}; + font-family: ${({ theme }) => theme.font.family}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + } + + :focus { + outline: none; + } + } + + & svg { + border-radius: ${({ theme }) => theme.border.radius.xs}; + height: 12px; + } + width: calc(100% - ${({ theme }) => theme.spacing(8)}); +`; + +type PhonesFieldInputProps = { + onCancel?: () => void; +}; + +export const PhonesFieldInput = ({ onCancel }: PhonesFieldInputProps) => { + const { persistPhonesField, hotkeyScope, fieldValue } = usePhonesField(); + + const phones = useMemo<{ number: string; countryCode: string }[]>( + () => + [ + fieldValue.primaryPhoneNumber + ? { + number: fieldValue.primaryPhoneNumber, + countryCode: fieldValue.primaryPhoneCountryCode, + } + : null, + ...(fieldValue.additionalPhones ?? []), + ].filter(isDefined), + [ + fieldValue.primaryPhoneNumber, + fieldValue.primaryPhoneCountryCode, + fieldValue.additionalPhones, + ], + ); + + const handlePersistPhones = ( + updatedPhones: { number: string; countryCode: string }[], + ) => { + const [nextPrimaryPhone, ...nextAdditionalPhones] = updatedPhones; + persistPhonesField({ + primaryPhoneNumber: nextPrimaryPhone?.number ?? '', + primaryPhoneCountryCode: nextPrimaryPhone?.countryCode ?? '', + additionalPhones: nextAdditionalPhones, + }); + }; + + return ( + <MultiItemFieldInput + items={phones} + onPersist={handlePersistPhones} + onCancel={onCancel} + placeholder="Phone" + fieldMetadataType={FieldMetadataType.Phones} + formatInput={(input) => { + const phone = parsePhoneNumber(input); + if (phone !== undefined) { + return { + number: phone.nationalNumber, + countryCode: `+${phone.countryCallingCode}`, + }; + } + return { + number: '', + countryCode: '', + }; + }} + renderItem={({ + value: phone, + index, + handleEdit, + handleSetPrimary, + handleDelete, + }) => ( + <PhonesFieldMenuItem + key={index} + dropdownId={`${hotkeyScope}-phones-${index}`} + isPrimary={index === 0} + phone={phone} + onEdit={handleEdit} + onSetAsPrimary={handleSetPrimary} + onDelete={handleDelete} + /> + )} + renderInput={({ value, onChange, autoFocus, placeholder }) => { + return ( + <StyledCustomPhoneInput + autoFocus={autoFocus} + placeholder={placeholder} + value={value as E164Number} + onChange={onChange as unknown as (newValue: E164Number) => void} + international={true} + withCountryCallingCode={true} + countrySelectComponent={PhoneCountryPickerDropdownButton} + /> + ); + }} + hotkeyScope={hotkeyScope} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem.tsx new file mode 100644 index 000000000000..3f793d38fcd5 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem.tsx @@ -0,0 +1,32 @@ +import { PhoneDisplay } from '@/ui/field/display/components/PhoneDisplay'; +import { MultiItemFieldMenuItem } from './MultiItemFieldMenuItem'; + +type PhonesFieldMenuItemProps = { + dropdownId: string; + isPrimary?: boolean; + onEdit?: () => void; + onSetAsPrimary?: () => void; + onDelete?: () => void; + phone: { number: string; countryCode: string }; +}; + +export const PhonesFieldMenuItem = ({ + dropdownId, + isPrimary, + onEdit, + onSetAsPrimary, + onDelete, + phone, +}: PhonesFieldMenuItemProps) => { + return ( + <MultiItemFieldMenuItem + dropdownId={dropdownId} + isPrimary={isPrimary} + value={phone.countryCode + phone.number} + onEdit={onEdit} + onSetAsPrimary={onSetAsPrimary} + onDelete={onDelete} + DisplayComponent={PhoneDisplay} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx index d9082b850279..86bea16ad5a0 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/SelectFieldInput.tsx @@ -27,7 +27,7 @@ export const SelectFieldInput = ({ const [filteredOptions, setFilteredOptions] = useState<SelectOption[]>([]); - const { handleResetSelectedPosition } = useSelectableList( + const { resetSelectedItem } = useSelectableList( SINGLE_ENTITY_SELECT_BASE_LIST, ); const clearField = useClearField(); @@ -44,17 +44,17 @@ export const SelectFieldInput = ({ const handleSubmit = (option: SelectOption) => { onSubmit?.(() => persistField(option?.value)); - handleResetSelectedPosition(); + resetSelectedItem(); }; useScopedHotkeys( Key.Escape, () => { onCancel?.(); - handleResetSelectedPosition(); + resetSelectedItem(); }, hotkeyScope, - [onCancel, handleResetSelectedPosition], + [onCancel, resetSelectedItem], ); const optionIds = [ @@ -74,7 +74,7 @@ export const SelectFieldInput = ({ ); if (isDefined(option)) { onSubmit?.(() => persistField(option.value)); - handleResetSelectedPosition(); + resetSelectedItem(); } }} > diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/TextFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/TextFieldInput.tsx index 087dc37f48de..365ceb325f0c 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/TextFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/TextFieldInput.tsx @@ -4,6 +4,7 @@ import { TextAreaInput } from '@/ui/field/input/components/TextAreaInput'; import { usePersistField } from '../../../hooks/usePersistField'; import { useTextField } from '../../hooks/useTextField'; +import { turnIntoUndefinedIfWhitespacesOnly } from '~/utils/string/turnIntoUndefinedIfWhitespacesOnly'; import { FieldInputEvent } from './DateTimeFieldInput'; export type TextFieldInputProps = { @@ -25,32 +26,31 @@ export const TextFieldInput = ({ useTextField(); const persistField = usePersistField(); - const handleEnter = (newText: string) => { - onEnter?.(() => persistField(newText)); + onEnter?.(() => persistField(newText.trim())); }; const handleEscape = (newText: string) => { - onEscape?.(() => persistField(newText)); + onEscape?.(() => persistField(newText.trim())); }; const handleClickOutside = ( event: MouseEvent | TouchEvent, newText: string, ) => { - onClickOutside?.(() => persistField(newText)); + onClickOutside?.(() => persistField(newText.trim())); }; const handleTab = (newText: string) => { - onTab?.(() => persistField(newText)); + onTab?.(() => persistField(newText.trim())); }; const handleShiftTab = (newText: string) => { - onShiftTab?.(() => persistField(newText)); + onShiftTab?.(() => persistField(newText.trim())); }; const handleChange = (newText: string) => { - setDraftValue(newText); + setDraftValue(turnIntoUndefinedIfWhitespacesOnly(newText)); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx index 58de113f3113..09c405061fb7 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationToOneFieldInput.stories.tsx @@ -1,4 +1,3 @@ -import { useEffect } from 'react'; import { Decorator, Meta, StoryObj } from '@storybook/react'; import { expect, @@ -8,6 +7,7 @@ import { waitFor, within, } from '@storybook/test'; +import { useEffect } from 'react'; import { useSetRecoilState } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; @@ -141,7 +141,9 @@ export const Submit: Story = { expect(submitJestFn).toHaveBeenCalledTimes(0); - const item = await canvas.findByText('John Wick'); + const item = await canvas.findByText('John Wick', undefined, { + timeout: 3000, + }); await waitFor(() => { userEvent.click(item); @@ -156,7 +158,7 @@ export const Cancel: Story = { const canvas = within(canvasElement); expect(cancelJestFn).toHaveBeenCalledTimes(0); - await canvas.findByText('John Wick'); + await canvas.findByText('John Wick', undefined, { timeout: 3000 }); const emptyDiv = canvas.getByTestId('data-field-input-click-outside-div'); fireEvent.click(emptyDiv); diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty.ts new file mode 100644 index 000000000000..1ffdc0e78ffa --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty.ts @@ -0,0 +1,9 @@ +import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleText'; + +export const isDoubleTextFieldEmpty = (doubleText: FieldDoubleText) => { + const { firstValue, secondValue } = doubleText; + + const totalLength = firstValue.trim().length + secondValue.trim().length; + + return totalLength > 0 ? false : true; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/scopes/scope-internal-context/RecordFieldInputScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/record-field/scopes/scope-internal-context/RecordFieldInputScopeInternalContext.ts index eebf6c22d583..94769746b2fc 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/scopes/scope-internal-context/RecordFieldInputScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/scopes/scope-internal-context/RecordFieldInputScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type RecordFieldInputScopeInternalContextProps = ComponentStateKey; +type RecordFieldInputScopeInternalContextProps = RecoilComponentStateKey; export const RecordFieldInputScopeInternalContext = createScopeInternalContext<RecordFieldInputScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/FieldDefinition.ts b/packages/twenty-front/src/modules/object-record/record-field/types/FieldDefinition.ts index f1ab2a9929e2..16f05f2418d2 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/FieldDefinition.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/FieldDefinition.ts @@ -4,17 +4,6 @@ import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldMetadata } from './FieldMetadata'; -export type FieldDefinitionRelationType = - | 'FROM_MANY_OBJECTS' - | 'FROM_ONE_OBJECT' - | 'TO_MANY_OBJECTS' - | 'TO_ONE_OBJECT'; - -export type RelationDirections = { - from: FieldDefinitionRelationType; - to: FieldDefinitionRelationType; -}; - export type FieldDefinition<T extends FieldMetadata> = { fieldMetadataId: string; label: string; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/FieldInputDraftValue.ts b/packages/twenty-front/src/modules/object-record/record-field/types/FieldInputDraftValue.ts index b3196f1c702f..9ab99492f651 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/FieldInputDraftValue.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/FieldInputDraftValue.ts @@ -13,6 +13,7 @@ import { FieldLinkValue, FieldMultiSelectValue, FieldNumberValue, + FieldPhonesValue, FieldPhoneValue, FieldRatingValue, FieldRelationFromManyValue, @@ -20,12 +21,18 @@ import { FieldSelectValue, FieldTextValue, FieldUUidValue, + PhoneRecord, } from '@/object-record/record-field/types/FieldMetadata'; export type FieldTextDraftValue = string; -export type FieldNumberDraftValue = string; +export type FieldNumberDraftValue = number; export type FieldDateTimeDraftValue = string; export type FieldPhoneDraftValue = string; +export type FieldPhonesDraftValue = { + primaryPhoneNumber: string; + primaryPhoneCountryCode: string; + additionalPhones?: PhoneRecord[] | null; +}; export type FieldEmailDraftValue = string; export type FieldEmailsDraftValue = { primaryEmail: string; @@ -75,32 +82,34 @@ export type FieldInputDraftValue<FieldValue> = FieldValue extends FieldTextValue ? FieldBooleanValue : FieldValue extends FieldPhoneValue ? FieldPhoneDraftValue - : FieldValue extends FieldEmailValue - ? FieldEmailDraftValue - : FieldValue extends FieldEmailsValue - ? FieldEmailsDraftValue - : FieldValue extends FieldLinkValue - ? FieldLinkDraftValue - : FieldValue extends FieldLinksValue - ? FieldLinksDraftValue - : FieldValue extends FieldCurrencyValue - ? FieldCurrencyDraftValue - : FieldValue extends FieldFullNameValue - ? FieldFullNameDraftValue - : FieldValue extends FieldRatingValue - ? FieldRatingValue - : FieldValue extends FieldSelectValue - ? FieldSelectDraftValue - : FieldValue extends FieldMultiSelectValue - ? FieldMultiSelectDraftValue - : FieldValue extends FieldRelationToOneValue - ? FieldRelationDraftValue - : FieldValue extends FieldRelationFromManyValue - ? FieldRelationManyDraftValue - : FieldValue extends FieldAddressValue - ? FieldAddressDraftValue - : FieldValue extends FieldJsonValue - ? FieldJsonDraftValue - : FieldValue extends FieldActorValue - ? FieldActorDraftValue - : never; + : FieldValue extends FieldPhonesValue + ? FieldPhonesDraftValue + : FieldValue extends FieldEmailValue + ? FieldEmailDraftValue + : FieldValue extends FieldEmailsValue + ? FieldEmailsDraftValue + : FieldValue extends FieldLinkValue + ? FieldLinkDraftValue + : FieldValue extends FieldLinksValue + ? FieldLinksDraftValue + : FieldValue extends FieldCurrencyValue + ? FieldCurrencyDraftValue + : FieldValue extends FieldFullNameValue + ? FieldFullNameDraftValue + : FieldValue extends FieldRatingValue + ? FieldRatingValue + : FieldValue extends FieldSelectValue + ? FieldSelectDraftValue + : FieldValue extends FieldMultiSelectValue + ? FieldMultiSelectDraftValue + : FieldValue extends FieldRelationToOneValue + ? FieldRelationDraftValue + : FieldValue extends FieldRelationFromManyValue + ? FieldRelationManyDraftValue + : FieldValue extends FieldAddressValue + ? FieldAddressDraftValue + : FieldValue extends FieldJsonValue + ? FieldJsonDraftValue + : FieldValue extends FieldActorValue + ? FieldActorDraftValue + : never; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts b/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts index 367f14680570..a2a3339e1977 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts @@ -3,8 +3,8 @@ import { ThemeColor } from 'twenty-ui'; import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; import { ZodHelperLiteral } from '@/object-record/record-field/types/ZodHelperLiteral'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; -import { WithNarrowedStringLiteralProperty } from '~/types/WithNarrowedStringLiteralProperty'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { CurrencyCode } from './CurrencyCode'; export type FieldUuidMetadata = { @@ -27,12 +27,18 @@ export type FieldDateTimeMetadata = { objectMetadataNameSingular?: string; placeHolder: string; fieldName: string; + settings?: { + displayAsRelativeDate?: boolean; + }; }; export type FieldDateMetadata = { objectMetadataNameSingular?: string; placeHolder: string; fieldName: string; + settings?: { + displayAsRelativeDate?: boolean; + }; }; export type FieldNumberMetadata = { @@ -110,35 +116,17 @@ export type FieldPositionMetadata = { fieldName: string; }; -export type FieldDefinitionRelationType = - | 'FROM_MANY_OBJECTS' - | 'FROM_ONE_OBJECT' - | 'TO_MANY_OBJECTS' - | 'TO_ONE_OBJECT'; - export type FieldRelationMetadata = { fieldName: string; objectMetadataNameSingular?: string; relationFieldMetadataId: string; relationObjectMetadataNamePlural: string; relationObjectMetadataNameSingular: string; - relationType?: FieldDefinitionRelationType; + relationType?: RelationDefinitionType; targetFieldMetadataName?: string; useEditButton?: boolean; }; -export type FieldRelationOneMetadata = WithNarrowedStringLiteralProperty< - FieldRelationMetadata, - 'relationType', - 'TO_ONE_OBJECT' ->; - -export type FieldRelationManyMetadata = WithNarrowedStringLiteralProperty< - FieldRelationMetadata, - 'relationType', - 'FROM_MANY_OBJECTS' ->; - export type FieldSelectMetadata = { objectMetadataNameSingular?: string; fieldName: string; @@ -157,6 +145,17 @@ export type FieldActorMetadata = { fieldName: string; }; +export type FieldArrayMetadata = { + objectMetadataNameSingular?: string; + fieldName: string; + values: { label: string; value: string }[]; +}; + +export type FieldPhonesMetadata = { + objectMetadataNameSingular?: string; + fieldName: string; +}; + export type FieldMetadata = | FieldBooleanMetadata | FieldCurrencyMetadata @@ -174,7 +173,8 @@ export type FieldMetadata = | FieldTextMetadata | FieldUuidMetadata | FieldAddressMetadata - | FieldActorMetadata; + | FieldActorMetadata + | FieldArrayMetadata; export type FieldTextValue = string; export type FieldUUidValue = string; @@ -230,3 +230,13 @@ export type FieldActorValue = { workspaceMemberId?: string; name: string; }; + +export type FieldArrayValue = string[]; + +export type PhoneRecord = { number: string; countryCode: string }; + +export type FieldPhonesValue = { + primaryPhoneNumber: string; + primaryPhoneCountryCode: string; + additionalPhones?: PhoneRecord[] | null; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/assertFieldMetadata.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/assertFieldMetadata.ts index 9c94d9b666a7..90e6960c77ba 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/assertFieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/assertFieldMetadata.ts @@ -4,6 +4,7 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldActorMetadata, FieldAddressMetadata, + FieldArrayMetadata, FieldBooleanMetadata, FieldCurrencyMetadata, FieldDateMetadata, @@ -17,6 +18,7 @@ import { FieldMultiSelectMetadata, FieldNumberMetadata, FieldPhoneMetadata, + FieldPhonesMetadata, FieldRatingMetadata, FieldRawJsonMetadata, FieldRelationMetadata, @@ -69,7 +71,11 @@ type AssertFieldMetadataFunction = < ? FieldTextMetadata : E extends 'ACTOR' ? FieldActorMetadata - : never, + : E extends 'ARRAY' + ? FieldArrayMetadata + : E extends 'PHONES' + ? FieldPhonesMetadata + : never, >( fieldType: E, fieldTypeGuard: ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArray.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArray.ts new file mode 100644 index 000000000000..c179d2514052 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArray.ts @@ -0,0 +1,9 @@ +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +import { FieldDefinition } from '../FieldDefinition'; +import { FieldArrayMetadata, FieldMetadata } from '../FieldMetadata'; + +export const isFieldArray = ( + field: Pick<FieldDefinition<FieldMetadata>, 'type'>, +): field is FieldDefinition<FieldArrayMetadata> => + field.type === FieldMetadataType.Array; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArrayValue.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArrayValue.ts new file mode 100644 index 000000000000..8be30f0e2646 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldArrayValue.ts @@ -0,0 +1,8 @@ +import { FieldArrayValue } from '@/object-record/record-field/types/FieldMetadata'; +import { z } from 'zod'; + +export const arraySchema = z.union([z.null(), z.array(z.string())]); + +export const isFieldArrayValue = ( + fieldValue: unknown, +): fieldValue is FieldArrayValue => arraySchema.safeParse(fieldValue).success; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhones.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhones.ts new file mode 100644 index 000000000000..156adfe6340c --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhones.ts @@ -0,0 +1,9 @@ +import { FieldMetadataType } from '~/generated-metadata/graphql'; + +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldPhonesMetadata } from '../FieldMetadata'; + +export const isFieldPhones = ( + field: Pick<FieldDefinition<FieldMetadata>, 'type'>, +): field is FieldDefinition<FieldPhonesMetadata> => + field.type === FieldMetadataType.Phones; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhonesValue.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhonesValue.ts new file mode 100644 index 000000000000..fa60d1980b9b --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhonesValue.ts @@ -0,0 +1,15 @@ +import { z } from 'zod'; + +import { FieldPhonesValue } from '../FieldMetadata'; + +export const phonesSchema = z.object({ + primaryPhoneNumber: z.string(), + primaryPhoneCountryCode: z.string(), + additionalPhones: z + .array(z.object({ number: z.string(), countryCode: z.string() })) + .nullable(), +}) satisfies z.ZodType<FieldPhonesValue>; + +export const isFieldPhonesValue = ( + fieldValue: unknown, +): fieldValue is FieldPhonesValue => phonesSchema.safeParse(fieldValue).success; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationFromManyObjects.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationFromManyObjects.ts index 03559df5d356..e325df622c5a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationFromManyObjects.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationFromManyObjects.ts @@ -1,9 +1,11 @@ import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; -import { FieldMetadata, FieldRelationManyMetadata } from '../FieldMetadata'; +import { FieldMetadata } from '../FieldMetadata'; export const isFieldRelationFromManyObjects = ( field: Pick<FieldDefinition<FieldMetadata>, 'type' | 'metadata'>, -): field is FieldDefinition<FieldRelationManyMetadata> => - isFieldRelation(field) && field.metadata.relationType === 'FROM_MANY_OBJECTS'; +): field is FieldDefinition<FieldMetadata> => + isFieldRelation(field) && + field.metadata.relationType === RelationDefinitionType.OneToMany; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationToOneObject.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationToOneObject.ts index d1a1bb365aab..12b9958ade93 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationToOneObject.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelationToOneObject.ts @@ -1,9 +1,11 @@ import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; -import { FieldMetadata, FieldRelationOneMetadata } from '../FieldMetadata'; +import { FieldMetadata } from '../FieldMetadata'; export const isFieldRelationToOneObject = ( field: Pick<FieldDefinition<FieldMetadata>, 'type' | 'metadata'>, -): field is FieldDefinition<FieldRelationOneMetadata> => - isFieldRelation(field) && field.metadata.relationType === 'TO_ONE_OBJECT'; +): field is FieldDefinition<FieldMetadata> => + isFieldRelation(field) && + field.metadata.relationType === RelationDefinitionType.ManyToOne; diff --git a/packages/twenty-front/src/modules/object-record/record-field/utils/computeDraftValueFromString.ts b/packages/twenty-front/src/modules/object-record/record-field/utils/computeDraftValueFromString.ts index d41d5fd85100..c668801e33aa 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/utils/computeDraftValueFromString.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/utils/computeDraftValueFromString.ts @@ -6,10 +6,12 @@ import { isFieldAddress } from '@/object-record/record-field/types/guards/isFiel import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency'; import { isFieldDateTime } from '@/object-record/record-field/types/guards/isFieldDateTime'; import { isFieldEmail } from '@/object-record/record-field/types/guards/isFieldEmail'; +import { isFieldEmails } from '@/object-record/record-field/types/guards/isFieldEmails'; import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName'; import { isFieldLink } from '@/object-record/record-field/types/guards/isFieldLink'; import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks'; import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText'; import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid'; @@ -66,5 +68,17 @@ export const computeDraftValueFromString = <FieldValue>({ } as FieldInputDraftValue<FieldValue>; } + if (isFieldEmails(fieldDefinition)) { + return { + primaryEmail: value, + } as FieldInputDraftValue<FieldValue>; + } + + if (isFieldPhones(fieldDefinition)) { + return { + primaryPhoneNumber: value, + } as FieldInputDraftValue<FieldValue>; + } + throw new Error(`Record field type not supported : ${fieldDefinition.type}}`); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/utils/getFieldButtonIcon.tsx b/packages/twenty-front/src/modules/object-record/record-field/utils/getFieldButtonIcon.tsx index b100872b5470..5743a74cbb1a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/utils/getFieldButtonIcon.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/utils/getFieldButtonIcon.tsx @@ -6,9 +6,11 @@ import { isFieldDisplayedAsPhone } from '@/object-record/record-field/types/guar import { isFieldEmails } from '@/object-record/record-field/types/guards/isFieldEmails'; import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks'; import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; +import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray'; import { isFieldEmail } from '../types/guards/isFieldEmail'; import { isFieldLink } from '../types/guards/isFieldLink'; import { isFieldPhone } from '../types/guards/isFieldPhone'; @@ -31,7 +33,9 @@ export const getFieldButtonIcon = ( fieldDefinition.metadata.relationObjectMetadataNameSingular !== 'workspaceMember') || isFieldLinks(fieldDefinition) || - isFieldEmails(fieldDefinition) + isFieldEmails(fieldDefinition) || + isFieldArray(fieldDefinition) || + isFieldPhones(fieldDefinition) ) { return IconPencil; } diff --git a/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts b/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts index 905afb646a25..0323ef19e099 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts @@ -6,6 +6,8 @@ import { isFieldActor } from '@/object-record/record-field/types/guards/isFieldA import { isFieldActorValue } from '@/object-record/record-field/types/guards/isFieldActorValue'; import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress'; import { isFieldAddressValue } from '@/object-record/record-field/types/guards/isFieldAddressValue'; +import { isFieldArray } from '@/object-record/record-field/types/guards/isFieldArray'; +import { isFieldArrayValue } from '@/object-record/record-field/types/guards/isFieldArrayValue'; import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean'; import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency'; import { isFieldCurrencyValue } from '@/object-record/record-field/types/guards/isFieldCurrencyValue'; @@ -24,6 +26,8 @@ import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/is import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue'; import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber'; import { isFieldPhone } from '@/object-record/record-field/types/guards/isFieldPhone'; +import { isFieldPhones } from '@/object-record/record-field/types/guards/isFieldPhones'; +import { isFieldPhonesValue } from '@/object-record/record-field/types/guards/isFieldPhonesValue'; import { isFieldPosition } from '@/object-record/record-field/types/guards/isFieldPosition'; import { isFieldRating } from '@/object-record/record-field/types/guards/isFieldRating'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; @@ -74,8 +78,9 @@ export const isFieldValueEmpty = ({ ); } - if (isFieldMultiSelect(fieldDefinition)) { + if (isFieldMultiSelect(fieldDefinition) || isFieldArray(fieldDefinition)) { return ( + !isFieldArrayValue(fieldValue) || !isFieldMultiSelectValue(fieldValue, selectOptionValues) || !isDefined(fieldValue) ); @@ -128,6 +133,13 @@ export const isFieldValueEmpty = ({ ); } + if (isFieldPhones(fieldDefinition)) { + return ( + !isFieldPhonesValue(fieldValue) || + isValueEmpty(fieldValue.primaryPhoneNumber) + ); + } + throw new Error( `Entity field type not supported in isFieldValueEmpty : ${fieldDefinition.type}}`, ); diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts index a60d907d685d..f83c82d0e865 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts @@ -14,6 +14,7 @@ import { LinksFilter, NotObjectRecordFilter, OrObjectRecordFilter, + PhonesFilter, RecordGqlOperationFilter, StringFilter, URLFilter, @@ -227,6 +228,7 @@ export const isRecordMatchingFilter = ({ }); }); } + case FieldMetadataType.Date: case FieldMetadataType.DateTime: { return isMatchingDateFilter({ dateFilter: filterValue as DateFilter, @@ -281,6 +283,26 @@ export const isRecordMatchingFilter = ({ value: record[filterKey].primaryEmail, }); } + case FieldMetadataType.Phones: { + const phonesFilter = filterValue as PhonesFilter; + + const keys: (keyof PhonesFilter)[] = [ + 'primaryPhoneNumber', + 'primaryPhoneCountryCode', + ]; + + return keys.some((key) => { + const value = phonesFilter[key]; + if (value === undefined) { + return false; + } + + return isMatchingStringFilter({ + stringFilter: value, + value: record[filterKey][key], + }); + }); + } case FieldMetadataType.Relation: { throw new Error( `Not implemented yet, use UUID filter instead on the corredponding "${filterKey}Id" field`, diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts index 6d93ceba9e1d..58cbaca25e9d 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts @@ -25,6 +25,9 @@ import { convertLessThanRatingToArrayOfRatingValues, convertRatingToRatingValue, } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput'; +import { resolveFilterValue } from '@/views/utils/view-filter-value/resolveFilterValue'; +import { endOfDay, roundToNearestMinutes, startOfDay } from 'date-fns'; +import { z } from 'zod'; import { Filter } from '../../object-filter-dropdown/types/Filter'; export type ObjectDropdownFilter = Omit<Filter, 'definition'> & { @@ -52,6 +55,19 @@ const applyEmptyFilters = ( ], }; break; + case 'PHONES': { + const phonesFilter = generateILikeFiltersForCompositeFields( + '', + correspondingField.name, + ['primaryPhoneNumber', 'primaryPhoneCountryCode'], + true, + ); + + emptyRecordFilter = { + and: phonesFilter, + }; + break; + } case 'CURRENCY': emptyRecordFilter = { or: [ @@ -199,6 +215,7 @@ const applyEmptyFilters = ( [correspondingField.name]: { is: 'NULL' } as StringFilter, }; break; + case 'DATE': case 'DATE_TIME': emptyRecordFilter = { [correspondingField.name]: { is: 'NULL' } as DateFilter, @@ -275,16 +292,19 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( (field) => field.id === rawUIFilter.fieldMetadataId, ); - const isEmptyOperand = [ + const isValuelessOperand = [ ViewFilterOperand.IsEmpty, ViewFilterOperand.IsNotEmpty, + ViewFilterOperand.IsInPast, + ViewFilterOperand.IsInFuture, + ViewFilterOperand.IsToday, ].includes(rawUIFilter.operand); if (!correspondingField) { continue; } - if (!isEmptyOperand) { + if (!isValuelessOperand) { if (!isDefined(rawUIFilter.value) || rawUIFilter.value === '') { continue; } @@ -326,24 +346,32 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( ); } break; - case 'DATE_TIME': + case 'DATE': + case 'DATE_TIME': { + const resolvedFilterValue = resolveFilterValue(rawUIFilter); + const now = roundToNearestMinutes(new Date()); + const date = + resolvedFilterValue instanceof Date ? resolvedFilterValue : now; + switch (rawUIFilter.operand) { - case ViewFilterOperand.GreaterThan: + case ViewFilterOperand.IsAfter: { objectRecordFilters.push({ [correspondingField.name]: { - gte: rawUIFilter.value, + gt: date.toISOString(), } as DateFilter, }); break; - case ViewFilterOperand.LessThan: + } + case ViewFilterOperand.IsBefore: { objectRecordFilters.push({ [correspondingField.name]: { - lte: rawUIFilter.value, + lt: date.toISOString(), } as DateFilter, }); break; + } case ViewFilterOperand.IsEmpty: - case ViewFilterOperand.IsNotEmpty: + case ViewFilterOperand.IsNotEmpty: { applyEmptyFilters( rawUIFilter.operand, correspondingField, @@ -351,12 +379,99 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( rawUIFilter.definition.type, ); break; + } + case ViewFilterOperand.IsRelative: { + const dateRange = z + .object({ start: z.date(), end: z.date() }) + .safeParse(resolvedFilterValue).data; + + const defaultDateRange = resolveFilterValue({ + value: 'PAST_1_DAY', + definition: { + type: 'DATE', + }, + operand: ViewFilterOperand.IsRelative, + }); + + if (!defaultDateRange) + throw new Error('Failed to resolve default date range'); + + const { start, end } = dateRange ?? defaultDateRange; + + objectRecordFilters.push({ + and: [ + { + [correspondingField.name]: { + gte: start.toISOString(), + } as DateFilter, + }, + { + [correspondingField.name]: { + lte: end.toISOString(), + } as DateFilter, + }, + ], + }); + break; + } + case ViewFilterOperand.Is: { + const isValid = resolvedFilterValue instanceof Date; + const date = isValid ? resolvedFilterValue : now; + + objectRecordFilters.push({ + and: [ + { + [correspondingField.name]: { + lte: endOfDay(date).toISOString(), + } as DateFilter, + }, + { + [correspondingField.name]: { + gte: startOfDay(date).toISOString(), + } as DateFilter, + }, + ], + }); + break; + } + case ViewFilterOperand.IsInPast: + objectRecordFilters.push({ + [correspondingField.name]: { + lte: now.toISOString(), + } as DateFilter, + }); + break; + case ViewFilterOperand.IsInFuture: + objectRecordFilters.push({ + [correspondingField.name]: { + gte: now.toISOString(), + } as DateFilter, + }); + break; + case ViewFilterOperand.IsToday: { + objectRecordFilters.push({ + and: [ + { + [correspondingField.name]: { + lte: endOfDay(now).toISOString(), + } as DateFilter, + }, + { + [correspondingField.name]: { + gte: startOfDay(now).toISOString(), + } as DateFilter, + }, + ], + }); + break; + } default: throw new Error( - `Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.type} filter`, + `Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.type} filter`, // ); } break; + } case 'RATING': switch (rawUIFilter.operand) { case ViewFilterOperand.Is: @@ -431,7 +546,7 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( } break; case 'RELATION': { - if (!isEmptyOperand) { + if (!isValuelessOperand) { try { JSON.parse(rawUIFilter.value); } catch (e) { @@ -728,7 +843,7 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( } break; case 'SELECT': { - if (isEmptyOperand) { + if (isValuelessOperand) { applyEmptyFilters( rawUIFilter.operand, correspondingField, @@ -868,6 +983,43 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( ); } break; + case 'PHONES': { + const phonesFilters = generateILikeFiltersForCompositeFields( + rawUIFilter.value, + correspondingField.name, + ['primaryPhoneNumber', 'primaryPhoneCountryCode'], + ); + switch (rawUIFilter.operand) { + case ViewFilterOperand.Contains: + objectRecordFilters.push({ + or: phonesFilters, + }); + break; + case ViewFilterOperand.DoesNotContain: + objectRecordFilters.push({ + and: phonesFilters.map((filter) => { + return { + not: filter, + }; + }), + }); + break; + case ViewFilterOperand.IsEmpty: + case ViewFilterOperand.IsNotEmpty: + applyEmptyFilters( + rawUIFilter.operand, + correspondingField, + objectRecordFilters, + rawUIFilter.definition.type, + ); + break; + default: + throw new Error( + `Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.type} filter`, + ); + } + break; + } default: throw new Error('Unknown filter type'); } diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainer.tsx index bd412f91020e..8bca151080a2 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardContainer.tsx @@ -14,7 +14,6 @@ type RecordIndexBoardContainerProps = { recordBoardId: string; viewBarId: string; objectNameSingular: string; - createRecord: () => Promise<void>; }; export const RecordIndexBoardContainer = ({ diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx index 833f92060456..3af3237929f4 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx @@ -4,14 +4,12 @@ import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; -import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; import { RecordIndexBoardContainer } from '@/object-record/record-index/components/RecordIndexBoardContainer'; import { RecordIndexBoardDataLoader } from '@/object-record/record-index/components/RecordIndexBoardDataLoader'; import { RecordIndexBoardDataLoaderEffect } from '@/object-record/record-index/components/RecordIndexBoardDataLoaderEffect'; import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer'; import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect'; import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect'; -import { RecordIndexEventContext } from '@/object-record/record-index/contexts/RecordIndexEventContext'; import { RecordIndexOptionsDropdown } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdown'; import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; @@ -21,16 +19,18 @@ import { recordIndexSortsState } from '@/object-record/record-index/states/recor import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper'; -import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; import { ViewBar } from '@/views/components/ViewBar'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; import { ViewField } from '@/views/types/ViewField'; import { ViewType } from '@/views/types/ViewType'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; +import { useContext } from 'react'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; const StyledContainer = styled.div` @@ -46,20 +46,15 @@ const StyledContainerWithPadding = styled.div<{ fullHeight?: boolean }>` padding-left: ${({ theme }) => theme.table.horizontalCellPadding}; `; -type RecordIndexContainerProps = { - recordIndexId: string; - objectNamePlural: string; - createRecord: () => Promise<void>; -}; - -export const RecordIndexContainer = ({ - createRecord, - recordIndexId, - objectNamePlural, -}: RecordIndexContainerProps) => { +export const RecordIndexContainer = () => { const [recordIndexViewType, setRecordIndexViewType] = useRecoilState( recordIndexViewTypeState, ); + + const { objectNamePlural, recordIndexId } = useContext( + RecordIndexRootPropsContext, + ); + const { objectNameSingular } = useObjectNameSingularFromPlural({ objectNamePlural, }); @@ -110,79 +105,67 @@ export const RecordIndexContainer = ({ [columnDefinitions, setTableColumns], ); - const { handleIndexIdentifierClick } = useHandleIndexIdentifierClick({ - objectMetadataItem, - recordIndexId, - }); - - const handleIndexRecordsLoaded = useRecoilCallback( - ({ set }) => - () => { - // TODO: find a better way to reset this state ? - set(lastShowPageRecordIdState, null); - }, - [], - ); - return ( <StyledContainer> <InformationBannerWrapper /> - <RecordFieldValueSelectorContextProvider> - <SpreadsheetImportProvider> - <StyledContainerWithPadding> - <ViewBar - viewBarId={recordIndexId} - optionsDropdownButton={ - <RecordIndexOptionsDropdown - recordIndexId={recordIndexId} - objectNameSingular={objectNameSingular} - viewType={recordIndexViewType ?? ViewType.Table} - /> - } - onCurrentViewChange={(view) => { - if (!view) { - return; + <ViewComponentInstanceContext.Provider + value={{ instanceId: recordIndexId }} + > + <RecordFieldValueSelectorContextProvider> + <SpreadsheetImportProvider> + <StyledContainerWithPadding> + <ViewBar + viewBarId={recordIndexId} + optionsDropdownButton={ + <RecordIndexOptionsDropdown + recordIndexId={recordIndexId} + objectNameSingular={objectNameSingular} + viewType={recordIndexViewType ?? ViewType.Table} + /> } + onCurrentViewChange={(view) => { + if (!view) { + return; + } + + onViewFieldsChange(view.viewFields); + setTableFilters( + mapViewFiltersToFilters( + view.viewFilters, + filterDefinitions, + ), + ); + setRecordIndexFilters( + mapViewFiltersToFilters( + view.viewFilters, + filterDefinitions, + ), + ); + setTableSorts( + mapViewSortsToSorts(view.viewSorts, sortDefinitions), + ); + setRecordIndexSorts( + mapViewSortsToSorts(view.viewSorts, sortDefinitions), + ); + setRecordIndexViewType(view.type); + setRecordIndexViewKanbanFieldMetadataIdState( + view.kanbanFieldMetadataId, + ); + setRecordIndexIsCompactModeActive(view.isCompact); + }} + /> + <RecordIndexViewBarEffect + objectNamePlural={objectNamePlural} + viewBarId={recordIndexId} + /> + </StyledContainerWithPadding> + </SpreadsheetImportProvider> - onViewFieldsChange(view.viewFields); - setTableFilters( - mapViewFiltersToFilters(view.viewFilters, filterDefinitions), - ); - setRecordIndexFilters( - mapViewFiltersToFilters(view.viewFilters, filterDefinitions), - ); - setTableSorts( - mapViewSortsToSorts(view.viewSorts, sortDefinitions), - ); - setRecordIndexSorts( - mapViewSortsToSorts(view.viewSorts, sortDefinitions), - ); - setRecordIndexViewType(view.type); - setRecordIndexViewKanbanFieldMetadataIdState( - view.kanbanFieldMetadataId, - ); - setRecordIndexIsCompactModeActive(view.isCompact); - }} - /> - <RecordIndexViewBarEffect - objectNamePlural={objectNamePlural} - viewBarId={recordIndexId} - /> - </StyledContainerWithPadding> - </SpreadsheetImportProvider> - <RecordIndexEventContext.Provider - value={{ - onIndexIdentifierClick: handleIndexIdentifierClick, - onIndexRecordsLoaded: handleIndexRecordsLoaded, - }} - > {recordIndexViewType === ViewType.Table && ( <> <RecordIndexTableContainer recordTableId={recordIndexId} viewBarId={recordIndexId} - objectNameSingular={objectNameSingular} - createRecord={createRecord} /> <RecordIndexTableContainerEffect objectNameSingular={objectNameSingular} @@ -197,7 +180,6 @@ export const RecordIndexContainer = ({ recordBoardId={recordIndexId} viewBarId={recordIndexId} objectNameSingular={objectNameSingular} - createRecord={createRecord} /> <RecordIndexBoardDataLoader objectNameSingular={objectNameSingular} @@ -209,8 +191,8 @@ export const RecordIndexContainer = ({ /> </StyledContainerWithPadding> )} - </RecordIndexEventContext.Provider> - </RecordFieldValueSelectorContextProvider> + </RecordFieldValueSelectorContextProvider> + </ViewComponentInstanceContext.Provider> </StyledContainer> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx index 5039ec7a3447..bb8c0197a940 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx @@ -1,27 +1,25 @@ -import { useParams } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { useIcons } from 'twenty-ui'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; +import { RecordIndexPageKanbanAddButton } from '@/object-record/record-index/components/RecordIndexPageKanbanAddButton'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; import { PageAddButton } from '@/ui/layout/page/PageAddButton'; import { PageHeader } from '@/ui/layout/page/PageHeader'; import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect'; import { ViewType } from '@/views/types/ViewType'; +import { useContext } from 'react'; import { capitalize } from '~/utils/string/capitalize'; -type RecordIndexPageHeaderProps = { - createRecord: () => void; -}; - -export const RecordIndexPageHeader = ({ - createRecord, -}: RecordIndexPageHeaderProps) => { - const objectNamePlural = useParams().objectNamePlural ?? ''; - +export const RecordIndexPageHeader = () => { const { findObjectMetadataItemByNamePlural } = useFilteredObjectMetadataItems(); + const { objectNamePlural, onCreateRecord } = useContext( + RecordIndexRootPropsContext, + ); + const objectMetadataItem = findObjectMetadataItemByNamePlural(objectNamePlural); @@ -32,16 +30,24 @@ export const RecordIndexPageHeader = ({ const recordIndexViewType = useRecoilValue(recordIndexViewTypeState); - const canAddRecord = + const isTable = recordIndexViewType === ViewType.Table && !objectMetadataItem?.isRemote; const pageHeaderTitle = objectMetadataItem?.labelPlural ?? capitalize(objectNamePlural); + const handleAddButtonClick = () => { + onCreateRecord(); + }; + return ( <PageHeader title={pageHeaderTitle} Icon={Icon}> - <PageHotkeysEffect onAddButtonClick={createRecord} /> - {canAddRecord && <PageAddButton onClick={createRecord} />} + <PageHotkeysEffect onAddButtonClick={handleAddButtonClick} /> + {isTable ? ( + <PageAddButton onClick={handleAddButtonClick} /> + ) : ( + <RecordIndexPageKanbanAddButton /> + )} </PageHeader> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddButton.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddButton.tsx new file mode 100644 index 000000000000..ea224bda6f81 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddButton.tsx @@ -0,0 +1,166 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates'; +import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard'; +import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/RecordBoardColumnDefinition'; +import { RecordIndexPageKanbanAddMenuItem } from '@/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; +import { useRecordIndexPageKanbanAddButton } from '@/object-record/record-index/hooks/useRecordIndexPageKanbanAddButton'; +import { SingleEntitySelect } from '@/object-record/relation-picker/components/SingleEntitySelect'; +import { useEntitySelectSearch } from '@/object-record/relation-picker/hooks/useEntitySelectSearch'; +import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; +import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; +import { IconButton } from '@/ui/input/button/components/IconButton'; +import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; +import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; +import styled from '@emotion/styled'; +import { useCallback, useContext, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { IconPlus, isDefined } from 'twenty-ui'; + +const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)` + width: 100%; +`; + +const StyledDropDownMenu = styled(DropdownMenu)` + width: 200px; +`; + +export const RecordIndexPageKanbanAddButton = () => { + const dropdownId = `record-index-page-add-button-dropdown`; + const [isSelectingCompany, setIsSelectingCompany] = useState(false); + const [selectedColumnDefinition, setSelectedColumnDefinition] = + useState<RecordBoardColumnDefinition>(); + + const { recordIndexId, objectNamePlural } = useContext( + RecordIndexRootPropsContext, + ); + + const { columnIdsState, visibleFieldDefinitionsState } = + useRecordBoardStates(recordIndexId); + const columnIds = useRecoilValue(columnIdsState); + const visibleFieldDefinitions = useRecoilValue( + visibleFieldDefinitionsState(), + ); + const labelIdentifierField = visibleFieldDefinitions.find( + (field) => field.isLabelIdentifier, + ); + + const { + setHotkeyScopeAndMemorizePreviousScope, + goBackToPreviousHotkeyScope, + } = usePreviousHotkeyScope(); + const { resetSearchFilter } = useEntitySelectSearch({ + relationPickerScopeId: 'relation-picker', + }); + + const { closeDropdown } = useDropdown(dropdownId); + + const { selectFieldMetadataItem, isOpportunity, createOpportunity } = + useRecordIndexPageKanbanAddButton({ + objectNamePlural, + }); + + const { handleAddNewCardClick } = useAddNewCard(); + + const handleItemClick = useCallback( + (columnDefinition: RecordBoardColumnDefinition) => { + if (isOpportunity) { + setIsSelectingCompany(true); + setSelectedColumnDefinition(columnDefinition); + setHotkeyScopeAndMemorizePreviousScope( + RelationPickerHotkeyScope.RelationPicker, + ); + } else { + handleAddNewCardClick( + labelIdentifierField?.label ?? '', + '', + 'first', + columnDefinition.id, + ); + closeDropdown(); + } + }, + [ + isOpportunity, + handleAddNewCardClick, + setHotkeyScopeAndMemorizePreviousScope, + closeDropdown, + labelIdentifierField, + ], + ); + const handleEntitySelect = useCallback( + (company?: EntityForSelect) => { + setIsSelectingCompany(false); + goBackToPreviousHotkeyScope(); + resetSearchFilter(); + if (isDefined(company) && isDefined(selectedColumnDefinition)) { + createOpportunity(company, selectedColumnDefinition); + } + closeDropdown(); + }, + [ + createOpportunity, + goBackToPreviousHotkeyScope, + resetSearchFilter, + selectedColumnDefinition, + closeDropdown, + ], + ); + + const handleCancel = useCallback(() => { + resetSearchFilter(); + goBackToPreviousHotkeyScope(); + setIsSelectingCompany(false); + }, [goBackToPreviousHotkeyScope, resetSearchFilter]); + + if (!selectFieldMetadataItem) { + return null; + } + + return ( + <Dropdown + dropdownMenuWidth="200px" + dropdownPlacement="bottom-start" + clickableComponent={ + <IconButton + Icon={IconPlus} + dataTestId="add-button" + size="medium" + variant="secondary" + accent="default" + ariaLabel="Add" + /> + } + dropdownId={dropdownId} + dropdownComponents={ + <StyledDropDownMenu> + {isOpportunity && isSelectingCompany ? ( + <SingleEntitySelect + disableBackgroundBlur + onCancel={handleCancel} + onEntitySelected={handleEntitySelect} + relationObjectNameSingular={CoreObjectNameSingular.Company} + relationPickerScopeId="relation-picker" + selectedRelationRecordIds={[]} + /> + ) : ( + <StyledDropdownMenuItemsContainer> + {columnIds.map((columnId) => ( + <RecordIndexPageKanbanAddMenuItem + key={columnId} + columnId={columnId} + recordIndexId={recordIndexId} + onItemClick={handleItemClick} + /> + ))} + </StyledDropdownMenuItemsContainer> + )} + </StyledDropDownMenu> + } + dropdownHotkeyScope={{ scope: dropdownId }} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem.tsx new file mode 100644 index 000000000000..a99b3abfd862 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem.tsx @@ -0,0 +1,55 @@ +import { RecordBoardColumnDefinitionType } from '@/object-record/record-board/types/RecordBoardColumnDefinition'; +import { useRecordIndexPageKanbanAddMenuItem } from '@/object-record/record-index/hooks/useRecordIndexPageKanbanAddMenuItem'; +import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; +import styled from '@emotion/styled'; +import { Tag } from 'twenty-ui'; + +const StyledMenuItem = styled(MenuItem)` + width: 200px; +`; + +type RecordIndexPageKanbanAddMenuItemProps = { + columnId: string; + recordIndexId: string; + onItemClick: (columnDefinition: any) => void; +}; + +export const RecordIndexPageKanbanAddMenuItem = ({ + columnId, + recordIndexId, + onItemClick, +}: RecordIndexPageKanbanAddMenuItemProps) => { + const { columnDefinition } = useRecordIndexPageKanbanAddMenuItem( + recordIndexId, + columnId, + ); + if (!columnDefinition) { + return null; + } + + return ( + <StyledMenuItem + text={ + <Tag + variant={ + columnDefinition.type === RecordBoardColumnDefinitionType.Value + ? 'solid' + : 'outline' + } + color={ + columnDefinition.type === RecordBoardColumnDefinitionType.Value + ? columnDefinition.color + : 'transparent' + } + text={columnDefinition.title} + weight={ + columnDefinition.type === RecordBoardColumnDefinitionType.Value + ? 'regular' + : 'medium' + } + /> + } + onClick={() => onItemClick(columnDefinition)} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx index 7def9788b07f..8e84fa83325d 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx @@ -1,9 +1,9 @@ -import { AvatarChip, AvatarChipVariant } from 'twenty-ui'; - +import { useGetStandardObjectIcon } from '@/object-metadata/hooks/useGetStandardObjectIcon'; import { useRecordChipData } from '@/object-record/hooks/useRecordChipData'; -import { RecordIndexEventContext } from '@/object-record/record-index/contexts/RecordIndexEventContext'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { useContext } from 'react'; +import { AvatarChip, AvatarChipVariant } from 'twenty-ui'; export type RecordIdentifierChipProps = { objectNameSingular: string; @@ -16,8 +16,7 @@ export const RecordIdentifierChip = ({ record, variant, }: RecordIdentifierChipProps) => { - const { onIndexIdentifierClick } = useContext(RecordIndexEventContext); - + const { onIndexIdentifierClick } = useContext(RecordIndexRootPropsContext); const { recordChipData } = useRecordChipData({ objectNameSingular, record, @@ -27,6 +26,8 @@ export const RecordIdentifierChip = ({ onIndexIdentifierClick(record.id); }; + const { Icon: LeftIcon, IconColor: LeftIconColor } = + useGetStandardObjectIcon(objectNameSingular); return ( <AvatarChip placeholderColorSeed={record.id} @@ -35,6 +36,8 @@ export const RecordIdentifierChip = ({ avatarUrl={recordChipData.avatarUrl ?? ''} onClick={handleAvatarChipClick} variant={variant} + LeftIcon={LeftIcon} + LeftIconColor={LeftIconColor} /> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRemoveSortingModal.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRemoveSortingModal.tsx index efe7e4cb9236..1a16e7feee6d 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRemoveSortingModal.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRemoveSortingModal.tsx @@ -2,7 +2,7 @@ import { useRecoilState } from 'recoil'; import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; -import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts'; +import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; export const RecordIndexRemoveSortingModal = ({ @@ -21,11 +21,11 @@ export const RecordIndexRemoveSortingModal = ({ isRemoveSortingModalOpenState, ); - const { removeCombinedViewSort } = useCombinedViewSorts(recordTableId); + const { deleteCombinedViewSort } = useDeleteCombinedViewSorts(recordTableId); const handleRemoveClick = () => { fieldMetadataIds.forEach((id) => { - removeCombinedViewSort(id); + deleteCombinedViewSort(id); }); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainer.tsx index f5af2e96fa20..50bb639f5237 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainer.tsx @@ -1,23 +1,23 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { RecordUpdateHookParams } from '@/object-record/record-field/contexts/FieldContext'; import { RecordIndexRemoveSortingModal } from '@/object-record/record-index/components/RecordIndexRemoveSortingModal'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; import { RecordTableActionBar } from '@/object-record/record-table/action-bar/components/RecordTableActionBar'; import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; import { RecordTableContextMenu } from '@/object-record/record-table/context-menu/components/RecordTableContextMenu'; +import { useContext } from 'react'; type RecordIndexTableContainerProps = { recordTableId: string; viewBarId: string; - objectNameSingular: string; - createRecord: () => Promise<void>; }; export const RecordIndexTableContainer = ({ recordTableId, viewBarId, - objectNameSingular, - createRecord, }: RecordIndexTableContainerProps) => { + const { objectNameSingular } = useContext(RecordIndexRootPropsContext); + const { updateOneRecord } = useUpdateOneRecord({ objectNameSingular, }); @@ -36,7 +36,6 @@ export const RecordIndexTableContainer = ({ objectNameSingular={objectNameSingular} viewBarId={viewBarId} updateRecordMutation={updateEntity} - createRecord={createRecord} /> <RecordTableActionBar recordTableId={recordTableId} /> <RecordIndexRemoveSortingModal recordTableId={recordTableId} /> diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx index 32ae2ffc5091..428537f69467 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx @@ -8,8 +8,9 @@ import { useHandleToggleColumnFilter } from '@/object-record/record-index/hooks/ import { useHandleToggleColumnSort } from '@/object-record/record-index/hooks/useHandleToggleColumnSort'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView'; +import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState'; type RecordIndexTableContainerEffectProps = { objectNameSingular: string; @@ -50,9 +51,10 @@ export const RecordIndexTableContainerEffect = ({ const { tableRowIdsState, hasUserSelectedAllRowsState } = useRecordTableStates(recordTableId); - const { entityCountInCurrentViewState } = useViewStates(recordTableId); - const entityCountInCurrentView = useRecoilValue( - entityCountInCurrentViewState, + // TODO: verify this instance id works + const entityCountInCurrentView = useRecoilComponentValueV2( + entityCountInCurrentViewComponentState, + recordTableId, ); const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState); const tableRowIds = useRecoilValue(tableRowIdsState); diff --git a/packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexEventContext.tsx b/packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexEventContext.tsx deleted file mode 100644 index 7de19221dc79..000000000000 --- a/packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexEventContext.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { createEventContext } from '~/utils/createEventContext'; - -export type RecordIndexEventContextProps = { - onIndexIdentifierClick: (recordId: string) => void; - onIndexRecordsLoaded: () => void; -}; - -export const RecordIndexEventContext = - createEventContext<RecordIndexEventContextProps>(); diff --git a/packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexRootPropsContext.ts b/packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexRootPropsContext.ts new file mode 100644 index 000000000000..6de7cd552657 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/contexts/RecordIndexRootPropsContext.ts @@ -0,0 +1,13 @@ +import { createRootPropsContext } from '~/utils/createRootPropsContext'; + +export type RecordIndexRootPropsContextProps = { + onIndexIdentifierClick: (recordId: string) => void; + onIndexRecordsLoaded: () => void; + onCreateRecord: () => void; + objectNamePlural: string; + objectNameSingular: string; + recordIndexId: string; +}; + +export const RecordIndexRootPropsContext = + createRootPropsContext<RecordIndexRootPropsContextProps>(); diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts index a72fda64b92c..2ea5bcdc416e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts @@ -1,8 +1,8 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; import { useNavigate } from 'react-router-dom'; -import { useRecoilValue } from 'recoil'; export const useHandleIndexIdentifierClick = ({ objectMetadataItem, @@ -13,10 +13,9 @@ export const useHandleIndexIdentifierClick = ({ }) => { const navigate = useNavigate(); - const currentViewId = useRecoilValue( - currentViewIdComponentState({ - scopeId: recordIndexId, - }), + const currentViewId = useRecoilComponentValueV2( + currentViewIdComponentState, + recordIndexId, ); const handleIndexIdentifierClick = (recordId: string) => { diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnFilter.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnFilter.ts index 18997fbadbae..41d4fc49d99c 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnFilter.ts @@ -7,7 +7,7 @@ import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldM import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType'; import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2'; -import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; +import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters'; import { isDefined } from '~/utils/isDefined'; type UseHandleToggleColumnFilterProps = { @@ -26,7 +26,7 @@ export const useHandleToggleColumnFilter = ({ const { columnDefinitions } = useColumnDefinitionsFromFieldMetadata(objectMetadataItem); - const { upsertCombinedViewFilter } = useCombinedViewFilters(viewBarId); + const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId); const { openDropdown } = useDropdownV2(); const handleToggleColumnFilter = useCallback( diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnSort.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnSort.ts index a5253a49e82a..b285fe345047 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnSort.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnSort.ts @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; -import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts'; +import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts'; import { isDefined } from '~/utils/isDefined'; type UseHandleToggleColumnSortProps = { @@ -22,7 +22,7 @@ export const useHandleToggleColumnSort = ({ const { columnDefinitions } = useColumnDefinitionsFromFieldMetadata(objectMetadataItem); - const { upsertCombinedViewSort } = useCombinedViewSorts(viewBarId); + const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(viewBarId); const handleToggleColumnSort = useCallback( (fieldMetadataId: string) => { diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts index 9e4a5c0c7e9e..31dac4ae702e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts @@ -5,8 +5,10 @@ import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/u import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; -import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; +import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; +import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { useRecoilCallback } from 'recoil'; import { isDefined } from '~/utils/isDefined'; type UseHandleToggleTrashColumnFilterProps = { @@ -25,11 +27,12 @@ export const useHandleToggleTrashColumnFilter = ({ const { columnDefinitions } = useColumnDefinitionsFromFieldMetadata(objectMetadataItem); - const { upsertCombinedViewFilter } = useCombinedViewFilters(viewBarId); + const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId); + const { isSoftDeleteActiveState } = useRecordTableStates(viewBarId); const handleToggleTrashColumnFilter = useCallback(() => { const trashFieldMetadata = objectMetadataItem.fields.find( - (field) => field.name === 'deletedAt', + (field: { name: string }) => field.name === 'deletedAt', ); if (!isDefined(trashFieldMetadata)) return; @@ -52,7 +55,7 @@ export const useHandleToggleTrashColumnFilter = ({ operand: ViewFilterOperand.IsNotEmpty, displayValue: '', definition: { - label: `Deleted ${objectMetadataItem.namePlural}`, + label: `Deleted`, iconName: 'IconTrash', fieldMetadataId: trashFieldMetadata.id, type: filterType, @@ -61,12 +64,17 @@ export const useHandleToggleTrashColumnFilter = ({ }; upsertCombinedViewFilter(newFilter); - }, [ - columnDefinitions, - objectMetadataItem.fields, - objectNameSingular, - upsertCombinedViewFilter, - ]); + }, [columnDefinitions, objectMetadataItem, upsertCombinedViewFilter]); - return handleToggleTrashColumnFilter; + const toggleSoftDeleteFilterState = useRecoilCallback( + ({ set }) => + (currentState: boolean) => { + set(isSoftDeleteActiveState, currentState); + }, + [isSoftDeleteActiveState], + ); + return { + handleToggleTrashColumnFilter, + toggleSoftDeleteFilterState, + }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddButton.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddButton.ts new file mode 100644 index 000000000000..ad5754dec815 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddButton.ts @@ -0,0 +1,53 @@ +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; +import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/RecordBoardColumnDefinition'; +import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState'; +import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +type useRecordIndexPageKanbanAddButtonProps = { + objectNamePlural: string; +}; + +export const useRecordIndexPageKanbanAddButton = ({ + objectNamePlural, +}: useRecordIndexPageKanbanAddButtonProps) => { + const { objectNameSingular } = useObjectNameSingularFromPlural({ + objectNamePlural, + }); + const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular }); + + const recordIndexKanbanFieldMetadataId = useRecoilValue( + recordIndexKanbanFieldMetadataIdState, + ); + const { createOneRecord } = useCreateOneRecord({ objectNameSingular }); + + const selectFieldMetadataItem = objectMetadataItem.fields.find( + (field) => field.id === recordIndexKanbanFieldMetadataId, + ); + const isOpportunity = + objectMetadataItem.nameSingular === CoreObjectNameSingular.Opportunity; + + const createOpportunity = ( + company: EntityForSelect, + columnDefinition: RecordBoardColumnDefinition, + ) => { + if (isDefined(selectFieldMetadataItem)) { + createOneRecord({ + name: company.name, + companyId: company.id, + position: 'first', + [selectFieldMetadataItem.name]: columnDefinition?.value, + }); + } + }; + + return { + selectFieldMetadataItem, + isOpportunity, + createOpportunity, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddMenuItem.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddMenuItem.ts new file mode 100644 index 000000000000..8e5604cb0fe8 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordIndexPageKanbanAddMenuItem.ts @@ -0,0 +1,12 @@ +import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates'; +import { useRecoilValue } from 'recoil'; + +export const useRecordIndexPageKanbanAddMenuItem = ( + recordIndexId: string, + columnId: string, +) => { + const { columnsFamilySelector } = useRecordBoardStates(recordIndexId); + const columnDefinition = useRecoilValue(columnsFamilySelector(columnId)); + + return { columnDefinition }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts index b9b3e12e8d5b..6e9661a120a2 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useRecordTableRecordGqlFields.ts @@ -1,7 +1,10 @@ import { useRecoilValue } from 'recoil'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getObjectMetadataIdentifierFields } from '@/object-metadata/utils/getObjectMetadataIdentifierFields'; +import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { isDefined } from '~/utils/isDefined'; @@ -27,6 +30,16 @@ export const useRecordTableRecordGqlFields = ({ identifierQueryFields[imageIdentifierFieldMetadataItem.name] = true; } + const { objectMetadataItem: noteTargetObjectMetadataItem } = + useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.NoteTarget, + }); + + const { objectMetadataItem: taskTargetObjectMetadataItem } = + useObjectMetadataItem({ + objectNameSingular: CoreObjectNameSingular.TaskTarget, + }); + const recordGqlFields: Record<string, any> = { id: true, ...Object.fromEntries( @@ -34,18 +47,12 @@ export const useRecordTableRecordGqlFields = ({ ), ...identifierQueryFields, position: true, - noteTargets: { - note: { - id: true, - title: true, - }, - }, - taskTargets: { - task: { - id: true, - title: true, - }, - }, + noteTargets: generateDepthOneRecordGqlFields({ + objectMetadataItem: noteTargetObjectMetadataItem, + }), + taskTargets: generateDepthOneRecordGqlFields({ + objectMetadataItem: taskTargetObjectMetadataItem, + }), }; return recordGqlFields; diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx index 9a5a050bc9b1..a884eda8582b 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx @@ -6,9 +6,9 @@ import { IconEyeOff, IconFileExport, IconFileImport, + IconRotate2, IconSettings, IconTag, - IconTrash, } from 'twenty-ui'; import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObjectNamePluralFromSingular'; @@ -90,10 +90,11 @@ export const RecordIndexOptionsDropdownContent = ({ hiddenTableColumns, } = useRecordIndexOptionsForTable(recordIndexId); - const handleToggleTrashColumnFilter = useHandleToggleTrashColumnFilter({ - objectNameSingular, - viewBarId: recordIndexId, - }); + const { handleToggleTrashColumnFilter, toggleSoftDeleteFilterState } = + useHandleToggleTrashColumnFilter({ + objectNameSingular, + viewBarId: recordIndexId, + }); const { visibleBoardFields, @@ -163,9 +164,10 @@ export const RecordIndexOptionsDropdownContent = ({ <MenuItem onClick={() => { handleToggleTrashColumnFilter(); + toggleSoftDeleteFilterState(true); closeDropdown(); }} - LeftIcon={IconTrash} + LeftIcon={IconRotate2} text={`Deleted ${objectNamePlural}`} /> </DropdownMenuItemsContainer> diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useExportTableData.test.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useExportTableData.test.ts index b7dfc586016f..0494fd32f023 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useExportTableData.test.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useExportTableData.test.ts @@ -1,6 +1,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { csvDownloader, displayedExportProgress, @@ -35,7 +36,10 @@ describe('generateCsv', () => { { label: 'Nested', metadata: { fieldName: 'nested' } }, { label: 'Relation', - metadata: { fieldName: 'relation', relationType: 'TO_ONE_OBJECT' }, + metadata: { + fieldName: 'relation', + relationType: RelationDefinitionType.ManyToOne, + }, }, ] as ColumnDefinition<FieldMetadata>[]; const rows = [ diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useTableData.test.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useTableData.test.tsx index 3d0ce75a0bef..752deafc8e7f 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useTableData.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useTableData.test.tsx @@ -1,17 +1,18 @@ -import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; import { act, renderHook, waitFor } from '@testing-library/react'; +import { ReactNode } from 'react'; import { percentage, sleep, useTableData } from '../useTableData'; import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard'; import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState'; import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard'; +import { SnackBarManagerScopeInternalContext } from '@/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; import { ViewType } from '@/views/types/ViewType'; import { MockedProvider, MockedResponse } from '@apollo/client/testing'; import gql from 'graphql-tag'; -import { ReactNode } from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; import { RecoilRoot, useRecoilValue } from 'recoil'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const defaultResponseData = { pageInfo: { @@ -26,7 +27,11 @@ const mockPerson = { __typename: 'Person', updatedAt: '2021-08-03T19:20:06.000Z', myCustomObjectId: '123', - whatsapp: '123', + whatsapp: { + primaryPhoneNumber: '+1', + primaryPhoneCountryCode: '234-567-890', + additionalPhones: [], + }, linkedinLink: { primaryLinkUrl: 'https://www.linkedin.com', primaryLinkLabel: 'linkedin', @@ -52,12 +57,16 @@ const mockPerson = { }, performanceRating: 1, createdAt: '2021-08-03T19:20:06.000Z', - phone: 'phone', + phone: { + primaryPhoneNumber: '+1', + primaryPhoneCountryCode: '234-567-890', + additionalPhones: [], + }, id: '123', city: 'city', companyId: '1', intro: 'intro', - workPrefereance: 'workPrefereance', + workPreference: 'workPrefereance', }; const mocks: MockedResponse[] = [ { @@ -78,40 +87,51 @@ const mocks: MockedResponse[] = [ edges { node { __typename - updatedAt - myCustomObjectId - whatsapp - linkedinLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } name { firstName lastName } - email - position - createdBy { - source - workspaceMemberId - name + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks } - avatarUrl + deletedAt + createdAt + updatedAt jobTitle + intro + workPrefereance + performanceRating xLink { primaryLinkUrl primaryLinkLabel secondaryLinks } - performanceRating - createdAt - phone - id city companyId - intro - workPrefereance + phones { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } + createdBy { + source + workspaceMemberId + name + } + id + position + emails { + primaryEmail + additionalEmails + } + avatarUrl + whatsapp { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } } cursor } @@ -148,15 +168,19 @@ const mocks: MockedResponse[] = [ ]; const Wrapper = ({ children }: { children: ReactNode }) => ( - <Router> - <RecoilRoot> - <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> + <SnackBarManagerScopeInternalContext.Provider + value={{ + scopeId: 'snack-bar-manager', + }} + > + <Router> + <RecoilRoot> <MockedProvider addTypename={false} mocks={mocks}> {children} </MockedProvider> - </SnackBarProviderScope> - </RecoilRoot> - </Router> + </RecoilRoot> + </Router> + </SnackBarManagerScopeInternalContext.Provider> ); const graphqlEmptyResponse = [ @@ -174,15 +198,19 @@ const graphqlEmptyResponse = [ ]; const WrapperWithEmptyResponse = ({ children }: { children: ReactNode }) => ( - <Router> - <RecoilRoot> - <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> + <SnackBarManagerScopeInternalContext.Provider + value={{ + scopeId: 'snack-bar-manager', + }} + > + <Router> + <RecoilRoot> <MockedProvider addTypename={false} mocks={graphqlEmptyResponse}> {children} </MockedProvider> - </SnackBarProviderScope> - </RecoilRoot> - </Router> + </RecoilRoot> + </Router> + </SnackBarManagerScopeInternalContext.Provider> ); describe('useTableData', () => { @@ -191,13 +219,13 @@ describe('useTableData', () => { describe('data fetching', () => { it('should handle no records', async () => { const callback = jest.fn(); + const { result } = renderHook( () => useTableData({ recordIndexId, objectNameSingular, callback, - delayMs: 0, viewType: ViewType.Kanban, }), @@ -209,7 +237,7 @@ describe('useTableData', () => { }); await waitFor(() => { - expect(callback).toHaveBeenCalledWith([], []); + expect(callback).not.toHaveBeenCalled(); }); }); @@ -268,9 +296,17 @@ describe('useTableData', () => { }, ); + const personObjectMetadataItem = generatedMockObjectMetadataItems.find( + (item) => item.nameSingular === 'person', + ); + + const updatedAtFieldMetadataItem = personObjectMetadataItem?.fields.find( + (field) => field.name === 'updatedAt', + ); + await act(async () => { result.current.setKanbanFieldName.setKanbanFieldMetadataName( - result.current.kanbanData.hiddenBoardFields[0].metadata.fieldName, + updatedAtFieldMetadataItem?.name, ); }); @@ -285,7 +321,7 @@ describe('useTableData', () => { { defaultValue: 'now', editButtonIcon: undefined, - fieldMetadataId: '102963b7-3e77-4293-a1e6-1ab59a02b663', + fieldMetadataId: updatedAtFieldMetadataItem?.id, iconName: 'IconCalendarClock', isFilterable: true, isLabelIdentifier: false, @@ -305,7 +341,7 @@ describe('useTableData', () => { relationType: undefined, targetFieldMetadataName: '', }, - position: 0, + position: 7, showLabel: undefined, size: 100, type: 'DATE_TIME', diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts index d6f6f83f3feb..8a535604dee8 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts @@ -9,6 +9,7 @@ import { } from '@/object-record/record-index/options/hooks/useTableData'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { FieldMetadataType } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; @@ -43,7 +44,7 @@ export const generateCsv: GenerateExport = ({ const columnsToExport = columns.filter( (col) => !('relationType' in col.metadata && col.metadata.relationType) || - col.metadata.relationType === 'TO_ONE_OBJECT', + col.metadata.relationType === RelationDefinitionType.ManyToOne, ); const objectIdColumn: ColumnDefinition<FieldMetadata> = { diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts index 9e1c2b28b6ed..c3d5e87d97f0 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard.ts @@ -1,5 +1,5 @@ -import { useCallback, useMemo } from 'react'; import { OnDragEndResponder } from '@hello-pangea/dnd'; +import { useCallback, useMemo } from 'react'; import { useRecoilState } from 'recoil'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; @@ -8,8 +8,8 @@ import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoar import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { useHandleViews } from '@/views/hooks/useHandleViews'; import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields'; +import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView'; import { GraphQLView } from '@/views/types/GraphQLView'; import { mapBoardFieldDefinitionsToViewFields } from '@/views/utils/mapBoardFieldDefinitionsToViewFields'; import { mapArrayToObject } from '~/utils/array/mapArrayToObject'; @@ -31,7 +31,7 @@ export const useRecordIndexOptionsForBoard = ({ useRecoilState(recordIndexFieldDefinitionsState); const { saveViewFields } = useSaveCurrentViewFields(viewBarId); - const { updateCurrentView } = useHandleViews(viewBarId); + const { updateCurrentView } = useUpdateCurrentView(viewBarId); const { isCompactModeActiveState } = useRecordBoard(recordBoardId); const [isCompactModeActive, setIsCompactModeActive] = useRecoilState( diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useTableData.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useTableData.ts index 46572dffe1bf..1e6255276919 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useTableData.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useTableData.ts @@ -142,10 +142,6 @@ export const useTableData = ({ }); useEffect(() => { - const MAXIMUM_REQUESTS = isDefined(totalCount) - ? Math.min(maximumRequests, totalCount / pageSize) - : maximumRequests; - const fetchNextPage = async () => { setInflight(true); setPreviousRecordCount(records.length); @@ -167,8 +163,8 @@ export const useTableData = ({ } if ( - pageCount >= MAXIMUM_REQUESTS || - (isDefined(totalCount) && records.length === totalCount) + pageCount >= maximumRequests || + (isDefined(totalCount) && records.length >= totalCount) ) { setPageCount(0); diff --git a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellContainer.tsx index 4c12e25417fe..c77c19fa88c4 100644 --- a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellContainer.tsx @@ -1,13 +1,17 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { ReactElement, useContext } from 'react'; -import { AppTooltip, IconComponent, TooltipDelay } from 'twenty-ui'; +import { + AppTooltip, + IconComponent, + TooltipDelay, + OverflowingTextWithTooltip, +} from 'twenty-ui'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus'; import { RecordInlineCellValue } from '@/object-record/record-inline-cell/components/RecordInlineCellValue'; import { getRecordFieldInputId } from '@/object-record/utils/getRecordFieldInputId'; -import { EllipsisDisplay } from '@/ui/field/display/components/EllipsisDisplay'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { useRecordInlineCellContext } from './RecordInlineCellContext'; @@ -120,7 +124,7 @@ export const RecordInlineCellContainer = () => { )} {showLabel && label && ( <StyledLabelContainer width={labelWidth}> - <EllipsisDisplay maxWidth={labelWidth}>{label}</EllipsisDisplay> + <OverflowingTextWithTooltip text={label} /> </StyledLabelContainer> )} {/* TODO: Displaying Tooltips on the board is causing performance issues https://react-tooltip.com/docs/examples/render */} diff --git a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx index 0bd0815cd4d4..7d6c6e4d50ed 100644 --- a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx @@ -19,7 +19,7 @@ const StyledInlineCellInput = styled.div` display: flex; min-height: 32px; - min-width: 320px; + min-width: 240px; width: inherit; diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 505dfae807c5..967825f3a5d7 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -5,8 +5,10 @@ import { ActivityTargetsInlineCell } from '@/activities/inline-cell/components/A import { Note } from '@/activities/types/Note'; import { Task } from '@/activities/types/Task'; import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord'; +import { useGetStandardObjectIcon } from '@/object-metadata/hooks/useGetStandardObjectIcon'; import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; @@ -56,6 +58,8 @@ export const RecordShowContainer = ({ objectNameSingular, }); + const { objectMetadataItems } = useObjectMetadataItems(); + const { labelIdentifierFieldMetadataItem } = useLabelIdentifierFieldMetadataItem({ objectNameSingular, @@ -119,7 +123,7 @@ export const RecordShowContainer = ({ const availableFieldMetadataItems = objectMetadataItem.fields .filter( (fieldMetadataItem) => - isFieldCellSupported(fieldMetadataItem) && + isFieldCellSupported(fieldMetadataItem, objectMetadataItems) && fieldMetadataItem.id !== labelIdentifierFieldMetadataItem?.id, ) .sort((fieldMetadataItemA, fieldMetadataItemB) => @@ -153,7 +157,7 @@ export const RecordShowContainer = ({ objectNameSingular !== CoreObjectNameSingular.Task && fieldMetadataItem.name !== 'taskTargets', ); - + const { Icon, IconColor } = useGetStandardObjectIcon(objectNameSingular); const isReadOnly = objectMetadataItem.isRemote; const isMobile = useIsMobile() || isInRightDrawer; const isPrefetchLoading = useIsPrefetchLoading(); @@ -163,6 +167,8 @@ export const RecordShowContainer = ({ isMobile={isMobile} id={objectRecordId} logoOrAvatar={recordIdentifier?.avatarUrl ?? ''} + icon={Icon} + iconColor={IconColor} avatarPlaceholder={recordIdentifier?.name ?? ''} date={recordFromStore.createdAt ?? ''} loading={isPrefetchLoading || loading || recordLoading} diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState.tsx deleted file mode 100644 index a47aa9de0393..000000000000 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useTheme } from '@emotion/react'; -import styled from '@emotion/styled'; -import { useIcons } from 'twenty-ui'; - -import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; - -type RecordDetailRelationRecordsListEmptyStateProps = { - relationObjectMetadataItem: ObjectMetadataItem; -}; - -const StyledRelationRecordsListEmptyState = styled.div` - color: ${({ theme }) => theme.font.color.light}; - align-items: center; - justify-content: center; - gap: ${({ theme }) => theme.spacing(2)}; - display: flex; - height: ${({ theme }) => theme.spacing(10)}; - text-transform: capitalize; -`; - -export const RecordDetailRelationRecordsListEmptyState = ({ - relationObjectMetadataItem, -}: RecordDetailRelationRecordsListEmptyStateProps) => { - const theme = useTheme(); - - const { getIcon } = useIcons(); - const Icon = getIcon(relationObjectMetadataItem.icon); - - return ( - <StyledRelationRecordsListEmptyState> - <Icon size={theme.icon.size.sm} /> - <div>No {relationObjectMetadataItem.labelSingular}</div> - </StyledRelationRecordsListEmptyState> - ); -}; diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx index 4eabe61e7907..36a3d7a1a2fe 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx @@ -1,7 +1,7 @@ -import { useCallback, useContext } from 'react'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; +import { useCallback, useContext } from 'react'; import { IconChevronDown, IconComponent, @@ -11,6 +11,7 @@ import { } from 'twenty-ui'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; import { RecordChip } from '@/object-record/components/RecordChip'; @@ -37,6 +38,7 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; const StyledListItem = styled(RecordDetailRecordsListItem)<{ isDropdownOpen?: boolean; @@ -89,12 +91,14 @@ export const RecordDetailRelationRecordsListItem = ({ relationType, } = fieldDefinition.metadata as FieldRelationMetadata; - const isToOneObject = relationType === 'TO_ONE_OBJECT'; + const isToOneObject = relationType === RelationDefinitionType.ManyToOne; const { objectMetadataItem: relationObjectMetadataItem } = useObjectMetadataItem({ objectNameSingular: relationObjectMetadataNameSingular, }); + const { objectMetadataItems } = useObjectMetadataItems(); + const persistField = usePersistField(); const { updateOneRecord: updateOneRelationRecord } = useUpdateOneRecord({ @@ -111,7 +115,7 @@ export const RecordDetailRelationRecordsListItem = ({ const availableRelationFieldMetadataItems = relationObjectMetadataItem.fields .filter( (fieldMetadataItem) => - isFieldCellSupported(fieldMetadataItem) && + isFieldCellSupported(fieldMetadataItem, objectMetadataItems) && fieldMetadataItem.id !== relationObjectMetadataItem.labelIdentifierFieldMetadataId && fieldMetadataItem.id !== relationFieldMetadataId, diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index 426078f807b4..23fc1f07096f 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -4,18 +4,20 @@ import { useCallback, useContext } from 'react'; import { useRecoilValue } from 'recoil'; import { IconForbid, IconPencil, IconPlus } from 'twenty-ui'; +import { ObjectMetadataItemsRelationPickerEffect } from '@/object-metadata/components/ObjectMetadataItemsRelationPickerEffect'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { usePersistField } from '@/object-record/record-field/hooks/usePersistField'; +import { RelationFromManyFieldInputMultiRecordsEffect } from '@/object-record/record-field/meta-types/input/components/RelationFromManyFieldInputMultiRecordsEffect'; +import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList'; -import { RecordDetailRelationRecordsListEmptyState } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState'; -import { RecordDetailRelationSectionSkeletonLoader } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader'; import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection'; import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; +import { MultiRecordSelect } from '@/object-record/relation-picker/components/MultiRecordSelect'; import { SingleEntitySelectMenuItemsWithSearch } from '@/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch'; import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer'; import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; @@ -26,8 +28,10 @@ import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; type RecordDetailRelationSectionProps = { loading: boolean; @@ -49,6 +53,7 @@ export const RecordDetailRelationSection = ({ } = fieldDefinition.metadata as FieldRelationMetadata; const record = useRecoilValue(recordStoreFamilyState(recordId)); + const isMobile = useIsMobile(); const { objectMetadataItem: relationObjectMetadataItem } = useObjectMetadataItem({ objectNameSingular: relationObjectMetadataNameSingular, @@ -63,8 +68,8 @@ export const RecordDetailRelationSection = ({ >(recordStoreFamilySelector({ recordId, fieldName })); // TODO: use new relation type - const isToOneObject = relationType === 'TO_ONE_OBJECT'; - const isFromManyObjects = relationType === 'FROM_MANY_OBJECTS'; + const isToOneObject = relationType === RelationDefinitionType.ManyToOne; + const isToManyObjects = RelationDefinitionType.OneToMany; const relationRecords: ObjectRecord[] = fieldValue && isToOneObject @@ -110,6 +115,10 @@ export const RecordDetailRelationSection = ({ }); }; + const { updateRelation } = useUpdateRelationFromManyFieldInput({ + scopeId: dropdownId, + }); + const filterQueryParams: FilterQueryParams = { filter: { [relationFieldMetadataItem?.name || '']: { @@ -122,20 +131,10 @@ export const RecordDetailRelationSection = ({ }?${qs.stringify(filterQueryParams)}`; const showContent = () => { - if (loading) { - return ( - <RecordDetailRelationSectionSkeletonLoader - numSkeletons={fieldName === 'people' ? 2 : 1} - /> - ); - } - - return relationRecords.length ? ( - <RecordDetailRelationRecordsList relationRecords={relationRecords} /> - ) : ( - <RecordDetailRelationRecordsListEmptyState - relationObjectMetadataItem={relationObjectMetadataItem} - /> + return ( + relationRecords.length > 0 && ( + <RecordDetailRelationRecordsList relationRecords={relationRecords} /> + ) ); }; @@ -147,19 +146,25 @@ export const RecordDetailRelationSection = ({ recordId, }); + if (loading) return null; + return ( <RecordDetailSection> <RecordDetailSectionHeader title={fieldDefinition.label} link={ - isFromManyObjects + isToManyObjects ? { to: filterLinkHref, - label: `All (${relationRecords.length})`, + label: + relationRecords.length > 0 + ? `All (${relationRecords.length})` + : '', } : undefined } - hideRightAdornmentOnMouseLeave={!isDropdownOpen} + hideRightAdornmentOnMouseLeave={!isDropdownOpen && !isMobile} + areRecordsAvailable={relationRecords.length > 0} rightAdornment={ <DropdownScope dropdownScopeId={dropdownId}> <StyledAddDropdown @@ -175,16 +180,28 @@ export const RecordDetailRelationSection = ({ } dropdownComponents={ <RelationPickerScope relationPickerScopeId={dropdownId}> - <SingleEntitySelectMenuItemsWithSearch - EmptyIcon={IconForbid} - onEntitySelected={handleRelationPickerEntitySelected} - selectedRelationRecordIds={relationRecordIds} - relationObjectNameSingular={ - relationObjectMetadataNameSingular - } - relationPickerScopeId={dropdownId} - onCreate={createNewRecordAndOpenRightDrawer} - /> + {isToOneObject ? ( + <SingleEntitySelectMenuItemsWithSearch + EmptyIcon={IconForbid} + onEntitySelected={handleRelationPickerEntitySelected} + selectedRelationRecordIds={relationRecordIds} + relationObjectNameSingular={ + relationObjectMetadataNameSingular + } + relationPickerScopeId={dropdownId} + onCreate={createNewRecordAndOpenRightDrawer} + /> + ) : ( + <> + <ObjectMetadataItemsRelationPickerEffect /> + <RelationFromManyFieldInputMultiRecordsEffect /> + <MultiRecordSelect + onCreate={createNewRecordAndOpenRightDrawer} + onChange={updateRelation} + onSubmit={closeDropdown} + /> + </> + )} </RelationPickerScope> } dropdownHotkeyScope={{ diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader.tsx deleted file mode 100644 index 12ba33e3b210..000000000000 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; -import { useTheme } from '@emotion/react'; -import styled from '@emotion/styled'; - -const StyledSkeletonDiv = styled.div` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spacing(4)}; - height: 40px; -`; - -export const RecordDetailRelationSectionSkeletonLoader = ({ - numSkeletons = 1, -}: { - numSkeletons?: number; -}) => { - const theme = useTheme(); - return ( - <SkeletonTheme - baseColor={theme.background.tertiary} - highlightColor={theme.background.transparent.lighter} - borderRadius={4} - > - <StyledSkeletonDiv> - {Array.from({ length: numSkeletons }).map((_, index) => ( - <Skeleton key={index} width={129} height={16} /> - ))} - </StyledSkeletonDiv> - </SkeletonTheme> - ); -}; diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader.tsx index b9087184b92a..158a80e6721e 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader.tsx @@ -1,12 +1,16 @@ +import styled from '@emotion/styled'; import { useState } from 'react'; import { Link } from 'react-router-dom'; -import styled from '@emotion/styled'; -const StyledHeader = styled.header<{ isDropdownOpen?: boolean }>` +const StyledHeader = styled.header<{ + isDropdownOpen?: boolean; + areRecordsAvailable?: boolean; +}>` align-items: center; display: flex; height: 24px; - margin-bottom: ${({ theme }) => theme.spacing(2)}; + margin-bottom: ${({ theme, areRecordsAvailable }) => + areRecordsAvailable && theme.spacing(2)}; `; const StyledTitle = styled.div` @@ -34,6 +38,7 @@ type RecordDetailSectionHeaderProps = { link?: { to: string; label: string }; rightAdornment?: React.ReactNode; hideRightAdornmentOnMouseLeave?: boolean; + areRecordsAvailable?: boolean; }; export const RecordDetailSectionHeader = ({ @@ -41,11 +46,13 @@ export const RecordDetailSectionHeader = ({ link, rightAdornment, hideRightAdornmentOnMouseLeave = true, + areRecordsAvailable = false, }: RecordDetailSectionHeaderProps) => { const [isHovered, setIsHovered] = useState(false); return ( <StyledHeader + areRecordsAvailable={areRecordsAvailable} onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > @@ -53,7 +60,9 @@ export const RecordDetailSectionHeader = ({ <StyledTitleLabel>{title}</StyledTitleLabel> {link && <StyledLink to={link.to}>{link.label}</StyledLink>} </StyledTitle> - {hideRightAdornmentOnMouseLeave && !isHovered ? null : rightAdornment} + {hideRightAdornmentOnMouseLeave && !isHovered && areRecordsAvailable + ? null + : rightAdornment} </StyledHeader> ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx index f41025398c22..0b2c810bc15c 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx @@ -2,7 +2,8 @@ import { useRecoilValue } from 'recoil'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { ActionBar } from '@/ui/navigation/action-bar/components/ActionBar'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState'; export const RecordTableActionBar = ({ recordTableId, @@ -15,10 +16,12 @@ export const RecordTableActionBar = ({ hasUserSelectedAllRowsState, } = useRecordTableStates(recordTableId); - const { entityCountInCurrentViewState } = useViewStates(recordTableId); - const entityCountInCurrentView = useRecoilValue( - entityCountInCurrentViewState, + // TODO: verify this instance id works + const entityCountInCurrentView = useRecoilComponentValueV2( + entityCountInCurrentViewComponentState, + recordTableId, ); + const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState); const tableRowIds = useRecoilValue(tableRowIdsState); const selectedRowIds = useRecoilValue(selectedRowIdsSelector()); diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx index 5e3b8c23af3e..ccec1297bf3b 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx @@ -1,9 +1,8 @@ import styled from '@emotion/styled'; import { isNonEmptyString, isNull } from '@sniptt/guards'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { RecordTableContextProvider } from '@/object-record/record-table/components/RecordTableContextProvider'; -import { RecordTableEmptyState } from '@/object-record/record-table/components/RecordTableEmptyState'; +import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { RecordTableBody } from '@/object-record/record-table/record-table-body/components/RecordTableBody'; import { RecordTableBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableBodyEffect'; @@ -14,10 +13,8 @@ import { useRecoilValue } from 'recoil'; const StyledTable = styled.table` border-radius: ${({ theme }) => theme.border.radius.sm}; border-spacing: 0; - margin-right: ${({ theme }) => theme.table.horizontalCellMargin}; table-layout: fixed; - - width: calc(100% - ${({ theme }) => theme.table.horizontalCellMargin} * 2); + width: 100%; `; type RecordTableProps = { @@ -25,7 +22,6 @@ type RecordTableProps = { recordTableId: string; objectNameSingular: string; onColumnsChange: (columns: any) => void; - createRecord: () => void; }; export const RecordTable = ({ @@ -33,7 +29,6 @@ export const RecordTable = ({ recordTableId, objectNameSingular, onColumnsChange, - createRecord, }: RecordTableProps) => { const { scopeId } = useRecordTableStates(recordTableId); @@ -51,12 +46,10 @@ export const RecordTable = ({ const pendingRecordId = useRecoilValue(pendingRecordIdState); - const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem( - { objectNameSingular }, - ); - - const objectLabel = foundObjectMetadataItem?.labelSingular; - const isRemote = foundObjectMetadataItem?.isRemote ?? false; + const recordTableIsEmpty = + !isRecordTableInitialLoading && + tableRowIds.length === 0 && + isNull(pendingRecordId); if (!isNonEmptyString(objectNameSingular)) { return <></>; @@ -73,18 +66,11 @@ export const RecordTable = ({ viewBarId={viewBarId} > <RecordTableBodyEffect /> - {!isRecordTableInitialLoading && - tableRowIds.length === 0 && - isNull(pendingRecordId) ? ( - <RecordTableEmptyState - objectNameSingular={objectNameSingular} - objectLabel={objectLabel} - createRecord={createRecord} - isRemote={isRemote} - /> + {recordTableIsEmpty ? ( + <RecordTableEmptyState /> ) : ( <StyledTable className="entity-table-cell"> - <RecordTableHeader createRecord={createRecord} /> + <RecordTableHeader /> <RecordTableBody /> </StyledTable> )} diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx deleted file mode 100644 index 18aef6779384..000000000000 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { useNavigate } from 'react-router-dom'; -import { IconPlus, IconSettings } from 'twenty-ui'; - -import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; -import { Button } from '@/ui/input/button/components/Button'; -import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder'; -import { - AnimatedPlaceholderEmptyContainer, - AnimatedPlaceholderEmptySubTitle, - AnimatedPlaceholderEmptyTextContainer, - AnimatedPlaceholderEmptyTitle, -} from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled'; - -type RecordTableEmptyStateProps = { - objectNameSingular: string; - objectLabel: string; - createRecord: () => void; - isRemote: boolean; -}; - -export const RecordTableEmptyState = ({ - objectNameSingular, - objectLabel, - createRecord, - isRemote, -}: RecordTableEmptyStateProps) => { - const navigate = useNavigate(); - const { totalCount } = useFindManyRecords({ objectNameSingular, limit: 1 }); - const noExistingRecords = totalCount === 0; - - const [title, subTitle, Icon, onClick, buttonTitle] = isRemote - ? [ - 'No Data Available for Remote Table', - 'If this is unexpected, please verify your settings.', - IconSettings, - () => navigate('/settings/integrations'), - 'Go to Settings', - ] - : [ - noExistingRecords - ? `Add your first ${objectLabel}` - : `No ${objectLabel} found`, - noExistingRecords - ? `Use our API or add your first ${objectLabel} manually` - : 'No records matching the filter criteria were found.', - IconPlus, - createRecord, - `Add a ${objectLabel}`, - ]; - - return ( - <AnimatedPlaceholderEmptyContainer> - <AnimatedPlaceholder type="noRecord" /> - <AnimatedPlaceholderEmptyTextContainer> - <AnimatedPlaceholderEmptyTitle>{title}</AnimatedPlaceholderEmptyTitle> - <AnimatedPlaceholderEmptySubTitle> - {subTitle} - </AnimatedPlaceholderEmptySubTitle> - </AnimatedPlaceholderEmptyTextContainer> - <Button - Icon={Icon} - title={buttonTitle} - variant={'secondary'} - onClick={onClick} - /> - </AnimatedPlaceholderEmptyContainer> - ); -}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx index a9080a4ddd21..268608e183cc 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx @@ -37,12 +37,10 @@ type RecordTableWithWrappersProps = { recordTableId: string; viewBarId: string; updateRecordMutation: (params: any) => void; - createRecord: () => Promise<void>; }; export const RecordTableWithWrappers = ({ updateRecordMutation, - createRecord, objectNameSingular, recordTableId, viewBarId, @@ -80,7 +78,6 @@ export const RecordTableWithWrappers = ({ recordTableId={recordTableId} objectNameSingular={objectNameSingular} onColumnsChange={handleColumnsChange} - createRecord={createRecord} /> <DragSelect dragSelectable={tableBodyRef} diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx index 44002bd598ab..9b68416e8192 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx @@ -5,7 +5,7 @@ import { ComponentDecorator } from 'twenty-ui'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; + import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { RecordFieldValueSelectorContextProvider, @@ -21,10 +21,9 @@ import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorato import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory'; import { RecordTableCellFieldContextWrapper } from '@/object-record/record-table/record-table-cell/components/RecordTableCellFieldContextWrapper'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { mockPerformance } from './mock'; -const objectMetadataItems = getObjectMetadataItemsMock(); - const RelationFieldValueSetterEffect = () => { const setEntity = useSetRecoilState( recordStoreFamilyState(mockPerformance.recordId), @@ -48,7 +47,7 @@ const RelationFieldValueSetterEffect = () => { mockPerformance.relationFieldValue, ); - setObjectMetadataItems(objectMetadataItems); + setObjectMetadataItems(generatedMockObjectMetadataItems); }, [setEntity, setRelationEntity, setRecordValue, setObjectMetadataItems]); return null; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts index 15da709584af..ce0253ddab59 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/mock.ts @@ -34,22 +34,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: { - __typename: 'relation', - id: '0cf72416-3d94-4d94-abf3-7dc9d734435b', - relationType: 'ONE_TO_MANY', - fromObjectMetadata: { - __typename: 'object', - id: '79c2d29c-76f6-432f-91c9-df1259b73d95', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'company', - namePlural: 'companies', - isSystem: false, - isRemote: false, - }, - fromFieldMetadataId: '7b281010-5f47-4771-b3f5-f4bcd24ed1b5', - }, defaultValue: null, options: null, relationDefinition: { @@ -94,8 +78,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: "''", options: null, relationDefinition: null, @@ -114,8 +96,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: "''", options: null, relationDefinition: null, @@ -134,22 +114,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: 'd76f949d-023d-4b45-a71e-f39e3b1562ba', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: '82222ca2-dd40-44ec-b8c5-eb0eca9ec625', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'activityTarget', - namePlural: 'activityTargets', - isSystem: true, - isRemote: false, - }, - toFieldMetadataId: 'f5f515cc-6d8a-44c3-b2d4-f04b9868a9c5', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -194,22 +158,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: 'a5a61d23-8ac9-4014-9441-ec3a1781a661', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: '494b9b7c-a44e-4d52-b274-cdfb0e322165', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'opportunity', - namePlural: 'opportunities', - isSystem: false, - isRemote: false, - }, - toFieldMetadataId: '86559a6f-6afc-4d5c-9bed-fc74d063791b', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -254,22 +202,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: '456f7875-b48c-4795-a0c7-a69d7339afee', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: 'eba13fca-57b7-470c-8c23-a0e640e04ffb', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'calendarEventParticipant', - namePlural: 'calendarEventParticipants', - isSystem: true, - isRemote: false, - }, - toFieldMetadataId: 'c1cdebda-b514-4487-9b9c-aa59d8fca8eb', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -314,8 +246,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: 'now', options: null, relationDefinition: null, @@ -334,22 +264,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: '31542774-fb15-4d01-b00b-8fc94887f458', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: 'f08422e2-14cd-4966-9cd3-bce0302cc56f', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'favorite', - namePlural: 'favorites', - isSystem: true, - isRemote: false, - }, - toFieldMetadataId: '67d28b17-ff3c-49b4-a6da-1354be9634b0', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -394,8 +308,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: { primaryLinkUrl: "''", primaryLinkLabel: "''", @@ -417,22 +329,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: 'c0cc3456-afa4-46e0-820d-2db0b63a8273', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: '0e3c9a9d-8a60-4671-a466-7b840a422da2', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'attachment', - namePlural: 'attachments', - isSystem: true, - isRemote: false, - }, - toFieldMetadataId: 'a920a0d6-8e71-4ab8-90b9-ab540e04732a', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -477,8 +373,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: "''", options: null, relationDefinition: null, @@ -497,8 +391,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: null, @@ -517,8 +409,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: "''", options: null, relationDefinition: null, @@ -537,8 +427,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: "''", options: null, relationDefinition: null, @@ -557,8 +445,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: 'now', options: null, relationDefinition: null, @@ -577,8 +463,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: null, @@ -597,22 +481,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: '25150feb-fcd7-407e-b5fa-ffe58a0450ac', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: '83b5ff3e-975e-4dc9-ba4d-c645a0d8afb2', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'timelineActivity', - namePlural: 'timelineActivities', - isSystem: true, - isRemote: false, - }, - toFieldMetadataId: '556a12d4-ef0a-4232-963f-0f317f4c5ef5', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -657,8 +525,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: { lastName: "''", firstName: "''", @@ -680,8 +546,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: { primaryLinkUrl: "''", primaryLinkLabel: "''", @@ -703,22 +567,6 @@ export const mockPerformance = { isNullable: true, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: { - __typename: 'relation', - id: 'e2eb7156-6e65-4bf8-922b-670179744f27', - relationType: 'ONE_TO_MANY', - toObjectMetadata: { - __typename: 'object', - id: 'ffd8e640-84b7-4ed6-99e9-14def0f9d82b', - dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768', - nameSingular: 'messageParticipant', - namePlural: 'messageParticipants', - isSystem: true, - isRemote: false, - }, - toFieldMetadataId: '8c4593a1-ad40-4681-92fe-43ad4fe60205', - }, - toRelationMetadata: null, defaultValue: null, options: null, relationDefinition: { @@ -763,8 +611,6 @@ export const mockPerformance = { isNullable: false, createdAt: '2024-05-16T10:54:27.788Z', updatedAt: '2024-05-16T10:54:27.788Z', - fromRelationMetadata: null, - toRelationMetadata: null, defaultValue: 'uuid', options: null, relationDefinition: null, @@ -816,7 +662,10 @@ export const mockPerformance = { }, id: '20202020-2d40-4e49-8df4-9c6a049191df', email: 'lorie.vladim@google.com', - phone: '+33788901235', + phones: { + primaryPhoneCountryCode: '+33', + primaryPhoneNumber: '788901235', + }, linkedinLink: { __typename: 'Link', primaryLinkLabel: '', diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyState.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyState.tsx new file mode 100644 index 000000000000..c25a3cf11990 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyState.tsx @@ -0,0 +1,34 @@ +import { useObjectIsRemote } from '@/object-metadata/hooks/useObjectIsRemote'; +import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; +import { RecordTableEmptyStateNoRecordAtAll } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordAtAll'; +import { RecordTableEmptyStateNoRecordFoundForFilter } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordFoundForFilter'; +import { RecordTableEmptyStateRemote } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateRemote'; +import { RecordTableEmptyStateSoftDelete } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete'; +import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; +import { useContext } from 'react'; +import { useRecoilValue } from 'recoil'; + +export const RecordTableEmptyState = () => { + const { objectNameSingular, recordTableId, objectMetadataItem } = + useContext(RecordTableContext); + + const { isSoftDeleteActiveState } = useRecordTableStates(recordTableId); + + const { totalCount } = useFindManyRecords({ objectNameSingular, limit: 1 }); + const noRecordAtAll = totalCount === 0; + + const isRemote = useObjectIsRemote(objectMetadataItem); + + const isSoftDeleteActive = useRecoilValue(isSoftDeleteActiveState); + + if (isRemote) { + return <RecordTableEmptyStateRemote />; + } else if (isSoftDeleteActive === true) { + return <RecordTableEmptyStateSoftDelete />; + } else if (noRecordAtAll) { + return <RecordTableEmptyStateNoRecordAtAll />; + } else { + return <RecordTableEmptyStateNoRecordFoundForFilter />; + } +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx new file mode 100644 index 000000000000..80c5ecaefeb1 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay.tsx @@ -0,0 +1,48 @@ +import AnimatedPlaceholder, { + AnimatedPlaceholderType, +} from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder'; +import { + AnimatedPlaceholderEmptyContainer, + AnimatedPlaceholderEmptySubTitle, + AnimatedPlaceholderEmptyTextContainer, + AnimatedPlaceholderEmptyTitle, +} from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled'; + +import { Button } from '@/ui/input/button/components/Button'; +import { IconComponent } from 'twenty-ui'; + +type RecordTableEmptyStateDisplayProps = { + animatedPlaceholderType: AnimatedPlaceholderType; + title: string; + subTitle: string; + Icon: IconComponent; + buttonTitle: string; + onClick: () => void; +}; + +export const RecordTableEmptyStateDisplay = ({ + Icon, + animatedPlaceholderType, + buttonTitle, + onClick, + subTitle, + title, +}: RecordTableEmptyStateDisplayProps) => { + return ( + <AnimatedPlaceholderEmptyContainer> + <AnimatedPlaceholder type={animatedPlaceholderType} /> + <AnimatedPlaceholderEmptyTextContainer> + <AnimatedPlaceholderEmptyTitle>{title}</AnimatedPlaceholderEmptyTitle> + <AnimatedPlaceholderEmptySubTitle> + {subTitle} + </AnimatedPlaceholderEmptySubTitle> + </AnimatedPlaceholderEmptyTextContainer> + <Button + Icon={Icon} + title={buttonTitle} + variant={'secondary'} + onClick={onClick} + /> + </AnimatedPlaceholderEmptyContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordAtAll.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordAtAll.tsx new file mode 100644 index 000000000000..00678d00ec30 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordAtAll.tsx @@ -0,0 +1,36 @@ +import { IconPlus } from 'twenty-ui'; + +import { useObjectLabel } from '@/object-metadata/hooks/useObjectLabel'; +import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; +import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay'; +import { useCreateNewTableRecord } from '@/object-record/record-table/hooks/useCreateNewTableRecords'; +import { useContext } from 'react'; + +export const RecordTableEmptyStateNoRecordAtAll = () => { + const { createNewTableRecord } = useCreateNewTableRecord(); + + const { objectMetadataItem } = useContext(RecordTableContext); + + const handleButtonClick = () => { + createNewTableRecord(); + }; + + const objectLabel = useObjectLabel(objectMetadataItem); + + const buttonTitle = `Add a ${objectLabel}`; + + const title = `Add your first ${objectLabel}`; + + const subTitle = `Use our API or add your first ${objectLabel} manually`; + + return ( + <RecordTableEmptyStateDisplay + buttonTitle={buttonTitle} + subTitle={subTitle} + title={title} + Icon={IconPlus} + animatedPlaceholderType="noRecord" + onClick={handleButtonClick} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordFoundForFilter.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordFoundForFilter.tsx new file mode 100644 index 000000000000..f733a636ddcc --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordFoundForFilter.tsx @@ -0,0 +1,36 @@ +import { IconPlus } from 'twenty-ui'; + +import { useObjectLabel } from '@/object-metadata/hooks/useObjectLabel'; +import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; +import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay'; +import { useCreateNewTableRecord } from '@/object-record/record-table/hooks/useCreateNewTableRecords'; +import { useContext } from 'react'; + +export const RecordTableEmptyStateNoRecordFoundForFilter = () => { + const { createNewTableRecord } = useCreateNewTableRecord(); + + const { objectMetadataItem } = useContext(RecordTableContext); + + const handleButtonClick = () => { + createNewTableRecord(); + }; + + const objectLabel = useObjectLabel(objectMetadataItem); + + const buttonTitle = `Add a ${objectLabel}`; + + const title = `No ${objectLabel} found`; + + const subTitle = 'No records matching the filter criteria were found.'; + + return ( + <RecordTableEmptyStateDisplay + buttonTitle={buttonTitle} + subTitle={subTitle} + title={title} + Icon={IconPlus} + animatedPlaceholderType="noMatchRecord" + onClick={handleButtonClick} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateRemote.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateRemote.tsx new file mode 100644 index 000000000000..3554bf8e1bf6 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateRemote.tsx @@ -0,0 +1,24 @@ +/* eslint-disable @nx/workspace-no-navigate-prefer-link */ +import { IconSettings } from 'twenty-ui'; + +import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay'; +import { useNavigate } from 'react-router-dom'; + +export const RecordTableEmptyStateRemote = () => { + const navigate = useNavigate(); + + const handleButtonClick = () => { + navigate('/settings/integrations'); + }; + + return ( + <RecordTableEmptyStateDisplay + buttonTitle={'Go to Settings'} + subTitle={'If this is unexpected, please verify your settings.'} + title={'No Data Available for Remote Table'} + Icon={IconSettings} + animatedPlaceholderType="noRecord" + onClick={handleButtonClick} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx new file mode 100644 index 000000000000..71eb045abda2 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx @@ -0,0 +1,50 @@ +import { IconFilterOff } from 'twenty-ui'; + +import { useObjectLabel } from '@/object-metadata/hooks/useObjectLabel'; +import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter'; +import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; +import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay'; +import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; +import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters'; +import { useContext } from 'react'; +import { useRecoilValue } from 'recoil'; + +export const RecordTableEmptyStateSoftDelete = () => { + const { objectMetadataItem, objectNameSingular, recordTableId } = + useContext(RecordTableContext); + + const { deleteCombinedViewFilter } = + useDeleteCombinedViewFilters(recordTableId); + const { tableFiltersState } = useRecordTableStates(recordTableId); + + const tableFilters = useRecoilValue(tableFiltersState); + + const { toggleSoftDeleteFilterState } = useHandleToggleTrashColumnFilter({ + objectNameSingular, + viewBarId: recordTableId, + }); + + const handleButtonClick = async () => { + deleteCombinedViewFilter( + tableFilters.find( + (filter) => + filter.definition.label === 'Deleted at' && + filter.operand === 'isNotEmpty', + )?.id ?? '', + ); + toggleSoftDeleteFilterState(false); + }; + + const objectLabel = useObjectLabel(objectMetadataItem); + + return ( + <RecordTableEmptyStateDisplay + buttonTitle={'Remove Deleted filter'} + subTitle={'No deleted records matching the filter criteria were found.'} + title={`No Deleted ${objectLabel} found`} + Icon={IconFilterOff} + animatedPlaceholderType="noDeletedRecord" + onClick={handleButtonClick} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordAtAll.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordAtAll.stories.tsx new file mode 100644 index 000000000000..0288c2560a82 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordAtAll.stories.tsx @@ -0,0 +1,39 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { RecordTableEmptyStateNoRecordAtAll } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordAtAll'; +import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { ComponentDecorator } from 'twenty-ui'; +import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { RecordTableDecorator } from '~/testing/decorators/RecordTableDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +const meta: Meta = { + title: 'Modules/ObjectRecord/RecordTable/RecordTableEmptyStateNoRecordAtAll', + component: RecordTableEmptyStateNoRecordAtAll, + decorators: [ + ComponentDecorator, + MemoryRouterDecorator, + ObjectMetadataItemsDecorator, + RecordTableDecorator, + (Story) => ( + <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> + <RecordTableScope + recordTableScopeId="persons" + onColumnsChange={() => {}} + > + <Story /> + </RecordTableScope> + </SnackBarProviderScope> + ), + ], + parameters: { + msw: graphqlMocks, + }, +}; + +export default meta; +type Story = StoryObj<typeof RecordTableEmptyStateNoRecordAtAll>; + +export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordFoundForFilter.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordFoundForFilter.stories.tsx new file mode 100644 index 000000000000..d46d99f58179 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateNoRecordFoundForFilter.stories.tsx @@ -0,0 +1,40 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { RecordTableEmptyStateNoRecordFoundForFilter } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateNoRecordFoundForFilter'; +import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { ComponentDecorator } from 'twenty-ui'; +import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { RecordTableDecorator } from '~/testing/decorators/RecordTableDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +const meta: Meta = { + title: + 'Modules/ObjectRecord/RecordTable/RecordTableEmptyStateNoRecordFoundForFilter', + component: RecordTableEmptyStateNoRecordFoundForFilter, + decorators: [ + ComponentDecorator, + MemoryRouterDecorator, + ObjectMetadataItemsDecorator, + RecordTableDecorator, + (Story) => ( + <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> + <RecordTableScope + recordTableScopeId="persons" + onColumnsChange={() => {}} + > + <Story /> + </RecordTableScope> + </SnackBarProviderScope> + ), + ], + parameters: { + msw: graphqlMocks, + }, +}; + +export default meta; +type Story = StoryObj<typeof RecordTableEmptyStateNoRecordFoundForFilter>; + +export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/RecordTableEmptyState.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateRemote.stories.tsx similarity index 53% rename from packages/twenty-front/src/modules/object-record/record-table/components/__stories__/RecordTableEmptyState.stories.tsx rename to packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateRemote.stories.tsx index 0cf38abdadec..07155f840339 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/RecordTableEmptyState.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateRemote.stories.tsx @@ -1,15 +1,22 @@ import { Meta, StoryObj } from '@storybook/react'; -import { RecordTableEmptyState } from '@/object-record/record-table/components/RecordTableEmptyState'; +import { RecordTableEmptyStateRemote } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateRemote'; import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { ComponentDecorator } from 'twenty-ui'; import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { RecordTableDecorator } from '~/testing/decorators/RecordTableDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; const meta: Meta = { - title: 'Modules/ObjectRecord/RecordTable/RecordTableEmptyState', - component: RecordTableEmptyState, + title: 'Modules/ObjectRecord/RecordTable/RecordTableEmptyStateRemote', + component: RecordTableEmptyStateRemote, decorators: [ + ComponentDecorator, MemoryRouterDecorator, + ObjectMetadataItemsDecorator, + RecordTableDecorator, (Story) => ( <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> <RecordTableScope @@ -21,25 +28,12 @@ const meta: Meta = { </SnackBarProviderScope> ), ], + parameters: { + msw: graphqlMocks, + }, }; export default meta; -type Story = StoryObj<typeof RecordTableEmptyState>; - -export const Default: Story = { - args: { - objectNameSingular: 'person', - objectLabel: 'person', - isRemote: false, - createRecord: () => {}, - }, -}; +type Story = StoryObj<typeof RecordTableEmptyStateRemote>; -export const Remote: Story = { - args: { - objectNameSingular: 'person', - objectLabel: 'remote person', - isRemote: true, - createRecord: () => {}, - }, -}; +export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateSoftDelete.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateSoftDelete.stories.tsx new file mode 100644 index 000000000000..85193da6bdc5 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/__stories__/RecordTableEmptyStateSoftDelete.stories.tsx @@ -0,0 +1,39 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { RecordTableEmptyStateSoftDelete } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete'; +import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { ComponentDecorator } from 'twenty-ui'; +import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { RecordTableDecorator } from '~/testing/decorators/RecordTableDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +const meta: Meta = { + title: 'Modules/ObjectRecord/RecordTable/RecordTableEmptyStateSoftDelete', + component: RecordTableEmptyStateSoftDelete, + decorators: [ + ComponentDecorator, + MemoryRouterDecorator, + ObjectMetadataItemsDecorator, + RecordTableDecorator, + (Story) => ( + <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> + <RecordTableScope + recordTableScopeId="persons" + onColumnsChange={() => {}} + > + <Story /> + </RecordTableScope> + </SnackBarProviderScope> + ), + ], + parameters: { + msw: graphqlMocks, + }, +}; + +export default meta; +type Story = StoryObj<typeof RecordTableEmptyStateSoftDelete>; + +export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts index 1fbc4a8bd810..106b1174de02 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useRecordTableStates.ts @@ -4,6 +4,7 @@ import { RecordTableScopeInternalContext } from '@/object-record/record-table/sc import { availableTableColumnsComponentState } from '@/object-record/record-table/states/availableTableColumnsComponentState'; import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState'; import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState'; +import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState'; import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState'; import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState'; import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState'; @@ -88,6 +89,10 @@ export const useRecordTableStates = (recordTableId?: string) => { isTableCellInEditModeComponentFamilyState, scopeId, ), + isSoftDeleteActiveState: extractComponentState( + isSoftDeleteFilterActiveComponentState, + scopeId, + ), isSoftFocusActiveState: extractComponentState( isSoftFocusActiveComponentState, scopeId, diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useCreateNewTableRecords.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useCreateNewTableRecords.ts new file mode 100644 index 000000000000..15056d35102d --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useCreateNewTableRecords.ts @@ -0,0 +1,33 @@ +import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; +import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; +import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2'; +import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode'; +import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { useContext } from 'react'; +import { v4 } from 'uuid'; + +export const useCreateNewTableRecord = (recordTableIdFromProps?: string) => { + const { recordTableId } = useContext(RecordTableContext); + + const recordTableIdToUse = recordTableIdFromProps ?? recordTableId; + + const { setSelectedTableCellEditMode } = useSelectedTableCellEditMode({ + scopeId: recordTableIdToUse, + }); + + const setHotkeyScope = useSetHotkeyScope(); + + const { setPendingRecordId } = useRecordTable({ + recordTableId: recordTableIdToUse, + }); + + const createNewTableRecord = () => { + setPendingRecordId(v4()); + setSelectedTableCellEditMode(-1, 0); + setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes); + }; + + return { + createNewTableRecord, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx index 20941b7c63a6..84a332a62f96 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx @@ -18,6 +18,7 @@ const StyledInnerContainer = styled.div` height: 100%; overflow: hidden; width: 100%; + flex-wrap: wrap; `; export type EditableCellDisplayContainerProps = { diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx index 49f51197db11..5aca062fbac2 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableTd.tsx @@ -43,8 +43,8 @@ const StyledTd = styled.td<{ ${({ freezeFirstColumns }) => freezeFirstColumns ? `@media (max-width: ${MOBILE_VIEWPORT}px) { - width: 35px; - max-width: 35px; + width: 32px; + max-width: 32px; }` : ''} `; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx index 1e7ec2088d27..23b7e3b00d96 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useSelectedTableCellEditMode.test.tsx @@ -48,14 +48,14 @@ describe('useSelectedTableCellEditMode', () => { expect(mockCallbackInterface.set).toHaveBeenCalledWith( { - key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"scopeId":"yourScopeId-scope"}', + key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"scopeId":"yourScopeId"}', }, false, ); expect(mockCallbackInterface.set).toHaveBeenCalledWith( { - key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"scopeId":"yourScopeId-scope"}', + key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"scopeId":"yourScopeId"}', }, true, ); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useUpsertRecord.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useUpsertRecord.test.tsx index 1712e01c2033..e592107c5a1b 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useUpsertRecord.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__tests__/useUpsertRecord.test.tsx @@ -5,12 +5,12 @@ import { createState } from 'twenty-ui'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { textfieldDefinition } from '@/object-record/record-field/__mocks__/fieldDefinitions'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { useUpsertRecord } from '@/object-record/record-table/record-table-cell/hooks/useUpsertRecord'; import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const draftValue = 'updated Name'; @@ -55,8 +55,6 @@ const updateOneRecordMock = jest.fn(); createOneRecord: createOneRecordMock, }); -const objectMetadataItems = getObjectMetadataItemsMock(); - const Wrapper = ({ children, pendingRecordIdMockedValue, @@ -68,7 +66,7 @@ const Wrapper = ({ }) => ( <RecoilRoot initializeState={(snapshot) => { - snapshot.set(objectMetadataItemsState, objectMetadataItems); + snapshot.set(objectMetadataItemsState, generatedMockObjectMetadataItems); snapshot.set(pendingRecordIdState, pendingRecordIdMockedValue); snapshot.set(draftValueState, draftValueMockedValue); }} diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index d25f41655f34..0159b907b4b3 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -20,7 +20,7 @@ import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useC import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; import { isDefined } from '~/utils/isDefined'; -import { RecordIndexEventContext } from '@/object-record/record-index/contexts/RecordIndexEventContext'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; import { useContext } from 'react'; import { TableHotkeyScope } from '../../types/TableHotkeyScope'; @@ -41,7 +41,7 @@ export type OpenTableCellArgs = { }; export const useOpenRecordTableCellV2 = (tableScopeId: string) => { - const { onIndexIdentifierClick } = useContext(RecordIndexEventContext); + const { onIndexIdentifierClick } = useContext(RecordIndexRootPropsContext); const moveEditModeToTableCellPosition = useMoveEditModeToTableCellPosition(tableScopeId); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx index 34009d15421d..a21a0578ab0d 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeader.tsx @@ -73,11 +73,7 @@ const StyledTableHead = styled.thead<{ } `; -export const RecordTableHeader = ({ - createRecord, -}: { - createRecord: () => void; -}) => { +export const RecordTableHeader = () => { const { visibleTableColumnsSelector } = useRecordTableStates(); const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector()); @@ -88,11 +84,7 @@ export const RecordTableHeader = ({ <RecordTableHeaderDragDropColumn /> <RecordTableHeaderCheckboxColumn /> {visibleTableColumns.map((column) => ( - <RecordTableHeaderCell - key={column.fieldMetadataId} - column={column} - createRecord={createRecord} - /> + <RecordTableHeaderCell key={column.fieldMetadataId} column={column} /> ))} <RecordTableHeaderLastColumn /> </tr> diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx index 82a222695e5a..4084b95dd9b2 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderCell.tsx @@ -5,6 +5,7 @@ import { IconPlus } from 'twenty-ui'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; +import { useCreateNewTableRecord } from '@/object-record/record-table/hooks/useCreateNewTableRecords'; import { useTableColumns } from '@/object-record/record-table/hooks/useTableColumns'; import { RecordTableColumnHeadWithDropdown } from '@/object-record/record-table/record-table-header/components/RecordTableColumnHeadWithDropdown'; import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState'; @@ -90,10 +91,8 @@ const StyledHeaderIcon = styled.div` export const RecordTableHeaderCell = ({ column, - createRecord, }: { column: ColumnDefinition<FieldMetadata>; - createRecord: () => void; }) => { const { resizeFieldOffsetState, tableColumnsState } = useRecordTableStates(); @@ -185,6 +184,12 @@ export const RecordTableHeaderCell = ({ const disableColumnResize = column.isLabelIdentifier && isMobile && !isRecordTableScrolledLeft; + const { createNewTableRecord } = useCreateNewTableRecord(); + + const handlePlusButtonClick = () => { + createNewTableRecord(); + }; + return ( <StyledColumnHeaderCell key={column.fieldMetadataId} @@ -206,7 +211,7 @@ export const RecordTableHeaderCell = ({ Icon={IconPlus} size="small" accent="tertiary" - onClick={createRecord} + onClick={handlePlusButtonClick} /> </StyledHeaderIcon> )} diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLastColumn.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLastColumn.tsx index 0a548ae5f8de..8a87fd63c560 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLastColumn.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderLastColumn.tsx @@ -19,7 +19,6 @@ const StyledPlusIconHeaderCell = styled.th<{ &:hover { background: ${theme.background.transparent.light}; }; - padding-left: ${theme.spacing(3)}; `; }}; border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; @@ -28,12 +27,12 @@ const StyledPlusIconHeaderCell = styled.th<{ border-left: none !important; color: ${({ theme }) => theme.font.color.tertiary}; min-width: 32px; + width: 32px; border-right: none !important; ${({ isTableWiderThanScreen, theme }) => isTableWiderThanScreen ? ` - width: 32px; background-color: ${theme.background.primary}; ` : ''}; @@ -45,7 +44,7 @@ const StyledPlusIconContainer = styled.div` display: flex; height: 32px; justify-content: center; - width: 32px; + width: 100%; `; const HIDDEN_TABLE_COLUMN_DROPDOWN_HOTKEY_SCOPE_ID = diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderPlusButtonContent.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderPlusButtonContent.tsx index 1766407a022c..f258a921383f 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderPlusButtonContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/components/RecordTableHeaderPlusButtonContent.tsx @@ -59,6 +59,7 @@ export const RecordTableHeaderPlusButtonContent = () => { )} <DropdownMenuItemsContainer> <UndecoratedLink + fullWidth to={`/settings/objects/${getObjectSlug(objectMetadataItem)}`} onClick={() => { setNavigationMemorizedUrl(location.pathname + location.search); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx index 421c800e21c6..ef0b399fd457 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-row/components/RecordTableRowWrapper.tsx @@ -5,7 +5,7 @@ import { useInView } from 'react-intersection-observer'; import { useRecoilValue } from 'recoil'; import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage'; -import { RecordIndexEventContext } from '@/object-record/record-index/contexts/RecordIndexEventContext'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; @@ -24,7 +24,7 @@ export const RecordTableRowWrapper = ({ children: ReactNode; }) => { const { objectMetadataItem } = useContext(RecordTableContext); - const { onIndexRecordsLoaded } = useContext(RecordIndexEventContext); + const { onIndexRecordsLoaded } = useContext(RecordIndexRootPropsContext); const theme = useTheme(); diff --git a/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts index 40e3e30c2d1c..1665e2b960e7 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts @@ -1,11 +1,11 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; import { ColumnDefinition } from '../../types/ColumnDefinition'; // TODO: separate scope contexts from event contexts -type RecordTableScopeInternalContextProps = ComponentStateKey & { +type RecordTableScopeInternalContextProps = RecoilComponentStateKey & { onColumnsChange: (columns: ColumnDefinition<FieldMetadata>[]) => void; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts b/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts index f8b6716a8659..9cd066b84e5e 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2.ts @@ -1,8 +1,8 @@ import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { createComponentStateV2_alpha } from '@/ui/utilities/state/component-state/utils/createComponentStateV2_alpha'; export const hasRecordTableFetchedAllRecordsComponentStateV2 = - createComponentStateV2<boolean>({ + createComponentStateV2_alpha<boolean>({ key: 'hasRecordTableFetchedAllRecordsComponentStateV2', componentContext: RecordTableScopeInternalContext, defaultValue: false, diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledLeftComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledLeftComponentState.ts index 6f26d8a6082a..b51a7f63f48d 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledLeftComponentState.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledLeftComponentState.ts @@ -1,8 +1,8 @@ import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { createComponentStateV2_alpha } from '@/ui/utilities/state/component-state/utils/createComponentStateV2_alpha'; export const isRecordTableScrolledLeftComponentState = - createComponentStateV2<boolean>({ + createComponentStateV2_alpha<boolean>({ key: 'isRecordTableScrolledLeftComponentState', componentContext: RecordTableScopeInternalContext, defaultValue: true, diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledTopComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledTopComponentState.ts index 564c567a6062..5a206e88b7a5 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledTopComponentState.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/states/isRecordTableScrolledTopComponentState.ts @@ -1,8 +1,8 @@ import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { createComponentStateV2_alpha } from '@/ui/utilities/state/component-state/utils/createComponentStateV2_alpha'; export const isRecordTableScrolledTopComponentState = - createComponentStateV2<boolean>({ + createComponentStateV2_alpha<boolean>({ key: 'isRecordTableScrolledTopComponentState', componentContext: RecordTableScopeInternalContext, defaultValue: true, diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/isSoftDeleteFilterActiveComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/isSoftDeleteFilterActiveComponentState.ts new file mode 100644 index 000000000000..58b236c9571e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/states/isSoftDeleteFilterActiveComponentState.ts @@ -0,0 +1,7 @@ +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const isSoftDeleteFilterActiveComponentState = + createComponentState<boolean>({ + key: 'isSoftDeleteFilterActiveComponentState', + defaultValue: false, + }); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx index 87c0532208fe..f325edecc22f 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/MultiRecordSelect.tsx @@ -48,7 +48,7 @@ export const MultiRecordSelect = ({ const { objectRecordsIdsMultiSelectState, recordMultiSelectIsLoadingState } = useObjectRecordMultiSelectScopedStates(relationPickerScopedId); - const { handleResetSelectedPosition } = useSelectableList( + const { resetSelectedItem } = useSelectableList( MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID, ); const recordMultiSelectIsLoading = useRecoilValue( @@ -79,10 +79,10 @@ export const MultiRecordSelect = ({ () => { onSubmit?.(); goBackToPreviousHotkeyScope(); - handleResetSelectedPosition(); + resetSelectedItem(); }, relationPickerScopedId, - [onSubmit, goBackToPreviousHotkeyScope, handleResetSelectedPosition], + [onSubmit, goBackToPreviousHotkeyScope, resetSelectedItem], ); const debouncedOnCreate = useDebouncedCallback( @@ -123,7 +123,7 @@ export const MultiRecordSelect = ({ hotkeyScope={relationPickerScopedId} onEnter={(selectedId) => { onChange?.(selectedId); - handleResetSelectedPosition(); + resetSelectedItem(); }} > {objectRecordsIdsMultiSelect?.map((recordId) => { @@ -133,7 +133,7 @@ export const MultiRecordSelect = ({ objectRecordId={recordId} onChange={(recordId) => { onChange?.(recordId); - handleResetSelectedPosition(); + resetSelectedItem(); }} /> ); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx index ee4885258f2d..0f2356e63f72 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/MultipleObjectRecordSelectItem.tsx @@ -1,7 +1,6 @@ import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; import { Avatar } from 'twenty-ui'; -import { v4 } from 'uuid'; import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useObjectRecordMultiSelectScopedStates'; import { MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID } from '@/object-record/relation-picker/constants/MultiObjectRecordSelectSelectableListId'; @@ -69,7 +68,7 @@ export const MultipleObjectRecordSelectItem = ({ : false; return ( - <StyledSelectableItem itemId={objectRecordId} key={objectRecordId + v4()}> + <StyledSelectableItem itemId={objectRecordId} key={objectRecordId}> <MenuItemMultiSelectAvatar onSelectChange={(_isNewlySelectedValue) => handleSelectChange()} isKeySelected={isSelectedByKeyboard} diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx index 204467062765..eef1523d1505 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SelectableMenuItemSelect.tsx @@ -27,7 +27,6 @@ export const SelectableMenuItemSelect = ({ ); const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(entity.id)); - return ( <StyledSelectableItem itemId={entity.id} key={entity.id}> <MenuItemSelectAvatar diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx index ac7d5c1ab6e0..a7f029e127c9 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx @@ -1,5 +1,5 @@ -import { useRef } from 'react'; import { isNonEmptyString } from '@sniptt/guards'; +import { Fragment, useRef } from 'react'; import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { IconComponent, IconPlus } from 'twenty-ui'; @@ -92,8 +92,9 @@ export const SingleEntitySelectMenuItems = ({ isDefined(entity) && isNonEmptyString(entity.name), ); - const { isSelectedItemIdSelector, handleResetSelectedPosition } = - useSelectableList(SINGLE_ENTITY_SELECT_BASE_LIST); + const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList( + SINGLE_ENTITY_SELECT_BASE_LIST, + ); const isSelectedAddNewButton = useRecoilValue( isSelectedItemIdSelector('add-new'), @@ -110,11 +111,11 @@ export const SingleEntitySelectMenuItems = ({ useScopedHotkeys( [Key.Escape], () => { - handleResetSelectedPosition(); + resetSelectedItem(); onCancel?.(); }, hotkeyScope, - [onCancel, handleResetSelectedPosition], + [onCancel, resetSelectedItem], ); const selectableItemIds = entitiesInDropdown.map((entity) => entity.id); @@ -134,7 +135,7 @@ export const SingleEntitySelectMenuItems = ({ ); onEntitySelected(entitiesInDropdown[entityIndex]); } - handleResetSelectedPosition(); + resetSelectedItem(); }} > <DropdownMenuItemsContainer hasMaxHeight> @@ -157,16 +158,15 @@ export const SingleEntitySelectMenuItems = ({ switch (entity.id) { case 'add-new': { return ( - <> + <Fragment key={entity.id}> {entitiesToSelect.length > 0 && <DropdownMenuSeparator />} <CreateNewButton - key={entity.id} onClick={onCreate} LeftIcon={IconPlus} text="Add New" hovered={isSelectedAddNewButton} /> - </> + </Fragment> ); } case 'select-none': { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx index 9bd679cc47ee..9eb2e7b3642e 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx @@ -2,9 +2,9 @@ import { act, renderHook } from '@testing-library/react'; import { RecoilRoot, useSetRecoilState } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; const scopeId = 'scopeId'; const Wrapper = ({ children }: { children: React.ReactNode }) => ( @@ -13,8 +13,6 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => ( </RelationPickerScopeInternalContext.Provider> ); -const objectMetadataItemsMock = getObjectMetadataItemsMock(); - const opportunityId = 'cb702502-4b1d-488e-9461-df3fb096ebf6'; const personId = 'ab091fd9-1b81-4dfd-bfdb-564ffee032a2'; @@ -70,7 +68,7 @@ describe('useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray' }, ); act(() => { - result.current.setObjectMetadata(objectMetadataItemsMock); + result.current.setObjectMetadata(generatedMockObjectMetadataItems); }); expect( diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts index 3dbbfc7eff08..eda26d3f1ff5 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type RelationPickerScopeInternalContextProps = ComponentStateKey; +type RelationPickerScopeInternalContextProps = RecoilComponentStateKey; export const RelationPickerScopeInternalContext = createScopeInternalContext<RelationPickerScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx b/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx index e8a286ad4d36..3914a41633fe 100644 --- a/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx @@ -40,7 +40,7 @@ export const MultipleRecordSelectDropdown = ({ selectableListScopeId: selectableListId, }); - const { handleResetSelectedPosition } = useSelectableList(selectableListId); + const { resetSelectedItem } = useSelectableList(selectableListId); const selectedItemId = useRecoilValue(selectedItemIdState); @@ -75,10 +75,10 @@ export const MultipleRecordSelectDropdown = ({ [Key.Escape], () => { closeDropdown(); - handleResetSelectedPosition(); + resetSelectedItem(); }, hotkeyScope, - [closeDropdown, handleResetSelectedPosition], + [closeDropdown, resetSelectedItem], ); const showNoResult = @@ -105,7 +105,7 @@ export const MultipleRecordSelectDropdown = ({ recordsInDropdown[record], !recordIsSelectedInDropwdown, ); - handleResetSelectedPosition(); + resetSelectedItem(); }} > <DropdownMenuItemsContainer hasMaxHeight> @@ -116,7 +116,7 @@ export const MultipleRecordSelectDropdown = ({ selected={record.isSelected} isKeySelected={record.id === selectedItemId} onSelectChange={(newCheckedValue) => { - handleResetSelectedPosition(); + resetSelectedItem(); handleRecordSelectChange(record, newCheckedValue); }} avatar={ diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useOpenObjectRecordsSpreasheetImportDialog.test.tsx b/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useOpenObjectRecordsSpreasheetImportDialog.test.tsx index a9680898821f..da745581eb75 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useOpenObjectRecordsSpreasheetImportDialog.test.tsx +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/__tests__/useOpenObjectRecordsSpreasheetImportDialog.test.tsx @@ -26,35 +26,13 @@ const companyMocks = [ ) { createCompanies(data: $data, upsert: $upsert) { __typename - id - visaSponsorship - createdBy { - source - workspaceMemberId - name - } + updatedAt domainName { primaryLinkUrl primaryLinkLabel secondaryLinks } - introVideo { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - position - annualRecurringRevenue { - amountMicros - currencyCode - } - employees - linkedinLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - workPolicy + visaSponsorship address { addressStreet1 addressStreet2 @@ -65,16 +43,38 @@ const companyMocks = [ addressLat addressLng } + position + employees + deletedAt + accountOwnerId + annualRecurringRevenue { + amountMicros + currencyCode + } + id name - updatedAt xLink { primaryLinkUrl primaryLinkLabel secondaryLinks } - myCustomField createdAt - accountOwnerId + createdBy { + source + workspaceMemberId + name + } + workPolicy + introVideo { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } tagline idealCustomerProfile } diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreasheetImportDialog.ts b/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreasheetImportDialog.ts index 80b547eaa5a6..e5be43858442 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreasheetImportDialog.ts +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreasheetImportDialog.ts @@ -6,7 +6,10 @@ import { useOpenSpreadsheetImportDialog } from '@/spreadsheet-import/hooks/useOp import { SpreadsheetImportDialogOptions } from '@/spreadsheet-import/types'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; +import { + FieldMetadataType, + RelationDefinitionType, +} from '~/generated-metadata/graphql'; export const useOpenObjectRecordsSpreasheetImportDialog = ( objectNameSingular: string, @@ -37,7 +40,8 @@ export const useOpenObjectRecordsSpreasheetImportDialog = ( (!fieldMetadataItem.isSystem || fieldMetadataItem.name === 'id') && fieldMetadataItem.name !== 'createdAt' && (fieldMetadataItem.type !== FieldMetadataType.Relation || - fieldMetadataItem.toRelationMetadata), + fieldMetadataItem.relationDefinition?.direction === + RelationDefinitionType.ManyToOne), ) .sort((fieldMetadataItemA, fieldMetadataItemB) => fieldMetadataItemA.name.localeCompare(fieldMetadataItemB.name), diff --git a/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts b/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts index eadb16fd47c8..492a2b9a9a35 100644 --- a/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts +++ b/packages/twenty-front/src/modules/object-record/utils/filterAvailableTableColumns.ts @@ -2,14 +2,15 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata' import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { TABLE_COLUMNS_DENY_LIST } from '@/object-record/relation-picker/constants/TableColumnsDenyList'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; export const filterAvailableTableColumns = ( columnDefinition: ColumnDefinition<FieldMetadata>, ): boolean => { if ( isFieldRelation(columnDefinition) && - columnDefinition.metadata?.relationType !== 'TO_ONE_OBJECT' && - columnDefinition.metadata?.relationType !== 'FROM_MANY_OBJECTS' + columnDefinition.metadata?.relationType === + RelationDefinitionType.ManyToMany ) { return false; } diff --git a/packages/twenty-front/src/modules/object-record/utils/generateDefaultFieldValue.ts b/packages/twenty-front/src/modules/object-record/utils/generateDefaultFieldValue.ts index 2ed467659cf3..4a12f3ee72d8 100644 --- a/packages/twenty-front/src/modules/object-record/utils/generateDefaultFieldValue.ts +++ b/packages/twenty-front/src/modules/object-record/utils/generateDefaultFieldValue.ts @@ -4,10 +4,7 @@ import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFiel import { v4 } from 'uuid'; export const generateDefaultFieldValue = ( - fieldMetadataItem: Pick< - FieldMetadataItem, - 'defaultValue' | 'type' | 'fromRelationMetadata' - >, + fieldMetadataItem: Pick<FieldMetadataItem, 'defaultValue' | 'type'>, ) => { const defaultValue = isFieldValueEmpty({ fieldValue: fieldMetadataItem.defaultValue, diff --git a/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts b/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts index f9d6be3208c0..a0a69349fc35 100644 --- a/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts +++ b/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts @@ -1,10 +1,11 @@ -import { isNonEmptyString } from '@sniptt/guards'; - import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; +import { + FieldMetadataType, + RelationDefinitionType, +} from '~/generated-metadata/graphql'; export const generateEmptyFieldValue = ( - fieldMetadataItem: Pick<FieldMetadataItem, 'type' | 'fromRelationMetadata'>, + fieldMetadataItem: Pick<FieldMetadataItem, 'type' | 'relationDefinition'>, ) => { switch (fieldMetadataItem.type) { case FieldMetadataType.Email: @@ -62,10 +63,8 @@ export const generateEmptyFieldValue = ( } case FieldMetadataType.Relation: { if ( - !isNonEmptyString( - fieldMetadataItem.fromRelationMetadata?.toObjectMetadata - ?.nameSingular, - ) + fieldMetadataItem.relationDefinition?.direction === + RelationDefinitionType.ManyToOne ) { return null; } @@ -84,6 +83,9 @@ export const generateEmptyFieldValue = ( case FieldMetadataType.MultiSelect: { return null; } + case FieldMetadataType.Array: { + return null; + } case FieldMetadataType.RawJson: { return null; } @@ -97,6 +99,13 @@ export const generateEmptyFieldValue = ( name: '', }; } + case FieldMetadataType.Phones: { + return { + primaryPhoneNumber: '', + primaryPhoneCountryCode: '', + additionalPhones: null, + }; + } default: { throw new Error('Unhandled FieldMetadataType'); } diff --git a/packages/twenty-front/src/modules/object-record/utils/getDestroyOneRecordMutationResponseField.ts b/packages/twenty-front/src/modules/object-record/utils/getDestroyOneRecordMutationResponseField.ts new file mode 100644 index 000000000000..f93c64915de3 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/utils/getDestroyOneRecordMutationResponseField.ts @@ -0,0 +1,5 @@ +import { capitalize } from '~/utils/string/capitalize'; + +export const getDestroyOneRecordMutationResponseField = ( + objectNameSingular: string, +) => `destroy${capitalize(objectNameSingular)}`; diff --git a/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts b/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts index bfdeb6e174f2..df03a87311ca 100644 --- a/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts +++ b/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts @@ -1,12 +1,16 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation'; import { FieldMetadataType, - RelationMetadataType, + RelationDefinitionType, } from '~/generated-metadata/graphql'; -export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => { +export const isFieldCellSupported = ( + fieldMetadataItem: FieldMetadataItem, + objectMetadataItems: ObjectMetadataItem[], +) => { if ( [ FieldMetadataType.Uuid, @@ -18,17 +22,17 @@ export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => { } if (fieldMetadataItem.type === FieldMetadataType.Relation) { - const relationMetadata = - fieldMetadataItem.fromRelationMetadata ?? - fieldMetadataItem.toRelationMetadata; - const relationObjectMetadataItem = - fieldMetadataItem.fromRelationMetadata?.toObjectMetadata ?? - fieldMetadataItem.toRelationMetadata?.fromObjectMetadata; + const relationObjectMetadataItemId = + fieldMetadataItem.relationDefinition?.targetObjectMetadata.id; + + const relationObjectMetadataItem = objectMetadataItems.find( + (item) => item.id === relationObjectMetadataItemId, + ); // Hack to display targets on Notes and Tasks if ( - fieldMetadataItem.fromRelationMetadata?.toObjectMetadata?.nameSingular === - CoreObjectNameSingular.NoteTarget && + fieldMetadataItem.relationDefinition?.targetObjectMetadata + ?.nameSingular === CoreObjectNameSingular.NoteTarget && fieldMetadataItem.relationDefinition?.sourceObjectMetadata .nameSingular === CoreObjectNameSingular.Note ) { @@ -36,8 +40,8 @@ export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => { } if ( - fieldMetadataItem.fromRelationMetadata?.toObjectMetadata?.nameSingular === - CoreObjectNameSingular.TaskTarget && + fieldMetadataItem.relationDefinition?.targetObjectMetadata + ?.nameSingular === CoreObjectNameSingular.TaskTarget && fieldMetadataItem.relationDefinition?.sourceObjectMetadata .nameSingular === CoreObjectNameSingular.Task ) { @@ -45,9 +49,10 @@ export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => { } if ( - !relationMetadata || + !fieldMetadataItem.relationDefinition || // TODO: Many to many relations are not supported yet. - relationMetadata.relationType === RelationMetadataType.ManyToMany || + fieldMetadataItem.relationDefinition.direction === + RelationDefinitionType.ManyToMany || !relationObjectMetadataItem || !isObjectMetadataAvailableForRelation(relationObjectMetadataItem) ) { diff --git a/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts b/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts index bbad8bd461cd..cc3fb4ba46fa 100644 --- a/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts +++ b/packages/twenty-front/src/modules/object-record/utils/sanitizeRecordInput.ts @@ -1,8 +1,8 @@ import { isString } from '@sniptt/guards'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { isFieldRelationToOneValue } from '@/object-record/record-field/types/guards/isFieldRelationToOneValue'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { FieldMetadataType } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; import { getUrlHostName } from '~/utils/url/getUrlHostName'; @@ -29,7 +29,8 @@ export const sanitizeRecordInput = ({ if ( fieldMetadataItem.type === FieldMetadataType.Relation && - isFieldRelationToOneValue(fieldValue) + fieldMetadataItem.relationDefinition?.direction === + RelationDefinitionType.ManyToOne ) { const relationIdFieldName = `${fieldMetadataItem.name}Id`; const relationIdFieldMetadataItem = objectMetadataItem.fields.find( @@ -41,6 +42,14 @@ export const sanitizeRecordInput = ({ : undefined; } + if ( + fieldMetadataItem.type === FieldMetadataType.Relation && + fieldMetadataItem.relationDefinition?.direction === + RelationDefinitionType.OneToMany + ) { + return undefined; + } + return [fieldName, fieldValue]; }) .filter(isDefined), diff --git a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx index 23b7409799ca..83fa74e7b864 100644 --- a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx +++ b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx @@ -1,14 +1,14 @@ -import { ReactNode } from 'react'; import { MockedProvider } from '@apollo/client/testing'; import { renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; import { RecoilRoot, useSetRecoilState } from 'recoil'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { EntitiesForMultipleEntitySelect } from '@/object-record/relation-picker/types/EntitiesForMultipleEntitySelect'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; import { query, responseData, @@ -75,11 +75,9 @@ describe('useFilteredSearchEntityQuery', () => { locale: 'en', }); - const mockObjectMetadataItems = getObjectMetadataItemsMock(); - const setMetadataItems = useSetRecoilState(objectMetadataItemsState); - setMetadataItems(mockObjectMetadataItems); + setMetadataItems(generatedMockObjectMetadataItems); return useFilteredSearchEntityQuery({ orderByField: 'name', diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsContainer.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsContainer.tsx index 16b1255ffeec..9556441e6267 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsContainer.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsCalendarChannelsContainer.tsx @@ -8,7 +8,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { SettingsAccountsCalendarChannelDetails } from '@/settings/accounts/components/SettingsAccountsCalendarChannelDetails'; import { SettingsAccountsCalendarChannelsGeneral } from '@/settings/accounts/components/SettingsAccountsCalendarChannelsGeneral'; -import { SettingsAccountsListEmptyStateCard } from '@/settings/accounts/components/SettingsAccountsListEmptyStateCard'; +import { SettingsNewAccountSection } from '@/settings/accounts/components/SettingsNewAccountSection'; import { SETTINGS_ACCOUNT_CALENDAR_CHANNELS_TAB_LIST_COMPONENT_ID } from '@/settings/accounts/constants/SettingsAccountCalendarChannelsTabListComponentId'; import { TabList } from '@/ui/layout/tab/components/TabList'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; @@ -45,6 +45,7 @@ export const SettingsAccountsCalendarChannelsContainer = () => { in: accounts.map((account) => account.id), }, }, + skip: !accounts.length, }); const tabs = [ @@ -55,7 +56,7 @@ export const SettingsAccountsCalendarChannelsContainer = () => { ]; if (!calendarChannels.length) { - return <SettingsAccountsListEmptyStateCard />; + return <SettingsNewAccountSection />; } return ( diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer.tsx index 2d05e37524cf..2091be23645c 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer.tsx @@ -1,8 +1,9 @@ import { ConnectedAccount } from '@/accounts/types/ConnectedAccount'; import { SettingsAccountsRowDropdownMenu } from '@/settings/accounts/components/SettingsAccountsRowDropdownMenu'; +import { SyncStatus } from '@/settings/accounts/constants/SyncStatus'; +import { computeSyncStatus } from '@/settings/accounts/utils/computeSyncStatus'; import { Status } from '@/ui/display/status/components/Status'; import styled from '@emotion/styled'; -import { useMemo } from 'react'; const StyledRowRightContainer = styled.div` align-items: center; @@ -15,39 +16,26 @@ export const SettingsAccountsConnectedAccountsRowRightContainer = ({ }: { account: ConnectedAccount; }) => { - const mCSyncStatus = account.messageChannels[0]?.syncStatus; - const cCSyncStatus = account.calendarChannels[0]?.syncStatus; + const messageChannelSyncStatus = account.messageChannels[0]?.syncStatus; + const calendarChannelSyncStatus = account.calendarChannels[0]?.syncStatus; - const status = useMemo(() => { - if (mCSyncStatus === 'ACTIVE' && cCSyncStatus === 'ACTIVE') { - return 'Synced'; - } else if (mCSyncStatus === 'NOT_SYNCED' && cCSyncStatus === 'NOT_SYNCED') { - return 'Not synced'; - } else if (mCSyncStatus === 'ONGOING' || cCSyncStatus === 'ONGOING') { - return 'Importing'; - } else if ( - mCSyncStatus === 'FAILED' || - mCSyncStatus === 'FAILED_INSUFFICIENT_PERMISSIONS' || - cCSyncStatus === 'FAILED' || - cCSyncStatus === 'FAILED_INSUFFICIENT_PERMISSIONS' - ) { - return 'Failed'; - } - return ''; - }, [mCSyncStatus, cCSyncStatus]); + const status = computeSyncStatus( + messageChannelSyncStatus, + calendarChannelSyncStatus, + ); return ( <StyledRowRightContainer> - {status === 'Failed' && ( + {status === SyncStatus.FAILED && ( <Status color="red" text="Sync failed" weight="medium" /> )} - {status === 'Synced' && ( + {status === SyncStatus.SYNCED && ( <Status color="green" text="Synced" weight="medium" /> )} - {status === 'Not synced' && ( + {status === SyncStatus.NOT_SYNCED && ( <Status color="orange" text="Not synced" weight="medium" /> )} - {status === 'Importing' && ( + {status === SyncStatus.IMPORTING && ( <Status color="turquoise" text="Importing" diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx index 930d749abd39..622f9ca06f26 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelDetails.tsx @@ -103,7 +103,8 @@ export const SettingsAccountsMessageChannelDetails = ({ parameters={[ { title: 'Exclude non-professional emails', - description: 'Don’t sync emails from/to Gmail, Outlook...', + description: + 'Don’t create contacts from/to Gmail, Outlook emails', value: !!messageChannel.excludeNonProfessionalEmails, onToggle: handleIsNonProfessionalEmailExcludedToggle, }, diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx index 3bbe93deb532..2c5e1102d3b3 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsMessageChannelsContainer.tsx @@ -6,8 +6,8 @@ import { MessageChannel } from '@/accounts/types/MessageChannel'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; -import { SettingsAccountsListEmptyStateCard } from '@/settings/accounts/components/SettingsAccountsListEmptyStateCard'; import { SettingsAccountsMessageChannelDetails } from '@/settings/accounts/components/SettingsAccountsMessageChannelDetails'; +import { SettingsNewAccountSection } from '@/settings/accounts/components/SettingsNewAccountSection'; import { SETTINGS_ACCOUNT_MESSAGE_CHANNELS_TAB_LIST_COMPONENT_ID } from '@/settings/accounts/constants/SettingsAccountMessageChannelsTabListComponentId'; import { TabList } from '@/ui/layout/tab/components/TabList'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; @@ -44,6 +44,7 @@ export const SettingsAccountsMessageChannelsContainer = () => { in: accounts.map((account) => account.id), }, }, + skip: !accounts.length, }); const tabs = [ @@ -54,7 +55,7 @@ export const SettingsAccountsMessageChannelsContainer = () => { ]; if (!messageChannels.length) { - return <SettingsAccountsListEmptyStateCard />; + return <SettingsNewAccountSection />; } return ( diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx index 515dce50a610..beba37f8b4a6 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsRowDropdownMenu.tsx @@ -9,7 +9,7 @@ import { import { ConnectedAccount } from '@/accounts/types/ConnectedAccount'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; +import { useDestroyOneRecord } from '@/object-record/hooks/useDestroyOneRecord'; import { useTriggerGoogleApisOAuth } from '@/settings/accounts/hooks/useTriggerGoogleApisOAuth'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; @@ -32,7 +32,7 @@ export const SettingsAccountsRowDropdownMenu = ({ const navigate = useNavigate(); const { closeDropdown } = useDropdown(dropdownId); - const { deleteOneRecord } = useDeleteOneRecord({ + const { destroyOneRecord } = useDestroyOneRecord({ objectNameSingular: CoreObjectNameSingular.ConnectedAccount, }); @@ -81,7 +81,7 @@ export const SettingsAccountsRowDropdownMenu = ({ LeftIcon={IconTrash} text="Remove account" onClick={() => { - deleteOneRecord(account.id); + destroyOneRecord(account.id); closeDropdown(); }} /> diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx index 3bcb19ea0f3c..5ca4cb832d68 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx @@ -1,11 +1,12 @@ import styled from '@emotion/styled'; import { H2Title, IconCalendarEvent, IconMailCog } from 'twenty-ui'; -import { SettingsNavigationCard } from '@/settings/components/SettingsNavigationCard'; +import { SettingsCard } from '@/settings/components/SettingsCard'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { SettingsPath } from '@/types/SettingsPath'; import { Section } from '@/ui/layout/section/components/Section'; import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink'; +import { useTheme } from '@emotion/react'; const StyledCardsContainer = styled.div` display: flex; @@ -14,6 +15,7 @@ const StyledCardsContainer = styled.div` `; export const SettingsAccountsSettingsSection = () => { + const theme = useTheme(); return ( <Section> <H2Title @@ -22,16 +24,30 @@ export const SettingsAccountsSettingsSection = () => { /> <StyledCardsContainer> <UndecoratedLink to={getSettingsPagePath(SettingsPath.AccountsEmails)}> - <SettingsNavigationCard Icon={IconMailCog} title="Emails"> - Set email visibility, manage your blocklist and more. - </SettingsNavigationCard> + <SettingsCard + Icon={ + <IconMailCog + size={theme.icon.size.lg} + stroke={theme.icon.stroke.sm} + /> + } + title="Emails" + description="Set email visibility, manage your blocklist and more." + /> </UndecoratedLink> <UndecoratedLink to={getSettingsPagePath(SettingsPath.AccountsCalendars)} > - <SettingsNavigationCard Icon={IconCalendarEvent} title="Calendar"> - Configure and customize your calendar preferences. - </SettingsNavigationCard> + <SettingsCard + Icon={ + <IconCalendarEvent + size={theme.icon.size.lg} + stroke={theme.icon.stroke.sm} + /> + } + title="Calendar" + description="Configure and customize your calendar preferences." + /> </UndecoratedLink> </StyledCardsContainer> </Section> diff --git a/packages/twenty-front/src/modules/settings/accounts/constants/SyncStatus.ts b/packages/twenty-front/src/modules/settings/accounts/constants/SyncStatus.ts new file mode 100644 index 000000000000..8031d55e91ab --- /dev/null +++ b/packages/twenty-front/src/modules/settings/accounts/constants/SyncStatus.ts @@ -0,0 +1,6 @@ +export enum SyncStatus { + SYNCED = 'SYNCED', + FAILED = 'FAILED', + NOT_SYNCED = 'NOT_SYNCED', + IMPORTING = 'IMPORTING', +} diff --git a/packages/twenty-front/src/modules/settings/accounts/utils/__tests__/computeSyncStatus.test.ts b/packages/twenty-front/src/modules/settings/accounts/utils/__tests__/computeSyncStatus.test.ts new file mode 100644 index 000000000000..06e14e77b2e6 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/accounts/utils/__tests__/computeSyncStatus.test.ts @@ -0,0 +1,87 @@ +import { CalendarChannelSyncStatus } from '@/accounts/types/CalendarChannel'; +import { MessageChannelSyncStatus } from '@/accounts/types/MessageChannel'; +import { SyncStatus } from '@/settings/accounts/constants/SyncStatus'; +import { computeSyncStatus } from '../computeSyncStatus'; + +describe('computeSyncStatus', () => { + test('should return FAILED when both sync statuses are FAILED', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.FAILED_UNKNOWN, + CalendarChannelSyncStatus.FAILED_UNKNOWN, + ), + ).toEqual(SyncStatus.FAILED); + }); + + test('should return FAILED when message channel sync status is FAILED_UNKNOWN', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.FAILED_UNKNOWN, + CalendarChannelSyncStatus.ACTIVE, + ), + ).toEqual(SyncStatus.FAILED); + }); + + test('should return FAILED when message channel sync status is FAILED_INSUFFICIENT_PERMISSIONS', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS, + CalendarChannelSyncStatus.ACTIVE, + ), + ).toEqual(SyncStatus.FAILED); + }); + + test('should return FAILED when calendar channel sync status is FAILED_UNKNOWN', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.ACTIVE, + CalendarChannelSyncStatus.FAILED_UNKNOWN, + ), + ).toEqual(SyncStatus.FAILED); + }); + + test('should return FAILED when calendar channel sync status is FAILED_INSUFFICIENT_PERMISSIONS', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.ACTIVE, + CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS, + ), + ).toEqual(SyncStatus.FAILED); + }); + + test('should return IMPORTING when message channel sync status is ONGOING', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.ONGOING, + CalendarChannelSyncStatus.ACTIVE, + ), + ).toEqual(SyncStatus.IMPORTING); + }); + + test('should return IMPORTING when calendar channel sync status is ONGOING', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.ACTIVE, + CalendarChannelSyncStatus.ONGOING, + ), + ).toEqual(SyncStatus.IMPORTING); + }); + + test('should return SYNCED when one channel is ACTIVE and the other is NOT_SYNCED', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.NOT_SYNCED, + CalendarChannelSyncStatus.ACTIVE, + ), + ).toEqual(SyncStatus.SYNCED); + }); + + test('should return SYNCED when one channel is ACTIVE and the other is NOT_SYNCED', () => { + expect( + computeSyncStatus( + MessageChannelSyncStatus.ACTIVE, + CalendarChannelSyncStatus.NOT_SYNCED, + ), + ).toEqual(SyncStatus.SYNCED); + }); +}); diff --git a/packages/twenty-front/src/modules/settings/accounts/utils/computeSyncStatus.ts b/packages/twenty-front/src/modules/settings/accounts/utils/computeSyncStatus.ts new file mode 100644 index 000000000000..5528535f68cf --- /dev/null +++ b/packages/twenty-front/src/modules/settings/accounts/utils/computeSyncStatus.ts @@ -0,0 +1,42 @@ +import { CalendarChannelSyncStatus } from '@/accounts/types/CalendarChannel'; +import { MessageChannelSyncStatus } from '@/accounts/types/MessageChannel'; +import { SyncStatus } from '@/settings/accounts/constants/SyncStatus'; + +export const computeSyncStatus = ( + messageChannelSyncStatus: MessageChannelSyncStatus, + calendarChannelSyncStatus: CalendarChannelSyncStatus, +) => { + if ( + messageChannelSyncStatus === MessageChannelSyncStatus.FAILED_UNKNOWN || + messageChannelSyncStatus === + MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS || + calendarChannelSyncStatus === CalendarChannelSyncStatus.FAILED_UNKNOWN || + calendarChannelSyncStatus === + CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS + ) { + return SyncStatus.FAILED; + } + + if ( + messageChannelSyncStatus === MessageChannelSyncStatus.ONGOING || + calendarChannelSyncStatus === CalendarChannelSyncStatus.ONGOING + ) { + return SyncStatus.IMPORTING; + } + + if ( + messageChannelSyncStatus === MessageChannelSyncStatus.NOT_SYNCED && + calendarChannelSyncStatus === CalendarChannelSyncStatus.NOT_SYNCED + ) { + return SyncStatus.NOT_SYNCED; + } + + if ( + messageChannelSyncStatus === MessageChannelSyncStatus.ACTIVE || + calendarChannelSyncStatus === CalendarChannelSyncStatus.ACTIVE + ) { + return SyncStatus.SYNCED; + } + + return SyncStatus.NOT_SYNCED; +}; diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx b/packages/twenty-front/src/modules/settings/components/SettingsCard.tsx similarity index 67% rename from packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx rename to packages/twenty-front/src/modules/settings/components/SettingsCard.tsx index 8d44dfcfc30f..972bac3d77a4 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsCard.tsx @@ -1,16 +1,16 @@ -import { ReactNode } from 'react'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { IconChevronRight, IconComponent, Pill } from 'twenty-ui'; +import { IconChevronRight, Pill } from 'twenty-ui'; import { Card } from '@/ui/layout/card/components/Card'; import { CardContent } from '@/ui/layout/card/components/CardContent'; +import { ReactNode } from 'react'; -type SettingsNavigationCardProps = { - children: ReactNode; +type SettingsCardProps = { + description?: string; disabled?: boolean; soon?: boolean; - Icon: IconComponent; + Icon: ReactNode; onClick?: () => void; title: string; className?: string; @@ -24,19 +24,24 @@ const StyledCard = styled(Card)<{ disabled ? theme.font.color.extraLight : theme.font.color.tertiary}; cursor: ${({ disabled, onClick }) => disabled ? 'not-allowed' : onClick ? 'pointer' : 'default'}; + width: 100%; + & :hover { + background-color: ${({ theme }) => theme.background.quaternary}; + cursor: pointer; + } `; -const StyledCardContent = styled(CardContent)` +const StyledCardContent = styled(CardContent)<object>` display: flex; flex-direction: column; gap: ${({ theme }) => theme.spacing(2)}; - padding: ${({ theme }) => theme.spacing(4, 3)}; + padding: ${({ theme }) => theme.spacing(2, 2)}; `; const StyledHeader = styled.div` align-items: center; display: flex; - gap: ${({ theme }) => theme.spacing(3)}; + gap: ${({ theme }) => theme.spacing(2)}; `; const StyledTitle = styled.div<{ disabled?: boolean }>` @@ -54,18 +59,27 @@ const StyledIconChevronRight = styled(IconChevronRight)` `; const StyledDescription = styled.div` - padding-left: ${({ theme }) => theme.spacing(8)}; + padding-bottom: ${({ theme }) => theme.spacing(2)}; + padding-left: ${({ theme }) => theme.spacing(7)}; +`; + +const StyledIconContainer = styled.div` + align-items: center; + display: flex; + height: 24px; + justify-content: center; + width: 24px; `; -export const SettingsNavigationCard = ({ - children, +export const SettingsCard = ({ + description, soon, disabled = soon, Icon, onClick, title, className, -}: SettingsNavigationCardProps) => { +}: SettingsCardProps) => { const theme = useTheme(); return ( @@ -73,17 +87,18 @@ export const SettingsNavigationCard = ({ disabled={disabled} onClick={disabled ? undefined : onClick} className={className} + rounded={true} > <StyledCardContent> <StyledHeader> - <Icon size={theme.icon.size.lg} stroke={theme.icon.stroke.sm} /> + <StyledIconContainer>{Icon}</StyledIconContainer> <StyledTitle disabled={disabled}> {title} {soon && <Pill label="Soon" />} </StyledTitle> <StyledIconChevronRight size={theme.icon.size.sm} /> </StyledHeader> - <StyledDescription>{children}</StyledDescription> + {description && <StyledDescription>{description}</StyledDescription>} </StyledCardContent> </StyledCard> ); diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx index 60733c0b60f9..050ca38f9e9b 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx @@ -6,32 +6,38 @@ import { NavigationDrawerItem, NavigationDrawerItemProps, } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; type SettingsNavigationDrawerItemProps = Pick< NavigationDrawerItemProps, - 'Icon' | 'label' | 'level' | 'soon' + 'Icon' | 'label' | 'indentationLevel' | 'soon' > & { matchSubPages?: boolean; path: SettingsPath; + subItemState?: NavigationDrawerSubItemState; }; export const SettingsNavigationDrawerItem = ({ Icon, label, - level, + indentationLevel, matchSubPages = false, path, soon, + subItemState, }: SettingsNavigationDrawerItemProps) => { const href = getSettingsPagePath(path); + const pathName = useResolvedPath(href).pathname; + const isActive = !!useMatch({ - path: useResolvedPath(href).pathname, + path: pathName, end: !matchSubPages, }); return ( <NavigationDrawerItem - level={level} + indentationLevel={indentationLevel} + subItemState={subItemState} label={label} to={href} Icon={Icon} diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx index 89bb9c0de214..04f11020758a 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx @@ -5,6 +5,7 @@ import { IconCalendarEvent, IconCode, IconColorSwatch, + IconComponent, IconCurrencyDollar, IconDoorEnter, IconFunction, @@ -19,12 +20,26 @@ import { import { useAuth } from '@/auth/hooks/useAuth'; import { billingState } from '@/client-config/states/billingState'; import { SettingsNavigationDrawerItem } from '@/settings/components/SettingsNavigationDrawerItem'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { SettingsPath } from '@/types/SettingsPath'; -import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; +import { + NavigationDrawerItem, + NavigationDrawerItemIndentationLevel, +} from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; import { NavigationDrawerItemGroup } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup'; import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; +import { getNavigationSubItemState } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemState'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +import { matchPath, resolvePath, useLocation } from 'react-router-dom'; + +type SettingsNavigationItem = { + label: string; + path: SettingsPath; + Icon: IconComponent; + matchSubPages?: boolean; + indentationLevel?: NavigationDrawerItemIndentationLevel; +}; export const SettingsNavigationDrawerItems = () => { const { signOut } = useAuth(); @@ -38,6 +53,39 @@ export const SettingsNavigationDrawerItems = () => { const isBillingPageEnabled = billing?.isBillingEnabled && !isFreeAccessEnabled; + // TODO: Refactor this part to only have arrays of navigation items + const currentPathName = useLocation().pathname; + + const accountSubSettings: SettingsNavigationItem[] = [ + { + label: 'Emails', + path: SettingsPath.AccountsEmails, + Icon: IconMail, + matchSubPages: true, + indentationLevel: 2, + }, + { + label: 'Calendars', + path: SettingsPath.AccountsCalendars, + Icon: IconCalendarEvent, + matchSubPages: true, + indentationLevel: 2, + }, + ]; + + const selectedIndex = accountSubSettings.findIndex((accountSubSetting) => { + const href = getSettingsPagePath(accountSubSetting.path); + const pathName = resolvePath(href).pathname; + + return matchPath( + { + path: pathName, + end: !accountSubSetting.matchSubPages, + }, + currentPathName, + ); + }); + return ( <> <NavigationDrawerSection> @@ -48,7 +96,7 @@ export const SettingsNavigationDrawerItems = () => { Icon={IconUserCircle} /> <SettingsNavigationDrawerItem - label="Appearance" + label="Experience" path={SettingsPath.Appearance} Icon={IconColorSwatch} /> @@ -58,23 +106,22 @@ export const SettingsNavigationDrawerItems = () => { path={SettingsPath.Accounts} Icon={IconAt} /> - <SettingsNavigationDrawerItem - level={2} - label="Emails" - path={SettingsPath.AccountsEmails} - Icon={IconMail} - matchSubPages - /> - <SettingsNavigationDrawerItem - level={2} - label="Calendars" - path={SettingsPath.AccountsCalendars} - Icon={IconCalendarEvent} - matchSubPages - /> + {accountSubSettings.map((navigationItem, index) => ( + <SettingsNavigationDrawerItem + key={index} + label={navigationItem.label} + path={navigationItem.path} + Icon={navigationItem.Icon} + indentationLevel={navigationItem.indentationLevel} + subItemState={getNavigationSubItemState({ + arrayLength: accountSubSettings.length, + index, + selectedIndex, + })} + /> + ))} </NavigationDrawerItemGroup> </NavigationDrawerSection> - <NavigationDrawerSection> <NavigationDrawerSectionTitle label="Workspace" /> <SettingsNavigationDrawerItem @@ -125,7 +172,6 @@ export const SettingsNavigationDrawerItems = () => { /> )} </NavigationDrawerSection> - <NavigationDrawerSection> <NavigationDrawerSectionTitle label="Other" /> <SettingsNavigationDrawerItem diff --git a/packages/twenty-front/src/modules/settings/components/SettingsPageContainer.tsx b/packages/twenty-front/src/modules/settings/components/SettingsPageContainer.tsx index 2fc661c7a756..879e95b82650 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsPageContainer.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsPageContainer.tsx @@ -1,18 +1,16 @@ -import styled from '@emotion/styled'; -import { ReactNode } from 'react'; - import { OBJECT_SETTINGS_WIDTH } from '@/settings/data-model/constants/ObjectSettings'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; -import { isDefined } from '~/utils/isDefined'; - import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; +import styled from '@emotion/styled'; +import { ReactNode } from 'react'; +import { isDefined } from '~/utils/isDefined'; const StyledSettingsPageContainer = styled.div<{ width?: number }>` display: flex; flex-direction: column; gap: ${({ theme }) => theme.spacing(8)}; overflow: auto; - padding: ${({ theme }) => theme.spacing(8)}; + padding: ${({ theme }) => theme.spacing(6, 8, 8)}; width: ${({ width }) => { if (isDefined(width)) { return width + 'px'; @@ -22,11 +20,7 @@ const StyledSettingsPageContainer = styled.div<{ width?: number }>` } return OBJECT_SETTINGS_WIDTH + 'px'; }}; -`; - -const StyledScrollWrapper = styled(ScrollWrapper)` - background-color: ${({ theme }) => theme.background.secondary}; - border-radius: ${({ theme }) => theme.border.radius.md}; + padding-bottom: ${({ theme }) => theme.spacing(20)}; `; export const SettingsPageContainer = ({ @@ -34,7 +28,7 @@ export const SettingsPageContainer = ({ }: { children: ReactNode; }) => ( - <StyledScrollWrapper contextProviderName="settingsPageContainer"> + <ScrollWrapper contextProviderName="settingsPageContainer"> <StyledSettingsPageContainer>{children}</StyledSettingsPageContainer> - </StyledScrollWrapper> + </ScrollWrapper> ); diff --git a/packages/twenty-front/src/modules/settings/components/__stories__/SettingsCard.stories.tsx b/packages/twenty-front/src/modules/settings/components/__stories__/SettingsCard.stories.tsx new file mode 100644 index 000000000000..5bcb36f90efe --- /dev/null +++ b/packages/twenty-front/src/modules/settings/components/__stories__/SettingsCard.stories.tsx @@ -0,0 +1,24 @@ +import { SettingsCard } from '@/settings/components/SettingsCard'; +import { Meta, StoryObj } from '@storybook/react'; +import React from 'react'; +import { ComponentDecorator, IconMailCog } from 'twenty-ui'; + +const meta: Meta<typeof SettingsCard> = { + title: 'Modules/Settings/SettingsCard', + component: SettingsCard, + decorators: [ComponentDecorator], +}; +export default meta; +type Story = StoryObj<typeof SettingsCard>; + +export const Default: Story = { + args: { + onClick: () => {}, + Icon: React.createElement(IconMailCog), + title: 'Settings Card', + }, + argTypes: { + className: { control: 'false' }, + Icon: { control: 'false' }, + }, +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelNewFieldBreadcrumbDropDown.tsx b/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelNewFieldBreadcrumbDropDown.tsx new file mode 100644 index 000000000000..0521676c7cf0 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelNewFieldBreadcrumbDropDown.tsx @@ -0,0 +1,103 @@ +import { Button } from '@/ui/input/button/components/Button'; +import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; +import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { IconChevronDown } from 'twenty-ui'; + +type SettingsDataModelNewFieldBreadcrumbDropDownProps = { + isConfigureStep: boolean; + onBreadcrumbClick: (isConfigureStep: boolean) => void; +}; + +const StyledContainer = styled.div` + align-items: center; + color: ${({ theme }) => theme.font.color.secondary}; + cursor: pointer; + display: flex; + font-size: ${({ theme }) => theme.font.size.md}; +`; +const StyledButtonContainer = styled.div` + position: relative; + width: 100%; +`; + +const StyledDownChevron = styled(IconChevronDown)` + color: ${({ theme }) => theme.font.color.primary}; + position: absolute; + right: ${({ theme }) => theme.spacing(1.5)}; + top: 50%; + transform: translateY(-50%); +`; + +const StyledMenuItem = styled(MenuItem)<{ selected?: boolean }>` + background: ${({ theme, selected }) => + selected ? theme.background.quaternary : 'transparent'}; + cursor: pointer; +`; + +const StyledSpan = styled.span` + margin-left: ${({ theme }) => theme.spacing(2)}; +`; + +const StyledButton = styled(Button)` + color: ${({ theme }) => theme.font.color.primary}; + padding-right: ${({ theme }) => theme.spacing(6)}; +`; + +export const SettingsDataModelNewFieldBreadcrumbDropDown = ({ + isConfigureStep, + onBreadcrumbClick, +}: SettingsDataModelNewFieldBreadcrumbDropDownProps) => { + const dropdownId = `settings-object-new-field-breadcrumb-dropdown`; + + const { closeDropdown } = useDropdown(dropdownId); + + const handleClick = (step: boolean) => { + onBreadcrumbClick(step); + closeDropdown(); + }; + const theme = useTheme(); + + return ( + <StyledContainer> + New Field <StyledSpan>-</StyledSpan> + <Dropdown + dropdownPlacement="bottom-start" + dropdownId={dropdownId} + clickableComponent={ + <StyledButtonContainer> + <StyledDownChevron size={theme.icon.size.md} /> + {isConfigureStep ? ( + <StyledButton variant="tertiary" title="2. Configure" /> + ) : ( + <StyledButton variant="tertiary" title="1. Type" /> + )} + </StyledButtonContainer> + } + dropdownComponents={ + <DropdownMenu> + <DropdownMenuItemsContainer> + <StyledMenuItem + text="1. Type" + onClick={() => handleClick(false)} + selected={!isConfigureStep} + /> + <StyledMenuItem + text="2. Configure" + onClick={() => handleClick(true)} + selected={isConfigureStep} + /> + </DropdownMenuItemsContainer> + </DropdownMenu> + } + dropdownHotkeyScope={{ + scope: dropdownId, + }} + /> + </StyledContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelPreviewFormCard.tsx b/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelPreviewFormCard.tsx index 34e514abe83f..bf02470ca68c 100644 --- a/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelPreviewFormCard.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/components/SettingsDataModelPreviewFormCard.tsx @@ -1,6 +1,7 @@ -import { ReactNode } from 'react'; import styled from '@emotion/styled'; +import { ReactNode } from 'react'; +import { StyledFormCardTitle } from '@/settings/data-model/fields/components/StyledFormCardTitle'; import { Card } from '@/ui/layout/card/components/Card'; import { CardContent } from '@/ui/layout/card/components/CardContent'; @@ -14,14 +15,6 @@ const StyledPreviewContainer = styled(CardContent)` background-color: ${({ theme }) => theme.background.transparent.lighter}; `; -const StyledTitle = styled.h3` - color: ${({ theme }) => theme.font.color.extraLight}; - font-size: ${({ theme }) => theme.font.size.sm}; - font-weight: ${({ theme }) => theme.font.weight.medium}; - margin: 0; - margin-bottom: ${({ theme }) => theme.spacing(4)}; -`; - const StyledFormContainer = styled(CardContent)` padding: 0; `; @@ -33,7 +26,7 @@ export const SettingsDataModelPreviewFormCard = ({ }: SettingsDataModelPreviewFormCardProps) => ( <Card className={className} fullWidth> <StyledPreviewContainer divider={!!form}> - <StyledTitle>Preview</StyledTitle> + <StyledFormCardTitle>Preview</StyledFormCardTitle> {preview} </StyledPreviewContainer> {!!form && <StyledFormContainer>{form}</StyledFormContainer>} diff --git a/packages/twenty-front/src/modules/settings/data-model/constants/RelationTypes.ts b/packages/twenty-front/src/modules/settings/data-model/constants/RelationTypes.ts index 08127f6c9888..179f60fe8979 100644 --- a/packages/twenty-front/src/modules/settings/data-model/constants/RelationTypes.ts +++ b/packages/twenty-front/src/modules/settings/data-model/constants/RelationTypes.ts @@ -1,12 +1,11 @@ import { IconComponent, - IconRelationManyToOne, - IconRelationOneToMany, - IconRelationOneToOne, + IllustrationIconManyToMany, + IllustrationIconOneToMany, + IllustrationIconOneToOne, } from 'twenty-ui'; -import { RelationMetadataType } from '~/generated-metadata/graphql'; - +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import OneToManySvg from '../assets/OneToMany.svg'; import OneToOneSvg from '../assets/OneToOne.svg'; import { RelationType } from '../types/RelationType'; @@ -20,19 +19,26 @@ export const RELATION_TYPES: Record< isImageFlipped?: boolean; } > = { - [RelationMetadataType.OneToMany]: { + [RelationDefinitionType.OneToMany]: { label: 'Has many', - Icon: IconRelationOneToMany, + Icon: IllustrationIconOneToMany, imageSrc: OneToManySvg, }, - [RelationMetadataType.OneToOne]: { + [RelationDefinitionType.OneToOne]: { label: 'Has one', - Icon: IconRelationOneToOne, + Icon: IllustrationIconOneToOne, imageSrc: OneToOneSvg, }, - MANY_TO_ONE: { + [RelationDefinitionType.ManyToOne]: { label: 'Belongs to one', - Icon: IconRelationManyToOne, + Icon: IllustrationIconOneToMany, + imageSrc: OneToManySvg, + isImageFlipped: true, + }, + // Not supported yet + [RelationDefinitionType.ManyToMany]: { + label: 'Belongs to many', + Icon: IllustrationIconManyToMany, imageSrc: OneToManySvg, isImageFlipped: true, }, diff --git a/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategories.ts b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategories.ts new file mode 100644 index 000000000000..07f8aa28cc9a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategories.ts @@ -0,0 +1,7 @@ +import { SettingsFieldTypeCategoryType } from '@/settings/data-model/types/SettingsFieldTypeCategoryType'; + +export const SETTINGS_FIELD_TYPE_CATEGORIES: SettingsFieldTypeCategoryType[] = [ + 'Basic', + 'Relation', + 'Advanced', +]; diff --git a/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategoryDescriptions.ts b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategoryDescriptions.ts new file mode 100644 index 000000000000..aac9c81638f9 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeCategoryDescriptions.ts @@ -0,0 +1,10 @@ +import { SettingsFieldTypeCategoryType } from '@/settings/data-model/types/SettingsFieldTypeCategoryType'; + +export const SETTINGS_FIELD_TYPE_CATEGORY_DESCRIPTIONS: Record< + SettingsFieldTypeCategoryType, + string +> = { + Basic: 'All the basic field types you need to start', + Advanced: 'More advanced fields for advanced projects', + Relation: 'Create a relation with another object', +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeConfigs.ts b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeConfigs.ts index 75d74c569619..c8cea11fdeb3 100644 --- a/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeConfigs.ts +++ b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldTypeConfigs.ts @@ -1,28 +1,29 @@ import { - IconCalendarEvent, - IconCalendarTime, - IconCheck, - IconCoins, IconComponent, - IconCreativeCommonsSa, - IconFilePencil, - IconJson, - IconKey, - IconLink, - IconMail, - IconMap, - IconNumbers, - IconPhone, - IconRelationManyToMany, - IconTag, - IconTags, - IconTextSize, - IconTwentyStar, - IconUser, + IllustrationIconArray, + IllustrationIconCalendarEvent, + IllustrationIconCalendarTime, + IllustrationIconCurrency, + IllustrationIconJson, + IllustrationIconLink, + IllustrationIconMail, + IllustrationIconMap, + IllustrationIconNumbers, + IllustrationIconOneToMany, + IllustrationIconPhone, + IllustrationIconSetting, + IllustrationIconStar, + IllustrationIconTag, + IllustrationIconTags, + IllustrationIconText, + IllustrationIconToggle, + IllustrationIconUid, + IllustrationIconUser, } from 'twenty-ui'; import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode'; import { DEFAULT_DATE_VALUE } from '@/settings/data-model/constants/DefaultDateValue'; +import { SettingsFieldTypeCategoryType } from '@/settings/data-model/types/SettingsFieldTypeCategoryType'; import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType'; import { FieldMetadataType } from '~/generated-metadata/graphql'; @@ -32,96 +33,127 @@ export type SettingsFieldTypeConfig = { label: string; Icon: IconComponent; exampleValue?: unknown; + category: SettingsFieldTypeCategoryType; }; export const SETTINGS_FIELD_TYPE_CONFIGS = { [FieldMetadataType.Uuid]: { label: 'Unique ID', - Icon: IconKey, + Icon: IllustrationIconUid, exampleValue: '00000000-0000-0000-0000-000000000000', + category: 'Advanced', }, [FieldMetadataType.Text]: { label: 'Text', - Icon: IconTextSize, + Icon: IllustrationIconText, exampleValue: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum magna enim, dapibus non enim in, lacinia faucibus nunc. Sed interdum ante sed felis facilisis, eget ultricies neque molestie. Mauris auctor, justo eu volutpat cursus, libero erat tempus nulla, non sodales lorem lacus a est.', + category: 'Basic', }, [FieldMetadataType.Numeric]: { label: 'Numeric', - Icon: IconNumbers, + Icon: IllustrationIconNumbers, exampleValue: 2000, + category: 'Basic', }, [FieldMetadataType.Number]: { label: 'Number', - Icon: IconNumbers, + Icon: IllustrationIconNumbers, exampleValue: 2000, + category: 'Basic', }, [FieldMetadataType.Link]: { label: 'Link', - Icon: IconLink, - exampleValue: { url: 'www.funnelmink.com', label: '' }, + Icon: IllustrationIconLink, + exampleValue: { url: 'www.twenty.com', label: '' }, + category: 'Basic', }, [FieldMetadataType.Links]: { label: 'Links', - Icon: IconLink, - exampleValue: { primaryLinkUrl: 'funnelmink.com', primaryLinkLabel: '' }, + Icon: IllustrationIconLink, + exampleValue: { primaryLinkUrl: 'twenty.com', primaryLinkLabel: '' }, + category: 'Basic', }, [FieldMetadataType.Boolean]: { label: 'True/False', - Icon: IconCheck, + Icon: IllustrationIconToggle, exampleValue: true, + category: 'Basic', }, [FieldMetadataType.DateTime]: { label: 'Date and Time', - Icon: IconCalendarTime, + Icon: IllustrationIconCalendarTime, exampleValue: DEFAULT_DATE_VALUE.toISOString(), + category: 'Basic', }, [FieldMetadataType.Date]: { label: 'Date', - Icon: IconCalendarEvent, + Icon: IllustrationIconCalendarEvent, exampleValue: DEFAULT_DATE_VALUE.toISOString(), + category: 'Basic', }, [FieldMetadataType.Select]: { label: 'Select', - Icon: IconTag, + Icon: IllustrationIconTag, + category: 'Basic', }, [FieldMetadataType.MultiSelect]: { label: 'Multi-select', - Icon: IconTags, + Icon: IllustrationIconTags, + category: 'Basic', }, [FieldMetadataType.Currency]: { label: 'Currency', - Icon: IconCoins, + Icon: IllustrationIconCurrency, exampleValue: { amountMicros: 2000000000, currencyCode: CurrencyCode.USD }, + category: 'Basic', }, [FieldMetadataType.Relation]: { label: 'Relation', - Icon: IconRelationManyToMany, + Icon: IllustrationIconOneToMany, + category: 'Relation', + }, + [FieldMetadataType.Email]: { + label: 'Email', + Icon: IllustrationIconMail, + category: 'Basic', }, - [FieldMetadataType.Email]: { label: 'Email', Icon: IconMail }, [FieldMetadataType.Emails]: { label: 'Emails', - Icon: IconMail, + Icon: IllustrationIconMail, exampleValue: { primaryEmail: 'john@twenty.com' }, + category: 'Basic', }, [FieldMetadataType.Phone]: { label: 'Phone', - Icon: IconPhone, + Icon: IllustrationIconPhone, exampleValue: '+1234-567-890', + category: 'Basic', + }, + [FieldMetadataType.Phones]: { + label: 'Phones', + Icon: IllustrationIconPhone, + exampleValue: { + primaryPhoneNumber: '234-567-890', + primaryPhoneCountryCode: '+1', + }, + category: 'Basic', }, [FieldMetadataType.Rating]: { label: 'Rating', - Icon: IconTwentyStar, + Icon: IllustrationIconStar, exampleValue: '3', + category: 'Basic', }, [FieldMetadataType.FullName]: { label: 'Full Name', - Icon: IconUser, + Icon: IllustrationIconUser, exampleValue: { firstName: 'John', lastName: 'Doe' }, + category: 'Advanced', }, [FieldMetadataType.Address]: { label: 'Address', - Icon: IconMap, + Icon: IllustrationIconMap, exampleValue: { addressStreet1: '456 Oak Street', addressStreet2: 'Unit 3B', @@ -132,20 +164,31 @@ export const SETTINGS_FIELD_TYPE_CONFIGS = { addressLat: 34.0522, addressLng: -118.2437, }, + category: 'Basic', }, [FieldMetadataType.RawJson]: { label: 'JSON', - Icon: IconJson, + Icon: IllustrationIconJson, exampleValue: { key: 'value' }, + + category: 'Basic', }, [FieldMetadataType.RichText]: { - label: 'Rich Text', - Icon: IconFilePencil, + label: 'System', + Icon: IllustrationIconSetting, exampleValue: { key: 'value' }, + category: 'Basic', }, [FieldMetadataType.Actor]: { - label: 'Actor', - Icon: IconCreativeCommonsSa, + label: 'System', + Icon: IllustrationIconSetting, + category: 'Basic', + }, + [FieldMetadataType.Array]: { + label: 'Array', + Icon: IllustrationIconArray, + category: 'Basic', + exampleValue: ['value1', 'value2'], }, } as const satisfies Record< SettingsSupportedFieldType, diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/components/StyledFormCardTitle.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/components/StyledFormCardTitle.tsx new file mode 100644 index 000000000000..03d4ebb91523 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/components/StyledFormCardTitle.tsx @@ -0,0 +1,9 @@ +import styled from '@emotion/styled'; + +export const StyledFormCardTitle = styled.h3` + color: ${({ theme }) => theme.font.color.extraLight}; + font-size: ${({ theme }) => theme.font.size.sm}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + margin: 0; + margin-bottom: ${({ theme }) => theme.spacing(4)}; +`; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm.tsx deleted file mode 100644 index ee825e7761f2..000000000000 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import styled from '@emotion/styled'; -import { Controller, useFormContext } from 'react-hook-form'; -import { z } from 'zod'; - -import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; -import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema'; -import { getErrorMessageFromError } from '@/settings/data-model/fields/forms/utils/errorMessages'; -import { IconPicker } from '@/ui/input/components/IconPicker'; -import { TextArea } from '@/ui/input/components/TextArea'; -import { TextInput } from '@/ui/input/components/TextInput'; - -export const settingsDataModelFieldAboutFormSchema = ( - existingLabels?: string[], -) => { - return fieldMetadataItemSchema(existingLabels || []).pick({ - description: true, - icon: true, - label: true, - }); -}; - -// Correctly infer the type from the returned schema -type SettingsDataModelFieldAboutFormValues = z.infer< - ReturnType<typeof settingsDataModelFieldAboutFormSchema> ->; - -type SettingsDataModelFieldAboutFormProps = { - disabled?: boolean; - fieldMetadataItem?: FieldMetadataItem; - maxLength?: number; -}; - -const StyledInputsContainer = styled.div` - display: flex; - gap: ${({ theme }) => theme.spacing(2)}; - margin-bottom: ${({ theme }) => theme.spacing(2)}; - width: 100%; -`; - -const LABEL = 'label'; - -export const SettingsDataModelFieldAboutForm = ({ - disabled, - fieldMetadataItem, - maxLength, -}: SettingsDataModelFieldAboutFormProps) => { - const { - control, - trigger, - formState: { errors }, - } = useFormContext<SettingsDataModelFieldAboutFormValues>(); - return ( - <> - <StyledInputsContainer> - <Controller - name="icon" - control={control} - defaultValue={fieldMetadataItem?.icon ?? 'IconUsers'} - render={({ field: { onChange, value } }) => ( - <IconPicker - disabled={disabled} - selectedIconKey={value ?? ''} - onChange={({ iconKey }) => onChange(iconKey)} - variant="primary" - /> - )} - /> - <Controller - name={LABEL} - control={control} - defaultValue={fieldMetadataItem?.label} - render={({ field: { onChange, value } }) => ( - <TextInput - placeholder="Employees" - value={value} - onChange={(e) => { - onChange(e); - trigger(LABEL); - }} - error={getErrorMessageFromError(errors.label?.message)} - disabled={disabled} - maxLength={maxLength} - fullWidth - /> - )} - /> - </StyledInputsContainer> - <Controller - name="description" - control={control} - defaultValue={fieldMetadataItem?.description} - render={({ field: { onChange, value } }) => ( - <TextArea - placeholder="Write a description" - minRows={4} - value={value ?? undefined} - onChange={onChange} - disabled={disabled} - /> - )} - /> - </> - ); -}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm.tsx new file mode 100644 index 000000000000..40341b6b5f96 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm.tsx @@ -0,0 +1,47 @@ +import { Controller, useFormContext } from 'react-hook-form'; +import { z } from 'zod'; + +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema'; + +import { TextArea } from '@/ui/input/components/TextArea'; + +export const settingsDataModelFieldDescriptionFormSchema = () => { + return fieldMetadataItemSchema([]).pick({ + description: true, + }); +}; + +type SettingsDataModelFieldDescriptionFormValues = z.infer< + ReturnType<typeof settingsDataModelFieldDescriptionFormSchema> +>; + +type SettingsDataModelFieldDescriptionFormProps = { + disabled?: boolean; + fieldMetadataItem?: FieldMetadataItem; +}; + +export const SettingsDataModelFieldDescriptionForm = ({ + disabled, + fieldMetadataItem, +}: SettingsDataModelFieldDescriptionFormProps) => { + const { control } = + useFormContext<SettingsDataModelFieldDescriptionFormValues>(); + + return ( + <Controller + name="description" + control={control} + defaultValue={fieldMetadataItem?.description} + render={({ field: { onChange, value } }) => ( + <TextArea + placeholder="Write a description" + minRows={4} + value={value ?? undefined} + onChange={onChange} + disabled={disabled} + /> + )} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm.tsx new file mode 100644 index 000000000000..d4771446e5d3 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm.tsx @@ -0,0 +1,84 @@ +import styled from '@emotion/styled'; +import { Controller, useFormContext } from 'react-hook-form'; +import { z } from 'zod'; + +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema'; +import { getErrorMessageFromError } from '@/settings/data-model/fields/forms/utils/errorMessages'; +import { IconPicker } from '@/ui/input/components/IconPicker'; +import { TextInput } from '@/ui/input/components/TextInput'; + +export const settingsDataModelFieldIconLabelFormSchema = ( + existingOtherLabels: string[] = [], +) => { + return fieldMetadataItemSchema(existingOtherLabels).pick({ + icon: true, + label: true, + }); +}; + +type SettingsDataModelFieldIconLabelFormValues = z.infer< + ReturnType<typeof settingsDataModelFieldIconLabelFormSchema> +>; + +const StyledInputsContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + margin-bottom: ${({ theme }) => theme.spacing(2)}; + width: 100%; +`; + +type SettingsDataModelFieldIconLabelFormProps = { + disabled?: boolean; + fieldMetadataItem?: FieldMetadataItem; + maxLength?: number; +}; + +export const SettingsDataModelFieldIconLabelForm = ({ + disabled, + fieldMetadataItem, + maxLength, +}: SettingsDataModelFieldIconLabelFormProps) => { + const { + control, + trigger, + formState: { errors }, + } = useFormContext<SettingsDataModelFieldIconLabelFormValues>(); + + return ( + <StyledInputsContainer> + <Controller + name="icon" + control={control} + defaultValue={fieldMetadataItem?.icon ?? 'IconUsers'} + render={({ field: { onChange, value } }) => ( + <IconPicker + disabled={disabled} + selectedIconKey={value ?? ''} + onChange={({ iconKey }) => onChange(iconKey)} + variant="primary" + /> + )} + /> + <Controller + name="label" + control={control} + defaultValue={fieldMetadataItem?.label} + render={({ field: { onChange, value } }) => ( + <TextInput + placeholder="Employees" + value={value} + onChange={(e) => { + onChange(e); + trigger('label'); + }} + error={getErrorMessageFromError(errors.label?.message)} + disabled={disabled} + maxLength={maxLength} + fullWidth + /> + )} + /> + </StyledInputsContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx index 65f2505bc47c..a71cc1654bcf 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard.tsx @@ -9,6 +9,8 @@ import { settingsDataModelFieldBooleanFormSchema } from '@/settings/data-model/f import { SettingsDataModelFieldBooleanSettingsFormCard } from '@/settings/data-model/fields/forms/boolean/components/SettingsDataModelFieldBooleanSettingsFormCard'; import { settingsDataModelFieldCurrencyFormSchema } from '@/settings/data-model/fields/forms/currency/components/SettingsDataModelFieldCurrencyForm'; import { SettingsDataModelFieldCurrencySettingsFormCard } from '@/settings/data-model/fields/forms/currency/components/SettingsDataModelFieldCurrencySettingsFormCard'; +import { settingsDataModelFieldDateFormSchema } from '@/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm'; +import { SettingsDataModelFieldDateSettingsFormCard } from '@/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateSettingsFormCard'; import { settingsDataModelFieldRelationFormSchema } from '@/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationForm'; import { SettingsDataModelFieldRelationSettingsFormCard } from '@/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationSettingsFormCard'; import { @@ -30,6 +32,14 @@ const currencyFieldFormSchema = z .object({ type: z.literal(FieldMetadataType.Currency) }) .merge(settingsDataModelFieldCurrencyFormSchema); +const dateFieldFormSchema = z + .object({ type: z.literal(FieldMetadataType.Date) }) + .merge(settingsDataModelFieldDateFormSchema); + +const dateTimeFieldFormSchema = z + .object({ type: z.literal(FieldMetadataType.DateTime) }) + .merge(settingsDataModelFieldDateFormSchema); + const relationFieldFormSchema = z .object({ type: z.literal(FieldMetadataType.Relation) }) .merge(settingsDataModelFieldRelationFormSchema); @@ -51,6 +61,8 @@ const otherFieldsFormSchema = z.object({ FieldMetadataType.Relation, FieldMetadataType.Select, FieldMetadataType.MultiSelect, + FieldMetadataType.Date, + FieldMetadataType.DateTime, ]), ) as [FieldMetadataType, ...FieldMetadataType[]], ), @@ -61,6 +73,8 @@ export const settingsDataModelFieldSettingsFormSchema = z.discriminatedUnion( [ booleanFieldFormSchema, currencyFieldFormSchema, + dateFieldFormSchema, + dateTimeFieldFormSchema, relationFieldFormSchema, selectFieldFormSchema, multiSelectFieldFormSchema, @@ -69,7 +83,7 @@ export const settingsDataModelFieldSettingsFormSchema = z.discriminatedUnion( ); type SettingsDataModelFieldSettingsFormCardProps = { - disableCurrencyForm?: boolean; + isCreatingField?: boolean; fieldMetadataItem: Pick<FieldMetadataItem, 'icon' | 'label' | 'type'> & Partial<Omit<FieldMetadataItem, 'icon' | 'label' | 'type'>>; } & Pick<SettingsDataModelFieldPreviewCardProps, 'objectMetadataItem'>; @@ -80,6 +94,7 @@ const StyledFieldPreviewCard = styled(SettingsDataModelFieldPreviewCard)` `; const previewableTypes = [ + FieldMetadataType.Array, FieldMetadataType.Address, FieldMetadataType.Boolean, FieldMetadataType.Currency, @@ -92,6 +107,7 @@ const previewableTypes = [ FieldMetadataType.MultiSelect, FieldMetadataType.Number, FieldMetadataType.Phone, + FieldMetadataType.Phones, FieldMetadataType.Rating, FieldMetadataType.RawJson, FieldMetadataType.Relation, @@ -100,7 +116,7 @@ const previewableTypes = [ ]; export const SettingsDataModelFieldSettingsFormCard = ({ - disableCurrencyForm, + isCreatingField, fieldMetadataItem, objectMetadataItem, }: SettingsDataModelFieldSettingsFormCardProps) => { @@ -118,7 +134,20 @@ export const SettingsDataModelFieldSettingsFormCard = ({ if (fieldMetadataItem.type === FieldMetadataType.Currency) { return ( <SettingsDataModelFieldCurrencySettingsFormCard - disabled={disableCurrencyForm} + disabled={!isCreatingField} + fieldMetadataItem={fieldMetadataItem} + objectMetadataItem={objectMetadataItem} + /> + ); + } + + if ( + fieldMetadataItem.type === FieldMetadataType.Date || + fieldMetadataItem.type === FieldMetadataType.DateTime + ) { + return ( + <SettingsDataModelFieldDateSettingsFormCard + disabled={!isCreatingField} fieldMetadataItem={fieldMetadataItem} objectMetadataItem={objectMetadataItem} /> diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldToggle.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldToggle.tsx new file mode 100644 index 000000000000..e859d652daca --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldToggle.tsx @@ -0,0 +1,91 @@ +import { Toggle } from '@/ui/input/components/Toggle'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { createPortal } from 'react-dom'; +import { + AppTooltip, + IconComponent, + IconInfoCircle, + TooltipDelay, +} from 'twenty-ui'; + +const StyledContainer = styled.div<{ disabled?: boolean }>` + align-items: center; + background-color: ${({ theme }) => theme.background.transparent.lighter}; + border: 1px solid ${({ theme }) => theme.border.color.medium}; + box-sizing: border-box; + border-radius: ${({ theme }) => theme.border.radius.sm}; + color: ${({ disabled, theme }) => + disabled ? theme.font.color.tertiary : theme.font.color.primary}; + display: flex; + gap: ${({ theme }) => theme.spacing(1)}; + height: ${({ theme }) => theme.spacing(8)}; + justify-content: space-between; + padding: 0 ${({ theme }) => theme.spacing(2)}; +`; + +const StyledGroup = styled.div` + align-items: center; + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; +`; + +interface SettingsDataModelFieldToggleProps { + disabled?: boolean; + Icon?: IconComponent; + label: string; + tooltip?: string; + value?: boolean; + onChange: (value: boolean) => void; +} + +export const SettingsDataModelFieldToggle = ({ + disabled, + Icon, + label, + tooltip, + value, + onChange, +}: SettingsDataModelFieldToggleProps) => { + const theme = useTheme(); + const infoCircleElementId = `info-circle-id-${Math.random().toString(36).slice(2)}`; + + return ( + <StyledContainer> + <StyledGroup> + {Icon && ( + <Icon color={theme.font.color.tertiary} size={theme.icon.size.md} /> + )} + {label} + </StyledGroup> + <StyledGroup> + {tooltip && ( + <IconInfoCircle + id={infoCircleElementId} + size={theme.icon.size.md} + color={theme.font.color.tertiary} + /> + )} + {tooltip && + createPortal( + <AppTooltip + anchorSelect={`#${infoCircleElementId}`} + content={tooltip} + offset={5} + noArrow + place="bottom" + positionStrategy="absolute" + delay={TooltipDelay.shortDelay} + />, + document.body, + )} + <Toggle + disabled={disabled} + value={value} + onChange={onChange} + toggleSize="small" + /> + </StyledGroup> + </StyledContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect.tsx index 5d517c61a5dc..14e68598e33d 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect.tsx @@ -1,8 +1,7 @@ -import omit from 'lodash.omit'; -import { Controller, useFormContext } from 'react-hook-form'; -import { z } from 'zod'; - import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { SettingsCard } from '@/settings/components/SettingsCard'; +import { SETTINGS_FIELD_TYPE_CATEGORIES } from '@/settings/data-model/constants/SettingsFieldTypeCategories'; +import { SETTINGS_FIELD_TYPE_CATEGORY_DESCRIPTIONS } from '@/settings/data-model/constants/SettingsFieldTypeCategoryDescriptions'; import { SETTINGS_FIELD_TYPE_CONFIGS, SettingsFieldTypeConfig, @@ -11,7 +10,14 @@ import { useBooleanSettingsFormInitialValues } from '@/settings/data-model/field import { useCurrencySettingsFormInitialValues } from '@/settings/data-model/fields/forms/currency/hooks/useCurrencySettingsFormInitialValues'; import { useSelectSettingsFormInitialValues } from '@/settings/data-model/fields/forms/select/hooks/useSelectSettingsFormInitialValues'; import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType'; -import { Select, SelectOption } from '@/ui/input/components/Select'; +import { TextInput } from '@/ui/input/components/TextInput'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { Section } from '@react-email/components'; +import { useState } from 'react'; +import { Controller, useFormContext } from 'react-hook-form'; +import { H2Title, IconSearch } from 'twenty-ui'; +import { z } from 'zod'; import { FieldMetadataType } from '~/generated-metadata/graphql'; export const settingsDataModelFieldTypeFormSchema = z.object({ @@ -23,39 +29,62 @@ export const settingsDataModelFieldTypeFormSchema = z.object({ ), }); -type SettingsDataModelFieldTypeFormValues = z.infer< +export type SettingsDataModelFieldTypeFormValues = z.infer< typeof settingsDataModelFieldTypeFormSchema >; type SettingsDataModelFieldTypeSelectProps = { className?: string; - disabled?: boolean; excludedFieldTypes?: SettingsSupportedFieldType[]; fieldMetadataItem?: Pick< FieldMetadataItem, 'defaultValue' | 'options' | 'type' >; + onFieldTypeSelect: () => void; }; +const StyledTypeSelectContainer = styled.div` + display: flex; + flex-direction: column; + gap: inherit; + width: 100%; +`; + +const StyledContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + justify-content: flex-start; + flex-wrap: wrap; + width: 100%; +`; + +const StyledCardContainer = styled.div` + display: flex; + + position: relative; + width: calc(50% - ${({ theme }) => theme.spacing(1)}); +`; + +const StyledSearchInput = styled(TextInput)` + width: 100%; +`; + export const SettingsDataModelFieldTypeSelect = ({ className, - disabled, excludedFieldTypes = [], fieldMetadataItem, + onFieldTypeSelect, }: SettingsDataModelFieldTypeSelectProps) => { + const theme = useTheme(); const { control } = useFormContext<SettingsDataModelFieldTypeFormValues>(); - - const fieldTypeConfigs: Partial< - Record<SettingsSupportedFieldType, SettingsFieldTypeConfig> - > = omit(SETTINGS_FIELD_TYPE_CONFIGS, excludedFieldTypes); - - const fieldTypeOptions = Object.entries<SettingsFieldTypeConfig>( - fieldTypeConfigs, - ).map<SelectOption<SettingsSupportedFieldType>>(([key, dataTypeConfig]) => ({ - Icon: dataTypeConfig.Icon, - label: dataTypeConfig.label, - value: key as SettingsSupportedFieldType, - })); + const [searchQuery, setSearchQuery] = useState(''); + const fieldTypeConfigs = Object.entries<SettingsFieldTypeConfig>( + SETTINGS_FIELD_TYPE_CONFIGS, + ).filter( + ([key, config]) => + !excludedFieldTypes.includes(key as SettingsSupportedFieldType) && + config.label.toLowerCase().includes(searchQuery.toLowerCase()), + ); const { resetDefaultValueField: resetBooleanDefaultValueField } = useBooleanSettingsFormInitialValues({ fieldMetadataItem }); @@ -66,8 +95,6 @@ export const SettingsDataModelFieldTypeSelect = ({ const { resetDefaultValueField: resetSelectDefaultValueField } = useSelectSettingsFormInitialValues({ fieldMetadataItem }); - // Reset defaultValue on type change with a valid value for the selected type - // so the form does not become invalid. const resetDefaultValueField = (nextValue: SettingsSupportedFieldType) => { switch (nextValue) { case FieldMetadataType.Boolean: @@ -94,19 +121,52 @@ export const SettingsDataModelFieldTypeSelect = ({ ? (fieldMetadataItem.type as SettingsSupportedFieldType) : FieldMetadataType.Text } - render={({ field: { onChange, value } }) => ( - <Select - className={className} - fullWidth - disabled={disabled} - dropdownId="object-field-type-select" - value={value} - onChange={(nextValue) => { - onChange(nextValue); - resetDefaultValueField(nextValue); - }} - options={fieldTypeOptions} - /> + render={({ field: { onChange } }) => ( + <StyledTypeSelectContainer className={className}> + <Section> + <StyledSearchInput + LeftIcon={IconSearch} + placeholder="Search a type" + value={searchQuery} + onChange={setSearchQuery} + /> + </Section> + {SETTINGS_FIELD_TYPE_CATEGORIES.map((category) => ( + <Section key={category}> + <H2Title + title={category} + description={ + SETTINGS_FIELD_TYPE_CATEGORY_DESCRIPTIONS[category] + } + /> + <StyledContainer> + {fieldTypeConfigs + .filter(([, config]) => config.category === category) + .map(([key, config]) => ( + <StyledCardContainer> + <SettingsCard + key={key} + onClick={() => { + onChange(key as SettingsSupportedFieldType); + resetDefaultValueField( + key as SettingsSupportedFieldType, + ); + onFieldTypeSelect(); + }} + Icon={ + <config.Icon + size={theme.icon.size.xl} + stroke={theme.icon.stroke.sm} + /> + } + title={config.label} + /> + </StyledCardContainer> + ))} + </StyledContainer> + </Section> + ))} + </StyledTypeSelectContainer> )} /> ); diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldDescriptionForm.stories.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldDescriptionForm.stories.tsx new file mode 100644 index 000000000000..7499adea0338 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldDescriptionForm.stories.tsx @@ -0,0 +1,40 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { ComponentDecorator } from 'twenty-ui'; + +import { FormProviderDecorator } from '~/testing/decorators/FormProviderDecorator'; + +import { mockedPersonObjectMetadataItem } from '~/testing/mock-data/metadata'; +import { SettingsDataModelFieldDescriptionForm } from '../SettingsDataModelFieldDescriptionForm'; + +const meta: Meta<typeof SettingsDataModelFieldDescriptionForm> = { + title: 'Modules/Settings/DataModel/SettingsDataModelFieldDescriptionForm', + component: SettingsDataModelFieldDescriptionForm, + decorators: [ + (Story) => ( + <div style={{ flex: 1 }}> + <Story /> + </div> + ), + FormProviderDecorator, + ComponentDecorator, + ], +}; + +export default meta; +type Story = StoryObj<typeof SettingsDataModelFieldDescriptionForm>; + +export const Default: Story = {}; + +export const WithFieldMetadataItem: Story = { + args: { + fieldMetadataItem: mockedPersonObjectMetadataItem.fields.find( + ({ description }) => description === 'description', + )!, + }, +}; + +export const Disabled: Story = { + args: { + disabled: true, + }, +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldAboutForm.stories.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldIconLabelForm.stories.tsx similarity index 65% rename from packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldAboutForm.stories.tsx rename to packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldIconLabelForm.stories.tsx index 501dcb1afb49..150efdc46683 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldAboutForm.stories.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldIconLabelForm.stories.tsx @@ -4,17 +4,17 @@ import { ComponentDecorator } from 'twenty-ui'; import { FormProviderDecorator } from '~/testing/decorators/FormProviderDecorator'; import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; -import { mockedPersonObjectMetadataItem } from '~/testing/mock-data/metadata'; -import { SettingsDataModelFieldAboutForm } from '../SettingsDataModelFieldAboutForm'; +import { mockedPersonObjectMetadataItem } from '~/testing/mock-data/metadata'; +import { SettingsDataModelFieldIconLabelForm } from '../SettingsDataModelFieldIconLabelForm'; const StyledContainer = styled.div` flex: 1; `; -const meta: Meta<typeof SettingsDataModelFieldAboutForm> = { - title: 'Modules/Settings/DataModel/SettingsDataModelFieldAboutForm', - component: SettingsDataModelFieldAboutForm, +const meta: Meta<typeof SettingsDataModelFieldIconLabelForm> = { + title: 'Modules/Settings/DataModel/SettingsDataModelFieldIconLabelForm', + component: SettingsDataModelFieldIconLabelForm, decorators: [ (Story) => ( <StyledContainer> @@ -28,11 +28,11 @@ const meta: Meta<typeof SettingsDataModelFieldAboutForm> = { }; export default meta; -type Story = StoryObj<typeof SettingsDataModelFieldAboutForm>; +type Story = StoryObj<typeof SettingsDataModelFieldIconLabelForm>; export const Default: Story = {}; -export const WithDefaultValues: Story = { +export const WithFieldMetadataItem: Story = { args: { fieldMetadataItem: mockedPersonObjectMetadataItem.fields.find( ({ name }) => name === 'name', @@ -45,3 +45,9 @@ export const Disabled: Story = { disabled: true, }, }; + +export const WithMaxLength: Story = { + args: { + maxLength: 50, + }, +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldTypeSelect.stories.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldTypeSelect.stories.tsx index 01b5164d1f8d..dbd3ea3c93bd 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldTypeSelect.stories.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldTypeSelect.stories.tsx @@ -24,12 +24,6 @@ type Story = StoryObj<typeof SettingsDataModelFieldTypeSelect>; export const Default: Story = {}; -export const Disabled: Story = { - args: { - disabled: true, - }, -}; - export const WithOpenSelect: Story = { play: async () => { const canvas = within(document.body); diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm.tsx new file mode 100644 index 000000000000..c7d029abe811 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm.tsx @@ -0,0 +1,63 @@ +import { Controller, useFormContext } from 'react-hook-form'; +import { z } from 'zod'; + +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { StyledFormCardTitle } from '@/settings/data-model/fields/components/StyledFormCardTitle'; +import { SettingsDataModelFieldToggle } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldToggle'; +import { useDateSettingsFormInitialValues } from '@/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues'; +import { CardContent } from '@/ui/layout/card/components/CardContent'; +import { IconClockShare } from 'twenty-ui'; + +export const settingsDataModelFieldDateFormSchema = z.object({ + settings: z + .object({ + displayAsRelativeDate: z.boolean().optional(), + }) + .optional(), +}); + +export type SettingsDataModelFieldDateFormValues = z.infer< + typeof settingsDataModelFieldDateFormSchema +>; + +type SettingsDataModelFieldDateFormProps = { + disabled?: boolean; + fieldMetadataItem: Pick<FieldMetadataItem, 'settings'>; +}; + +export const SettingsDataModelFieldDateForm = ({ + disabled, + fieldMetadataItem, +}: SettingsDataModelFieldDateFormProps) => { + const { control } = useFormContext<SettingsDataModelFieldDateFormValues>(); + + const { initialDisplayAsRelativeDateValue } = + useDateSettingsFormInitialValues({ + fieldMetadataItem, + }); + + return ( + <CardContent> + <Controller + name="settings.displayAsRelativeDate" + control={control} + defaultValue={initialDisplayAsRelativeDateValue} + render={({ field: { onChange, value } }) => ( + <> + <StyledFormCardTitle>Options</StyledFormCardTitle> + <SettingsDataModelFieldToggle + label="Display as relative date" + Icon={IconClockShare} + onChange={onChange} + value={value} + disabled={disabled} + tooltip={ + 'Show dates in a human-friendly format. Example: "13 mins ago" instead of "Jul 30, 2024 7:11pm"' + } + /> + </> + )} + /> + </CardContent> + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateSettingsFormCard.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateSettingsFormCard.tsx new file mode 100644 index 000000000000..418d9d93cc19 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateSettingsFormCard.tsx @@ -0,0 +1,66 @@ +import styled from '@emotion/styled'; +import { useFormContext } from 'react-hook-form'; + +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { SettingsDataModelPreviewFormCard } from '@/settings/data-model/components/SettingsDataModelPreviewFormCard'; +import { + SettingsDataModelFieldDateForm, + SettingsDataModelFieldDateFormValues, +} from '@/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm'; +import { useDateSettingsFormInitialValues } from '@/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues'; +import { + SettingsDataModelFieldPreviewCard, + SettingsDataModelFieldPreviewCardProps, +} from '@/settings/data-model/fields/preview/components/SettingsDataModelFieldPreviewCard'; + +type SettingsDataModelFieldDateSettingsFormCardProps = { + disabled?: boolean; + fieldMetadataItem: Pick< + FieldMetadataItem, + 'icon' | 'label' | 'type' | 'settings' + >; +} & Pick<SettingsDataModelFieldPreviewCardProps, 'objectMetadataItem'>; + +const StyledFieldPreviewCard = styled(SettingsDataModelFieldPreviewCard)` + display: grid; + flex: 1 1 100%; +`; + +export const SettingsDataModelFieldDateSettingsFormCard = ({ + disabled, + fieldMetadataItem, + objectMetadataItem, +}: SettingsDataModelFieldDateSettingsFormCardProps) => { + const { initialDisplayAsRelativeDateValue } = + useDateSettingsFormInitialValues({ + fieldMetadataItem, + }); + + const { watch: watchFormValue } = + useFormContext<SettingsDataModelFieldDateFormValues>(); + + return ( + <SettingsDataModelPreviewFormCard + preview={ + <StyledFieldPreviewCard + fieldMetadataItem={{ + ...fieldMetadataItem, + settings: { + displayAsRelativeDate: watchFormValue( + 'settings.displayAsRelativeDate', + initialDisplayAsRelativeDateValue, + ), + }, + }} + objectMetadataItem={objectMetadataItem} + /> + } + form={ + <SettingsDataModelFieldDateForm + disabled={disabled} + fieldMetadataItem={fieldMetadataItem} + /> + } + /> + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues.ts b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues.ts new file mode 100644 index 000000000000..4726db3ec55e --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues.ts @@ -0,0 +1,25 @@ +import { useFormContext } from 'react-hook-form'; + +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { SettingsDataModelFieldDateFormValues } from '@/settings/data-model/fields/forms/date/components/SettingsDataModelFieldDateForm'; + +export const useDateSettingsFormInitialValues = ({ + fieldMetadataItem, +}: { + fieldMetadataItem?: Pick<FieldMetadataItem, 'settings'>; +}) => { + const initialDisplayAsRelativeDateValue = + fieldMetadataItem?.settings?.displayAsRelativeDate; + + const { resetField } = useFormContext<SettingsDataModelFieldDateFormValues>(); + + const resetDefaultValueField = () => + resetField('settings.displayAsRelativeDate', { + defaultValue: initialDisplayAsRelativeDateValue, + }); + + return { + initialDisplayAsRelativeDateValue, + resetDefaultValueField, + }; +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationForm.tsx index 1ee8522bfd73..d30e05193f4b 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationForm.tsx @@ -1,5 +1,5 @@ -import { Controller, useFormContext } from 'react-hook-form'; import styled from '@emotion/styled'; +import { Controller, useFormContext } from 'react-hook-form'; import { useIcons } from 'twenty-ui'; import { z } from 'zod'; @@ -14,6 +14,7 @@ import { RelationType } from '@/settings/data-model/types/RelationType'; import { IconPicker } from '@/ui/input/components/IconPicker'; import { Select } from '@/ui/input/components/Select'; import { TextInput } from '@/ui/input/components/TextInput'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; export const settingsDataModelFieldRelationFormSchema = z.object({ relation: z.object({ @@ -23,7 +24,10 @@ export const settingsDataModelFieldRelationFormSchema = z.object({ }), objectMetadataId: z.string().uuid(), type: z.enum( - Object.keys(RELATION_TYPES) as [RelationType, ...RelationType[]], + Object.keys(RELATION_TYPES) as [ + RelationDefinitionType, + ...RelationDefinitionType[], + ], ), }), }); @@ -33,10 +37,7 @@ export type SettingsDataModelFieldRelationFormValues = z.infer< >; type SettingsDataModelFieldRelationFormProps = { - fieldMetadataItem: Pick< - FieldMetadataItem, - 'fromRelationMetadata' | 'toRelationMetadata' | 'type' - >; + fieldMetadataItem: Pick<FieldMetadataItem, 'type'>; }; const StyledContainer = styled.div` diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationSettingsFormCard.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationSettingsFormCard.tsx index 808153bd7878..7452d5f014e2 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationSettingsFormCard.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/components/SettingsDataModelFieldRelationSettingsFormCard.tsx @@ -1,5 +1,5 @@ -import { useFormContext } from 'react-hook-form'; import styled from '@emotion/styled'; +import { useFormContext } from 'react-hook-form'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; @@ -29,11 +29,13 @@ const StyledFieldPreviewCard = styled(SettingsDataModelFieldPreviewCard)` const StyledPreviewContent = styled.div` display: flex; + flex-direction: column; gap: 6px; `; const StyledRelationImage = styled.img<{ flip?: boolean }>` - transform: ${({ flip }) => (flip ? 'scaleX(-1)' : 'none')}; + transform: ${({ flip }) => (flip ? 'scaleX(-1) rotate(270deg)' : 'none')}; + margin: auto; width: 54px; `; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/hooks/useRelationSettingsFormInitialValues.ts b/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/hooks/useRelationSettingsFormInitialValues.ts index c429eceb1bf5..bd4b2badd0e2 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/hooks/useRelationSettingsFormInitialValues.ts +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/relation/hooks/useRelationSettingsFormInitialValues.ts @@ -5,15 +5,12 @@ import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMe import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation'; -import { RelationMetadataType } from '~/generated-metadata/graphql'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; export const useRelationSettingsFormInitialValues = ({ fieldMetadataItem, }: { - fieldMetadataItem?: Pick< - FieldMetadataItem, - 'fromRelationMetadata' | 'toRelationMetadata' | 'type' - >; + fieldMetadataItem?: Pick<FieldMetadataItem, 'type' | 'relationDefinition'>; }) => { const { objectMetadataItems } = useFilteredObjectMetadataItems(); @@ -39,7 +36,7 @@ export const useRelationSettingsFormInitialValues = ({ ); const initialRelationType = - relationTypeFromFieldMetadata ?? RelationMetadataType.OneToMany; + relationTypeFromFieldMetadata ?? RelationDefinitionType.OneToMany; return { disableFieldEdition: diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema.ts b/packages/twenty-front/src/modules/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema.ts index f1a24d833a68..4d7a171f46a4 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema.ts +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema.ts @@ -1,13 +1,15 @@ import { z } from 'zod'; -import { settingsDataModelFieldAboutFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm'; +import { settingsDataModelFieldDescriptionFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm'; +import { settingsDataModelFieldIconLabelFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm'; import { settingsDataModelFieldSettingsFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard'; import { settingsDataModelFieldTypeFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect'; -export const settingsFieldFormSchema = (existingLabels?: string[]) => { +export const settingsFieldFormSchema = (existingOtherLabels?: string[]) => { return z .object({}) - .merge(settingsDataModelFieldAboutFormSchema(existingLabels)) + .merge(settingsDataModelFieldIconLabelFormSchema(existingOtherLabels)) + .merge(settingsDataModelFieldDescriptionFormSchema()) .merge(settingsDataModelFieldTypeFormSchema) .and(settingsDataModelFieldSettingsFormSchema); }; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/SettingsDataModelFieldPreview.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/SettingsDataModelFieldPreview.tsx index a7b69af6a905..1fbefb2d3238 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/SettingsDataModelFieldPreview.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/SettingsDataModelFieldPreview.tsx @@ -18,7 +18,7 @@ import { FieldMetadataType } from '~/generated-metadata/graphql'; export type SettingsDataModelFieldPreviewProps = { fieldMetadataItem: Pick< FieldMetadataItem, - 'icon' | 'label' | 'type' | 'defaultValue' | 'options' + 'icon' | 'label' | 'type' | 'defaultValue' | 'options' | 'settings' > & { id?: string; name?: string; @@ -132,6 +132,7 @@ export const SettingsDataModelFieldPreview = ({ relationObjectMetadataNameSingular: relationObjectMetadataItem?.nameSingular, options: fieldMetadataItem.options ?? [], + settings: fieldMetadataItem.settings, }, defaultValue: fieldMetadataItem.defaultValue, }, diff --git a/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx b/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx index 1cb6c6716bd1..af4694f66d48 100644 --- a/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewEffect.tsx @@ -1,7 +1,7 @@ -import { useEffect } from 'react'; -import { Edge, Node } from 'reactflow'; import dagre from '@dagrejs/dagre'; import { useTheme } from '@emotion/react'; +import { useEffect } from 'react'; +import { Edge, Node } from 'reactflow'; import { useRecoilValue } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; @@ -43,10 +43,10 @@ export const SettingsDataModelOverviewEffect = ({ for (const field of object.fields) { if ( - isDefined(field.toRelationMetadata) && + isDefined(field.relationDefinition) && isDefined( items.find( - (x) => x.id === field.toRelationMetadata?.fromObjectMetadata.id, + (x) => x.id === field.relationDefinition?.targetObjectMetadata.id, ), ) ) { @@ -59,8 +59,8 @@ export const SettingsDataModelOverviewEffect = ({ id: `${sourceObj}-${targetObj}`, source: object.namePlural, sourceHandle: `${field.id}-right`, - target: field.toRelationMetadata.fromObjectMetadata.namePlural, - targetHandle: `${field.toRelationMetadata.fromFieldMetadataId}-left`, + target: field.relationDefinition.targetObjectMetadata.namePlural, + targetHandle: `${field.relationDefinition.targetObjectMetadata}-left`, type: 'smoothstep', style: { strokeWidth: 1, @@ -70,8 +70,8 @@ export const SettingsDataModelOverviewEffect = ({ markerStart: 'marker', data: { sourceField: field.id, - targetField: field.toRelationMetadata.fromFieldMetadataId, - relation: field.toRelationMetadata.relationType, + targetField: field.relationDefinition.targetFieldMetadata.id, + relation: field.relationDefinition.direction, sourceObject: sourceObj, targetObject: targetObj, }, diff --git a/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewField.tsx b/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewField.tsx index a3804093bf33..98c0321056e7 100644 --- a/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewField.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/graph-overview/components/SettingsDataModelOverviewField.tsx @@ -6,6 +6,7 @@ import { useIcons } from 'twenty-ui'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; type ObjectFieldRowProps = { field: FieldMetadataItem; @@ -42,21 +43,33 @@ export const ObjectFieldRow = ({ field }: ObjectFieldRowProps) => { {Icon && <Icon size={theme.icon.size.md} />} <StyledFieldName>{relatedObject?.labelPlural ?? ''}</StyledFieldName> <Handle - type={field.toRelationMetadata ? 'source' : 'target'} + type={ + field.relationDefinition?.direction === + RelationDefinitionType.OneToMany + ? 'source' + : 'target' + } position={Position.Right} id={`${field.id}-right`} className={ - field.fromRelationMetadata + field.relationDefinition?.direction === + RelationDefinitionType.OneToMany ? 'right-handle source-handle' : 'right-handle target-handle' } /> <Handle - type={field.toRelationMetadata ? 'source' : 'target'} + type={ + field.relationDefinition?.direction === + RelationDefinitionType.OneToMany + ? 'source' + : 'target' + } position={Position.Left} id={`${field.id}-left`} className={ - field.fromRelationMetadata + field.relationDefinition?.direction === + RelationDefinitionType.OneToMany ? 'left-handle source-handle' : 'left-handle target-handle' } diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDataType.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDataType.tsx index fb6457cf1466..4fe7cccf71ff 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDataType.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDataType.tsx @@ -1,6 +1,6 @@ -import { Link } from 'react-router-dom'; import { css, useTheme } from '@emotion/react'; import styled from '@emotion/styled'; +import { Link } from 'react-router-dom'; import { IconComponent, IconTwentyStar } from 'twenty-ui'; import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType'; @@ -23,10 +23,9 @@ const StyledDataType = styled.div<{ border-radius: ${({ theme }) => theme.border.radius.sm}; display: flex; font-size: ${({ theme }) => theme.font.size.sm}; - gap: ${({ theme }) => theme.spacing(1)}; + gap: ${({ theme }) => theme.spacing(2)}; height: 20px; overflow: hidden; - padding: 0 ${({ theme }) => theme.spacing(2)}; text-decoration: none; ${({ to }) => @@ -36,11 +35,11 @@ const StyledDataType = styled.div<{ ` : ''} - ${({ theme, value }) => + ${({ value, theme }) => value === FieldMetadataType.Relation ? css` - border-color: ${theme.tag.background.purple}; - color: ${theme.color.purple}; + color: ${theme.font.color.secondary}; + text-decoration: underline; ` : ''} `; diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown.tsx index 6879667dc8dc..a6b68c6b5a41 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown.tsx @@ -1,4 +1,10 @@ -import { IconArchiveOff, IconDotsVertical, IconTrash } from 'twenty-ui'; +import { + IconArchiveOff, + IconDotsVertical, + IconEye, + IconPencil, + IconTrash, +} from 'twenty-ui'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; @@ -12,6 +18,7 @@ type SettingsObjectFieldInactiveActionDropdownProps = { isCustomField?: boolean; fieldType?: FieldMetadataType; onActivate: () => void; + onEdit: () => void; onDelete: () => void; scopeKey: string; }; @@ -20,6 +27,7 @@ export const SettingsObjectFieldInactiveActionDropdown = ({ onActivate, scopeKey, onDelete, + onEdit, isCustomField, }: SettingsObjectFieldInactiveActionDropdownProps) => { const dropdownId = `${scopeKey}-settings-field-disabled-action-dropdown`; @@ -36,6 +44,11 @@ export const SettingsObjectFieldInactiveActionDropdown = ({ closeDropdown(); }; + const handleEdit = () => { + onEdit(); + closeDropdown(); + }; + const isDeletable = isCustomField; return ( @@ -47,6 +60,11 @@ export const SettingsObjectFieldInactiveActionDropdown = ({ dropdownComponents={ <DropdownMenu width="160px"> <DropdownMenuItemsContainer> + <MenuItem + text={isCustomField ? 'Edit' : 'View'} + LeftIcon={isCustomField ? IconPencil : IconEye} + onClick={handleEdit} + /> <MenuItem text="Activate" LeftIcon={IconArchiveOff} diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx index 8793be03d520..6052b9f23efa 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx @@ -29,7 +29,7 @@ import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMe import { View } from '@/views/types/View'; import { useNavigate } from 'react-router-dom'; import { useRecoilState } from 'recoil'; -import { RelationMetadataType } from '~/generated-metadata/graphql'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; import { SettingsObjectDetailTableItem } from '~/pages/settings/data-model/types/SettingsObjectDetailTableItem'; import { SettingsObjectFieldDataType } from './SettingsObjectFieldDataType'; @@ -48,6 +48,12 @@ const StyledNameTableCell = styled(TableCell)` gap: ${({ theme }) => theme.spacing(2)}; `; +const StyledNameLabel = styled.div` + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +`; + const StyledIconTableCell = styled(TableCell)` justify-content: center; padding-right: ${({ theme }) => theme.spacing(1)}; @@ -203,17 +209,23 @@ export const SettingsObjectFieldItemTableRow = ({ > <StyledNameTableCell> {!!Icon && ( - <Icon size={theme.icon.size.md} stroke={theme.icon.stroke.sm} /> + <Icon + style={{ minWidth: theme.icon.size.md }} + size={theme.icon.size.md} + stroke={theme.icon.stroke.sm} + /> )} - {fieldMetadataItem.label} + <StyledNameLabel title={fieldMetadataItem.label}> + {fieldMetadataItem.label} + </StyledNameLabel> </StyledNameTableCell> <TableCell>{typeLabel}</TableCell> <TableCell> <SettingsObjectFieldDataType Icon={RelationIcon} label={ - relationType === RelationMetadataType.ManyToOne || - relationType === RelationMetadataType.OneToOne + relationType === RelationDefinitionType.ManyToOne || + relationType === RelationDefinitionType.OneToOne ? relationObjectMetadataItem?.labelSingular : relationObjectMetadataItem?.labelPlural } @@ -257,6 +269,7 @@ export const SettingsObjectFieldItemTableRow = ({ <SettingsObjectFieldInactiveActionDropdown isCustomField={fieldMetadataItem.isCustom === true} scopeKey={fieldMetadataItem.id} + onEdit={() => navigate(linkToNavigate)} onActivate={() => activateMetadataField(fieldMetadataItem)} onDelete={() => deleteMetadataField(fieldMetadataItem)} /> diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx index 0c69f4b81afe..27e1a97823cd 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectItemTableRow.tsx @@ -25,6 +25,12 @@ const StyledNameTableCell = styled(TableCell)` gap: ${({ theme }) => theme.spacing(2)}; `; +const StyledNameLabel = styled.div` + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +`; + const StyledActionTableCell = styled(TableCell)` justify-content: center; padding-right: ${({ theme }) => theme.spacing(1)}; @@ -46,9 +52,15 @@ export const SettingsObjectMetadataItemTableRow = ({ <StyledObjectTableRow key={objectMetadataItem.namePlural} to={link}> <StyledNameTableCell> {!!Icon && ( - <Icon size={theme.icon.size.md} stroke={theme.icon.stroke.sm} /> + <Icon + style={{ minWidth: theme.icon.size.md }} + size={theme.icon.size.md} + stroke={theme.icon.stroke.sm} + /> )} - {objectMetadataItem.labelPlural} + <StyledNameLabel title={objectMetadataItem.labelPlural}> + {objectMetadataItem.labelPlural} + </StyledNameLabel> </StyledNameTableCell> <TableCell> <SettingsDataModelObjectTypeTag objectTypeLabel={objectTypeLabel} /> diff --git a/packages/twenty-front/src/modules/settings/data-model/types/RelationType.ts b/packages/twenty-front/src/modules/settings/data-model/types/RelationType.ts index ba2fc606c561..a6537b41e8aa 100644 --- a/packages/twenty-front/src/modules/settings/data-model/types/RelationType.ts +++ b/packages/twenty-front/src/modules/settings/data-model/types/RelationType.ts @@ -1,5 +1,3 @@ -import { RelationMetadataType } from '~/generated-metadata/graphql'; +import { RelationDefinitionType } from '~/generated-metadata/graphql'; -export type RelationType = - | Exclude<RelationMetadataType, 'MANY_TO_MANY'> - | 'MANY_TO_ONE'; +export type RelationType = RelationDefinitionType; diff --git a/packages/twenty-front/src/modules/settings/data-model/types/SettingsFieldTypeCategoryType.ts b/packages/twenty-front/src/modules/settings/data-model/types/SettingsFieldTypeCategoryType.ts new file mode 100644 index 000000000000..a6972dae7544 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/data-model/types/SettingsFieldTypeCategoryType.ts @@ -0,0 +1 @@ +export type SettingsFieldTypeCategoryType = 'Basic' | 'Advanced' | 'Relation'; diff --git a/packages/twenty-front/src/modules/settings/developers/components/ApiKeyInput.tsx b/packages/twenty-front/src/modules/settings/developers/components/ApiKeyInput.tsx index e4f3f7b43e28..298d24d0f845 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/ApiKeyInput.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/ApiKeyInput.tsx @@ -32,7 +32,7 @@ export const ApiKeyInput = ({ apiKey }: ApiKeyInputProps) => { Icon={IconCopy} title="Copy" onClick={() => { - enqueueSnackBar('Api Key copied to clipboard', { + enqueueSnackBar('API Key copied to clipboard', { variant: SnackBarVariant.Success, icon: <IconCopy size={theme.icon.size.md} />, duration: 2000, diff --git a/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx b/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx index f5d86e6a3b3d..ede12c34bf6c 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/SettingsApiKeysTable.tsx @@ -13,6 +13,8 @@ import { TableRow } from '@/ui/layout/table/components/TableRow'; const StyledTableBody = styled(TableBody)` border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + max-height: 260px; + overflow-y: auto; `; const StyledTableRow = styled(TableRow)` diff --git a/packages/twenty-front/src/modules/settings/developers/components/SettingsReadDocumentationButton.tsx b/packages/twenty-front/src/modules/settings/developers/components/SettingsReadDocumentationButton.tsx index 1a3be93423cf..c1efcc117a2b 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/SettingsReadDocumentationButton.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/SettingsReadDocumentationButton.tsx @@ -6,7 +6,7 @@ export const SettingsReadDocumentationButton = () => { return ( <Button title="Read documentation" - variant="primary" + variant="secondary" accent="default" size="small" Icon={IconBook2} diff --git a/packages/twenty-front/src/modules/settings/developers/components/SettingsWebhooksTable.tsx b/packages/twenty-front/src/modules/settings/developers/components/SettingsWebhooksTable.tsx index b10a1de71377..15c479d501a5 100644 --- a/packages/twenty-front/src/modules/settings/developers/components/SettingsWebhooksTable.tsx +++ b/packages/twenty-front/src/modules/settings/developers/components/SettingsWebhooksTable.tsx @@ -11,6 +11,8 @@ import { TableRow } from '@/ui/layout/table/components/TableRow'; const StyledTableBody = styled(TableBody)` border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + max-height: 260px; + overflow-y: auto; `; const StyledTableRow = styled(TableRow)` diff --git a/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts b/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts index 38a639127fb5..d70dd9b493e0 100644 --- a/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts +++ b/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts @@ -29,15 +29,17 @@ export const useSettingsIntegrationCategories = ({ name }) => name === 'stripe', )?.isActive; + const allIntegrations = getSettingsIntegrationAll({ + isAirtableIntegrationEnabled, + isAirtableIntegrationActive, + isPostgresqlIntegrationEnabled, + isPostgresqlIntegrationActive, + isStripeIntegrationEnabled, + isStripeIntegrationActive, + }); + return [ - getSettingsIntegrationAll({ - isAirtableIntegrationEnabled, - isAirtableIntegrationActive, - isPostgresqlIntegrationEnabled, - isPostgresqlIntegrationActive, - isStripeIntegrationEnabled, - isStripeIntegrationActive, - }), + ...(allIntegrations.integrations.length > 0 ? [allIntegrations] : []), SETTINGS_INTEGRATION_ZAPIER_CATEGORY, SETTINGS_INTEGRATION_WINDMILL_CATEGORY, SETTINGS_INTEGRATION_REQUEST_CATEGORY, diff --git a/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts b/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts index a61532673dc9..97061ade9951 100644 --- a/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts +++ b/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts @@ -1,3 +1,4 @@ +import { SettingsIntegration } from '@/settings/integrations/types/SettingsIntegration'; import { SettingsIntegrationCategory } from '@/settings/integrations/types/SettingsIntegrationCategory'; export const getSettingsIntegrationAll = ({ @@ -18,44 +19,32 @@ export const getSettingsIntegrationAll = ({ key: 'all', title: 'All', integrations: [ - { + isAirtableIntegrationEnabled && { from: { key: 'airtable', image: '/images/integrations/airtable-logo.png', }, - type: !isAirtableIntegrationEnabled - ? 'Soon' - : isAirtableIntegrationActive - ? 'Active' - : 'Add', + type: isAirtableIntegrationActive ? 'Active' : 'Add', text: 'Airtable', link: '/settings/integrations/airtable', }, - { + isPostgresqlIntegrationEnabled && { from: { key: 'postgresql', image: '/images/integrations/postgresql-logo.png', }, - type: !isPostgresqlIntegrationEnabled - ? 'Soon' - : isPostgresqlIntegrationActive - ? 'Active' - : 'Add', + type: isPostgresqlIntegrationActive ? 'Active' : 'Add', text: 'PostgreSQL', link: '/settings/integrations/postgresql', }, - { + isStripeIntegrationEnabled && { from: { key: 'stripe', image: '/images/integrations/stripe-logo.png', }, - type: !isStripeIntegrationEnabled - ? 'Soon' - : isStripeIntegrationActive - ? 'Active' - : 'Add', + type: isStripeIntegrationActive ? 'Active' : 'Add', text: 'Stripe', link: '/settings/integrations/stripe', }, - ], + ].filter(Boolean) as SettingsIntegration[], }); diff --git a/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx b/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx index f63782fa35e5..190bd601667f 100644 --- a/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx +++ b/packages/twenty-front/src/modules/settings/profile/components/DeleteWorkspace.tsx @@ -1,15 +1,12 @@ import { useState } from 'react'; import { useRecoilValue } from 'recoil'; -import { H2Title } from 'twenty-ui'; +import { H2Title, IconTrash } from 'twenty-ui'; import { useAuth } from '@/auth/hooks/useAuth'; import { currentUserState } from '@/auth/states/currentUserState'; -import { - ConfirmationModal, - StyledConfirmationButton, -} from '@/ui/layout/modal/components/ConfirmationModal'; +import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useDeleteCurrentWorkspaceMutation } from '~/generated/graphql'; - +import { Button } from '@/ui/input/button/components/Button'; export const DeleteWorkspace = () => { const [isDeleteWorkSpaceModalOpen, setIsDeleteWorkSpaceModalOpen] = useState(false); @@ -28,10 +25,12 @@ export const DeleteWorkspace = () => { return ( <> <H2Title title="Danger zone" description="Delete your whole workspace" /> - <StyledConfirmationButton - onClick={() => setIsDeleteWorkSpaceModalOpen(true)} + <Button + accent="danger" variant="secondary" title="Delete workspace" + Icon={IconTrash} + onClick={() => setIsDeleteWorkSpaceModalOpen(true)} /> <ConfirmationModal diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx b/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx index a7b857bf621a..d34186b3f738 100644 --- a/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx +++ b/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx @@ -8,10 +8,7 @@ import { Table } from '@/ui/layout/table/components/Table'; import { TableBody } from '@/ui/layout/table/components/TableBody'; import { TableHeader } from '@/ui/layout/table/components/TableHeader'; import { TableRow } from '@/ui/layout/table/components/TableRow'; -import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import styled from '@emotion/styled'; -import { useNavigate } from 'react-router-dom'; -import { Key } from 'ts-key-enum'; import { ServerlessFunction } from '~/generated-metadata/graphql'; import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount'; @@ -25,19 +22,11 @@ const StyledTableBody = styled(TableBody)` export const SettingsServerlessFunctionsTable = () => { const { serverlessFunctions } = useGetManyServerlessFunctions(); - const navigate = useNavigate(); useHotkeyScopeOnMount( SettingsServerlessFunctionHotkeyScope.ServerlessFunction, ); - useScopedHotkeys( - [Key.Enter], - () => { - navigate(getSettingsPagePath(SettingsPath.NewServerlessFunction)); - }, - SettingsServerlessFunctionHotkeyScope.ServerlessFunction, - ); return ( <> {serverlessFunctions.length ? ( diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/graphql/queries/findManyAvailablePackages.ts b/packages/twenty-front/src/modules/settings/serverless-functions/graphql/queries/findManyAvailablePackages.ts new file mode 100644 index 000000000000..3d2532673e9a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/serverless-functions/graphql/queries/findManyAvailablePackages.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const FIND_MANY_AVAILABLE_PACKAGES = gql` + query FindManyAvailablePackages { + getAvailablePackages + } +`; diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/hooks/useGetAvailablePackages.ts b/packages/twenty-front/src/modules/settings/serverless-functions/hooks/useGetAvailablePackages.ts new file mode 100644 index 000000000000..a2a8f1f36d1a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/serverless-functions/hooks/useGetAvailablePackages.ts @@ -0,0 +1,20 @@ +import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient'; +import { useQuery } from '@apollo/client'; +import { FIND_MANY_AVAILABLE_PACKAGES } from '@/settings/serverless-functions/graphql/queries/findManyAvailablePackages'; +import { + FindManyAvailablePackagesQuery, + FindManyAvailablePackagesQueryVariables, +} from '~/generated-metadata/graphql'; + +export const useGetAvailablePackages = () => { + const apolloMetadataClient = useApolloMetadataClient(); + const { data } = useQuery< + FindManyAvailablePackagesQuery, + FindManyAvailablePackagesQueryVariables + >(FIND_MANY_AVAILABLE_PACKAGES, { + client: apolloMetadataClient ?? undefined, + }); + return { + availablePackages: data?.getAvailablePackages || null, + }; +}; diff --git a/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx b/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx index 3a921e92f658..31b5f31b3e79 100644 --- a/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx +++ b/packages/twenty-front/src/modules/settings/workspace/components/NameField.tsx @@ -1,10 +1,11 @@ -import { useCallback, useEffect, useState } from 'react'; import styled from '@emotion/styled'; +import { useCallback, useEffect, useState } from 'react'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useDebouncedCallback } from 'use-debounce'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { TextInput } from '@/ui/input/components/TextInput'; +import isEmpty from 'lodash.isempty'; import { useUpdateWorkspaceMutation } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; @@ -40,6 +41,7 @@ export const NameField = ({ // eslint-disable-next-line react-hooks/exhaustive-deps const debouncedUpdate = useCallback( useDebouncedCallback(async (name: string) => { + if (isEmpty(name)) return; // update local recoil state when workspace name is updated setCurrentWorkspace((currentValue) => { if (currentValue === null) { diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx index 699b82af7bff..1ce2f5affe9c 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx @@ -4,6 +4,7 @@ import { RecordIndexOptionsDropdown } from '@/object-record/record-index/options import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect'; import { ViewBar } from '@/views/components/ViewBar'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; import { ViewType } from '@/views/types/ViewType'; const StyledContainer = styled.div` @@ -21,29 +22,30 @@ export const SignInBackgroundMockContainer = () => { return ( <StyledContainer> - <ViewBar - viewBarId={viewBarId} - onCurrentViewChange={async () => {}} - optionsDropdownButton={ - <RecordIndexOptionsDropdown - recordIndexId={recordIndexId} - objectNameSingular={objectNameSingular} - viewType={ViewType.Table} - /> - } - /> - <SignInBackgroundMockContainerEffect - objectNamePlural={objectNamePlural} - recordTableId={recordIndexId} - viewId={viewBarId} - /> - <RecordTableWithWrappers - objectNameSingular={objectNameSingular} - recordTableId={recordIndexId} - viewBarId={viewBarId} - createRecord={async () => {}} - updateRecordMutation={() => {}} - /> + <ViewComponentInstanceContext.Provider value={{ instanceId: viewBarId }}> + <ViewBar + viewBarId={viewBarId} + onCurrentViewChange={async () => {}} + optionsDropdownButton={ + <RecordIndexOptionsDropdown + recordIndexId={recordIndexId} + objectNameSingular={objectNameSingular} + viewType={ViewType.Table} + /> + } + /> + <SignInBackgroundMockContainerEffect + objectNamePlural={objectNamePlural} + recordTableId={recordIndexId} + viewId={viewBarId} + /> + <RecordTableWithWrappers + objectNameSingular={objectNameSingular} + recordTableId={recordIndexId} + viewBarId={viewBarId} + updateRecordMutation={() => {}} + /> + </ViewComponentInstanceContext.Provider> </StyledContainer> ); }; diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts index 5e4e4377de89..e1ebdec28b73 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions.ts @@ -1,8 +1,10 @@ -import { COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; +import { + FieldMetadataType, + RelationDefinitionType, +} from '~/generated-metadata/graphql'; export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( [ @@ -42,7 +44,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( }, { position: 2, - fieldMetadataId: COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID, + fieldMetadataId: 'REPLACE_ME', label: 'Name', size: 100, type: FieldMetadataType.Text, @@ -65,7 +67,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( type: FieldMetadataType.Relation, metadata: { fieldName: 'favorites', - relationType: 'FROM_MANY_OBJECTS', + relationType: RelationDefinitionType.OneToMany, relationObjectMetadataNameSingular: '', relationObjectMetadataNamePlural: '', objectMetadataNameSingular: 'company', @@ -99,7 +101,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( type: FieldMetadataType.Relation, metadata: { fieldName: 'accountOwner', - relationType: 'TO_ONE_OBJECT', + relationType: RelationDefinitionType.ManyToOne, relationObjectMetadataNameSingular: 'workspaceMember', relationObjectMetadataNamePlural: 'workspaceMembers', objectMetadataNameSingular: 'company', @@ -116,7 +118,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( type: FieldMetadataType.Relation, metadata: { fieldName: 'people', - relationType: 'FROM_MANY_OBJECTS', + relationType: RelationDefinitionType.OneToMany, relationObjectMetadataNameSingular: '', relationObjectMetadataNamePlural: '', objectMetadataNameSingular: 'company', @@ -133,7 +135,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( type: FieldMetadataType.Relation, metadata: { fieldName: 'attachments', - relationType: 'FROM_MANY_OBJECTS', + relationType: RelationDefinitionType.OneToMany, relationObjectMetadataNameSingular: '', relationObjectMetadataNamePlural: '', objectMetadataNameSingular: 'company', @@ -201,7 +203,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( type: FieldMetadataType.Relation, metadata: { fieldName: 'opportunities', - relationType: 'FROM_MANY_OBJECTS', + relationType: RelationDefinitionType.OneToMany, relationObjectMetadataNameSingular: '', relationObjectMetadataNamePlural: '', objectMetadataNameSingular: 'company', @@ -235,7 +237,7 @@ export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = ( type: FieldMetadataType.Relation, metadata: { fieldName: 'activityTargets', - relationType: 'FROM_MANY_OBJECTS', + relationType: RelationDefinitionType.OneToMany, relationObjectMetadataNameSingular: '', relationObjectMetadataNamePlural: '', objectMetadataNameSingular: 'company', diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts index ab67214dd3db..f3d24ae7a95c 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockFilterDefinitions.ts @@ -1,4 +1,3 @@ -import { COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; export const SIGN_IN_BACKGROUND_MOCK_FILTER_DEFINITIONS = [ @@ -15,7 +14,7 @@ export const SIGN_IN_BACKGROUND_MOCK_FILTER_DEFINITIONS = [ type: 'NUMBER', }, { - fieldMetadataId: COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID, + fieldMetadataId: 'REPLACE_ME', label: 'Name', iconName: 'IconBuildingSkyscraper', type: 'TEXT', diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions.ts index 24adc014bb37..a65f08439312 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions.ts @@ -1,4 +1,3 @@ -import { COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; export const SIGN_IN_BACKGROUND_MOCK_SORT_DEFINITIONS = [ @@ -13,7 +12,7 @@ export const SIGN_IN_BACKGROUND_MOCK_SORT_DEFINITIONS = [ iconName: 'IconUsers', }, { - fieldMetadataId: COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID, + fieldMetadataId: 'REPLACE_ME', label: 'Name', iconName: 'IconBuildingSkyscraper', }, diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockViewFields.ts b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockViewFields.ts index dabbe2434355..29599b850494 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockViewFields.ts +++ b/packages/twenty-front/src/modules/sign-in-background-mock/constants/SignInBackgroundMockViewFields.ts @@ -1,4 +1,3 @@ -import { COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { ViewField } from '@/views/types/ViewField'; export const SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS = [ @@ -60,7 +59,7 @@ export const SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS = [ { __typename: 'ViewField', id: 'cafacdc8-cbfc-4545-8242-94787f144ace', - fieldMetadataId: COMPANY_LABEL_IDENTIFIER_FIELD_METADATA_ID, + fieldMetadataId: 'REPLACE_ME', size: 180, createdAt: '2023-11-23T15:38:03.706Z', viewId: '20202020-2441-4424-8163-4002c523d415', diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumn.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumn.tsx index 3e1cd3abb2b2..ee5eb779e44c 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumn.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumn.tsx @@ -1,56 +1,13 @@ import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal'; import { SubMatchingSelect } from '@/spreadsheet-import/steps/components/MatchColumnsStep/components/SubMatchingSelect'; +import { UnmatchColumnBanner } from '@/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumnBanner'; import { Column } from '@/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep'; import { Fields } from '@/spreadsheet-import/types'; -import { - Accordion, - AccordionIcon, - AccordionItem, - AccordionPanel, - AccordionButton as ChakraAccordionButton, -} from '@chakra-ui/accordion'; import styled from '@emotion/styled'; -import { IconChevronDown, IconInfoCircle, isDefined } from 'twenty-ui'; +import { useState } from 'react'; +import { ExpandableContainer, isDefined } from 'twenty-ui'; -const StyledAccordionButton = styled(ChakraAccordionButton)` - align-items: center; - background-color: ${({ theme }) => theme.accent.secondary}; - border: none; - border-radius: ${({ theme }) => theme.border.radius.md}; - box-sizing: border-box; - color: ${({ theme }) => theme.font.color.primary}; - display: flex; - flex-direction: row; - padding: ${({ theme }) => theme.spacing(2)}; - width: 100%; - height: 40px; - - &:hover { - background-color: ${({ theme }) => theme.accent.primary}; - } -`; - -const StyledAccordionContainer = styled.div` - display: flex; - width: 100%; - height: auto; -`; - -const StyledAccordionLabel = styled.span` - color: ${({ theme }) => theme.color.blue}; - display: flex; - flex: 1; - font-size: ${({ theme }) => theme.font.size.sm}; - align-items: center; - gap: ${({ theme }) => theme.spacing(2)}; - text-align: left; -`; - -const StyledIconChevronDown = styled(IconChevronDown)` - color: ${({ theme }) => theme.color.blue} !important; -`; - -const getAccordionTitle = <T extends string>( +const getExpandableContainerTitle = <T extends string>( fields: Fields<T>, column: Column<T>, ) => { @@ -70,42 +27,51 @@ type UnmatchColumnProps<T extends string> = { onSubChange: (val: T, index: number, option: string) => void; }; +const StyledContainer = styled.div` + position: relative; + width: 100%; +`; + +const StyledContentWrapper = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(3)}; + margin-top: ${({ theme }) => theme.spacing(4)}; + padding-bottom: ${({ theme }) => theme.spacing(4)}; +`; + export const UnmatchColumn = <T extends string>({ columns, columnIndex, onSubChange, }: UnmatchColumnProps<T>) => { const { fields } = useSpreadsheetImportInternal<T>(); - + const [isExpanded, setIsExpanded] = useState(false); const column = columns[columnIndex]; const isSelect = 'matchedOptions' in column; + if (!isSelect) return null; + return ( - isSelect && ( - <StyledAccordionContainer> - <Accordion allowMultiple width="100%" height="100%"> - <AccordionItem border="none" py={1} height="100%"> - <StyledAccordionButton data-testid="accordion-button"> - <StyledAccordionLabel> - <IconInfoCircle /> - {getAccordionTitle(fields, column)} - </StyledAccordionLabel> - <AccordionIcon as={StyledIconChevronDown} /> - </StyledAccordionButton> - <AccordionPanel mt={16} gap={12} display="flex" flexDir="column"> - {column.matchedOptions.map((option) => ( - <SubMatchingSelect - option={option} - column={column} - onSubChange={onSubChange} - key={option.entry} - placeholder="Select an option" - /> - ))} - </AccordionPanel> - </AccordionItem> - </Accordion> - </StyledAccordionContainer> - ) + <StyledContainer> + <UnmatchColumnBanner + message={getExpandableContainerTitle(fields, column)} + buttonOnClick={() => setIsExpanded(!isExpanded)} + isExpanded={isExpanded} + /> + <ExpandableContainer isExpanded={isExpanded}> + <StyledContentWrapper> + {column.matchedOptions.map((option) => ( + <SubMatchingSelect + option={option} + column={column} + onSubChange={onSubChange} + key={option.entry} + placeholder="Select an option" + /> + ))} + </StyledContentWrapper> + </ExpandableContainer> + </StyledContainer> ); }; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumnBanner.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumnBanner.tsx new file mode 100644 index 000000000000..a22ac52f8949 --- /dev/null +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumnBanner.tsx @@ -0,0 +1,53 @@ +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { Banner, IconChevronDown, IconInfoCircle } from 'twenty-ui'; + +const StyledBanner = styled(Banner)` + background: ${({ theme }) => theme.accent.secondary}; + border-radius: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(2) + ' ' + theme.spacing(2.5)}; +`; + +const StyledText = styled.div` + color: ${({ theme }) => theme.color.blue}; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; + +const StyledTransitionedIconChevronDown = styled(IconChevronDown)<{ + isExpanded: boolean; +}>` + color: ${({ theme }) => theme.color.blue}; + transform: ${({ isExpanded }) => + isExpanded ? 'rotate(180deg)' : 'rotate(0deg)'}; + transition: ${({ theme }) => + `transform ${theme.animation.duration.normal}s ease`}; + cursor: pointer; +`; + +export const UnmatchColumnBanner = ({ + message, + isExpanded, + buttonOnClick, +}: { + message: string; + isExpanded: boolean; + buttonOnClick?: () => void; +}) => { + const theme = useTheme(); + return ( + <StyledBanner> + <IconInfoCircle color={theme.color.blue} size={theme.icon.size.md} /> + <StyledText>{message}</StyledText> + {buttonOnClick && ( + <StyledTransitionedIconChevronDown + isExpanded={isExpanded} + onClick={buttonOnClick} + size={theme.icon.size.md} + /> + )} + </StyledBanner> + ); +}; diff --git a/packages/twenty-front/src/modules/ui/feedback/dialog-manager/scopes/scope-internal-context/DialogManagerScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/feedback/dialog-manager/scopes/scope-internal-context/DialogManagerScopeInternalContext.ts index fb6183db810a..8620b0d28d51 100644 --- a/packages/twenty-front/src/modules/ui/feedback/dialog-manager/scopes/scope-internal-context/DialogManagerScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/ui/feedback/dialog-manager/scopes/scope-internal-context/DialogManagerScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type DialogManagerScopeInternalContextProps = ComponentStateKey; +type DialogManagerScopeInternalContextProps = RecoilComponentStateKey; export const DialogManagerScopeInternalContext = createScopeInternalContext<DialogManagerScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/components/SnackBar.tsx b/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/components/SnackBar.tsx index 5104ecdbb520..b1f663065012 100644 --- a/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/components/SnackBar.tsx +++ b/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/components/SnackBar.tsx @@ -1,7 +1,7 @@ -import { ComponentPropsWithoutRef, ReactNode, useMemo } from 'react'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { isUndefined } from '@sniptt/guards'; +import { ComponentPropsWithoutRef, ReactNode, useMemo } from 'react'; import { IconAlertTriangle, IconInfoCircle, @@ -46,7 +46,6 @@ const StyledContainer = styled.div` box-shadow: ${({ theme }) => theme.boxShadow.strong}; box-sizing: border-box; cursor: pointer; - height: 61px; padding: ${({ theme }) => theme.spacing(2)}; position: relative; width: 296px; @@ -90,7 +89,6 @@ const StyledDescription = styled.div` padding-left: ${({ theme }) => theme.spacing(6)}; overflow: hidden; text-overflow: ellipsis; - white-space: nowrap; width: 200px; `; diff --git a/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext.ts index 75b7e1e13588..c9686c2d2ece 100644 --- a/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type SnackBarManagerScopeInternalContextProps = ComponentStateKey; +type SnackBarManagerScopeInternalContextProps = RecoilComponentStateKey; export const SnackBarManagerScopeInternalContext = createScopeInternalContext<SnackBarManagerScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/ui/field/display/components/ArrayDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/ArrayDisplay.tsx new file mode 100644 index 000000000000..4985a0a9af15 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/field/display/components/ArrayDisplay.tsx @@ -0,0 +1,62 @@ +import { + BORDER_COMMON, + OverflowingTextWithTooltip, + THEME_COMMON, +} from 'twenty-ui'; + +import { FieldArrayValue } from '@/object-record/record-field/types/FieldMetadata'; +import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList'; +import styled from '@emotion/styled'; + +type ArrayDisplayProps = { + value: FieldArrayValue; + isFocused?: boolean; + isInputDisplay?: boolean; +}; + +const themeSpacing = THEME_COMMON.spacingMultiplicator; + +const StyledContainer = styled.div` + align-items: center; + display: flex; + gap: ${themeSpacing * 1}px; + justify-content: flex-start; + + max-width: 100%; + + overflow: hidden; + + width: 100%; +`; + +const StyledTag = styled.div<{ isInputDisplay?: boolean }>` + background-color: ${({ theme, isInputDisplay }) => + isInputDisplay ? 'transparent' : theme.background.tertiary}; + padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)}; + border-radius: ${BORDER_COMMON.radius.sm}; + font-weight: ${({ theme }) => theme.font.weight.regular}; +`; + +export const ArrayDisplay = ({ + value, + isFocused, + isInputDisplay = false, +}: ArrayDisplayProps) => { + return isFocused ? ( + <ExpandableList isChipCountDisplayed> + {value?.map((item, index) => ( + <StyledTag key={index}> + <OverflowingTextWithTooltip text={item} /> + </StyledTag> + ))} + </ExpandableList> + ) : ( + <StyledContainer> + {value?.map((item, index) => ( + <StyledTag key={index} isInputDisplay={isInputDisplay}> + <OverflowingTextWithTooltip text={item} /> + </StyledTag> + ))} + </StyledContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/ui/field/display/components/DateDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/DateDisplay.tsx index 982e7a9af07e..767671d62482 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/DateDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/DateDisplay.tsx @@ -1,17 +1,24 @@ import { formatDateISOStringToDate } from '@/localization/utils/formatDateISOStringToDate'; +import { formatDateISOStringToRelativeDate } from '@/localization/utils/formatDateISOStringToRelativeDate'; import { UserContext } from '@/users/contexts/UserContext'; import { useContext } from 'react'; import { EllipsisDisplay } from './EllipsisDisplay'; type DateDisplayProps = { value: string | null | undefined; + displayAsRelativeDate?: boolean; }; -export const DateDisplay = ({ value }: DateDisplayProps) => { +export const DateDisplay = ({ + value, + displayAsRelativeDate, +}: DateDisplayProps) => { const { dateFormat, timeZone } = useContext(UserContext); const formattedDate = value - ? formatDateISOStringToDate(value, timeZone, dateFormat) + ? displayAsRelativeDate + ? formatDateISOStringToRelativeDate(value, true) + : formatDateISOStringToDate(value, timeZone, dateFormat) : ''; return <EllipsisDisplay>{formattedDate}</EllipsisDisplay>; diff --git a/packages/twenty-front/src/modules/ui/field/display/components/DateTimeDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/DateTimeDisplay.tsx index f90e4a0c560c..7f2432639a11 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/DateTimeDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/DateTimeDisplay.tsx @@ -1,17 +1,24 @@ import { formatDateISOStringToDateTime } from '@/localization/utils/formatDateISOStringToDateTime'; +import { formatDateISOStringToRelativeDate } from '@/localization/utils/formatDateISOStringToRelativeDate'; import { UserContext } from '@/users/contexts/UserContext'; import { useContext } from 'react'; import { EllipsisDisplay } from './EllipsisDisplay'; type DateTimeDisplayProps = { value: string | null | undefined; + displayAsRelativeDate?: boolean; }; -export const DateTimeDisplay = ({ value }: DateTimeDisplayProps) => { +export const DateTimeDisplay = ({ + value, + displayAsRelativeDate, +}: DateTimeDisplayProps) => { const { dateFormat, timeFormat, timeZone } = useContext(UserContext); const formattedDate = value - ? formatDateISOStringToDateTime(value, timeZone, dateFormat, timeFormat) + ? displayAsRelativeDate + ? formatDateISOStringToRelativeDate(value) + : formatDateISOStringToDateTime(value, timeZone, dateFormat, timeFormat) : ''; return <EllipsisDisplay>{formattedDate}</EllipsisDisplay>; diff --git a/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx index d18ac35109aa..7c79ac85e7f6 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/PhoneDisplay.tsx @@ -24,7 +24,7 @@ export const PhoneDisplay = ({ value }: PhoneDisplayProps) => { } const URI = parsedPhoneNumber.getURI(); - const formattedNational = parsedPhoneNumber?.formatNational(); + const formatedPhoneNumber = parsedPhoneNumber.formatInternational(); return ( <ContactLink @@ -33,7 +33,7 @@ export const PhoneDisplay = ({ value }: PhoneDisplayProps) => { event.stopPropagation(); }} > - {formattedNational || value} + {formatedPhoneNumber || value} </ContactLink> ); }; diff --git a/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx new file mode 100644 index 000000000000..deee867fc16e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/field/display/components/PhonesDisplay.tsx @@ -0,0 +1,122 @@ +import styled from '@emotion/styled'; +import { useMemo } from 'react'; +import { THEME_COMMON } from 'twenty-ui'; + +import { FieldPhonesValue } from '@/object-record/record-field/types/FieldMetadata'; +import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList'; +import { RoundedLink } from '@/ui/navigation/link/components/RoundedLink'; + +import { parsePhoneNumber } from 'libphonenumber-js'; +import { isDefined } from '~/utils/isDefined'; +import { logError } from '~/utils/logError'; + +type PhonesDisplayProps = { + value?: FieldPhonesValue; + isFocused?: boolean; +}; + +const themeSpacing = THEME_COMMON.spacingMultiplicator; + +const StyledContainer = styled.div` + align-items: center; + display: flex; + gap: ${themeSpacing * 1}px; + justify-content: flex-start; + + max-width: 100%; + + overflow: hidden; + + width: 100%; +`; + +export const PhonesDisplay = ({ value, isFocused }: PhonesDisplayProps) => { + const phones = useMemo( + () => + [ + value?.primaryPhoneNumber + ? { + number: value.primaryPhoneNumber, + countryCode: value.primaryPhoneCountryCode, + } + : null, + ...parseAdditionalPhones(value?.additionalPhones), + ] + .filter(isDefined) + .map(({ number, countryCode }) => { + return { + number, + countryCode, + }; + }), + [ + value?.primaryPhoneNumber, + value?.primaryPhoneCountryCode, + value?.additionalPhones, + ], + ); + + const parsePhoneNumberOrReturnInvalidValue = (number: string) => { + try { + return { parsedPhone: parsePhoneNumber(number) }; + } catch (e) { + return { invalidPhone: number }; + } + }; + + return isFocused ? ( + <ExpandableList isChipCountDisplayed> + {phones.map(({ number, countryCode }, index) => { + const { parsedPhone, invalidPhone } = + parsePhoneNumberOrReturnInvalidValue(countryCode + number); + const URI = parsedPhone?.getURI(); + return ( + <RoundedLink + key={index} + href={URI || ''} + label={ + parsedPhone ? parsedPhone.formatInternational() : invalidPhone + } + /> + ); + })} + </ExpandableList> + ) : ( + <StyledContainer> + {phones.map(({ number, countryCode }, index) => { + const { parsedPhone, invalidPhone } = + parsePhoneNumberOrReturnInvalidValue(countryCode + number); + const URI = parsedPhone?.getURI(); + return ( + <RoundedLink + key={index} + href={URI || ''} + label={ + parsedPhone ? parsedPhone.formatInternational() : invalidPhone + } + /> + ); + })} + </StyledContainer> + ); +}; + +const parseAdditionalPhones = (additionalPhones?: any) => { + if (!additionalPhones) { + return []; + } + + if (typeof additionalPhones === 'object') { + return additionalPhones; + } + + if (typeof additionalPhones === 'string') { + try { + return JSON.parse(additionalPhones); + } catch (error) { + logError(`Error parsing additional phones' : ` + error); + } + } + + return []; +}; diff --git a/packages/twenty-front/src/modules/ui/field/input/components/AddressInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/AddressInput.tsx index 5067405a43e0..e54de48bb274 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/AddressInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/AddressInput.tsx @@ -1,5 +1,5 @@ -import { RefObject, useEffect, useRef, useState } from 'react'; import styled from '@emotion/styled'; +import { RefObject, useEffect, useRef, useState } from 'react'; import { Key } from 'ts-key-enum'; import { FieldAddressDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue'; @@ -8,6 +8,7 @@ import { CountrySelect } from '@/ui/input/components/internal/country/components import { TextInputV2 } from '@/ui/input/components/TextInputV2'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; +import { MOBILE_VIEWPORT } from 'twenty-ui'; import { isDefined } from '~/utils/isDefined'; const StyledAddressContainer = styled.div` @@ -23,11 +24,27 @@ const StyledAddressContainer = styled.div` > div { margin-bottom: 6px; } + + @media (max-width: ${MOBILE_VIEWPORT}px) { + min-width: 100px; + max-width: 200px; + overflow: hidden; + > div { + margin-bottom: 8px; + } + } `; const StyledHalfRowContainer = styled.div` display: flex; gap: 8px; + + @media (max-width: ${MOBILE_VIEWPORT}px) { + display: block; + > div { + margin-bottom: 7px; + } + } `; export type AddressInputProps = { diff --git a/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx index c0e312a92184..c003bde596c5 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/DoubleTextInput.tsx @@ -13,6 +13,8 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { isDefined } from '~/utils/isDefined'; +import { splitFullName } from '~/utils/format/spiltFullName'; +import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; import { StyledTextInput } from './TextInput'; const StyledContainer = styled.div` @@ -167,9 +169,19 @@ export const DoubleTextInput = ({ const name = event.clipboardData.getData('Text'); - const splittedName = name.split(' '); + const splittedName = splitFullName(name); - onPaste?.({ firstValue: splittedName[0], secondValue: splittedName[1] }); + onPaste?.({ + firstValue: splittedName[0], + secondValue: splittedName[1], + }); + }; + + const handleClickToPreventParentClickEvents = ( + event: React.MouseEvent<HTMLInputElement>, + ) => { + event.stopPropagation(); + event.preventDefault(); }; return ( @@ -182,11 +194,15 @@ export const DoubleTextInput = ({ placeholder={firstValuePlaceholder} value={firstInternalValue} onChange={(event: ChangeEvent<HTMLInputElement>) => { - handleChange(event.target.value, secondInternalValue); + handleChange( + turnIntoEmptyStringIfWhitespacesOnly(event.target.value), + secondInternalValue, + ); }} onPaste={(event: ClipboardEvent<HTMLInputElement>) => handleOnPaste(event) } + onClick={handleClickToPreventParentClickEvents} /> <StyledTextInput autoComplete="off" @@ -195,8 +211,12 @@ export const DoubleTextInput = ({ placeholder={secondValuePlaceholder} value={secondInternalValue} onChange={(event: ChangeEvent<HTMLInputElement>) => { - handleChange(firstInternalValue, event.target.value); + handleChange( + firstInternalValue, + turnIntoEmptyStringIfWhitespacesOnly(event.target.value), + ); }} + onClick={handleClickToPreventParentClickEvents} /> </StyledContainer> ); diff --git a/packages/twenty-front/src/modules/ui/field/input/components/TextAreaInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/TextAreaInput.tsx index b9a08ef1f87c..c2da43576095 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/TextAreaInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/TextAreaInput.tsx @@ -1,11 +1,12 @@ +import styled from '@emotion/styled'; import { ChangeEvent, useEffect, useRef, useState } from 'react'; import TextareaAutosize from 'react-textarea-autosize'; -import styled from '@emotion/styled'; import { TEXT_INPUT_STYLE } from 'twenty-ui'; import { LightCopyIconButton } from '@/object-record/record-field/components/LightCopyIconButton'; import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents'; import { isDefined } from '~/utils/isDefined'; +import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; export type TextAreaInputProps = { disabled?: boolean; @@ -67,10 +68,12 @@ export const TextAreaInput = ({ copyButton = true, }: TextAreaInputProps) => { const [internalText, setInternalText] = useState(value); - const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => { - setInternalText(event.target.value); - onChange?.(event.target.value); + const targetValue = turnIntoEmptyStringIfWhitespacesOnly( + event.target.value, + ); + setInternalText(targetValue); + onChange?.(targetValue); }; const wrapperRef = useRef<HTMLTextAreaElement>(null); diff --git a/packages/twenty-front/src/modules/ui/field/input/components/TextInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/TextInput.tsx index 1490e1f7d587..b932cbdc5fab 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/TextInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/TextInput.tsx @@ -1,5 +1,5 @@ -import { ChangeEvent, useEffect, useRef, useState } from 'react'; import styled from '@emotion/styled'; +import { ChangeEvent, useEffect, useRef, useState } from 'react'; import { TEXT_INPUT_STYLE } from 'twenty-ui'; import { LightCopyIconButton } from '@/object-record/record-field/components/LightCopyIconButton'; @@ -44,12 +44,11 @@ export const TextInput = ({ const copyRef = useRef<HTMLDivElement>(null); const handleChange = (event: ChangeEvent<HTMLInputElement>) => { - setInternalText(event.target.value); - onChange?.(event.target.value); + setInternalText(event.target.value.trim()); + onChange?.(event.target.value.trim()); }; - useEffect(() => { - setInternalText(value); + setInternalText(value.trim()); }, [value]); useRegisterInputEvents({ diff --git a/packages/twenty-front/src/modules/ui/input/button/components/IconButton.tsx b/packages/twenty-front/src/modules/ui/input/button/components/IconButton.tsx index 421962c878be..e5e83551cdcc 100644 --- a/packages/twenty-front/src/modules/ui/input/button/components/IconButton.tsx +++ b/packages/twenty-front/src/modules/ui/input/button/components/IconButton.tsx @@ -1,6 +1,6 @@ -import React from 'react'; import { css, useTheme } from '@emotion/react'; import styled from '@emotion/styled'; +import React from 'react'; import { IconComponent } from 'twenty-ui'; export type IconButtonSize = 'medium' | 'small'; @@ -233,7 +233,7 @@ const StyledButton = styled.button< white-space: nowrap; - width: ${({ size }) => (size === 'small' ? '24px' : '32px')}; + min-width: ${({ size }) => (size === 'small' ? '24px' : '32px')}; &:focus { outline: none; diff --git a/packages/twenty-front/src/modules/ui/input/code-editor/components/CodeEditor.tsx b/packages/twenty-front/src/modules/ui/input/code-editor/components/CodeEditor.tsx index 6f99e8310bab..3c24d62cdef8 100644 --- a/packages/twenty-front/src/modules/ui/input/code-editor/components/CodeEditor.tsx +++ b/packages/twenty-front/src/modules/ui/input/code-editor/components/CodeEditor.tsx @@ -1,9 +1,12 @@ import Editor, { Monaco, EditorProps } from '@monaco-editor/react'; +import { AutoTypings } from 'monaco-editor-auto-typings'; import { editor, MarkerSeverity } from 'monaco-editor'; import { codeEditorTheme } from '@/ui/input/code-editor/theme/CodeEditorTheme'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useEffect } from 'react'; +import { useGetAvailablePackages } from '@/settings/serverless-functions/hooks/useGetAvailablePackages'; +import { isDefined } from '~/utils/isDefined'; export const DEFAULT_CODE = `export const handler = async ( event: object, @@ -38,12 +41,24 @@ export const CodeEditor = ({ }: CodeEditorProps) => { const theme = useTheme(); - const handleEditorDidMount = ( + const { availablePackages } = useGetAvailablePackages(); + + const handleEditorDidMount = async ( editor: editor.IStandaloneCodeEditor, monaco: Monaco, ) => { monaco.editor.defineTheme('codeEditorTheme', codeEditorTheme(theme)); monaco.editor.setTheme('codeEditorTheme'); + + if (language === 'typescript') { + await AutoTypings.create(editor, { + monaco, + preloadPackages: true, + onlySpecifiedPackages: true, + versions: availablePackages, + debounceDuration: 0, + }); + } }; const handleEditorValidation = (markers: editor.IMarker[]) => { @@ -68,28 +83,31 @@ export const CodeEditor = ({ document.head.removeChild(style); }; }, []); + return ( - <div> - {header} - <StyledEditor - height={height} - language={language} - value={value} - onMount={handleEditorDidMount} - onChange={(value?: string) => value && onChange?.(value)} - onValidate={handleEditorValidation} - options={{ - ...options, - overviewRulerLanes: 0, - scrollbar: { - vertical: 'hidden', - horizontal: 'hidden', - }, - minimap: { - enabled: false, - }, - }} - /> - </div> + isDefined(availablePackages) && ( + <> + {header} + <StyledEditor + height={height} + language={language} + value={value} + onMount={handleEditorDidMount} + onChange={(value?: string) => value && onChange?.(value)} + onValidate={handleEditorValidation} + options={{ + ...options, + overviewRulerLanes: 0, + scrollbar: { + vertical: 'hidden', + horizontal: 'hidden', + }, + minimap: { + enabled: false, + }, + }} + /> + </> + ) ); }; diff --git a/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx b/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx index 00daf1cff11e..85bb45a675aa 100644 --- a/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx +++ b/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemeCard.tsx @@ -41,7 +41,7 @@ const StyledColorSchemeBackground = styled.div< overflow: hidden; padding-left: ${({ theme }) => theme.spacing(6)}; padding-top: ${({ theme }) => theme.spacing(6)}; - width: 120px; + width: 160px; `; const StyledColorSchemeContent = styled(motion.div)< @@ -120,7 +120,7 @@ const ColorSchemeSegment = ({ const StyledContainer = styled.div` position: relative; - width: 120px; + width: 160px; `; const StyledMixedColorSchemeSegment = styled.div` @@ -130,7 +130,7 @@ const StyledMixedColorSchemeSegment = styled.div` height: 80px; overflow: hidden; position: relative; - width: 120px; + width: 160px; `; const StyledCheckmarkContainer = styled(motion.div)` diff --git a/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx b/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx index 71e900ab42f4..4835fab24755 100644 --- a/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx +++ b/packages/twenty-front/src/modules/ui/input/color-scheme/components/ColorSchemePicker.tsx @@ -4,6 +4,7 @@ import styled from '@emotion/styled'; import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; import { ColorSchemeCard } from './ColorSchemeCard'; +import { MOBILE_VIEWPORT } from 'twenty-ui'; const StyledContainer = styled.div` display: flex; @@ -11,6 +12,9 @@ const StyledContainer = styled.div` > * + * { margin-left: ${({ theme }) => theme.spacing(4)}; } + @media (max-width: ${MOBILE_VIEWPORT}px) { + overflow: scroll; + } `; const StyledCardContainer = styled.div` diff --git a/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx b/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx index df318dd3b6e7..77779acc58ae 100644 --- a/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/ImageInput.tsx @@ -1,8 +1,7 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import React, { useMemo } from 'react'; -import { IconFileUpload, IconTrash, IconUpload, IconX } from 'twenty-ui'; - +import { IconPhotoUp, IconTrash, IconUpload, IconX } from 'twenty-ui'; import { Button } from '@/ui/input/button/components/Button'; import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI'; import { isDefined } from '~/utils/isDefined'; @@ -15,8 +14,8 @@ const StyledContainer = styled.div` const StyledPicture = styled.button<{ withPicture: boolean }>` align-items: center; background: ${({ theme, disabled }) => - disabled ? theme.background.secondary : theme.background.tertiary}; - border: none; + disabled ? theme.background.secondary : theme.background.transparent.light}; + border: 1px solid ${({ theme }) => theme.border.color.medium}; border-radius: ${({ theme }) => theme.border.radius.sm}; color: ${({ theme }) => theme.font.color.light}; cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')}; @@ -35,6 +34,10 @@ const StyledPicture = styled.button<{ withPicture: boolean }>` width: 100%; } + &:hover svg { + color: ${({ theme }) => theme.font.color.tertiary}; + } + ${({ theme, withPicture, disabled }) => { if ((withPicture || disabled) === true) { return ''; @@ -42,7 +45,7 @@ const StyledPicture = styled.button<{ withPicture: boolean }>` return ` &:hover { - background: ${theme.background.quaternary}; + background: ${theme.background.transparent.medium}; } `; }}; @@ -52,16 +55,17 @@ const StyledContent = styled.div` display: flex; flex: 1; flex-direction: column; - justify-content: space-between; + justify-content: start; margin-left: ${({ theme }) => theme.spacing(4)}; + + gap: ${({ theme }) => theme.spacing(3)}; `; const StyledButtonContainer = styled.div` display: flex; flex-direction: row; - > * + * { - margin-left: ${({ theme }) => theme.spacing(2)}; - } + + gap: ${({ theme }) => theme.spacing(2)}; `; const StyledText = styled.span` @@ -121,7 +125,7 @@ export const ImageInput = ({ alt="profile" /> ) : ( - <IconFileUpload size={theme.icon.size.md} /> + <IconPhotoUp size={theme.icon.size.lg} /> )} </StyledPicture> <StyledContent> @@ -143,7 +147,6 @@ export const ImageInput = ({ variant="secondary" title="Abort" disabled={!pictureURI || disabled} - fullWidth /> ) : ( <Button @@ -152,7 +155,6 @@ export const ImageInput = ({ variant="secondary" title="Upload" disabled={disabled} - fullWidth /> )} <Button @@ -161,7 +163,6 @@ export const ImageInput = ({ variant="secondary" title="Remove" disabled={!pictureURI || disabled} - fullWidth /> </StyledButtonContainer> <StyledText> diff --git a/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx b/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx index aee5943e6e16..9b50504c757b 100644 --- a/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/TextArea.tsx @@ -1,9 +1,10 @@ +import styled from '@emotion/styled'; import { FocusEventHandler } from 'react'; import TextareaAutosize from 'react-textarea-autosize'; -import styled from '@emotion/styled'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; +import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; import { InputHotkeyScope } from '../types/InputHotkeyScope'; const MAX_ROWS = 5; @@ -75,7 +76,9 @@ export const TextArea = ({ maxRows={MAX_ROWS} minRows={computedMinRows} value={value} - onChange={(event) => onChange?.(event.target.value)} + onChange={(event) => + onChange?.(turnIntoEmptyStringIfWhitespacesOnly(event.target.value)) + } onFocus={handleFocus} onBlur={handleBlur} disabled={disabled} diff --git a/packages/twenty-front/src/modules/ui/input/components/TextInput.tsx b/packages/twenty-front/src/modules/ui/input/components/TextInput.tsx index d856c37faf37..b0841eaa710f 100644 --- a/packages/twenty-front/src/modules/ui/input/components/TextInput.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/TextInput.tsx @@ -13,6 +13,7 @@ import { isDefined } from '~/utils/isDefined'; export type TextInputProps = TextInputV2ComponentProps & { disableHotkeys?: boolean; onInputEnter?: () => void; + dataTestId?: string; focused?: boolean; }; @@ -22,6 +23,7 @@ export const TextInput = ({ onInputEnter, disableHotkeys = false, focused, + dataTestId, ...props }: TextInputProps) => { const inputRef = useRef<HTMLInputElement>(null); @@ -87,7 +89,6 @@ export const TextInput = ({ onInputEnter?.(); if (isDefined(inputRef) && 'current' in inputRef) { - inputRef.current?.blur(); setIsFocused(false); } }, @@ -103,6 +104,7 @@ export const TextInput = ({ ref={inputRef} // eslint-disable-next-line react/jsx-props-no-spreading {...props} + dataTestId={dataTestId} onFocus={handleFocus} onBlur={handleBlur} /> diff --git a/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx b/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx index ca88e8ad4cba..cf4b06f6aba9 100644 --- a/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx @@ -11,6 +11,7 @@ import { } from 'react'; import { IconComponent, IconEye, IconEyeOff } from 'twenty-ui'; import { useCombinedRefs } from '~/hooks/useCombinedRefs'; +import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; const StyledContainer = styled.div< Pick<TextInputV2ComponentProps, 'fullWidth'> @@ -127,6 +128,7 @@ export type TextInputV2ComponentProps = Omit< LeftIcon?: IconComponent; onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void; onBlur?: FocusEventHandler<HTMLInputElement>; + dataTestId?: string; }; const TextInputV2Component = ( @@ -151,6 +153,7 @@ const TextInputV2Component = ( LeftIcon, autoComplete, maxLength, + dataTestId, }: TextInputV2ComponentProps, // eslint-disable-next-line @nx/workspace-component-props-naming ref: ForwardedRef<HTMLInputElement>, @@ -178,6 +181,7 @@ const TextInputV2Component = ( </StyledLeftIconContainer> )} <StyledInput + data-testid={dataTestId} autoComplete={autoComplete || 'off'} ref={combinedRef} tabIndex={tabIndex ?? 0} @@ -185,7 +189,9 @@ const TextInputV2Component = ( onBlur={onBlur} type={passwordVisible ? 'text' : type} onChange={(event: ChangeEvent<HTMLInputElement>) => { - onChange?.(event.target.value); + onChange?.( + turnIntoEmptyStringIfWhitespacesOnly(event.target.value), + ); }} onKeyDown={onKeyDown} {...{ diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/AbsoluteDatePickerHeader.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/AbsoluteDatePickerHeader.tsx new file mode 100644 index 000000000000..1efc985d34f6 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/AbsoluteDatePickerHeader.tsx @@ -0,0 +1,108 @@ +import styled from '@emotion/styled'; +import { DateTime } from 'luxon'; +import { IconChevronLeft, IconChevronRight } from 'twenty-ui'; + +import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; +import { Select } from '@/ui/input/components/Select'; +import { DateTimeInput } from '@/ui/input/components/internal/date/components/DateTimeInput'; + +import { getMonthSelectOptions } from '@/ui/input/components/internal/date/utils/getMonthSelectOptions'; +import { + MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, + MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID, +} from './InternalDatePicker'; + +const StyledCustomDatePickerHeader = styled.div` + align-items: center; + display: flex; + justify-content: flex-end; + padding-left: ${({ theme }) => theme.spacing(2)}; + padding-right: ${({ theme }) => theme.spacing(2)}; + padding-top: ${({ theme }) => theme.spacing(2)}; + + gap: ${({ theme }) => theme.spacing(1)}; +`; + +const years = Array.from( + { length: 200 }, + (_, i) => new Date().getFullYear() + 5 - i, +).map((year) => ({ label: year.toString(), value: year })); + +type AbsoluteDatePickerHeaderProps = { + date: Date; + onChange?: (date: Date | null) => void; + onChangeMonth: (month: number) => void; + onChangeYear: (year: number) => void; + onAddMonth: () => void; + onSubtractMonth: () => void; + prevMonthButtonDisabled: boolean; + nextMonthButtonDisabled: boolean; + isDateTimeInput?: boolean; + timeZone: string; +}; + +export const AbsoluteDatePickerHeader = ({ + date, + onChange, + onChangeMonth, + onChangeYear, + onAddMonth, + onSubtractMonth, + prevMonthButtonDisabled, + nextMonthButtonDisabled, + isDateTimeInput, + timeZone, +}: AbsoluteDatePickerHeaderProps) => { + const endOfDayDateTimeInLocalTimezone = DateTime.now().set({ + day: date.getDate(), + month: date.getMonth() + 1, + year: date.getFullYear(), + hour: 23, + minute: 59, + second: 59, + millisecond: 999, + }); + + const endOfDayInLocalTimezone = endOfDayDateTimeInLocalTimezone.toJSDate(); + + return ( + <> + <DateTimeInput + date={date} + isDateTimeInput={isDateTimeInput} + onChange={onChange} + userTimezone={timeZone} + /> + <StyledCustomDatePickerHeader> + <Select + dropdownId={MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID} + options={getMonthSelectOptions()} + disableBlur + onChange={onChangeMonth} + value={endOfDayInLocalTimezone.getMonth()} + fullWidth + /> + <Select + dropdownId={MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID} + onChange={onChangeYear} + value={endOfDayInLocalTimezone.getFullYear()} + options={years} + disableBlur + fullWidth + /> + <LightIconButton + Icon={IconChevronLeft} + onClick={onSubtractMonth} + size="medium" + disabled={prevMonthButtonDisabled} + /> + <LightIconButton + Icon={IconChevronRight} + onClick={onAddMonth} + size="medium" + disabled={nextMonthButtonDisabled} + /> + </StyledCustomDatePickerHeader> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx index a3004373d059..e7a330c81ff3 100644 --- a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx @@ -2,52 +2,32 @@ import styled from '@emotion/styled'; import { DateTime } from 'luxon'; import ReactDatePicker from 'react-datepicker'; import { Key } from 'ts-key-enum'; -import { - IconCalendarX, - IconChevronLeft, - IconChevronRight, - OVERLAY_BACKGROUND, -} from 'twenty-ui'; +import { IconCalendarX, OVERLAY_BACKGROUND } from 'twenty-ui'; -import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { DateTimeInput } from '@/ui/input/components/internal/date/components/DateTimeInput'; -import { Select } from '@/ui/input/components/Select'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItemLeftContent } from '@/ui/navigation/menu-item/internals/components/MenuItemLeftContent'; import { StyledHoverableMenuItemBase } from '@/ui/navigation/menu-item/internals/components/StyledMenuItemBase'; import { isDefined } from '~/utils/isDefined'; +import { AbsoluteDatePickerHeader } from '@/ui/input/components/internal/date/components/AbsoluteDatePickerHeader'; +import { RelativeDatePickerHeader } from '@/ui/input/components/internal/date/components/RelativeDatePickerHeader'; +import { getHighlightedDates } from '@/ui/input/components/internal/date/utils/getHighlightedDates'; import { UserContext } from '@/users/contexts/UserContext'; +import { + VariableDateViewFilterValueDirection, + VariableDateViewFilterValueUnit, +} from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; import { useContext } from 'react'; import 'react-datepicker/dist/react-datepicker.css'; -const months = [ - { label: 'January', value: 0 }, - { label: 'February', value: 1 }, - { label: 'March', value: 2 }, - { label: 'April', value: 3 }, - { label: 'May', value: 4 }, - { label: 'June', value: 5 }, - { label: 'July', value: 6 }, - { label: 'August', value: 7 }, - { label: 'September', value: 8 }, - { label: 'October', value: 9 }, - { label: 'November', value: 10 }, - { label: 'December', value: 11 }, -]; - -const years = Array.from( - { length: 200 }, - (_, i) => new Date().getFullYear() + 5 - i, -).map((year) => ({ label: year.toString(), value: year })); - export const MONTH_AND_YEAR_DROPDOWN_ID = 'date-picker-month-and-year-dropdown'; export const MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID = 'date-picker-month-and-year-dropdown-month-select'; export const MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID = 'date-picker-month-and-year-dropdown-year-select'; -const StyledContainer = styled.div` +const StyledContainer = styled.div<{ calendarDisabled?: boolean }>` & .react-datepicker { border-color: ${({ theme }) => theme.border.color.light}; background: transparent; @@ -207,6 +187,10 @@ const StyledContainer = styled.div` & .react-datepicker__month { margin-top: 0; + + pointer-events: ${({ calendarDisabled }) => + calendarDisabled ? 'none' : 'auto'}; + opacity: ${({ calendarDisabled }) => (calendarDisabled ? '0.5' : '1')}; } & .react-datepicker__day { @@ -288,21 +272,27 @@ const StyledButton = styled(MenuItemLeftContent)` justify-content: start; `; -const StyledCustomDatePickerHeader = styled.div` - align-items: center; - display: flex; - justify-content: flex-end; - padding-left: ${({ theme }) => theme.spacing(2)}; - padding-right: ${({ theme }) => theme.spacing(2)}; - padding-top: ${({ theme }) => theme.spacing(2)}; - - gap: ${({ theme }) => theme.spacing(1)}; -`; - type InternalDatePickerProps = { + isRelative?: boolean; date: Date | null; + relativeDate?: { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; + }; + highlightedDateRange?: { + start: Date; + end: Date; + }; onMouseSelect?: (date: Date | null) => void; onChange?: (date: Date | null) => void; + onRelativeDateChange?: ( + relativeDate: { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; + } | null, + ) => void; clearable?: boolean; isDateTimeInput?: boolean; onEnter?: (date: Date | null) => void; @@ -321,6 +311,10 @@ export const InternalDatePicker = ({ isDateTimeInput, keyboardEventsDisabled, onClear, + isRelative, + relativeDate, + onRelativeDateChange, + highlightedDateRange, }: InternalDatePickerProps) => { const internalDate = date ?? new Date(); @@ -469,15 +463,20 @@ export const InternalDatePicker = ({ const dateToUse = isDateTimeInput ? endOfDayInLocalTimezone : dateWithoutTime; + const highlightedDates = getHighlightedDates(highlightedDateRange); + + const selectedDates = isRelative ? highlightedDates : [dateToUse]; + return ( - <StyledContainer onKeyDown={handleKeyDown}> + <StyledContainer onKeyDown={handleKeyDown} calendarDisabled={isRelative}> <div className={clearable ? 'clearable ' : ''}> <ReactDatePicker open={true} selected={dateToUse} + selectedDates={selectedDates} openToDate={isDefined(dateToUse) ? dateToUse : undefined} disabledKeyboardNavigation - onChange={handleDateChange} + onChange={handleDateChange as any} customInput={ <DateTimeInput date={internalDate} @@ -489,47 +488,31 @@ export const InternalDatePicker = ({ renderCustomHeader={({ prevMonthButtonDisabled, nextMonthButtonDisabled, - }) => ( - <> - <DateTimeInput + }) => + isRelative ? ( + <RelativeDatePickerHeader + direction={relativeDate?.direction ?? 'PAST'} + amount={relativeDate?.amount} + unit={relativeDate?.unit ?? 'DAY'} + onChange={onRelativeDateChange} + /> + ) : ( + <AbsoluteDatePickerHeader date={internalDate} - isDateTimeInput={isDateTimeInput} onChange={onChange} - userTimezone={timeZone} + onChangeMonth={handleChangeMonth} + onChangeYear={handleChangeYear} + onAddMonth={handleAddMonth} + onSubtractMonth={handleSubtractMonth} + prevMonthButtonDisabled={prevMonthButtonDisabled} + nextMonthButtonDisabled={nextMonthButtonDisabled} + isDateTimeInput={isDateTimeInput} + timeZone={timeZone} /> - <StyledCustomDatePickerHeader> - <Select - dropdownId={MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID} - options={months} - disableBlur - onChange={handleChangeMonth} - value={endOfDayInLocalTimezone.getMonth()} - fullWidth - /> - <Select - dropdownId={MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID} - onChange={handleChangeYear} - value={endOfDayInLocalTimezone.getFullYear()} - options={years} - disableBlur - fullWidth - /> - <LightIconButton - Icon={IconChevronLeft} - onClick={handleSubtractMonth} - size="medium" - disabled={prevMonthButtonDisabled} - /> - <LightIconButton - Icon={IconChevronRight} - onClick={handleAddMonth} - size="medium" - disabled={nextMonthButtonDisabled} - /> - </StyledCustomDatePickerHeader> - </> - )} + ) + } onSelect={handleDateSelect} + selectsMultiple={isRelative} /> </div> {clearable && ( diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx new file mode 100644 index 000000000000..0a9328577dba --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx @@ -0,0 +1,113 @@ +import { RELATIVE_DATE_DIRECTION_SELECT_OPTIONS } from '@/ui/input/components/internal/date/constants/RelativeDateDirectionSelectOptions'; +import { RELATIVE_DATE_UNITS_SELECT_OPTIONS } from '@/ui/input/components/internal/date/constants/RelativeDateUnitSelectOptions'; +import { Select } from '@/ui/input/components/Select'; +import { TextInput } from '@/ui/input/components/TextInput'; +import { + VariableDateViewFilterValueDirection, + variableDateViewFilterValuePartsSchema, + VariableDateViewFilterValueUnit, +} from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; +import styled from '@emotion/styled'; +import { useEffect, useState } from 'react'; + +const StyledContainer = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.spacing(1)}; + padding: ${({ theme }) => theme.spacing(2)}; + padding-bottom: 0; +`; + +type RelativeDatePickerHeaderProps = { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; + onChange?: (value: { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; + }) => void; +}; + +export const RelativeDatePickerHeader = ( + props: RelativeDatePickerHeaderProps, +) => { + const [direction, setDirection] = useState(props.direction); + const [amountString, setAmountString] = useState( + props.amount ? props.amount.toString() : '', + ); + const [unit, setUnit] = useState(props.unit); + + useEffect(() => { + setAmountString(props.amount ? props.amount.toString() : ''); + setUnit(props.unit); + setDirection(props.direction); + }, [props.amount, props.unit, props.direction]); + + const textInputValue = direction === 'THIS' ? '' : amountString; + const textInputPlaceholder = direction === 'THIS' ? '-' : 'Number'; + + const isUnitPlural = props.amount && props.amount > 1 && direction !== 'THIS'; + const unitSelectOptions = RELATIVE_DATE_UNITS_SELECT_OPTIONS.map((unit) => ({ + ...unit, + label: `${unit.label}${isUnitPlural ? 's' : ''}`, + })); + + return ( + <StyledContainer> + <Select + disableBlur + dropdownId="direction-select" + value={direction} + onChange={(newDirection) => { + setDirection(newDirection); + if (props.amount === undefined && newDirection !== 'THIS') return; + props.onChange?.({ + direction: newDirection, + amount: props.amount, + unit: unit, + }); + }} + options={RELATIVE_DATE_DIRECTION_SELECT_OPTIONS} + /> + <TextInput + value={textInputValue} + onChange={(text) => { + const amountString = text.replace(/[^0-9]|^0+/g, ''); + const amount = parseInt(amountString); + + setAmountString(amountString); + + const valueParts = { + direction, + amount, + unit, + }; + + if ( + variableDateViewFilterValuePartsSchema.safeParse(valueParts).success + ) { + props.onChange?.(valueParts); + } + }} + placeholder={textInputPlaceholder} + disabled={direction === 'THIS'} + /> + <Select + disableBlur + dropdownId="unit-select" + value={unit} + onChange={(newUnit) => { + setUnit(newUnit); + if (direction !== 'THIS' && props.amount === undefined) return; + props.onChange?.({ + direction, + amount: props.amount, + unit: newUnit, + }); + }} + options={unitSelectOptions} + /> + </StyledContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateDirectionSelectOptions.ts b/packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateDirectionSelectOptions.ts new file mode 100644 index 000000000000..d13926719f0f --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateDirectionSelectOptions.ts @@ -0,0 +1,13 @@ +import { VariableDateViewFilterValueDirection } from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; + +type RelativeDateDirectionOption = { + value: VariableDateViewFilterValueDirection; + label: string; +}; + +export const RELATIVE_DATE_DIRECTION_SELECT_OPTIONS: RelativeDateDirectionOption[] = + [ + { value: 'PAST', label: 'Past' }, + { value: 'THIS', label: 'This' }, + { value: 'NEXT', label: 'Next' }, + ]; diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateUnitSelectOptions.ts b/packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateUnitSelectOptions.ts new file mode 100644 index 000000000000..bf65953f63bc --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/constants/RelativeDateUnitSelectOptions.ts @@ -0,0 +1,13 @@ +import { VariableDateViewFilterValueUnit } from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; + +type RelativeDateUnit = { + value: VariableDateViewFilterValueUnit; + label: string; +}; + +export const RELATIVE_DATE_UNITS_SELECT_OPTIONS: RelativeDateUnit[] = [ + { value: 'DAY', label: 'Day' }, + { value: 'WEEK', label: 'Week' }, + { value: 'MONTH', label: 'Month' }, + { value: 'YEAR', label: 'Year' }, +]; diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getHighlightedDates.ts b/packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getHighlightedDates.ts new file mode 100644 index 000000000000..813b36996833 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getHighlightedDates.ts @@ -0,0 +1,24 @@ +import { addDays, addMonths, startOfDay, subMonths } from 'date-fns'; + +export const getHighlightedDates = (highlightedDateRange?: { + start: Date; + end: Date; +}): Date[] => { + if (!highlightedDateRange) return []; + const { start, end } = highlightedDateRange; + + const highlightedDates: Date[] = []; + const currentDate = startOfDay(new Date()); + const minDate = subMonths(currentDate, 2); + const maxDate = addMonths(currentDate, 2); + + let dateToHighlight = start < minDate ? minDate : start; + const lastDate = end > maxDate ? maxDate : end; + + while (dateToHighlight <= lastDate) { + highlightedDates.push(dateToHighlight); + dateToHighlight = addDays(dateToHighlight, 1); + } + + return highlightedDates; +}; diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getMonthSelectOptions.ts b/packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getMonthSelectOptions.ts new file mode 100644 index 000000000000..3f5e395174ee --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/utils/getMonthSelectOptions.ts @@ -0,0 +1,16 @@ +const getMonthName = (index: number): string => + new Intl.DateTimeFormat('en-US', { month: 'long' }).format( + new Date(0, index, 1), + ); + +const getMonthNames = (monthNames: string[] = []): string[] => { + if (monthNames.length === 12) return monthNames; + + return getMonthNames([...monthNames, getMonthName(monthNames.length)]); +}; + +export const getMonthSelectOptions = (): { label: string; value: number }[] => + getMonthNames().map((month, index) => ({ + label: month, + value: index, + })); diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownSelect.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownSelect.tsx index b651d38007e6..d5f46a71a2c7 100644 --- a/packages/twenty-front/src/modules/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownSelect.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/internal/phone/components/PhoneCountryPickerDropdownSelect.tsx @@ -48,7 +48,7 @@ export const PhoneCountryPickerDropdownSelect = ({ ); return ( - <DropdownMenu width="200px" disableBlur> + <DropdownMenu width="auto" disableBlur> <DropdownMenuSearchInput value={searchFilter} onChange={(event) => setSearchFilter(event.currentTarget.value)} diff --git a/packages/twenty-front/src/modules/ui/input/editor/components/BlockEditor.tsx b/packages/twenty-front/src/modules/ui/input/editor/components/BlockEditor.tsx index a6732a34f4b8..f2a940de52bd 100644 --- a/packages/twenty-front/src/modules/ui/input/editor/components/BlockEditor.tsx +++ b/packages/twenty-front/src/modules/ui/input/editor/components/BlockEditor.tsx @@ -93,6 +93,16 @@ const StyledEditor = styled.div` & .bn-color-picker-dropdown { margin-left: 8px; } + + & .bn-inline-content code { + font-family: monospace; + color: ${({ theme }) => theme.font.color.danger}; + padding: 2px 4px; + border-radius: 4px; + border: 1px solid ${({ theme }) => theme.font.color.extraLight}; + font-size: 0.9rem; + background-color: ${({ theme }) => theme.background.transparent.light}; + } `; export const BlockEditor = ({ diff --git a/packages/twenty-front/src/modules/ui/input/hooks/useInputFocusWithoutScrollOnMount.ts b/packages/twenty-front/src/modules/ui/input/hooks/useInputFocusWithoutScrollOnMount.ts new file mode 100644 index 000000000000..a771bcd6e238 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/input/hooks/useInputFocusWithoutScrollOnMount.ts @@ -0,0 +1,14 @@ +import { useEffect, useRef } from 'react'; +import { isDefined } from 'twenty-ui'; + +export const useInputFocusWithoutScrollOnMount = () => { + const inputRef = useRef<HTMLInputElement>(null); + + useEffect(() => { + if (isDefined(inputRef.current)) { + inputRef.current.focus({ preventScroll: true }); + } + }); + + return { inputRef }; +}; diff --git a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/components/AnimatedPlaceholder.tsx b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/components/AnimatedPlaceholder.tsx index cd173e0aeaea..49c69778856e 100644 --- a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/components/AnimatedPlaceholder.tsx +++ b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/components/AnimatedPlaceholder.tsx @@ -1,7 +1,7 @@ -import { useEffect } from 'react'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { animate, motion, useMotionValue, useTransform } from 'framer-motion'; +import { useEffect } from 'react'; import { BACKGROUND } from '@/ui/layout/animated-placeholder/constants/Background'; import { DARK_BACKGROUND } from '@/ui/layout/animated-placeholder/constants/DarkBackground'; @@ -35,8 +35,12 @@ const StyledMovingImage = styled(motion.img)<StyledImageProps>` z-index: 2; `; +export type AnimatedPlaceholderType = + | keyof typeof BACKGROUND + | keyof typeof MOVING_IMAGE; + interface AnimatedPlaceholderProps { - type: keyof typeof BACKGROUND | keyof typeof MOVING_IMAGE; + type: AnimatedPlaceholderType; } const AnimatedPlaceholder = ({ type }: AnimatedPlaceholderProps) => { diff --git a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/Background.ts b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/Background.ts index cbe6ee21af7a..40733baae19f 100644 --- a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/Background.ts +++ b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/Background.ts @@ -12,4 +12,5 @@ export const BACKGROUND: Record<string, string> = { emptyInbox: '/images/placeholders/background/empty_inbox_bg.png', error404: '/images/placeholders/background/404_bg.png', error500: '/images/placeholders/background/500_bg.png', + noDeletedRecord: '/images/placeholders/background/no_deleted_record_bg.png', }; diff --git a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkBackground.ts b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkBackground.ts index c609745b5d93..62cc0eec7904 100644 --- a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkBackground.ts +++ b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkBackground.ts @@ -12,4 +12,6 @@ export const DARK_BACKGROUND: Record<string, string> = { loadingMessages: '/images/placeholders/background/loading_messages_bg.png', loadingAccounts: '/images/placeholders/background/loading_accounts_bg.png', emptyFunctions: '/images/placeholders/dark-background/empty_functions_bg.png', + noDeletedRecord: + '/images/placeholders/dark-background/no_deleted_record_bg.png', }; diff --git a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkMovingImage.ts b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkMovingImage.ts index f39ed95a6d51..a4499ef7c6da 100644 --- a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkMovingImage.ts +++ b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/DarkMovingImage.ts @@ -12,4 +12,6 @@ export const DARK_MOVING_IMAGE: Record<string, string> = { loadingMessages: '/images/placeholders/moving-image/loading_messages.png', loadingAccounts: '/images/placeholders/moving-image/loading_accounts.png', emptyFunctions: '/images/placeholders/dark-moving-image/empty_functions.png', + noDeletedRecord: + '/images/placeholders/dark-moving-image/no_deleted_record.png', }; diff --git a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/MovingImage.ts b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/MovingImage.ts index 6b23d3f97b12..690623c32d25 100644 --- a/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/MovingImage.ts +++ b/packages/twenty-front/src/modules/ui/layout/animated-placeholder/constants/MovingImage.ts @@ -12,4 +12,5 @@ export const MOVING_IMAGE: Record<string, string> = { emptyInbox: '/images/placeholders/moving-image/empty_inbox.png', error404: '/images/placeholders/moving-image/404.png', error500: '/images/placeholders/moving-image/500.png', + noDeletedRecord: '/images/placeholders/moving-image/no_deleted_record.png', }; diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/Dropdown.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/Dropdown.tsx index 7be32100909a..98da24f05159 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/Dropdown.tsx +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/Dropdown.tsx @@ -10,9 +10,7 @@ import { MouseEvent, useRef } from 'react'; import { Keys } from 'react-hotkeys-hook'; import { Key } from 'ts-key-enum'; -import { SINGLE_ENTITY_SELECT_BASE_LIST } from '@/object-record/relation-picker/constants/SingleEntitySelectBaseList'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; -import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { HotkeyEffect } from '@/ui/utilities/hotkey/components/HotkeyEffect'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; @@ -69,9 +67,6 @@ export const Dropdown = ({ const { isDropdownOpen, toggleDropdown, closeDropdown, dropdownWidth } = useDropdown(dropdownId); - const { handleResetSelectedPosition } = useSelectableList( - SINGLE_ENTITY_SELECT_BASE_LIST, - ); const offsetMiddlewares = []; if (isDefined(dropdownOffset.x)) { @@ -108,7 +103,6 @@ export const Dropdown = ({ if (isDropdownOpen) { closeDropdown(); - handleResetSelectedPosition(); } }, }); @@ -122,10 +116,9 @@ export const Dropdown = ({ [Key.Escape], () => { closeDropdown(); - handleResetSelectedPosition(); }, dropdownHotkeyScope.scope, - [closeDropdown, handleResetSelectedPosition], + [closeDropdown], ); return ( diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx index 5022ffecb6dc..5a123105c153 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInput.tsx @@ -1,6 +1,7 @@ -import { forwardRef, InputHTMLAttributes, ReactNode, useRef } from 'react'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; +import { forwardRef, InputHTMLAttributes, ReactNode, useRef } from 'react'; +import 'react-phone-number-input/style.css'; import { RGBA, TEXT_INPUT_STYLE } from 'twenty-ui'; import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents'; @@ -43,7 +44,9 @@ const StyledRightContainer = styled.div` transform: translateY(-50%); `; -type DropdownMenuInputProps = InputHTMLAttributes<HTMLInputElement> & { +type HTMLInputProps = InputHTMLAttributes<HTMLInputElement>; + +export type DropdownMenuInputProps = HTMLInputProps & { hotkeyScope?: string; onClickOutside?: () => void; onEnter?: () => void; @@ -51,6 +54,12 @@ type DropdownMenuInputProps = InputHTMLAttributes<HTMLInputElement> & { onShiftTab?: () => void; onTab?: () => void; rightComponent?: ReactNode; + renderInput?: (props: { + value: HTMLInputProps['value']; + onChange: HTMLInputProps['onChange']; + autoFocus: HTMLInputProps['autoFocus']; + placeholder: HTMLInputProps['placeholder']; + }) => React.ReactNode; }; export const DropdownMenuInput = forwardRef< @@ -71,6 +80,7 @@ export const DropdownMenuInput = forwardRef< onShiftTab, onTab, rightComponent, + renderInput, }, ref, ) => { @@ -90,14 +100,23 @@ export const DropdownMenuInput = forwardRef< return ( <StyledInputContainer className={className}> - <StyledInput - autoFocus={autoFocus} - value={value} - placeholder={placeholder} - onChange={onChange} - ref={combinedRef} - withRightComponent={!!rightComponent} - /> + {renderInput ? ( + renderInput({ + value, + onChange, + autoFocus, + placeholder, + }) + ) : ( + <StyledInput + autoFocus={autoFocus} + value={value} + placeholder={placeholder} + onChange={onChange} + ref={combinedRef} + withRightComponent={!!rightComponent} + /> + )} {!!rightComponent && ( <StyledRightContainer>{rightComponent}</StyledRightContainer> )} diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx index 1c6b06c91527..b9f1bc87d286 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuSearchInput.tsx @@ -1,5 +1,6 @@ -import { forwardRef, InputHTMLAttributes } from 'react'; +import { useInputFocusWithoutScrollOnMount } from '@/ui/input/hooks/useInputFocusWithoutScrollOnMount'; import styled from '@emotion/styled'; +import { forwardRef, InputHTMLAttributes } from 'react'; import { TEXT_INPUT_STYLE } from 'twenty-ui'; const StyledDropdownMenuSearchInputContainer = styled.div` @@ -35,12 +36,16 @@ const StyledInput = styled.input` export const DropdownMenuSearchInput = forwardRef< HTMLInputElement, InputHTMLAttributes<HTMLInputElement> ->(({ value, onChange, autoFocus, placeholder = 'Search', type }, ref) => ( - <StyledDropdownMenuSearchInputContainer> - <StyledInput - autoComplete="off" - {...{ autoFocus, onChange, placeholder, type, value }} - ref={ref} - /> - </StyledDropdownMenuSearchInputContainer> -)); +>(({ value, onChange, placeholder = 'Search', type }) => { + const { inputRef } = useInputFocusWithoutScrollOnMount(); + + return ( + <StyledDropdownMenuSearchInputContainer> + <StyledInput + autoComplete="off" + {...{ onChange, placeholder, type, value }} + ref={inputRef} + /> + </StyledDropdownMenuSearchInputContainer> + ); +}); diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts index 0d117b23f227..ed9516be68f9 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type DropdownScopeInternalContextProps = ComponentStateKey; +type DropdownScopeInternalContextProps = RecoilComponentStateKey; export const DropdownScopeInternalContext = createScopeInternalContext<DropdownScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/ui/layout/hooks/useShowAuthModal.ts b/packages/twenty-front/src/modules/ui/layout/hooks/useShowAuthModal.ts index fc241a6655f7..3ab686d65524 100644 --- a/packages/twenty-front/src/modules/ui/layout/hooks/useShowAuthModal.ts +++ b/packages/twenty-front/src/modules/ui/layout/hooks/useShowAuthModal.ts @@ -15,19 +15,23 @@ export const useShowAuthModal = () => { const isLoggedIn = useIsLogged(); const onboardingStatus = useOnboardingStatus(); const subscriptionStatus = useSubscriptionStatus(); + const isDefaultLayoutAuthModalVisible = useRecoilValue( isDefaultLayoutAuthModalVisibleState, ); + return useMemo(() => { if (isMatchingLocation(AppPath.Verify)) { return false; } + if ( isMatchingLocation(AppPath.Invite) || isMatchingLocation(AppPath.ResetPassword) ) { return isDefaultLayoutAuthModalVisible; } + if ( !isLoggedIn || onboardingStatus === OnboardingStatus.PlanRequired || @@ -38,6 +42,7 @@ export const useShowAuthModal = () => { ) { return true; } + if (isMatchingLocation(AppPath.PlanRequired)) { return ( (onboardingStatus === OnboardingStatus.Completed && @@ -45,6 +50,7 @@ export const useShowAuthModal = () => { subscriptionStatus === SubscriptionStatus.Canceled ); } + return false; }, [ isLoggedIn, diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx index 67cb20253e90..04a80a1c827a 100644 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx +++ b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx @@ -17,6 +17,7 @@ import { export type ConfirmationModalProps = { isOpen: boolean; title: string; + loading?: boolean; subtitle: ReactNode; setIsOpen: (val: boolean) => void; onConfirmClick: () => void; @@ -59,6 +60,7 @@ export const StyledConfirmationButton = styled(StyledCenteredButton)` export const ConfirmationModal = ({ isOpen = false, title, + loading, subtitle, setIsOpen, onConfirmClick, @@ -83,6 +85,18 @@ export const ConfirmationModal = ({ 250, ); + const handleConfirmClick = () => { + onConfirmClick(); + + setIsOpen(false); + }; + + const handleEnter = () => { + if (isValidValue) { + handleConfirmClick(); + } + }; + return ( <AnimatePresence mode="wait"> <LayoutGroup> @@ -93,7 +107,7 @@ export const ConfirmationModal = ({ setIsOpen(false); } }} - onEnter={onConfirmClick} + onEnter={handleEnter} isClosable={true} padding="large" > @@ -109,6 +123,7 @@ export const ConfirmationModal = ({ {confirmationValue && ( <Section> <TextInput + dataTestId="confirmation-modal-input" value={inputConfirmationValue} onChange={handleInputConfimrationValueChange} placeholder={confirmationPlaceholder} @@ -124,14 +139,11 @@ export const ConfirmationModal = ({ fullWidth /> <StyledCenteredButton - onClick={async () => { - await onConfirmClick(); - setIsOpen(false); - }} + onClick={handleConfirmClick} variant="secondary" accent={confirmButtonAccent} title={deleteButtonText} - disabled={!isValidValue} + disabled={!isValidValue || loading} fullWidth dataTestId="confirmation-modal-confirm-button" /> diff --git a/packages/twenty-front/src/modules/ui/layout/page/PageHeader.tsx b/packages/twenty-front/src/modules/ui/layout/page/PageHeader.tsx index f9f9a1046e9c..ed9586bf969a 100644 --- a/packages/twenty-front/src/modules/ui/layout/page/PageHeader.tsx +++ b/packages/twenty-front/src/modules/ui/layout/page/PageHeader.tsx @@ -30,11 +30,12 @@ const StyledTopBarContainer = styled.div<{ width?: number }>` padding: ${({ theme }) => theme.spacing(2)}; padding-left: 0; padding-right: ${({ theme }) => theme.spacing(3)}; - z-index: 20; width: ${({ width }) => width + 'px' || '100%'}; @media (max-width: ${MOBILE_VIEWPORT}px) { - padding-left: ${({ theme }) => theme.spacing(3)}; + width: 100%; + box-sizing: border-box; + padding: ${({ theme }) => theme.spacing(3)}; } `; @@ -56,7 +57,7 @@ const StyledTitleContainer = styled.div` font-size: ${({ theme }) => theme.font.size.md}; font-weight: ${({ theme }) => theme.font.weight.medium}; margin-left: ${({ theme }) => theme.spacing(1)}; - max-width: 50%; + width: 100%; `; const StyledTopBarIconStyledTitleContainer = styled.div` @@ -65,6 +66,7 @@ const StyledTopBarIconStyledTitleContainer = styled.div` flex: 1 0 auto; gap: ${({ theme }) => theme.spacing(1)}; flex-direction: row; + width: 100%; `; const StyledPageActionContainer = styled.div` @@ -86,7 +88,7 @@ type PageHeaderProps = { hasNextRecord?: boolean; navigateToPreviousRecord?: () => void; navigateToNextRecord?: () => void; - Icon: IconComponent; + Icon?: IconComponent; children?: ReactNode; width?: number; }; diff --git a/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx b/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx index 8df4797d8199..ef767a67a41e 100644 --- a/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx @@ -2,48 +2,52 @@ import styled from '@emotion/styled'; import { JSX, ReactNode } from 'react'; import { IconComponent } from 'twenty-ui'; -import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; - import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper'; -import { OBJECT_SETTINGS_WIDTH } from '@/settings/data-model/constants/ObjectSettings'; +import { + Breadcrumb, + BreadcrumbProps, +} from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { PageBody } from './PageBody'; import { PageHeader } from './PageHeader'; type SubMenuTopBarContainerProps = { children: JSX.Element | JSX.Element[]; - title: string | ReactNode; + title?: string; actionButton?: ReactNode; Icon: IconComponent; className?: string; + links: BreadcrumbProps['links']; }; -const StyledContainer = styled.div<{ isMobile: boolean }>` +const StyledContainer = styled.div` display: flex; flex-direction: column; - padding-top: ${({ theme, isMobile }) => (!isMobile ? theme.spacing(3) : 0)}; width: 100%; `; +const StyledTitle = styled.h3` + color: ${({ theme }) => theme.font.color.primary}; + font-size: ${({ theme }) => theme.font.size.lg}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + line-height: 1.2; + margin: ${({ theme }) => theme.spacing(8, 8, 2)}; +`; + export const SubMenuTopBarContainer = ({ children, title, actionButton, - Icon, className, + links, }: SubMenuTopBarContainerProps) => { - const isMobile = useIsMobile(); - return ( - <StyledContainer isMobile={isMobile} className={className}> - <PageHeader - title={title} - Icon={Icon} - width={OBJECT_SETTINGS_WIDTH + 4 * 8} - > + <StyledContainer className={className}> + <PageHeader title={<Breadcrumb links={links} />}> {actionButton} </PageHeader> <PageBody> <InformationBannerWrapper /> + {title && <StyledTitle>{title}</StyledTitle>} {children} </PageBody> </StyledContainer> diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index 529b0d1f7ff6..d28366027c44 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -32,7 +32,7 @@ const StyledContainer = styled(motion.div)` background: ${({ theme }) => theme.background.primary}; border-left: 1px solid ${({ theme }) => theme.border.color.medium}; box-shadow: ${({ theme }) => theme.boxShadow.strong}; - height: 100%; + height: 100dvh; overflow-x: hidden; position: fixed; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx index bf5ab29bebf6..972b2a75e3a2 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx @@ -9,10 +9,11 @@ import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isR import { RightDrawerTopBar } from '@/ui/layout/right-drawer/components/RightDrawerTopBar'; import { ComponentByRightDrawerPage } from '@/ui/layout/right-drawer/types/ComponentByRightDrawerPage'; +import { RightDrawerWorkflowEditStep } from '@/workflow/components/RightDrawerWorkflowEditStep'; +import { RightDrawerWorkflowSelectAction } from '@/workflow/components/RightDrawerWorkflowSelectAction'; import { isDefined } from 'twenty-ui'; import { rightDrawerPageState } from '../states/rightDrawerPageState'; import { RightDrawerPages } from '../types/RightDrawerPages'; -import { RightDrawerWorkflow } from '@/workflow/components/RightDrawerWorkflow'; const StyledRightDrawerPage = styled.div` display: flex; @@ -36,7 +37,10 @@ const RIGHT_DRAWER_PAGES_CONFIG: ComponentByRightDrawerPage = { [RightDrawerPages.ViewCalendarEvent]: <RightDrawerCalendarEvent />, [RightDrawerPages.ViewRecord]: <RightDrawerRecord />, [RightDrawerPages.Copilot]: <RightDrawerAIChat />, - [RightDrawerPages.Workflow]: <RightDrawerWorkflow />, + [RightDrawerPages.WorkflowStepSelectAction]: ( + <RightDrawerWorkflowSelectAction /> + ), + [RightDrawerPages.WorkflowStepEdit]: <RightDrawerWorkflowEditStep />, }; export const RightDrawerRouter = () => { diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts index aed035783839..7fc5d9849d89 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts @@ -5,5 +5,6 @@ export const RIGHT_DRAWER_PAGE_ICONS = { [RightDrawerPages.ViewCalendarEvent]: 'IconCalendarEvent', [RightDrawerPages.ViewRecord]: 'Icon123', [RightDrawerPages.Copilot]: 'IconSparkles', - [RightDrawerPages.Workflow]: 'IconSparkles', + [RightDrawerPages.WorkflowStepEdit]: 'IconSparkles', + [RightDrawerPages.WorkflowStepSelectAction]: 'IconSparkles', }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts index bb74c9da8153..749fb10384fc 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts @@ -5,5 +5,6 @@ export const RIGHT_DRAWER_PAGE_TITLES = { [RightDrawerPages.ViewCalendarEvent]: 'Calendar Event', [RightDrawerPages.ViewRecord]: 'Record Editor', [RightDrawerPages.Copilot]: 'Copilot', - [RightDrawerPages.Workflow]: 'Workflow', + [RightDrawerPages.WorkflowStepEdit]: 'Workflow', + [RightDrawerPages.WorkflowStepSelectAction]: 'Workflow', }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts index 2217d437f4fd..f016669b48a2 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts @@ -3,5 +3,6 @@ export enum RightDrawerPages { ViewCalendarEvent = 'view-calendar-event', ViewRecord = 'view-record', Copilot = 'copilot', - Workflow = 'workflow', + WorkflowStepSelectAction = 'workflow-step-select-action', + WorkflowStepEdit = 'workflow-step-edit', } diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx index c4678f4d2d86..de7114062343 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx @@ -2,6 +2,12 @@ import { ReactNode, useEffect, useRef } from 'react'; import { useRecoilValue } from 'recoil'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import styled from '@emotion/styled'; + +const StyledContainer = styled.div` + height: 100%; + width: 100%; +`; export type SelectableItemProps = { itemId: string; @@ -27,8 +33,8 @@ export const SelectableItem = ({ }, [isSelectedItemId]); return ( - <div className={className} ref={scrollRef}> + <StyledContainer className={className} ref={scrollRef}> {children} - </div> + </StyledContainer> ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts index 89518de5de90..3dadd58d1c2e 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts @@ -1,8 +1,4 @@ -import { - useRecoilCallback, - useResetRecoilState, - useSetRecoilState, -} from 'recoil'; +import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; @@ -24,16 +20,11 @@ export const useSelectableList = (selectableListId?: string) => { selectableListOnEnterState, ); - const resetSelectedItemIdState = useResetRecoilState(selectedItemIdState); - - const resetSelectedItem = () => { - resetSelectedItemIdState(); - }; - - const handleResetSelectedPosition = useRecoilCallback( + const resetSelectedItem = useRecoilCallback( ({ snapshot, set }) => () => { const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState); + if (isDefined(selectedItemId)) { set(selectedItemIdState, null); set(isSelectedItemIdSelector(selectedItemId), false); @@ -44,11 +35,9 @@ export const useSelectableList = (selectableListId?: string) => { return { selectableListId: scopeId, - setSelectableItemIds, isSelectedItemIdSelector, setSelectableListOnEnter, resetSelectedItem, - handleResetSelectedPosition, }; }; diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts index c347ce3f0548..b28f36103a48 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type SelectableListScopeInternalContextProps = ComponentStateKey; +type SelectableListScopeInternalContextProps = RecoilComponentStateKey; export const SelectableListScopeInternalContext = createScopeInternalContext<SelectableListScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageActivityContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageActivityContainer.tsx index bdd81f97c93e..a69f54528cba 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageActivityContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageActivityContainer.tsx @@ -1,6 +1,7 @@ import { RichTextEditor } from '@/activities/components/RichTextEditor'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import styled from '@emotion/styled'; const StyledShowPageActivityContainer = styled.div` @@ -16,16 +17,18 @@ export const ShowPageActivityContainer = ({ >; }) => { return ( - <StyledShowPageActivityContainer> - <RichTextEditor - activityId={targetableObject.id} - fillTitleFromBody={false} - activityObjectNameSingular={ - targetableObject.targetObjectNameSingular as - | CoreObjectNameSingular.Note - | CoreObjectNameSingular.Task - } - /> - </StyledShowPageActivityContainer> + <ScrollWrapper contextProviderName="showPageActivityContainer"> + <StyledShowPageActivityContainer> + <RichTextEditor + activityId={targetableObject.id} + fillTitleFromBody={false} + activityObjectNameSingular={ + targetableObject.targetObjectNameSingular as + | CoreObjectNameSingular.Note + | CoreObjectNameSingular.Task + } + /> + </StyledShowPageActivityContainer> + </ScrollWrapper> ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index 96a129c122e5..0df732bfe2a9 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -7,6 +7,7 @@ import { IconMail, IconNotes, IconPaperclip, + IconSettings, IconTimelineEvent, } from 'twenty-ui'; @@ -22,6 +23,8 @@ import { ShowPageActivityContainer } from '@/ui/layout/show-page/components/Show import { TabList } from '@/ui/layout/tab/components/TabList'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { Workflow } from '@/workflow/components/Workflow'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; const StyledShowPageRightContainer = styled.div<{ isMobile: boolean }>` display: flex; @@ -95,6 +98,12 @@ export const ShowPageRightContainer = ({ CoreObjectNameSingular.Person, ].includes(targetObjectNameSingular); + const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED'); + const isWorkflow = + isWorkflowEnabled && + targetableObject.targetObjectNameSingular === + CoreObjectNameSingular.Workflow; + const shouldDisplayCalendarTab = isCompanyOrPerson; const shouldDisplayEmailsTab = emails && isCompanyOrPerson; @@ -122,7 +131,7 @@ export const ShowPageRightContainer = ({ id: 'timeline', title: 'Timeline', Icon: IconTimelineEvent, - hide: !timeline || isInRightDrawer, + hide: !timeline || isInRightDrawer || isWorkflow, }, { id: 'tasks', @@ -133,7 +142,8 @@ export const ShowPageRightContainer = ({ targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Note || targetableObject.targetObjectNameSingular === - CoreObjectNameSingular.Task, + CoreObjectNameSingular.Task || + isWorkflow, }, { id: 'notes', @@ -144,13 +154,14 @@ export const ShowPageRightContainer = ({ targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Note || targetableObject.targetObjectNameSingular === - CoreObjectNameSingular.Task, + CoreObjectNameSingular.Task || + isWorkflow, }, { id: 'files', title: 'Files', Icon: IconPaperclip, - hide: !notes, + hide: !notes || isWorkflow, }, { id: 'emails', @@ -164,6 +175,12 @@ export const ShowPageRightContainer = ({ Icon: IconCalendarEvent, hide: !shouldDisplayCalendarTab, }, + { + id: 'workflow', + title: 'Workflow', + Icon: IconSettings, + hide: !isWorkflow, + }, ]; const renderActiveTabContent = () => { switch (activeTabId) { @@ -202,6 +219,8 @@ export const ShowPageRightContainer = ({ return <EmailThreads targetableObject={targetableObject} />; case 'calendar': return <Calendar targetableObject={targetableObject} />; + case 'workflow': + return <Workflow targetableObject={targetableObject} />; default: return <></>; } diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx index 3d228d5bd792..137bad6002cf 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSummaryCard.tsx @@ -2,7 +2,7 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { ChangeEvent, ReactNode, useRef } from 'react'; import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; -import { AppTooltip, Avatar, AvatarType } from 'twenty-ui'; +import { AppTooltip, Avatar, AvatarType, IconComponent } from 'twenty-ui'; import { v4 as uuidV4 } from 'uuid'; import { @@ -17,6 +17,8 @@ type ShowPageSummaryCardProps = { date: string; id?: string; logoOrAvatar?: string; + icon?: IconComponent; + iconColor?: string; onUploadPicture?: (file: File) => void; title: ReactNode; loading: boolean; @@ -99,6 +101,8 @@ export const ShowPageSummaryCard = ({ date, id, logoOrAvatar, + icon, + iconColor, onUploadPicture, title, loading, @@ -133,7 +137,9 @@ export const ShowPageSummaryCard = ({ size="xl" placeholderColorSeed={id} placeholder={avatarPlaceholder} - type={avatarType} + type={icon ? 'icon' : avatarType} + Icon={icon} + iconColor={iconColor} /> <StyledFileInput ref={inputFileRef} diff --git a/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts b/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts index 9925dec4c655..0021c89fb758 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts +++ b/packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts @@ -4,7 +4,7 @@ import { useTabListStates } from '@/ui/layout/tab/hooks/internal/useTabListState export const useTabList = (tabListId?: string) => { const { activeTabIdState } = useTabListStates({ - tabListScopeId: `${tabListId}-scope`, + tabListScopeId: tabListId, }); const setActiveTabId = useSetRecoilState(activeTabIdState); diff --git a/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts index 878955256f77..5212b7bdba20 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext.ts @@ -1,7 +1,7 @@ import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type TabListScopeInternalContextProps = ComponentStateKey; +type TabListScopeInternalContextProps = RecoilComponentStateKey; export const TabListScopeInternalContext = createScopeInternalContext<TabListScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx b/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx index 486dafaa03f2..a73b21d95669 100644 --- a/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx +++ b/packages/twenty-front/src/modules/ui/layout/table/components/TableRow.tsx @@ -9,12 +9,13 @@ const StyledTableRow = styled('div', { isSelected?: boolean; onClick?: () => void; to?: string; + gridAutoColumns?: string; }>` background-color: ${({ isSelected, theme }) => isSelected ? theme.accent.quaternary : 'transparent'}; border-radius: ${({ theme }) => theme.border.radius.sm}; display: grid; - grid-auto-columns: 1fr; + grid-auto-columns: ${({ gridAutoColumns }) => gridAutoColumns ?? '1fr'}; grid-auto-flow: column; transition: background-color ${({ theme }) => theme.animation.duration.normal}s; @@ -33,6 +34,7 @@ type TableRowProps = { onClick?: () => void; to?: string; className?: string; + gridAutoColumns?: string; }; export const TableRow = ({ @@ -41,10 +43,12 @@ export const TableRow = ({ to, className, children, + gridAutoColumns, }: React.PropsWithChildren<TableRowProps>) => ( <StyledTableRow isSelected={isSelected} onClick={onClick} + gridAutoColumns={gridAutoColumns} className={className} to={to} as={to ? Link : 'div'} diff --git a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx index 1cb6a4af4f80..c020f42709c6 100644 --- a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx @@ -23,7 +23,7 @@ const StyledContainerActionBar = styled.div` box-shadow: ${({ theme }) => theme.boxShadow.strong}; display: flex; height: 48px; - + width: max-content; left: 50%; padding-left: ${({ theme }) => theme.spacing(2)}; padding-right: ${({ theme }) => theme.spacing(2)}; diff --git a/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx b/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx index d06cfc8263ca..a43ee3175fc2 100644 --- a/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/bread-crumb/components/Breadcrumb.tsx @@ -1,42 +1,62 @@ import styled from '@emotion/styled'; -import { Fragment } from 'react'; +import { Fragment, ReactNode } from 'react'; import { Link } from 'react-router-dom'; -type BreadcrumbProps = { +export type BreadcrumbProps = { className?: string; - links: { children: string; href?: string }[]; + links: { children: string | ReactNode; href?: string }[]; }; const StyledWrapper = styled.nav` align-items: center; - color: ${({ theme }) => theme.font.color.secondary}; - display: flex; + color: ${({ theme }) => theme.font.color.tertiary}; + display: grid; font-size: ${({ theme }) => theme.font.size.md}; - // font-weight: ${({ theme }) => theme.font.weight.semiBold}; - gap: ${({ theme }) => theme.spacing(2)}; - line-height: ${({ theme }) => theme.text.lineHeight.lg}; + grid-auto-flow: column; + grid-column-gap: ${({ theme }) => theme.spacing(1)}; + max-width: 100%; + min-width: 0; + height: ${({ theme }) => theme.spacing(8)}; `; const StyledLink = styled(Link)` color: inherit; text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; `; const StyledText = styled.span` color: ${({ theme }) => theme.font.color.primary}; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; `; -export const Breadcrumb = ({ className, links }: BreadcrumbProps) => ( - <StyledWrapper className={className}> - {links.map((link, index) => ( - <Fragment key={index}> - {link.href ? ( - <StyledLink to={link.href}>{link.children}</StyledLink> - ) : ( - <StyledText>{link.children}</StyledText> - )} - {index < links.length - 1 && '/'} - </Fragment> - ))} - </StyledWrapper> -); +const StyledDivider = styled.span` + width: ${({ theme }) => theme.spacing(2)}; +`; + +export const Breadcrumb = ({ className, links }: BreadcrumbProps) => { + return ( + <StyledWrapper className={className}> + {links.map((link, index) => { + const text = typeof link.children === 'string' ? link.children : ''; + + return ( + <Fragment key={index}> + {link.href ? ( + <StyledLink title={text} to={link.href}> + {link.children} + </StyledLink> + ) : ( + <StyledText title={text}>{link.children}</StyledText> + )} + {index < links.length - 1 && <StyledDivider>/</StyledDivider>} + </Fragment> + ); + })} + </StyledWrapper> + ); +}; diff --git a/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx b/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx index 61480f17fd2a..4db0e8dd2c4f 100644 --- a/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx @@ -1,6 +1,6 @@ -import { MouseEvent, useContext } from 'react'; import { styled } from '@linaria/react'; import { isNonEmptyString } from '@sniptt/guards'; +import { MouseEvent, useContext } from 'react'; import { FONT_COMMON, THEME_COMMON, ThemeContext } from 'twenty-ui'; type RoundedLinkProps = { diff --git a/packages/twenty-front/src/modules/ui/navigation/link/components/UndecoratedLink.tsx b/packages/twenty-front/src/modules/ui/navigation/link/components/UndecoratedLink.tsx index 05d39492eb96..09cae367bacf 100644 --- a/packages/twenty-front/src/modules/ui/navigation/link/components/UndecoratedLink.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/link/components/UndecoratedLink.tsx @@ -1,9 +1,17 @@ import styled from '@emotion/styled'; import React from 'react'; -import { Link } from 'react-router-dom'; +import { Link, LinkProps } from 'react-router-dom'; -const StyledUndecoratedLink = styled(Link)` +type StyledLinkProps = LinkProps & { + fullWidth?: boolean; +}; + +const StyledUndecoratedLink = styled( + // eslint-disable-next-line react/jsx-props-no-spreading + ({ fullWidth: _, ...props }: StyledLinkProps) => <Link {...props} />, +)<StyledLinkProps>` text-decoration: none; + width: ${({ fullWidth }) => (fullWidth ? '100%' : 'auto')}; `; type UndecoratedLinkProps = { @@ -11,6 +19,7 @@ type UndecoratedLinkProps = { children: React.ReactNode; replace?: boolean; onClick?: React.MouseEventHandler<HTMLAnchorElement>; + fullWidth?: boolean; }; export const UndecoratedLink = ({ @@ -18,12 +27,14 @@ export const UndecoratedLink = ({ to, replace = false, onClick, + fullWidth = false, }: UndecoratedLinkProps) => { return ( <StyledUndecoratedLink to={to as string} replace={replace} onClick={onClick} + fullWidth={fullWidth} > {children} </StyledUndecoratedLink> diff --git a/packages/twenty-front/src/modules/ui/navigation/menu-item/internals/components/StyledMenuItemBase.tsx b/packages/twenty-front/src/modules/ui/navigation/menu-item/internals/components/StyledMenuItemBase.tsx index 8ae22c23fc85..85d6391384e5 100644 --- a/packages/twenty-front/src/modules/ui/navigation/menu-item/internals/components/StyledMenuItemBase.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/menu-item/internals/components/StyledMenuItemBase.tsx @@ -8,12 +8,12 @@ export type MenuItemBaseProps = { accent?: MenuItemAccent; isKeySelected?: boolean; isHoverBackgroundDisabled?: boolean; + hovered?: boolean; }; export const StyledMenuItemBase = styled.div<MenuItemBaseProps>` --horizontal-padding: ${({ theme }) => theme.spacing(1)}; --vertical-padding: ${({ theme }) => theme.spacing(2)}; - align-items: center; border-radius: ${({ theme }) => theme.border.radius.sm}; @@ -69,7 +69,7 @@ export const StyledMenuItemBase = styled.div<MenuItemBaseProps>` `; export const StyledMenuItemLabel = styled.div<{ hasLeftIcon: boolean }>` - font-size: ${({ theme }) => theme.font.size.sm}; + font-size: ${({ theme }) => theme.font.size.md}; font-weight: ${({ theme }) => theme.font.weight.regular}; overflow: hidden; @@ -143,7 +143,7 @@ export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{ case 'not-allowed': return 'not-allowed'; default: - return 'default'; + return 'pointer'; } }}; `; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx index 07be1ee8bf14..25d934045851 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdownButton.tsx @@ -85,7 +85,7 @@ export const MultiWorkspaceDropdownButton = ({ scope: NavigationDrawerHotKeyScope.MultiWorkspaceDropdownButton, }} clickableComponent={ - <StyledContainer> + <StyledContainer data-testid="workspace-dropdown"> <StyledLogo logo={ getImageAbsoluteURI( diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx index 92b020a7dc7b..35fb3cae0d54 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx @@ -1,7 +1,7 @@ -import { ReactNode, useState } from 'react'; import { css, useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; +import { ReactNode, useState } from 'react'; import { useRecoilValue } from 'recoil'; import { MOBILE_VIEWPORT } from 'twenty-ui'; @@ -32,7 +32,7 @@ const StyledContainer = styled.div<{ isSubMenu?: boolean }>` box-sizing: border-box; display: flex; flex-direction: column; - gap: ${({ theme }) => theme.spacing(3.5)}; + gap: ${({ theme }) => theme.spacing(3)}; height: 100%; min-width: ${DESKTOP_NAV_DRAWER_WIDTHS.menu}px; padding: ${({ theme }) => theme.spacing(3, 2, 4)}; @@ -41,7 +41,6 @@ const StyledContainer = styled.div<{ isSubMenu?: boolean }>` isSubMenu ? css` padding-right: ${theme.spacing(8)}; - padding-top: 41px; ` : ''} diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx index ae4d2144dd5a..96490d7f0a7e 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx @@ -1,7 +1,7 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; -import { IconChevronLeft } from 'twenty-ui'; +import { IconX } from 'twenty-ui'; import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; @@ -18,17 +18,22 @@ const StyledIconAndButtonContainer = styled.button` cursor: pointer; display: flex; flex-direction: row; - font-size: ${({ theme }) => theme.font.size.lg}; - font-weight: ${({ theme }) => theme.font.weight.semiBold}; + font-weight: ${({ theme }) => theme.font.weight.medium}; gap: ${({ theme }) => theme.spacing(2)}; - line-height: ${({ theme }) => theme.text.lineHeight.md}; - padding: ${({ theme }) => theme.spacing(1)}; + padding: ${({ theme }) => theme.spacing(1.5, 1)}; width: 100%; + font-family: ${({ theme }) => theme.font.family}; + &:hover { + background: ${({ theme }) => theme.background.transparent.light}; + border-radius: ${({ theme }) => theme.border.radius.sm}; + } `; const StyledContainer = styled.div` + align-items: center; display: flex; flex-direction: row; + height: ${({ theme }) => theme.spacing(8)}; justify-content: space-between; `; @@ -42,9 +47,10 @@ export const NavigationDrawerBackButton = ({ <StyledContainer> <UndecoratedLink to={navigationMemorizedUrl} replace> <StyledIconAndButtonContainer> - <IconChevronLeft + <IconX size={theme.icon.size.md} stroke={theme.icon.stroke.lg} + color={theme.font.color.tertiary} /> <span>{title}</span> </StyledIconAndButtonContainer> diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx index 4d3ee0cfa208..a1ef582aaef3 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItem.tsx @@ -1,3 +1,5 @@ +import { NavigationDrawerItemBreadcrumb } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb'; +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; import { isNavigationDrawerOpenState } from '@/ui/navigation/states/isNavigationDrawerOpenState'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import isPropValid from '@emotion/is-prop-valid'; @@ -6,16 +8,26 @@ import styled from '@emotion/styled'; import { isNonEmptyString } from '@sniptt/guards'; import { Link, useNavigate } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; -import { IconComponent, MOBILE_VIEWPORT, Pill } from 'twenty-ui'; +import { + IconComponent, + MOBILE_VIEWPORT, + Pill, + TablerIconsProps, +} from 'twenty-ui'; import { isDefined } from '~/utils/isDefined'; +const DEFAULT_INDENTATION_LEVEL = 1; + +export type NavigationDrawerItemIndentationLevel = 1 | 2; + export type NavigationDrawerItemProps = { className?: string; label: string; - level?: 1 | 2; + indentationLevel?: NavigationDrawerItemIndentationLevel; + subItemState?: NavigationDrawerSubItemState; to?: string; onClick?: () => void; - Icon: IconComponent; + Icon: IconComponent | ((props: TablerIconsProps) => JSX.Element); active?: boolean; danger?: boolean; soon?: boolean; @@ -23,13 +35,10 @@ export type NavigationDrawerItemProps = { keyboard?: string[]; }; -type StyledItemProps = { - active?: boolean; - danger?: boolean; - level: 1 | 2; - soon?: boolean; - to?: string; -}; +type StyledItemProps = Pick< + NavigationDrawerItemProps, + 'active' | 'danger' | 'indentationLevel' | 'soon' | 'to' +>; const StyledItem = styled('div', { shouldForwardProp: (prop) => @@ -59,13 +68,17 @@ const StyledItem = styled('div', { font-family: 'Inter'; font-size: ${({ theme }) => theme.font.size.md}; gap: ${({ theme }) => theme.spacing(2)}; - margin-left: ${({ level, theme }) => theme.spacing((level - 1) * 4)}; + padding-bottom: ${({ theme }) => theme.spacing(1)}; padding-left: ${({ theme }) => theme.spacing(1)}; padding-right: ${({ theme }) => theme.spacing(1)}; padding-top: ${({ theme }) => theme.spacing(1)}; - pointer-events: ${(props) => (props.soon ? 'none' : 'auto')}; + margin-top: ${({ indentationLevel }) => + indentationLevel === 2 ? '2px' : '0'}; + + pointer-events: ${(props) => (props.soon ? 'none' : 'auto')}; + width: 100%; :hover { background: ${({ theme }) => theme.background.transparent.light}; color: ${(props) => @@ -116,10 +129,16 @@ const StyledKeyBoardShortcut = styled.div` visibility: hidden; `; +const StyledNavigationDrawerItemContainer = styled.div` + display: flex; + flex-grow: 1; + width: 100%; +`; + export const NavigationDrawerItem = ({ className, label, - level = 1, + indentationLevel = DEFAULT_INDENTATION_LEVEL, Icon, to, onClick, @@ -128,6 +147,7 @@ export const NavigationDrawerItem = ({ soon, count, keyboard, + subItemState, }: NavigationDrawerItemProps) => { const theme = useTheme(); const isMobile = useIsMobile(); @@ -136,6 +156,8 @@ export const NavigationDrawerItem = ({ isNavigationDrawerOpenState, ); + const showBreadcrumb = indentationLevel === 2; + const handleItemClick = () => { if (isMobile) { setIsNavigationDrawerOpen(false); @@ -152,26 +174,37 @@ export const NavigationDrawerItem = ({ }; return ( - <StyledItem - className={className} - level={level} - onClick={handleItemClick} - active={active} - aria-selected={active} - danger={danger} - soon={soon} - as={to ? Link : 'div'} - to={to ? to : undefined} - > - {Icon && <Icon size={theme.icon.size.md} stroke={theme.icon.stroke.md} />} - <StyledItemLabel>{label}</StyledItemLabel> - {soon && <Pill label="Soon" />} - {!!count && <StyledItemCount>{count}</StyledItemCount>} - {keyboard && ( - <StyledKeyBoardShortcut className="keyboard-shortcuts"> - {keyboard} - </StyledKeyBoardShortcut> - )} - </StyledItem> + <StyledNavigationDrawerItemContainer> + <StyledItem + className={className} + onClick={handleItemClick} + active={active} + aria-selected={active} + danger={danger} + soon={soon} + as={to ? Link : 'div'} + to={to ? to : undefined} + indentationLevel={indentationLevel} + > + {showBreadcrumb && ( + <NavigationDrawerItemBreadcrumb state={subItemState} /> + )} + {Icon && ( + <Icon + style={{ minWidth: theme.icon.size.md }} + size={theme.icon.size.md} + stroke={theme.icon.stroke.md} + /> + )} + <StyledItemLabel>{label}</StyledItemLabel> + {soon && <Pill label="Soon" />} + {!!count && <StyledItemCount>{count}</StyledItemCount>} + {keyboard && ( + <StyledKeyBoardShortcut className="keyboard-shortcuts"> + {keyboard} + </StyledKeyBoardShortcut> + )} + </StyledItem> + </StyledNavigationDrawerItemContainer> ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx new file mode 100644 index 000000000000..47e8bd120864 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx @@ -0,0 +1,79 @@ +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; +import styled from '@emotion/styled'; + +export type NavigationDrawerItemBreadcrumbProps = { + state?: NavigationDrawerSubItemState; +}; + +const StyledNavigationDrawerItemBreadcrumbContainer = styled.div` + margin-left: 7.5px; + + height: 28px; + width: 9px; +`; + +const StyledGapVerticalLine = styled.div<{ darker: boolean }>` + background: ${({ theme, darker }) => + darker ? theme.font.color.tertiary : theme.border.color.strong}; + + position: relative; + top: -2px; + + height: 2px; + width: 1px; +`; + +const StyledSecondaryFullVerticalBar = styled.div<{ darker: boolean }>` + background: ${({ theme, darker }) => + darker ? theme.font.color.tertiary : theme.border.color.strong}; + + position: relative; + top: -17px; + height: 28px; + width: 1px; +`; + +const StyledRoundedProtrusion = styled.div<{ darker: boolean }>` + position: relative; + top: -2px; + + border-bottom-left-radius: 4px; + + border: 1px solid + ${({ theme, darker }) => + darker ? theme.font.color.tertiary : theme.border.color.strong}; + + ${({ darker }) => (darker ? 'z-index: 1;' : '')} + + border-top: none; + border-right: none; + height: 14px; + width: 8px; +`; + +export const NavigationDrawerItemBreadcrumb = ({ + state, +}: NavigationDrawerItemBreadcrumbProps) => { + const showVerticalBar = + state !== 'last-not-selected' && state !== 'last-selected'; + + const verticalBarShouldBeDarker = state === 'intermediate-before-selected'; + + const protrusionShouldBeDarker = + state === 'intermediate-selected' || state === 'last-selected'; + + const gapShouldBeDarker = + state === 'intermediate-before-selected' || + state === 'intermediate-selected' || + state === 'last-selected'; + + return ( + <StyledNavigationDrawerItemBreadcrumbContainer> + <StyledGapVerticalLine darker={gapShouldBeDarker} /> + <StyledRoundedProtrusion darker={protrusionShouldBeDarker} /> + {showVerticalBar && ( + <StyledSecondaryFullVerticalBar darker={verticalBarShouldBeDarker} /> + )} + </StyledNavigationDrawerItemBreadcrumbContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx index 3df470edb4e3..dfb9b5f7c61a 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx @@ -3,7 +3,6 @@ import styled from '@emotion/styled'; const StyledGroup = styled.div` display: flex; flex-direction: column; - gap: ${({ theme }) => theme.spacing(0.5)}; `; export { StyledGroup as NavigationDrawerItemGroup }; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx index fad4149edbfd..4ef3f1c9654c 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx @@ -2,21 +2,12 @@ import { NavigationDrawerItem, NavigationDrawerItemProps, } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; -import styled from '@emotion/styled'; - -const StyledItem = styled.div` - &:not(:last-child) { - margin-bottom: ${({ theme }) => theme.spacing(0.5)}; - } - margin-left: ${({ theme }) => theme.spacing(4)}; -`; type NavigationDrawerSubItemProps = NavigationDrawerItemProps; export const NavigationDrawerSubItem = ({ className, label, - level = 1, Icon, to, onClick, @@ -25,22 +16,22 @@ export const NavigationDrawerSubItem = ({ soon, count, keyboard, + subItemState, }: NavigationDrawerSubItemProps) => { return ( - <StyledItem> - <NavigationDrawerItem - className={className} - label={label} - level={level} - Icon={Icon} - to={to} - onClick={onClick} - active={active} - danger={danger} - soon={soon} - count={count} - keyboard={keyboard} - /> - </StyledItem> + <NavigationDrawerItem + className={className} + label={label} + indentationLevel={2} + subItemState={subItemState} + Icon={Icon} + to={to} + onClick={onClick} + active={active} + danger={danger} + soon={soon} + count={count} + keyboard={keyboard} + /> ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx index 96d16a5526fe..dfbe324297a4 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx @@ -16,13 +16,14 @@ import { IconUsers, } from 'twenty-ui'; -import { Favorites } from '@/favorites/components/Favorites'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { SettingsPath } from '@/types/SettingsPath'; import { GithubVersionLink } from '@/ui/navigation/link/components/GithubVersionLink'; import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; +import { CurrentWorkspaceMemberFavorites } from '@/favorites/components/CurrentWorkspaceMemberFavorites'; +import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; import { NavigationDrawer } from '../NavigationDrawer'; import { NavigationDrawerItem } from '../NavigationDrawerItem'; import { NavigationDrawerItemGroup } from '../NavigationDrawerItemGroup'; @@ -65,7 +66,7 @@ export const Default: Story = { /> </NavigationDrawerSection> - <Favorites /> + <CurrentWorkspaceMemberFavorites /> <NavigationDrawerSection> <NavigationDrawerSectionTitle label="Workspace" /> @@ -108,17 +109,17 @@ export const Submenu: Story = { to={getSettingsPagePath(SettingsPath.Accounts)} Icon={IconAt} /> - <NavigationDrawerItem - level={2} + <NavigationDrawerSubItem label="Emails" to={getSettingsPagePath(SettingsPath.AccountsEmails)} Icon={IconMail} + subItemState="intermediate-before-selected" /> - <NavigationDrawerItem - level={2} + <NavigationDrawerSubItem label="Calendar" to={getSettingsPagePath(SettingsPath.AccountsCalendars)} Icon={IconCalendarEvent} + subItemState="last-selected" /> </NavigationDrawerItemGroup> </NavigationDrawerSection> diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx index f541a91aa615..81a0ffe4660b 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx @@ -37,6 +37,115 @@ export const Default: Story = { ], }; +export const Breadcrumb: Story = { + decorators: [ + (Story) => ( + <StyledContainer> + <h1>Breadcrumb</h1> + <Story + args={{ + indentationLevel: 1, + label: 'Search', + Icon: IconSearch, + }} + /> + <Story + args={{ + indentationLevel: 2, + subItemState: 'intermediate-before-selected', + label: 'First not selected', + Icon: IconSearch, + }} + /> + <Story + args={{ + indentationLevel: 2, + subItemState: 'intermediate-before-selected', + label: 'Before selected', + Icon: IconSearch, + }} + /> + <Story + args={{ + indentationLevel: 2, + subItemState: 'intermediate-selected', + label: 'Selected', + Icon: IconSearch, + }} + /> + <Story + args={{ + indentationLevel: 2, + subItemState: 'intermediate-after-selected', + label: 'After selected', + Icon: IconSearch, + }} + /> + <Story + args={{ + indentationLevel: 2, + subItemState: 'last-not-selected', + label: 'Last not selected', + Icon: IconSearch, + }} + /> + </StyledContainer> + ), + ComponentWithRouterDecorator, + ], +}; + +export const BreadcrumbCatalog: CatalogStory< + Story, + typeof NavigationDrawerItem +> = { + decorators: [ + (Story) => ( + <StyledContainer> + <Story /> + </StyledContainer> + ), + CatalogDecorator, + MemoryRouterDecorator, + ], + args: { + indentationLevel: 2, + }, + parameters: { + pseudo: { hover: ['.hover'] }, + catalog: { + dimensions: [ + { + name: 'subItemState', + values: [ + 'Intermediate before selected', + 'Intermediate selected', + 'Intermediate after selected', + 'Last not selected', + 'Last selected', + ], + props: (state: string) => { + switch (state) { + case 'Intermediate before selected': + return { subItemState: 'intermediate-before-selected' }; + case 'Intermediate selected': + return { subItemState: 'intermediate-selected' }; + case 'Intermediate after selected': + return { subItemState: 'intermediate-after-selected' }; + case 'Last not selected': + return { subItemState: 'last-not-selected' }; + case 'Last selected': + return { subItemState: 'last-selected' }; + default: + throw new Error(`Unknown state: ${state}`); + } + }, + }, + ], + }, + }, +}; + export const Catalog: CatalogStory<Story, typeof NavigationDrawerItem> = { decorators: [ (Story) => ( diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts new file mode 100644 index 000000000000..7de9e4ef5675 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts @@ -0,0 +1,6 @@ +export type NavigationDrawerSubItemState = + | 'intermediate-before-selected' + | 'intermediate-selected' + | 'intermediate-after-selected' + | 'last-selected' + | 'last-not-selected'; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts new file mode 100644 index 000000000000..dcb08f78ee13 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts @@ -0,0 +1,35 @@ +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; + +export const getNavigationSubItemState = ({ + index, + arrayLength, + selectedIndex, +}: { + index: number; + arrayLength: number; + selectedIndex: number; +}): NavigationDrawerSubItemState => { + const thereIsOnlyOneItem = arrayLength === 1; + + const itsTheLastItem = index === arrayLength - 1; + + const itsTheSelectedItem = index === selectedIndex; + + const itsBeforeTheSelectedItem = index < selectedIndex; + + if (thereIsOnlyOneItem || itsTheLastItem) { + if (itsTheSelectedItem) { + return 'last-selected'; + } else { + return 'last-not-selected'; + } + } else { + if (itsTheSelectedItem) { + return 'intermediate-selected'; + } else if (itsBeforeTheSelectedItem) { + return 'intermediate-before-selected'; + } else { + return 'intermediate-after-selected'; + } + } +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2.ts index 952fbfb0ee04..cf3b7474505d 100644 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2.ts +++ b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2.ts @@ -1,9 +1,9 @@ import { RecoilState, useRecoilState } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; export const useRecoilScopedStateV2 = <StateType>( - recoilState: (scopedKey: ComponentStateKey) => RecoilState<StateType>, + recoilState: (scopedKey: RecoilComponentStateKey) => RecoilState<StateType>, scopeId: string, ) => { return useRecoilState<StateType>( diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext.ts index 78911a1abcdd..abf1b33900b4 100644 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext.ts @@ -1,10 +1,11 @@ import { Context, createContext } from 'react'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; -type ScopeInternalContext<T extends ComponentStateKey> = Context<T | null>; +type ScopeInternalContext<T extends RecoilComponentStateKey> = + Context<T | null>; -export const createScopeInternalContext = <T extends ComponentStateKey>( +export const createScopeInternalContext = <T extends RecoilComponentStateKey>( initialValue?: T, ) => { return createContext<T | null>( diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedSelector.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedSelector.ts index 8e92014b557d..5f680bbda05a 100644 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedSelector.ts +++ b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedSelector.ts @@ -1,7 +1,7 @@ import { RecoilValueReadOnly } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; export type RecoilScopedSelector<StateType> = ( - scopedKey: ComponentStateKey, + scopedKey: RecoilComponentStateKey, ) => RecoilValueReadOnly<StateType>; diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedState.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedState.ts index beb36d9e9947..44ed24a23893 100644 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedState.ts +++ b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/types/RecoilScopedState.ts @@ -1,7 +1,7 @@ import { RecoilState } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; export type RecoilScopedState<StateType> = ( - scopedKey: ComponentStateKey, + scopedKey: RecoilComponentStateKey, ) => RecoilState<StateType>; diff --git a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId.ts b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId.ts index feb67c86dba3..bc5ce6e96b4c 100644 --- a/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId.ts +++ b/packages/twenty-front/src/modules/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId.ts @@ -1,2 +1,2 @@ export const getScopeIdFromComponentId = (componentId: string) => - `${componentId}-scope`; + `${componentId}`; diff --git a/packages/twenty-front/src/modules/ui/utilities/scroll/contexts/ScrollWrapperContexts.tsx b/packages/twenty-front/src/modules/ui/utilities/scroll/contexts/ScrollWrapperContexts.tsx index 1141b336346e..b6f7d2103a60 100644 --- a/packages/twenty-front/src/modules/ui/utilities/scroll/contexts/ScrollWrapperContexts.tsx +++ b/packages/twenty-front/src/modules/ui/utilities/scroll/contexts/ScrollWrapperContexts.tsx @@ -16,7 +16,8 @@ export type ContextProviderName = | 'showPageLeftContainer' | 'tabList' | 'releases' - | 'test'; + | 'test' + | 'showPageActivityContainer'; const createScrollWrapperContext = (id: string) => createContext<ScrollWrapperContextValue>({ @@ -44,6 +45,8 @@ export const TabListScrollWrapperContext = createScrollWrapperContext('tabList'); export const ReleasesScrollWrapperContext = createScrollWrapperContext('releases'); +export const ShowPageActivityContainerScrollWrapperContext = + createScrollWrapperContext('showPageActivityContainer'); export const TestScrollWrapperContext = createScrollWrapperContext('test'); export const getContextByProviderName = ( @@ -72,6 +75,8 @@ export const getContextByProviderName = ( return ReleasesScrollWrapperContext; case 'test': return TestScrollWrapperContext; + case 'showPageActivityContainer': + return ShowPageActivityContainerScrollWrapperContext; default: throw new Error('Context Provider not available'); } diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow.ts new file mode 100644 index 000000000000..8a497e3c3a7e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow.ts @@ -0,0 +1,24 @@ +import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext'; +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { isNonEmptyString } from '@sniptt/guards'; + +export const useAvailableComponentInstanceIdOrThrow = < + T extends { instanceId: string }, +>( + Context: ComponentInstanceStateContext<T>, + instanceIdFromProps?: string, +): string => { + const instanceStateContext = useComponentInstanceStateContext(Context); + + const instanceIdFromContext = instanceStateContext?.instanceId; + + if (isNonEmptyString(instanceIdFromProps)) { + return instanceIdFromProps; + } else if (isNonEmptyString(instanceIdFromContext)) { + return instanceIdFromContext; + } else { + throw new Error( + 'Instance id is not provided and cannot be found in context.', + ); + } +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext.ts new file mode 100644 index 000000000000..17dbbf158c92 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext.ts @@ -0,0 +1,12 @@ +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { useContext } from 'react'; + +export const useComponentInstanceStateContext = < + T extends { instanceId: string }, +>( + Context: ComponentInstanceStateContext<T>, +) => { + const context = useContext(Context); + + return context; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilCallbackState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilCallbackState.ts new file mode 100644 index 000000000000..bf1143c06a17 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilCallbackState.ts @@ -0,0 +1,27 @@ +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId'; +import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState'; + +export const useRecoilCallbackState = <Value>( + componentState: RecoilComponentState<Value>, + componentId?: string, +) => { + const componentContext = (window as any).componentContextStateMap?.get( + componentState.key, + ); + + if (!componentContext) { + throw new Error( + `Component context for key "${componentState.key}" is not defined`, + ); + } + + const internalScopeId = useAvailableScopeIdOrThrow( + componentContext, + getScopeIdOrUndefinedFromComponentId(componentId), + ); + + return componentState.atomFamily({ + scopeId: internalScopeId, + }); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2.ts new file mode 100644 index 000000000000..ff3f6ab06080 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2.ts @@ -0,0 +1,128 @@ +/* eslint-disable no-redeclare */ +/* eslint-disable prefer-arrow/prefer-arrow-functions */ +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2'; +import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2'; +import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2'; +import { ComponentReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2'; +import { ComponentSelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentSelectorV2'; +import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { RecoilState, RecoilValueReadOnly, SerializableParam } from 'recoil'; + +export function useRecoilComponentCallbackStateV2<ValueType>( + componentState: ComponentStateV2<ValueType>, + instanceIdFromProps?: string, +): RecoilState<ValueType>; +export function useRecoilComponentCallbackStateV2<ValueType>( + componentSelector: ComponentSelectorV2<ValueType>, + instanceIdFromProps?: string, +): RecoilState<ValueType>; +export function useRecoilComponentCallbackStateV2<ValueType>( + componentReadOnlySelector: ComponentReadOnlySelectorV2<ValueType>, + instanceIdFromProps?: string, +): RecoilValueReadOnly<ValueType>; +export function useRecoilComponentCallbackStateV2< + ValueType, + FamilyKey extends SerializableParam, +>( + componentFamilyState: ComponentFamilyStateV2<ValueType, FamilyKey>, + instanceIdFromProps?: string, +): (familyKey: FamilyKey) => RecoilState<ValueType>; +export function useRecoilComponentCallbackStateV2< + ValueType, + FamilyKey extends SerializableParam, +>( + componentFamilySelector: ComponentFamilySelectorV2<ValueType, FamilyKey>, + instanceIdFromProps?: string, +): (familyKey: FamilyKey) => RecoilState<ValueType>; +export function useRecoilComponentCallbackStateV2< + ValueType, + FamilyKey extends SerializableParam, +>( + componentFamilyReadOnlySelector: ComponentFamilyReadOnlySelectorV2< + ValueType, + FamilyKey + >, + instanceIdFromProps?: string, +): (familyKey: FamilyKey) => RecoilValueReadOnly<ValueType>; +export function useRecoilComponentCallbackStateV2< + ValueType, + FamilyKey extends SerializableParam, +>( + componentFamilyState: ComponentFamilyStateV2<ValueType, FamilyKey>, + instanceIdFromProps?: string, +): (familyKey: FamilyKey) => RecoilState<ValueType>; +export function useRecoilComponentCallbackStateV2< + ComponentState extends + | ComponentStateV2<ValueType> + | ComponentSelectorV2<ValueType> + | ComponentReadOnlySelectorV2<ValueType> + | ComponentFamilyStateV2<ValueType, FamilyKey> + | ComponentFamilySelectorV2<ValueType, FamilyKey> + | ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>, + ValueType, + FamilyKey extends SerializableParam = never, +>( + componentState: ComponentState, + instanceIdFromProps?: string, +): + | RecoilState<ValueType> + | RecoilValueReadOnly<ValueType> + | ((familyKey: FamilyKey) => RecoilState<ValueType>) + | ((familyKey: FamilyKey) => RecoilValueReadOnly<ValueType>) { + const componentStateKey = componentState.key; + + const componentInstanceContext = + globalComponentInstanceContextMap.get(componentStateKey); + + if (!componentInstanceContext) { + throw new Error( + `Instance context for key "${componentStateKey}" is not defined, check the component state declaration.`, + ); + } + + const instanceId = useAvailableComponentInstanceIdOrThrow( + componentInstanceContext, + instanceIdFromProps, + ); + + switch (componentState.type) { + case 'ComponentState': { + return componentState.atomFamily({ + instanceId, + }); + } + case 'ComponentSelector': { + return componentState.selectorFamily({ + instanceId, + }); + } + case 'ComponentReadOnlySelector': { + return componentState.selectorFamily({ + instanceId, + }); + } + case 'ComponentFamilyState': { + return (familyKey: FamilyKey) => + componentState.atomFamily({ + instanceId, + familyKey, + }); + } + case 'ComponentFamilySelector': { + return (familyKey: FamilyKey) => + componentState.selectorFamily({ + instanceId, + familyKey, + }); + } + case 'ComponentFamilyReadOnlySelector': { + return (familyKey: FamilyKey) => + componentState.selectorFamily({ + instanceId, + familyKey, + }); + } + } +} diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2.ts new file mode 100644 index 000000000000..4e8edaa4e9a0 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2.ts @@ -0,0 +1,52 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2'; +import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2'; +import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { SerializableParam, useRecoilValue } from 'recoil'; + +export const useRecoilComponentFamilyValueV2 = < + StateType, + FamilyKey extends SerializableParam, +>( + componentStateV2: + | ComponentFamilyStateV2<StateType, FamilyKey> + | ComponentFamilySelectorV2<StateType, FamilyKey> + | ComponentFamilyReadOnlySelectorV2<StateType, FamilyKey>, + familyKey: FamilyKey, + instanceIdFromProps?: string, +): StateType => { + const instanceContext = globalComponentInstanceContextMap.get( + componentStateV2.key, + ); + + if (!instanceContext) { + throw new Error( + `Instance context for key "${componentStateV2.key}" is not defined`, + ); + } + + const instanceId = useAvailableComponentInstanceIdOrThrow( + instanceContext, + instanceIdFromProps, + ); + + switch (componentStateV2.type) { + case 'ComponentFamilyState': { + return useRecoilValue( + componentStateV2.atomFamily({ familyKey, instanceId }), + ); + } + case 'ComponentFamilySelector': { + return useRecoilValue( + componentStateV2.selectorFamily({ familyKey, instanceId }), + ); + } + case 'ComponentFamilyReadOnlySelector': { + return useRecoilValue( + componentStateV2.selectorFamily({ familyKey, instanceId }), + ); + } + } +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentState.ts new file mode 100644 index 000000000000..c0bd5e9d53b0 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentState.ts @@ -0,0 +1,28 @@ +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId'; +import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState'; +import { useRecoilState } from 'recoil'; + +export const useRecoilComponentState = <StateType>( + componentState: RecoilComponentState<StateType>, + componentId?: string, +) => { + const componentContext = (window as any).componentContextStateMap?.get( + componentState.key, + ); + + if (!componentContext) { + throw new Error( + `Component context for key "${componentState.key}" is not defined`, + ); + } + + const internalComponentId = useAvailableScopeIdOrThrow( + componentContext, + getScopeIdOrUndefinedFromComponentId(componentId), + ); + + return useRecoilState( + componentState.atomFamily({ scopeId: internalComponentId }), + ); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2.ts new file mode 100644 index 000000000000..a3d16acd4ed7 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2.ts @@ -0,0 +1,26 @@ +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { useRecoilState } from 'recoil'; + +export const useRecoilComponentStateV2 = <StateType>( + componentState: ComponentStateV2<StateType>, + instanceIdFromProps?: string, +) => { + const componentInstanceContext = globalComponentInstanceContextMap.get( + componentState.key, + ); + + if (!componentInstanceContext) { + throw new Error( + `Instance context for key "${componentState.key}" is not defined`, + ); + } + + const instanceId = useAvailableComponentInstanceIdOrThrow( + componentInstanceContext, + instanceIdFromProps, + ); + + return useRecoilState(componentState.atomFamily({ instanceId })); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValue.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValue.ts index d72ee3cae3f2..efaa56de1ad8 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValue.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValue.ts @@ -2,10 +2,10 @@ import { useRecoilValue } from 'recoil'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId'; -import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState'; +import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState'; export const useRecoilComponentValue = <StateType>( - componentState: ComponentState<StateType>, + componentState: RecoilComponentState<StateType>, componentId?: string, ) => { const componentContext = (window as any).componentContextStateMap?.get( diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2.ts new file mode 100644 index 000000000000..a76b91c2eb15 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2.ts @@ -0,0 +1,26 @@ +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { useRecoilValue } from 'recoil'; + +export const useRecoilComponentValueV2 = <StateType>( + componentStateV2: ComponentStateV2<StateType>, + instanceIdFromProps?: string, +) => { + const instanceContext = globalComponentInstanceContextMap.get( + componentStateV2.key, + ); + + if (!instanceContext) { + throw new Error( + `Instance context for key "${componentStateV2.key}" is not defined`, + ); + } + + const instanceId = useAvailableComponentInstanceIdOrThrow( + instanceContext, + instanceIdFromProps, + ); + + return useRecoilValue(componentStateV2.atomFamily({ instanceId })); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts index e500060c98a3..fa30c4cd5371 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts @@ -1,9 +1,9 @@ import { useScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContext'; import { ComponentFamilyState } from '@/ui/utilities/state/component-state/types/ComponentFamilyState'; -import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState'; +import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState'; export const useScopeIdFromStateContext = ( - componentState: ComponentState<any> | ComponentFamilyState<any, any>, + componentState: RecoilComponentState<any> | ComponentFamilyState<any, any>, ) => { const componentContext = (window as any).componentContextStateMap?.get( componentState.key, diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2.ts new file mode 100644 index 000000000000..1ccf392a588e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2.ts @@ -0,0 +1,52 @@ +/* eslint-disable react-hooks/rules-of-hooks */ + +// We're disabling rules-of-hooks because we're sure that the call order cannot be modified +// because a component state cannot change its type during its lifecycle + +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2'; +import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { SerializableParam, SetterOrUpdater, useSetRecoilState } from 'recoil'; + +export const useSetRecoilComponentFamilyStateV2 = < + StateType, + FamilyKey extends SerializableParam, +>( + componentState: + | ComponentFamilyStateV2<StateType, FamilyKey> + | ComponentFamilySelectorV2<StateType, FamilyKey>, + familyKey: FamilyKey, + instanceIdFromProps?: string, +): SetterOrUpdater<StateType> => { + const componentInstanceContext = globalComponentInstanceContextMap.get( + componentState.key, + ); + + if (!componentInstanceContext) { + throw new Error( + `Instance context for key "${componentState.key}" is not defined`, + ); + } + + const instanceId = useAvailableComponentInstanceIdOrThrow( + componentInstanceContext, + instanceIdFromProps, + ); + + switch (componentState.type) { + case 'ComponentFamilyState': { + return useSetRecoilState( + componentState.atomFamily({ familyKey, instanceId }), + ); + } + case 'ComponentFamilySelector': { + return useSetRecoilState( + componentState.selectorFamily({ + familyKey, + instanceId, + }), + ); + } + } +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentState.ts index 938d699b3f51..9e1ca49a4187 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentState.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentState.ts @@ -2,10 +2,10 @@ import { useSetRecoilState } from 'recoil'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId'; -import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState'; +import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState'; export const useSetRecoilComponentState = <StateType>( - componentState: ComponentState<StateType>, + componentState: RecoilComponentState<StateType>, componentId?: string, ) => { const componentContext = (window as any).componentContextStateMap?.get( diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2.ts new file mode 100644 index 000000000000..29e5f1914a3d --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2.ts @@ -0,0 +1,26 @@ +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { SetterOrUpdater, useSetRecoilState } from 'recoil'; + +export const useSetRecoilComponentStateV2 = <ValueType>( + componentState: ComponentStateV2<ValueType>, + instanceIdFromProps?: string, +): SetterOrUpdater<ValueType> => { + const componentInstanceContext = globalComponentInstanceContextMap.get( + componentState.key, + ); + + if (!componentInstanceContext) { + throw new Error( + `Instance context for key "${componentState.key}" is not defined`, + ); + } + + const instanceId = useAvailableComponentInstanceIdOrThrow( + componentInstanceContext, + instanceIdFromProps, + ); + + return useSetRecoilState(componentState.atomFamily({ instanceId })); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2.ts new file mode 100644 index 000000000000..0a01f598b764 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2.ts @@ -0,0 +1,14 @@ +import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2'; +import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2'; +import { RecoilValueReadOnly, SerializableParam } from 'recoil'; + +export type ComponentFamilyReadOnlySelectorV2< + StateType, + FamilyKey extends SerializableParam, +> = { + type: Extract<ComponentStateTypeV2, 'ComponentFamilyReadOnlySelector'>; + key: string; + selectorFamily: ( + componentFamilyStateKey: ComponentFamilyStateKeyV2<FamilyKey>, + ) => RecoilValueReadOnly<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilySelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilySelectorV2.ts new file mode 100644 index 000000000000..9ac6c5879522 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilySelectorV2.ts @@ -0,0 +1,14 @@ +import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2'; +import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2'; +import { RecoilState, SerializableParam } from 'recoil'; + +export type ComponentFamilySelectorV2< + StateType, + FamilyKey extends SerializableParam, +> = { + type: Extract<ComponentStateTypeV2, 'ComponentFamilySelector'>; + key: string; + selectorFamily: ( + componentFamilyStateKey: ComponentFamilyStateKeyV2<FamilyKey>, + ) => RecoilState<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2.ts new file mode 100644 index 000000000000..a5e278b46cf2 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2.ts @@ -0,0 +1,7 @@ +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { SerializableParam } from 'recoil'; + +export type ComponentFamilyStateKeyV2<FamilyKey extends SerializableParam> = + ComponentStateKeyV2 & { + familyKey: FamilyKey; + }; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateV2.ts new file mode 100644 index 000000000000..0410896ad99a --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyStateV2.ts @@ -0,0 +1,14 @@ +import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2'; +import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2'; +import { RecoilState, SerializableParam } from 'recoil'; + +export type ComponentFamilyStateV2< + StateType, + FamilyKey extends SerializableParam, +> = { + type: Extract<ComponentStateTypeV2, 'ComponentFamilyState'>; + key: string; + atomFamily: ( + componentFamilyStateKey: ComponentFamilyStateKeyV2<FamilyKey>, + ) => RecoilState<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentInstanceStateContext.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentInstanceStateContext.ts new file mode 100644 index 000000000000..10f558926b57 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentInstanceStateContext.ts @@ -0,0 +1,4 @@ +import { Context } from 'react'; + +export type ComponentInstanceStateContext<T extends { instanceId: string }> = + Context<T | null>; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2.ts new file mode 100644 index 000000000000..9e62e0a484f0 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2.ts @@ -0,0 +1,11 @@ +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2'; +import { RecoilValueReadOnly } from 'recoil'; + +export type ComponentReadOnlySelectorV2<StateType> = { + type: Extract<ComponentStateTypeV2, 'ComponentReadOnlySelector'>; + key: string; + selectorFamily: ( + componentStateKey: ComponentStateKeyV2, + ) => RecoilValueReadOnly<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentSelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentSelectorV2.ts new file mode 100644 index 000000000000..f93ef3e2227e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentSelectorV2.ts @@ -0,0 +1,11 @@ +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2'; +import { RecoilState } from 'recoil'; + +export type ComponentSelectorV2<StateType> = { + type: Extract<ComponentStateTypeV2, 'ComponentSelector'>; + key: string; + selectorFamily: ( + componentStateKey: ComponentStateKeyV2, + ) => RecoilState<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentState.ts deleted file mode 100644 index 8fc43e8a291b..000000000000 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { RecoilState } from 'recoil'; - -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; - -export type ComponentState<StateType> = { - key: string; - atomFamily: (componentStateKey: ComponentStateKey) => RecoilState<StateType>; -}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKey.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKey.ts deleted file mode 100644 index fb69c4c12212..000000000000 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKey.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type ComponentStateKey = { - scopeId: string; -}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKeyV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKeyV2.ts new file mode 100644 index 000000000000..524b9dfc88c2 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateKeyV2.ts @@ -0,0 +1,3 @@ +export type ComponentStateKeyV2 = { + instanceId: string; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateTypeV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateTypeV2.ts new file mode 100644 index 000000000000..83a3182a6a21 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateTypeV2.ts @@ -0,0 +1,7 @@ +export type ComponentStateTypeV2 = + | 'ComponentState' + | 'ComponentFamilyState' + | 'ComponentSelector' + | 'ComponentReadOnlySelector' + | 'ComponentFamilySelector' + | 'ComponentFamilyReadOnlySelector'; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateV2.ts new file mode 100644 index 000000000000..faeab37dd22c --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentStateV2.ts @@ -0,0 +1,11 @@ +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2'; +import { RecoilState } from 'recoil'; + +export type ComponentStateV2<StateType> = { + type: Extract<ComponentStateTypeV2, 'ComponentState'>; + key: string; + atomFamily: ( + componentStateKey: ComponentStateKeyV2, + ) => RecoilState<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentState.ts new file mode 100644 index 000000000000..8c007e5bddaa --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentState.ts @@ -0,0 +1,9 @@ +import { RecoilState } from 'recoil'; +import { RecoilComponentStateKey } from './RecoilComponentStateKey'; + +export type RecoilComponentState<StateType> = { + key: string; + atomFamily: ( + componentStateKey: RecoilComponentStateKey, + ) => RecoilState<StateType>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentStateKey.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentStateKey.ts new file mode 100644 index 000000000000..6627f39f92a8 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/RecoilComponentStateKey.ts @@ -0,0 +1,3 @@ +export type RecoilComponentStateKey = { + scopeId: string; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts new file mode 100644 index 000000000000..04c9a2d2a8b4 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts @@ -0,0 +1,58 @@ +import { selectorFamily, SerializableParam } from 'recoil'; + +import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2'; +import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2'; +import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2'; +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter'; +import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter'; +import { isDefined } from 'twenty-ui'; + +export const createComponentFamilySelectorV2 = < + ValueType, + FamilyKey extends SerializableParam, +>({ + key, + get, + set, + componentInstanceContext, +}: { + key: string; + get: SelectorGetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>; + set?: SelectorSetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>; + componentInstanceContext: ComponentInstanceStateContext<any> | null; +}): + | ComponentFamilySelectorV2<ValueType, FamilyKey> + | ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey> => { + if (isDefined(componentInstanceContext)) { + globalComponentInstanceContextMap.set(key, componentInstanceContext); + } + + if (isDefined(set)) { + return { + type: 'ComponentFamilySelector', + key, + selectorFamily: selectorFamily< + ValueType, + ComponentFamilyStateKeyV2<FamilyKey> + >({ + key, + get, + set, + }), + } satisfies ComponentFamilySelectorV2<ValueType, FamilyKey>; + } else { + return { + type: 'ComponentFamilyReadOnlySelector', + key, + selectorFamily: selectorFamily< + ValueType, + ComponentFamilyStateKeyV2<FamilyKey> + >({ + key, + get, + }), + } satisfies ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>; + } +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts index b3f7b3b5b423..2d1f42e61fdb 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts @@ -1,13 +1,15 @@ +import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2'; +import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2'; +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; import { AtomEffect, atomFamily, SerializableParam } from 'recoil'; -import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext'; -import { ComponentFamilyStateKey } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKey'; import { isDefined } from 'twenty-ui'; -type CreateComponentFamilyStateV2Type<ValueType> = { +type CreateComponentFamilyStateArgs<ValueType> = { key: string; defaultValue: ValueType; - componentContext: ScopeInternalContext<any> | null; + componentInstanceContext: ComponentInstanceStateContext<any> | null; effects?: AtomEffect<ValueType>[]; }; @@ -18,22 +20,22 @@ export const createComponentFamilyStateV2 = < key, effects, defaultValue, - componentContext, -}: CreateComponentFamilyStateV2Type<ValueType>) => { - if (isDefined(componentContext)) { - if (!isDefined((window as any).componentContextStateMap)) { - (window as any).componentContextStateMap = new Map(); - } - - (window as any).componentContextStateMap.set(key, componentContext); + componentInstanceContext, +}: CreateComponentFamilyStateArgs<ValueType>): ComponentFamilyStateV2< + ValueType, + FamilyKey +> => { + if (isDefined(componentInstanceContext)) { + globalComponentInstanceContextMap.set(key, componentInstanceContext); } return { + type: 'ComponentFamilyState', key, - atomFamily: atomFamily<ValueType, ComponentFamilyStateKey<FamilyKey>>({ + atomFamily: atomFamily<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>({ key, default: defaultValue, effects, }), - }; + } satisfies ComponentFamilyStateV2<ValueType, FamilyKey>; }; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentInstanceContext.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentInstanceContext.ts new file mode 100644 index 000000000000..68b9d93a662c --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentInstanceContext.ts @@ -0,0 +1,13 @@ +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { createContext } from 'react'; + +export const createComponentInstanceContext = < + T extends ComponentStateKeyV2 = ComponentStateKeyV2, +>( + initialValue?: T, +) => { + return createContext<T | null>( + initialValue ?? null, + ) as ComponentInstanceStateContext<T>; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentReadOnlySelector.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentReadOnlySelector.ts index 3369abc7743c..5fa337823974 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentReadOnlySelector.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentReadOnlySelector.ts @@ -1,6 +1,6 @@ import { selectorFamily } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter'; export const createComponentReadOnlySelector = <ValueType>({ @@ -8,9 +8,9 @@ export const createComponentReadOnlySelector = <ValueType>({ get, }: { key: string; - get: SelectorGetter<ValueType, ComponentStateKey>; + get: SelectorGetter<ValueType, RecoilComponentStateKey>; }) => { - return selectorFamily<ValueType, ComponentStateKey>({ + return selectorFamily<ValueType, RecoilComponentStateKey>({ key, get, }); diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelector.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelector.ts index c4dfc647bb85..545845ccda78 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelector.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelector.ts @@ -1,6 +1,6 @@ import { selectorFamily } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter'; import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter'; @@ -10,10 +10,10 @@ export const createComponentSelector = <ValueType>({ set, }: { key: string; - get: SelectorGetter<ValueType, ComponentStateKey>; - set: SelectorSetter<ValueType, ComponentStateKey>; + get: SelectorGetter<ValueType, RecoilComponentStateKey>; + set: SelectorSetter<ValueType, RecoilComponentStateKey>; }) => { - return selectorFamily<ValueType, ComponentStateKey>({ + return selectorFamily<ValueType, RecoilComponentStateKey>({ key, get, set, diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelectorV2.ts new file mode 100644 index 000000000000..352bff92ff47 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentSelectorV2.ts @@ -0,0 +1,47 @@ +import { selectorFamily } from 'recoil'; + +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { ComponentReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2'; +import { ComponentSelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentSelectorV2'; +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; +import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter'; +import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter'; +import { isDefined } from 'twenty-ui'; + +export const createComponentSelectorV2 = <ValueType>({ + key, + get, + set, + instanceContext, +}: { + key: string; + get: SelectorGetter<ValueType, ComponentStateKeyV2>; + set?: SelectorSetter<ValueType, ComponentStateKeyV2>; + instanceContext: ComponentInstanceStateContext<any> | null; +}): ComponentSelectorV2<ValueType> | ComponentReadOnlySelectorV2<ValueType> => { + if (isDefined(instanceContext)) { + globalComponentInstanceContextMap.set(key, instanceContext); + } + + if (isDefined(set)) { + return { + type: 'ComponentSelector', + key, + selectorFamily: selectorFamily<ValueType, ComponentStateKeyV2>({ + key, + get, + set, + }), + } satisfies ComponentSelectorV2<ValueType>; + } else { + return { + type: 'ComponentReadOnlySelector', + key, + selectorFamily: selectorFamily<ValueType, ComponentStateKeyV2>({ + key, + get, + }), + } satisfies ComponentReadOnlySelectorV2<ValueType>; + } +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentState.ts index ffbd9dd7eb48..5f2cd0badc32 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentState.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentState.ts @@ -1,6 +1,6 @@ import { AtomEffect, atomFamily } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; type CreateComponentStateType<ValueType> = { key: string; @@ -13,7 +13,7 @@ export const createComponentState = <ValueType>({ defaultValue, effects, }: CreateComponentStateType<ValueType>) => { - return atomFamily<ValueType, ComponentStateKey>({ + return atomFamily<ValueType, RecoilComponentStateKey>({ key, default: defaultValue, effects: effects, diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2.ts index 1fda1db8210e..dc87cbf0cfab 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2.ts @@ -1,37 +1,35 @@ +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2'; +import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2'; +import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; import { AtomEffect, atomFamily } from 'recoil'; -import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext'; -import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; import { isDefined } from '~/utils/isDefined'; -type CreateComponentStateV2Type<ValueType> = { +type CreateComponentInstanceStateArgs<ValueType> = { key: string; defaultValue: ValueType; - componentContext?: ScopeInternalContext<any> | null; + componentInstanceContext: ComponentInstanceStateContext<any> | null; effects?: AtomEffect<ValueType>[]; }; export const createComponentStateV2 = <ValueType>({ key, defaultValue, - componentContext, + componentInstanceContext, effects, -}: CreateComponentStateV2Type<ValueType>): ComponentState<ValueType> => { - if (isDefined(componentContext)) { - if (!isDefined((window as any).componentContextStateMap)) { - (window as any).componentContextStateMap = new Map(); - } - - (window as any).componentContextStateMap.set(key, componentContext); +}: CreateComponentInstanceStateArgs<ValueType>): ComponentStateV2<ValueType> => { + if (isDefined(componentInstanceContext)) { + globalComponentInstanceContextMap.set(key, componentInstanceContext); } return { + type: 'ComponentState', key, - atomFamily: atomFamily<ValueType, ComponentStateKey>({ + atomFamily: atomFamily<ValueType, ComponentStateKeyV2>({ key, default: defaultValue, effects: effects, }), - }; + } satisfies ComponentStateV2<ValueType>; }; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2_alpha.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2_alpha.ts new file mode 100644 index 000000000000..2533b0542785 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentStateV2_alpha.ts @@ -0,0 +1,38 @@ +import { AtomEffect, atomFamily } from 'recoil'; + +import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext'; + +import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; +import { isDefined } from '~/utils/isDefined'; + +type CreateComponentStateV2Type<ValueType> = { + key: string; + defaultValue: ValueType; + componentContext?: ScopeInternalContext<any> | null; + effects?: AtomEffect<ValueType>[]; +}; + +export const createComponentStateV2_alpha = <ValueType>({ + key, + defaultValue, + componentContext, + effects, +}: CreateComponentStateV2Type<ValueType>): RecoilComponentState<ValueType> => { + if (isDefined(componentContext)) { + if (!isDefined((window as any).componentContextStateMap)) { + (window as any).componentContextStateMap = new Map(); + } + + (window as any).componentContextStateMap.set(key, componentContext); + } + + return { + key, + atomFamily: atomFamily<ValueType, RecoilComponentStateKey>({ + key, + default: defaultValue, + effects: effects, + }), + }; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createEventContext.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createEventContext.ts new file mode 100644 index 000000000000..723e1c3f3ef1 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createEventContext.ts @@ -0,0 +1,9 @@ +import { createContext } from 'react'; + +export const createEventContext = < + Events extends Record<string, (...args: any) => void>, +>( + initialValue?: Events, +) => { + return createContext<Events>((initialValue ?? {}) as Events); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector.ts index 98489a2669e2..da5b494b6e5a 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector.ts @@ -1,10 +1,10 @@ import { RecoilValueReadOnly } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; export const extractComponentReadOnlySelector = <StateType>( componentSelector: ( - componentStateKey: ComponentStateKey, + componentStateKey: RecoilComponentStateKey, ) => RecoilValueReadOnly<StateType>, scopeId: string, ) => { diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentSelector.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentSelector.ts index 60f6fa75da60..40befcf6feb6 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentSelector.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentSelector.ts @@ -1,10 +1,10 @@ import { RecoilState } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; export const extractComponentSelector = <StateType>( componentSelector: ( - componentStateKey: ComponentStateKey, + componentStateKey: RecoilComponentStateKey, ) => RecoilState<StateType>, scopeId: string, ) => { diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts index ea797fe77ea7..cac495c0c2dc 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/extractComponentState.ts @@ -1,10 +1,10 @@ import { RecoilState } from 'recoil'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; +import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; export const extractComponentState = <StateType>( componentState: ( - componentStateKey: ComponentStateKey, + componentStateKey: RecoilComponentStateKey, ) => RecoilState<StateType>, scopeId: string, ) => { diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap.ts new file mode 100644 index 000000000000..3dd5ce612f0d --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap.ts @@ -0,0 +1,21 @@ +import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext'; +import { isDefined } from 'twenty-ui'; + +class ComponentInstanceContextMap { + constructor() { + if (!isDefined((window as any).componentComponentStateContextMap)) { + (window as any).componentComponentStateContextMap = new Map(); + } + } + + public get(key: string): ComponentInstanceStateContext<any> { + return (window as any).componentComponentStateContextMap.get(key); + } + + public set(key: string, context: ComponentInstanceStateContext<any>) { + (window as any).componentComponentStateContextMap.set(key, context); + } +} + +export const globalComponentInstanceContextMap = + new ComponentInstanceContextMap(); diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx index 23613d5c35aa..b8b9fe56ffa4 100644 --- a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx @@ -1,5 +1,4 @@ import { useCallback, useEffect } from 'react'; -import { useRecoilValue } from 'recoil'; import { MultipleFiltersDropdownContent } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; @@ -8,8 +7,12 @@ import { FilterOperand } from '@/object-record/object-filter-dropdown/types/Filt import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { EditableFilterChip } from '@/views/components/EditableFilterChip'; -import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; + +import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; import { isDefined } from '~/utils/isDefined'; type EditableFilterDropdownButtonProps = { @@ -24,21 +27,23 @@ export const EditableFilterDropdownButton = ({ hotkeyScope, }: EditableFilterDropdownButtonProps) => { const { - availableFilterDefinitionsState, setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, setSelectedFilter, + setIsObjectFilterDropdownOperandSelectUnfolded, } = useFilterDropdown({ filterDropdownId: viewFilterDropdownId, }); - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + // TODO: verify this instance id works + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, + viewFilterDropdownId, ); const { closeDropdown } = useDropdown(viewFilterDropdownId); - const { removeCombinedViewFilter } = useCombinedViewFilters(); + const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters(); useEffect(() => { const filterDefinition = availableFilterDefinitions.find( @@ -63,18 +68,28 @@ export const EditableFilterDropdownButton = ({ const handleRemove = () => { closeDropdown(); - removeCombinedViewFilter(viewFilter.id); + deleteCombinedViewFilter(viewFilter.id); }; const handleDropdownClickOutside = useCallback(() => { const { id: fieldId, value, operand } = viewFilter; if ( !value && - ![FilterOperand.IsEmpty, FilterOperand.IsNotEmpty].includes(operand) + ![ + FilterOperand.IsEmpty, + FilterOperand.IsNotEmpty, + ViewFilterOperand.IsInPast, + ViewFilterOperand.IsInFuture, + ViewFilterOperand.IsToday, + ].includes(operand) ) { - removeCombinedViewFilter(fieldId); + deleteCombinedViewFilter(fieldId); } - }, [viewFilter, removeCombinedViewFilter]); + }, [viewFilter, deleteCombinedViewFilter]); + + const handleDropdownClose = useCallback(() => { + setIsObjectFilterDropdownOperandSelectUnfolded(false); + }, [setIsObjectFilterDropdownOperandSelectUnfolded]); return ( <Dropdown @@ -91,6 +106,7 @@ export const EditableFilterDropdownButton = ({ dropdownOffset={{ y: 8, x: 0 }} dropdownPlacement="bottom-start" onClickOutside={handleDropdownClickOutside} + onClose={handleDropdownClose} /> ); }; diff --git a/packages/twenty-front/src/modules/views/components/EditableSortChip.tsx b/packages/twenty-front/src/modules/views/components/EditableSortChip.tsx index c1cab0fdaede..87ed8e91d162 100644 --- a/packages/twenty-front/src/modules/views/components/EditableSortChip.tsx +++ b/packages/twenty-front/src/modules/views/components/EditableSortChip.tsx @@ -2,18 +2,20 @@ import { IconArrowDown, IconArrowUp } from 'twenty-ui'; import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; -import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts'; +import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts'; +import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts'; type EditableSortChipProps = { viewSort: Sort; }; export const EditableSortChip = ({ viewSort }: EditableSortChipProps) => { - const { removeCombinedViewSort, upsertCombinedViewSort } = - useCombinedViewSorts(); + const { deleteCombinedViewSort } = useDeleteCombinedViewSorts(); + + const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(); const handleRemoveClick = () => { - removeCombinedViewSort(viewSort.fieldMetadataId); + deleteCombinedViewSort(viewSort.fieldMetadataId); }; const handleClick = () => { diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx index 25278a77c9c4..10ecdfa83b87 100644 --- a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx @@ -1,18 +1,23 @@ import { useEffect } from 'react'; -import { useSetRecoilState } from 'recoil'; +import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2'; import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; +import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { isDefined } from 'twenty-ui'; export const QueryParamsFiltersEffect = () => { - const { hasFiltersQueryParams, getFiltersFromQueryParams } = + const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } = useViewFromQueryParams(); - const { unsavedToUpsertViewFiltersState } = useViewStates(); - const setUnsavedViewFilter = useSetRecoilState( - unsavedToUpsertViewFiltersState, + + const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2( + unsavedToUpsertViewFiltersComponentFamilyState, + { viewId: viewIdQueryParam }, ); - const { resetCurrentView } = useResetCurrentView(); + + const { resetUnsavedViewStates } = useResetUnsavedViewStates(); + const { currentViewId } = useGetCurrentView(); useEffect(() => { if (!hasFiltersQueryParams) { @@ -26,13 +31,16 @@ export const QueryParamsFiltersEffect = () => { }); return () => { - resetCurrentView(); + if (isDefined(currentViewId)) { + resetUnsavedViewStates(currentViewId); + } }; }, [ getFiltersFromQueryParams, hasFiltersQueryParams, - resetCurrentView, + resetUnsavedViewStates, setUnsavedViewFilter, + currentViewId, ]); return <></>; diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx index ddd25463b81c..2ee24d43fdc3 100644 --- a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx @@ -1,21 +1,26 @@ import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem'; import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; import { isUndefined } from '@sniptt/guards'; import { useEffect } from 'react'; -import { useRecoilState } from 'recoil'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDefined } from '~/utils/isDefined'; export const QueryParamsViewIdEffect = () => { const { getFiltersFromQueryParams, viewIdQueryParam } = useViewFromQueryParams(); - const { currentViewIdState, componentId: objectNamePlural } = useViewStates(); - const [currentViewId, setCurrentViewId] = useRecoilState(currentViewIdState); + // TODO: fix this implicit hack + const { instanceId: objectNamePlural } = useGetCurrentView(); + + const [currentViewId, setCurrentViewId] = useRecoilComponentStateV2( + currentViewIdComponentState, + ); + const { viewsOnCurrentObject } = useGetCurrentView(); const { findObjectMetadataItemByNamePlural } = useFilteredObjectMetadataItems(); @@ -33,6 +38,15 @@ export const QueryParamsViewIdEffect = () => { lastVisitedObjectMetadataItemId, ); + // // TODO: scope view bar per view id if possible + // const { resetCurrentView } = useResetCurrentView(); + + // useEffect(() => { + // if (isDefined(currentViewId)) { + // resetCurrentView(); + // } + // }, [resetCurrentView, currentViewId]); + useEffect(() => { const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX'); diff --git a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx index b41269b4e7a5..fa40544755de 100644 --- a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx +++ b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx @@ -1,6 +1,4 @@ -import { useCallback } from 'react'; import styled from '@emotion/styled'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; import { IconChevronDown, IconPlus } from 'twenty-ui'; import { Button } from '@/ui/input/button/components/Button'; @@ -10,14 +8,18 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { UPDATE_VIEW_BUTTON_DROPDOWN_ID } from '@/views/constants/UpdateViewButtonDropdownId'; import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { canPersistViewComponentFamilySelector } from '@/views/states/selectors/canPersistViewComponentFamilySelector'; import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId'; import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; +import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState'; const StyledContainer = styled.div` border-radius: ${({ theme }) => theme.border.radius.md}; @@ -33,12 +35,16 @@ export type UpdateViewButtonGroupProps = { export const UpdateViewButtonGroup = ({ hotkeyScope, }: UpdateViewButtonGroupProps) => { - const { canPersistViewSelector, currentViewIdState } = useViewStates(); const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts(); const { setViewPickerMode } = useViewPickerMode(); - const { viewPickerReferenceViewIdState } = useViewPickerStates(); - const canPersistView = useRecoilValue(canPersistViewSelector()); + + const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState); + + const canPersistView = useRecoilComponentFamilyValueV2( + canPersistViewComponentFamilySelector, + { viewId: currentViewId }, + ); const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown( UPDATE_VIEW_BUTTON_DROPDOWN_ID, @@ -48,30 +54,31 @@ export const UpdateViewButtonGroup = ({ ); const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); - const currentViewId = useRecoilValue(currentViewIdState); - - const setViewPickerReferenceViewId = useSetRecoilState( - viewPickerReferenceViewIdState, + const setViewPickerReferenceViewId = useSetRecoilComponentStateV2( + viewPickerReferenceViewIdComponentState, ); - const handleViewCreate = useCallback(() => { + const openViewPickerInCreateMode = () => { if (!currentViewId) { return; } + openViewPickerDropdown(); setViewPickerReferenceViewId(currentViewId); - setViewPickerMode('create'); + setViewPickerMode('create-from-current'); closeUpdateViewButtonDropdown(); - }, [ - closeUpdateViewButtonDropdown, - currentViewId, - openViewPickerDropdown, - setViewPickerMode, - setViewPickerReferenceViewId, - ]); - - const handleViewUpdate = async () => { + }; + + const handleCreateViewClick = () => { + openViewPickerInCreateMode(); + }; + + const handleSaveAsNewViewClick = () => { + openViewPickerInCreateMode(); + }; + + const handleUpdateViewClick = async () => { await saveCurrentViewFilterAndSorts(); }; @@ -87,7 +94,7 @@ export const UpdateViewButtonGroup = ({ <StyledContainer> {currentViewWithCombinedFiltersAndSorts?.key !== 'INDEX' ? ( <ButtonGroup size="small" accent="blue"> - <Button title="Update view" onClick={handleViewUpdate} /> + <Button title="Update view" onClick={handleUpdateViewClick} /> <Dropdown dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID} dropdownHotkeyScope={hotkeyScope} @@ -103,7 +110,7 @@ export const UpdateViewButtonGroup = ({ <> <DropdownMenuItemsContainer> <MenuItem - onClick={handleViewCreate} + onClick={handleCreateViewClick} LeftIcon={IconPlus} text="Create view" /> @@ -115,7 +122,7 @@ export const UpdateViewButtonGroup = ({ ) : ( <Button title="Save as new view" - onClick={handleViewCreate} + onClick={handleSaveAsNewViewClick} accent="blue" size="small" variant="secondary" diff --git a/packages/twenty-front/src/modules/views/components/VariantFilterChip.tsx b/packages/twenty-front/src/modules/views/components/VariantFilterChip.tsx index 70033af530d8..79834cb7d3c4 100644 --- a/packages/twenty-front/src/modules/views/components/VariantFilterChip.tsx +++ b/packages/twenty-front/src/modules/views/components/VariantFilterChip.tsx @@ -1,20 +1,44 @@ import { useIcons } from 'twenty-ui'; +import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; -import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; +import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters'; +import { useParams } from 'react-router-dom'; type VariantFilterChipProps = { viewFilter: Filter; + viewBarId: string; }; -export const VariantFilterChip = ({ viewFilter }: VariantFilterChipProps) => { - const { removeCombinedViewFilter } = useCombinedViewFilters(); +export const VariantFilterChip = ({ + viewFilter, + viewBarId, +}: VariantFilterChipProps) => { + const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters(); + + const { objectNamePlural } = useParams(); + + const { objectNameSingular } = useObjectNameSingularFromPlural({ + objectNamePlural: objectNamePlural ?? '', + }); + + const { toggleSoftDeleteFilterState } = useHandleToggleTrashColumnFilter({ + objectNameSingular, + viewBarId, + }); const { getIcon } = useIcons(); const handleRemoveClick = () => { - removeCombinedViewFilter(viewFilter.id); + deleteCombinedViewFilter(viewFilter.id); + if ( + viewFilter.definition.label === 'Deleted' && + viewFilter.operand === 'isNotEmpty' + ) { + toggleSoftDeleteFilterState(false); + } }; return ( diff --git a/packages/twenty-front/src/modules/views/components/ViewBar.tsx b/packages/twenty-front/src/modules/views/components/ViewBar.tsx index 3c600daec05f..724b80e461c3 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBar.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBar.tsx @@ -13,12 +13,12 @@ import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect'; import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle'; import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader'; import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect'; -import { ViewScope } from '@/views/scopes/ViewScope'; import { GraphQLView } from '@/views/types/GraphQLView'; import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown'; import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope'; +import { ViewEventContext } from '@/views/events/contexts/ViewEventContext'; import { UpdateViewButtonGroup } from './UpdateViewButtonGroup'; import { ViewBarDetails } from './ViewBarDetails'; @@ -41,15 +41,13 @@ export const ViewBar = ({ const sortDropdownId = 'view-sort'; const loading = useIsPrefetchLoading(); + if (!objectNamePlural) { return; } return ( - <ViewScope - viewScopeId={viewBarId} - onCurrentViewChange={onCurrentViewChange} - > + <ViewEventContext.Provider value={{ onCurrentViewChange }}> <ViewBarEffect viewBarId={viewBarId} /> <ViewBarFilterEffect filterDropdownId={filterDropdownId} /> <ViewBarSortEffect sortDropdownId={sortDropdownId} /> @@ -95,6 +93,6 @@ export const ViewBar = ({ /> } /> - </ViewScope> + </ViewEventContext.Provider> ); }; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx b/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx index 6f2c9f6e7076..e3d443ace9e1 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx @@ -1,20 +1,25 @@ import styled from '@emotion/styled'; import { ReactNode, useMemo } from 'react'; -import { useRecoilValue } from 'recoil'; import { AddObjectFilterFromDetailsButton } from '@/object-record/object-filter-dropdown/components/AddObjectFilterFromDetailsButton'; import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { EditableFilterDropdownButton } from '@/views/components/EditableFilterDropdownButton'; import { EditableSortChip } from '@/views/components/EditableSortChip'; import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect'; import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; -import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; +import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; +import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState'; +import { canPersistViewComponentFamilySelector } from '@/views/states/selectors/canPersistViewComponentFamilySelector'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; +import { isDefined } from 'twenty-ui'; import { VariantFilterChip } from './VariantFilterChip'; export type ViewBarDetailsProps = { @@ -97,27 +102,32 @@ export const ViewBarDetails = ({ hasFilterButton = false, rightComponent, filterDropdownId, + viewBarId, }: ViewBarDetailsProps) => { - const { - canPersistViewSelector, - isViewBarExpandedState, - availableFilterDefinitionsState, - availableSortDefinitionsState, - } = useViewStates(); - const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); - const isViewBarExpanded = useRecoilValue(isViewBarExpandedState); + const viewId = currentViewWithCombinedFiltersAndSorts?.id; + + const isViewBarExpanded = useRecoilComponentValueV2( + isViewBarExpandedComponentState, + ); + const { hasFiltersQueryParams } = useViewFromQueryParams(); - const canPersistView = useRecoilValue(canPersistViewSelector()); - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + + const canPersistView = useRecoilComponentFamilyValueV2( + canPersistViewComponentFamilySelector, + { viewId }, ); - const availableSortDefinitions = useRecoilValue( - availableSortDefinitionsState, + + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, + ); + + const availableSortDefinitions = useRecoilComponentValueV2( + availableSortDefinitionsComponentState, ); - const { resetCurrentView } = useResetCurrentView(); + const { resetUnsavedViewStates } = useResetUnsavedViewStates(); const canResetView = canPersistView && !hasFiltersQueryParams; const { otherViewFilters, defaultViewFilters } = useMemo(() => { @@ -144,7 +154,9 @@ export const ViewBarDetails = ({ }, [currentViewWithCombinedFiltersAndSorts]); const handleCancelClick = () => { - resetCurrentView(); + if (isDefined(viewId)) { + resetUnsavedViewStates(viewId); + } }; const shouldExpandViewBar = @@ -169,6 +181,7 @@ export const ViewBarDetails = ({ // Also as filter is spread into viewFilter, definition is present // FixMe: Ugly hack to make it work viewFilter={viewFilter as unknown as Filter} + viewBarId={viewBarId} /> ))} {!!otherViewFilters.length && diff --git a/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx index a23b73922d8b..8137fb6d1e66 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx @@ -1,9 +1,11 @@ import { isUndefined } from '@sniptt/guards'; -import { useEffect, useState } from 'react'; -import { useRecoilValue } from 'recoil'; +import { useContext, useEffect, useState } from 'react'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { ViewEventContext } from '@/views/events/contexts/ViewEventContext'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState'; import { View } from '@/views/types/View'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; @@ -14,21 +16,22 @@ type ViewBarEffectProps = { export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => { const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(viewBarId); - const { - onCurrentViewChangeState, - availableFilterDefinitionsState, - isPersistingViewFieldsState, - } = useViewStates(viewBarId); + + const { onCurrentViewChange } = useContext(ViewEventContext); const [currentViewSnapshot, setCurrentViewSnapshot] = useState< View | undefined >(undefined); - const onCurrentViewChange = useRecoilValue(onCurrentViewChangeState); - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, + viewBarId, + ); + + const isPersistingViewFields = useRecoilComponentValueV2( + isPersistingViewFieldsComponentState, + viewBarId, ); - const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState); useEffect(() => { if ( diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx index 544e3466fbb9..ed632475f0fe 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterEffect.tsx @@ -1,12 +1,15 @@ -import { useEffect } from 'react'; import { isNonEmptyString } from '@sniptt/guards'; +import { useEffect } from 'react'; import { useRecoilValue } from 'recoil'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; + import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; import { isDefined } from '~/utils/isDefined'; type ViewBarFilterEffectProps = { @@ -16,17 +19,15 @@ type ViewBarFilterEffectProps = { export const ViewBarFilterEffect = ({ filterDropdownId, }: ViewBarFilterEffectProps) => { - const { availableFilterDefinitionsState } = useViewStates(); - - const { upsertCombinedViewFilter } = useCombinedViewFilters(); + const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); - const availableFilterDefinitions = useRecoilValue( - availableFilterDefinitionsState, + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, ); + const { - setAvailableFilterDefinitions, setOnFilterSelect, filterDefinitionUsedInDropdownState, setObjectFilterDropdownSelectedRecordIds, @@ -37,6 +38,12 @@ export const ViewBarFilterEffect = ({ filterDefinitionUsedInDropdownState, ); + // TODO: verify this instance id works + const setAvailableFilterDefinitions = useSetRecoilComponentStateV2( + availableFilterDefinitionsComponentState, + filterDropdownId, + ); + useEffect(() => { if (isDefined(availableFilterDefinitions)) { setAvailableFilterDefinitions(availableFilterDefinitions); diff --git a/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx index 0baba6d0b403..78d00fbf9332 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarSortEffect.tsx @@ -1,10 +1,12 @@ import { useEffect } from 'react'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown'; import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; import { isDefined } from '~/utils/isDefined'; type ViewBarSortEffectProps = { @@ -14,23 +16,23 @@ type ViewBarSortEffectProps = { export const ViewBarSortEffect = ({ sortDropdownId, }: ViewBarSortEffectProps) => { - const { availableSortDefinitionsState } = useViewStates(); - const { upsertCombinedViewSort } = useCombinedViewSorts(); + const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(); - const availableSortDefinitions = useRecoilValue( - availableSortDefinitionsState, + // TDOO: verify this instance id works + const availableSortDefinitions = useRecoilComponentValueV2( + availableSortDefinitionsComponentState, ); - const { - availableSortDefinitionsState: availableSortDefinitionsInSortDropdownState, - onSortSelectState, - } = useSortDropdown({ + const { onSortSelectState } = useSortDropdown({ sortDropdownId, }); - const setAvailableSortDefinitionsInSortDropdown = useSetRecoilState( - availableSortDefinitionsInSortDropdownState, - ); + // TDOO: verify this instance id works + const setAvailableSortDefinitionsInSortDropdown = + useSetRecoilComponentStateV2( + availableSortDefinitionsComponentState, + sortDropdownId, + ); const setOnSortSelect = useSetRecoilState(onSortSelectState); useEffect(() => { diff --git a/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts b/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts new file mode 100644 index 000000000000..ba02a09aa2e4 --- /dev/null +++ b/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts @@ -0,0 +1,8 @@ +import { View } from '@/views/types/View'; +import { createEventContext } from '~/utils/createEventContext'; + +type ViewEventContextType = { + onCurrentViewChange: (view: View | undefined) => void | Promise<void>; +}; + +export const ViewEventContext = createEventContext<ViewEventContextType>(); diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts index 9198268946d4..53ce7b69fd43 100644 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts +++ b/packages/twenty-front/src/modules/views/hooks/internal/useViewFromQueryParams.ts @@ -1,8 +1,8 @@ -import { useMemo } from 'react'; -import { useParams, useSearchParams } from 'react-router-dom'; import { useApolloClient } from '@apollo/client'; import { isNonEmptyString } from '@sniptt/guards'; import qs from 'qs'; +import { useMemo } from 'react'; +import { useParams, useSearchParams } from 'react-router-dom'; import { useRecoilCallback, useRecoilValue } from 'recoil'; import z from 'zod'; @@ -92,12 +92,12 @@ export const useViewFromQueryParams = () => { if (isUndefinedOrNull(filterDefinition)) return null; const relationObjectMetadataNameSingular = - fieldMetadataItem.toRelationMetadata?.fromObjectMetadata - .nameSingular; + fieldMetadataItem.relationDefinition?.targetObjectMetadata + ?.nameSingular; const relationObjectMetadataNamePlural = - fieldMetadataItem.toRelationMetadata?.fromObjectMetadata - .namePlural; + fieldMetadataItem.relationDefinition?.targetObjectMetadata + ?.namePlural; const relationObjectMetadataItem = relationObjectMetadataNameSingular diff --git a/packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts b/packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts deleted file mode 100644 index 02f1a4cf6004..000000000000 --- a/packages/twenty-front/src/modules/views/hooks/internal/useViewStates.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { extractComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector'; -import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; -import { availableFieldDefinitionsComponentState } from '@/views/states/availableFieldDefinitionsComponentState'; -import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; -import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; -import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; -import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState'; -import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState'; -import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState'; -import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState'; -import { onCurrentViewChangeComponentState } from '@/views/states/onCurrentViewChangeComponentState'; -import { canPersistViewComponentSelector } from '@/views/states/selectors/canPersistViewComponentSelector'; -import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState'; -import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState'; -import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState'; -import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState'; -import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState'; - -import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext'; - -export const useViewStates = (viewComponentId?: string) => { - const componentId = useAvailableScopeIdOrThrow( - ViewScopeInternalContext, - viewComponentId, - ); - - return { - componentId, - currentViewIdState: extractComponentState( - currentViewIdComponentState, - componentId, - ), - availableFieldDefinitionsState: extractComponentState( - availableFieldDefinitionsComponentState, - componentId, - ), - availableFilterDefinitionsState: extractComponentState( - availableFilterDefinitionsComponentState, - componentId, - ), - availableSortDefinitionsState: extractComponentState( - availableSortDefinitionsComponentState, - componentId, - ), - canPersistViewSelector: extractComponentReadOnlySelector( - canPersistViewComponentSelector, - componentId, - ), - isViewBarExpandedState: extractComponentState( - isViewBarExpandedComponentState, - componentId, - ), - onCurrentViewChangeState: extractComponentState( - onCurrentViewChangeComponentState, - componentId, - ), - entityCountInCurrentViewState: extractComponentState( - entityCountInCurrentViewComponentState, - componentId, - ), - viewObjectMetadataIdState: extractComponentState( - viewObjectMetadataIdComponentState, - componentId, - ), - unsavedToUpsertViewFiltersState: extractComponentState( - unsavedToUpsertViewFiltersComponentState, - componentId, - ), - unsavedToUpsertViewSortsState: extractComponentState( - unsavedToUpsertViewSortsComponentState, - componentId, - ), - unsavedToDeleteViewFilterIdsState: extractComponentState( - unsavedToDeleteViewFilterIdsComponentState, - componentId, - ), - unsavedToDeleteViewSortIdsState: extractComponentState( - unsavedToDeleteViewSortIdsComponentState, - componentId, - ), - isPersistingViewFieldsState: extractComponentState( - isPersistingViewFieldsComponentState, - componentId, - ), - isCurrentViewKeyIndexState: extractComponentState( - isCurrentViewKeyIndexComponentState, - componentId, - ), - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts new file mode 100644 index 000000000000..669de5157b1b --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts @@ -0,0 +1,24 @@ +import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; +import { useSearchParams } from 'react-router-dom'; + +export const useChangeView = (viewBarComponentId?: string) => { + const { resetUnsavedViewStates } = + useResetUnsavedViewStates(viewBarComponentId); + + const [, setSearchParams] = useSearchParams(); + + const setViewInUrl = (viewId: string) => { + setSearchParams(() => { + const searchParams = new URLSearchParams(); + searchParams.set('view', viewId); + return searchParams; + }); + }; + + const changeView = async (viewId: string) => { + setViewInUrl(viewId); + resetUnsavedViewStates(viewId); + }; + + return { changeView }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts deleted file mode 100644 index fb93ea8205db..000000000000 --- a/packages/twenty-front/src/modules/views/hooks/useCombinedViewFilters.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { useRecoilCallback } from 'recoil'; - -import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; -import { ViewFilter } from '@/views/types/ViewFilter'; -import { isDefined } from '~/utils/isDefined'; - -export const useCombinedViewFilters = (viewBarComponentId?: string) => { - const { - unsavedToUpsertViewFiltersState, - unsavedToDeleteViewFilterIdsState, - currentViewIdState, - } = useViewStates(viewBarComponentId); - - const { getViewFromCache } = useGetViewFromCache(); - - const upsertCombinedViewFilter = useRecoilCallback( - ({ snapshot, set }) => - async (upsertedFilter: Filter) => { - const unsavedToUpsertViewFilters = getSnapshotValue( - snapshot, - unsavedToUpsertViewFiltersState, - ); - - const unsavedToDeleteViewFilterIds = getSnapshotValue( - snapshot, - unsavedToDeleteViewFilterIdsState, - ); - - const currentViewId = getSnapshotValue(snapshot, currentViewIdState); - - if (!currentViewId) { - return; - } - - const currentView = await getViewFromCache(currentViewId); - - if (!currentView) { - return; - } - - const matchingFilterInCurrentView = currentView.viewFilters.find( - (viewFilter) => - viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId, - ); - - const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find( - (viewFilter) => - viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId, - ); - - if (isDefined(matchingFilterInUnsavedFilters)) { - const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) => - viewFilter.fieldMetadataId === - matchingFilterInUnsavedFilters.fieldMetadataId - ? { ...viewFilter, ...upsertedFilter, id: viewFilter.id } - : viewFilter, - ); - - set(unsavedToUpsertViewFiltersState, updatedFilters); - return; - } - - if (isDefined(matchingFilterInCurrentView)) { - set(unsavedToUpsertViewFiltersState, [ - ...unsavedToUpsertViewFilters, - { - ...matchingFilterInCurrentView, - ...upsertedFilter, - id: matchingFilterInCurrentView.id, - }, - ]); - set( - unsavedToDeleteViewFilterIdsState, - unsavedToDeleteViewFilterIds.filter( - (id) => id !== matchingFilterInCurrentView.id, - ), - ); - return; - } - - set(unsavedToUpsertViewFiltersState, [ - ...unsavedToUpsertViewFilters, - { - ...upsertedFilter, - __typename: 'ViewFilter', - } satisfies ViewFilter, - ]); - }, - [ - currentViewIdState, - getViewFromCache, - unsavedToDeleteViewFilterIdsState, - unsavedToUpsertViewFiltersState, - ], - ); - const removeCombinedViewFilter = useRecoilCallback( - ({ snapshot, set }) => - async (fieldId: string) => { - const unsavedToUpsertViewFilters = getSnapshotValue( - snapshot, - unsavedToUpsertViewFiltersState, - ); - - const unsavedToDeleteViewFilterIds = getSnapshotValue( - snapshot, - unsavedToDeleteViewFilterIdsState, - ); - - const currentViewId = getSnapshotValue(snapshot, currentViewIdState); - - if (!currentViewId) { - return; - } - - const currentView = await getViewFromCache(currentViewId); - - if (!currentView) { - return; - } - - const matchingFilterInCurrentView = currentView.viewFilters.find( - (viewFilter) => viewFilter.id === fieldId, - ); - - const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find( - (viewFilter) => viewFilter.id === fieldId, - ); - - if (isDefined(matchingFilterInUnsavedFilters)) { - set( - unsavedToUpsertViewFiltersState, - unsavedToUpsertViewFilters.filter( - (viewFilter) => viewFilter.id !== fieldId, - ), - ); - } - - if (isDefined(matchingFilterInCurrentView)) { - set(unsavedToDeleteViewFilterIdsState, [ - ...new Set([ - ...unsavedToDeleteViewFilterIds, - matchingFilterInCurrentView.id, - ]), - ]); - } - }, - [ - currentViewIdState, - getViewFromCache, - unsavedToDeleteViewFilterIdsState, - unsavedToUpsertViewFiltersState, - ], - ); - return { - upsertCombinedViewFilter, - removeCombinedViewFilter, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts deleted file mode 100644 index 6f08d77b1715..000000000000 --- a/packages/twenty-front/src/modules/views/hooks/useCombinedViewSorts.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { useRecoilCallback } from 'recoil'; -import { v4 } from 'uuid'; - -import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; -import { ViewSort } from '@/views/types/ViewSort'; -import { isDefined } from '~/utils/isDefined'; - -export const useCombinedViewSorts = (viewBarComponentId?: string) => { - const { - unsavedToUpsertViewSortsState, - unsavedToDeleteViewSortIdsState, - currentViewIdState, - } = useViewStates(viewBarComponentId); - - const { getViewFromCache } = useGetViewFromCache(); - - const upsertCombinedViewSort = useRecoilCallback( - ({ snapshot, set }) => - async (upsertedSort: Sort) => { - const unsavedToUpsertViewSorts = getSnapshotValue( - snapshot, - unsavedToUpsertViewSortsState, - ); - - const unsavedToDeleteViewSortIds = getSnapshotValue( - snapshot, - unsavedToDeleteViewSortIdsState, - ); - - const currentViewId = getSnapshotValue(snapshot, currentViewIdState); - - if (!currentViewId) { - return; - } - - const currentView = await getViewFromCache(currentViewId); - - if (!currentView) { - return; - } - - const matchingSortInCurrentView = currentView.viewSorts.find( - (viewSort) => - viewSort.fieldMetadataId === upsertedSort.fieldMetadataId, - ); - - const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find( - (viewSort) => - viewSort.fieldMetadataId === upsertedSort.fieldMetadataId, - ); - - if (isDefined(matchingSortInUnsavedSorts)) { - const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) => - viewSort.id === matchingSortInUnsavedSorts.id - ? { ...viewSort, ...upsertedSort } - : viewSort, - ); - - set(unsavedToUpsertViewSortsState, updatedSorts); - return; - } - - if (isDefined(matchingSortInCurrentView)) { - set(unsavedToUpsertViewSortsState, [ - ...unsavedToUpsertViewSorts, - { ...matchingSortInCurrentView, ...upsertedSort }, - ]); - set( - unsavedToDeleteViewSortIdsState, - unsavedToDeleteViewSortIds.filter( - (id) => id !== matchingSortInCurrentView.id, - ), - ); - return; - } - - set(unsavedToUpsertViewSortsState, [ - ...unsavedToUpsertViewSorts, - { - ...upsertedSort, - id: v4(), - __typename: 'ViewSort', - } satisfies ViewSort, - ]); - }, - [ - currentViewIdState, - getViewFromCache, - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewSortsState, - ], - ); - const removeCombinedViewSort = useRecoilCallback( - ({ snapshot, set }) => - async (fieldMetadataId: string) => { - const unsavedToUpsertViewSorts = getSnapshotValue( - snapshot, - unsavedToUpsertViewSortsState, - ); - - const unsavedToDeleteViewSortIds = getSnapshotValue( - snapshot, - unsavedToDeleteViewSortIdsState, - ); - - const currentViewId = getSnapshotValue(snapshot, currentViewIdState); - - if (!currentViewId) { - return; - } - - const currentView = await getViewFromCache(currentViewId); - - if (!currentView) { - return; - } - - const matchingSortInCurrentView = currentView.viewSorts.find( - (viewSort) => viewSort.fieldMetadataId === fieldMetadataId, - ); - - const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find( - (viewSort) => viewSort.fieldMetadataId === fieldMetadataId, - ); - - if (isDefined(matchingSortInUnsavedSorts)) { - set( - unsavedToUpsertViewSortsState, - unsavedToUpsertViewSorts.filter( - (viewSort) => viewSort.fieldMetadataId !== fieldMetadataId, - ), - ); - return; - } - - if (isDefined(matchingSortInCurrentView)) { - set(unsavedToDeleteViewSortIdsState, [ - ...new Set([ - ...unsavedToDeleteViewSortIds, - matchingSortInCurrentView.id, - ]), - ]); - } - }, - [ - currentViewIdState, - getViewFromCache, - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewSortsState, - ], - ); - return { - upsertCombinedViewSort, - removeCombinedViewSort, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFiltersAndSorts.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFiltersAndSorts.ts new file mode 100644 index 000000000000..4f760b173c98 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFiltersAndSorts.ts @@ -0,0 +1,34 @@ +import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords'; +import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords'; + +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { ViewFilter } from '@/views/types/ViewFilter'; +import { ViewSort } from '@/views/types/ViewSort'; +import { isDefined } from '~/utils/isDefined'; + +export const useCreateViewFiltersAndSorts = () => { + const { getViewFromCache } = useGetViewFromCache(); + + const { createViewSortRecords } = usePersistViewSortRecords(); + + const { createViewFilterRecords } = usePersistViewFilterRecords(); + + const createViewFiltersAndSorts = async ( + viewIdToCreateOn: string, + filtersToCreate: ViewFilter[], + sortsToCreate: ViewSort[], + ) => { + const view = await getViewFromCache(viewIdToCreateOn); + + if (!isDefined(view)) { + return; + } + + await createViewSortRecords(sortsToCreate, view); + await createViewFilterRecords(filtersToCreate, view); + }; + + return { + createViewFiltersAndSorts, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts new file mode 100644 index 000000000000..fcf8a6c81647 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -0,0 +1,122 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; +import { useCreateViewFiltersAndSorts } from '@/views/hooks/useCreateViewFiltersAndSorts'; +import { useGetViewFiltersCombined } from '@/views/hooks/useGetCombinedViewFilters'; +import { useGetViewSortsCombined } from '@/views/hooks/useGetCombinedViewSorts'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { View } from '@/views/types/View'; +import { useRecoilCallback } from 'recoil'; +import { isDefined } from 'twenty-ui'; +import { v4 } from 'uuid'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; + +export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2( + isPersistingViewFieldsComponentState, + viewBarComponentId, + ); + + const { getViewFromCache } = useGetViewFromCache(); + + const { createOneRecord } = useCreateOneRecord<View>({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const { createViewFieldRecords } = usePersistViewFieldRecords(); + + const { createViewFiltersAndSorts } = useCreateViewFiltersAndSorts(); + + const { getViewSortsCombined } = useGetViewSortsCombined(viewBarComponentId); + const { getViewFiltersCombined } = + useGetViewFiltersCombined(viewBarComponentId); + + const createViewFromCurrentView = useRecoilCallback( + ({ snapshot, set }) => + async ( + { + id, + name, + icon, + kanbanFieldMetadataId, + type, + }: Partial< + Pick< + GraphQLView, + 'id' | 'name' | 'icon' | 'kanbanFieldMetadataId' | 'type' + > + >, + shouldCopyFiltersAndSorts?: boolean, + ) => { + const currentViewId = getSnapshotValue( + snapshot, + currentViewIdCallbackState, + ); + + if (!isDefined(currentViewId)) { + return; + } + + // Here we might instead want to get view from unsaved filters ? + const view = await getViewFromCache(currentViewId); + + if (!isDefined(view)) { + return; + } + + set(isPersistingViewFieldsCallbackState, true); + + const newView = await createOneRecord({ + id: id ?? v4(), + name: name ?? view.name, + icon: icon ?? view.icon, + key: null, + kanbanFieldMetadataId: + kanbanFieldMetadataId ?? view.kanbanFieldMetadataId, + type: type ?? view.type, + objectMetadataId: view.objectMetadataId, + }); + + if (isUndefinedOrNull(newView)) { + throw new Error('Failed to create view'); + } + + await createViewFieldRecords(view.viewFields, newView); + + if (shouldCopyFiltersAndSorts === true) { + const sourceViewCombinedFilters = getViewFiltersCombined(view.id); + const sourceViewCombinedSorts = getViewSortsCombined(view.id); + + await createViewFiltersAndSorts( + newView.id, + sourceViewCombinedFilters, + sourceViewCombinedSorts, + ); + } + + set(isPersistingViewFieldsCallbackState, false); + }, + [ + createOneRecord, + createViewFieldRecords, + getViewSortsCombined, + getViewFiltersCombined, + currentViewIdCallbackState, + getViewFromCache, + isPersistingViewFieldsCallbackState, + createViewFiltersAndSorts, + ], + ); + + return { createViewFromCurrentView }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts new file mode 100644 index 000000000000..af6ef7cba2e6 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts @@ -0,0 +1,101 @@ +import { useRecoilCallback } from 'recoil'; + +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { isDefined } from '~/utils/isDefined'; + +export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => { + const unsavedToUpsertViewFiltersCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewFiltersComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewFilterIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewFilterIdsComponentFamilyState, + viewBarComponentId, + ); + + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const { getViewFromCache } = useGetViewFromCache(); + + const deleteCombinedViewFilter = useRecoilCallback( + ({ snapshot, set }) => + async (fieldId: string) => { + const currentViewId = getSnapshotValue( + snapshot, + currentViewIdCallbackState, + ); + + const unsavedToUpsertViewFilters = getSnapshotValue( + snapshot, + unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }), + ); + + const unsavedToDeleteViewFilterIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }), + ); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingFilterInCurrentView = currentView.viewFilters.find( + (viewFilter) => viewFilter.id === fieldId, + ); + + const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find( + (viewFilter) => viewFilter.id === fieldId, + ); + + if (isDefined(matchingFilterInUnsavedFilters)) { + set( + unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }), + unsavedToUpsertViewFilters.filter( + (viewFilter) => viewFilter.id !== fieldId, + ), + ); + } + + if (isDefined(matchingFilterInCurrentView)) { + set( + unsavedToDeleteViewFilterIdsCallbackState({ + viewId: currentViewId, + }), + [ + ...new Set([ + ...unsavedToDeleteViewFilterIds, + matchingFilterInCurrentView.id, + ]), + ], + ); + } + }, + [ + currentViewIdCallbackState, + getViewFromCache, + unsavedToDeleteViewFilterIdsCallbackState, + unsavedToUpsertViewFiltersCallbackState, + ], + ); + + return { + deleteCombinedViewFilter, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts new file mode 100644 index 000000000000..4ff252cab654 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts @@ -0,0 +1,100 @@ +import { useRecoilCallback } from 'recoil'; + +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; +import { isDefined } from '~/utils/isDefined'; + +export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => { + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const unsavedToUpsertViewSortsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewSortsComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewSortIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewSortIdsComponentFamilyState, + viewBarComponentId, + ); + + const { getViewFromCache } = useGetViewFromCache(); + + const deleteCombinedViewSort = useRecoilCallback( + ({ snapshot, set }) => + async (fieldMetadataId: string) => { + const currentViewId = getSnapshotValue( + snapshot, + currentViewIdCallbackState, + ); + + if (!currentViewId) { + return; + } + + const unsavedToUpsertViewSorts = getSnapshotValue( + snapshot, + unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), + ); + + const unsavedToDeleteViewSortIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }), + ); + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingSortInCurrentView = currentView.viewSorts.find( + (viewSort) => viewSort.fieldMetadataId === fieldMetadataId, + ); + + const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find( + (viewSort) => viewSort.fieldMetadataId === fieldMetadataId, + ); + + if (isDefined(matchingSortInUnsavedSorts)) { + set( + unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), + unsavedToUpsertViewSorts.filter( + (viewSort) => viewSort.fieldMetadataId !== fieldMetadataId, + ), + ); + return; + } + + if (isDefined(matchingSortInCurrentView)) { + set( + unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }), + [ + ...new Set([ + ...unsavedToDeleteViewSortIds, + matchingSortInCurrentView.id, + ]), + ], + ); + } + }, + [ + currentViewIdCallbackState, + getViewFromCache, + unsavedToDeleteViewSortIdsCallbackState, + unsavedToUpsertViewSortsCallbackState, + ], + ); + + return { + deleteCombinedViewSort, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteView.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteView.ts new file mode 100644 index 000000000000..1cc88ceffd9a --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useDeleteView.ts @@ -0,0 +1,18 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; +import { useRecoilCallback } from 'recoil'; + +export const useDeleteView = () => { + const { deleteOneRecord } = useDeleteOneRecord({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const deleteView = useRecoilCallback( + () => async (viewId: string) => { + await deleteOneRecord(viewId); + }, + [deleteOneRecord], + ); + + return { deleteView }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts new file mode 100644 index 000000000000..20673087ed09 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts @@ -0,0 +1,67 @@ +import { useRecoilCallback } from 'recoil'; + +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { View } from '@/views/types/View'; +import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters'; +import { isDefined } from '~/utils/isDefined'; + +export const useGetViewFiltersCombined = (viewBarComponentId?: string) => { + const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews); + + const unsavedToUpsertViewFiltersCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewFiltersComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewFilterIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewFilterIdsComponentFamilyState, + viewBarComponentId, + ); + + const getViewFiltersCombined = useRecoilCallback( + ({ snapshot }) => + (viewId: string) => { + const view = views.find((view) => view.id === viewId); + + if (!isDefined(view)) { + throw new Error( + `Cannot get view with id ${viewId}, because it cannot be found in client cache data.`, + ); + } + + const unsavedToUpsertViewFilters = getSnapshotValue( + snapshot, + unsavedToUpsertViewFiltersCallbackState({ viewId: view.id }), + ); + + const unsavedToDeleteViewFilterIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewFilterIdsCallbackState({ viewId: view.id }), + ); + + const combinedViewFilters = getCombinedViewFilters( + view.viewFilters, + unsavedToUpsertViewFilters, + unsavedToDeleteViewFilterIds, + ); + + return combinedViewFilters; + }, + [ + views, + unsavedToDeleteViewFilterIdsCallbackState, + unsavedToUpsertViewFiltersCallbackState, + ], + ); + + return { + getViewFiltersCombined, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts new file mode 100644 index 000000000000..f275b6dc0e07 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts @@ -0,0 +1,68 @@ +import { useRecoilCallback } from 'recoil'; + +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; +import { View } from '@/views/types/View'; +import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts'; +import { isDefined } from '~/utils/isDefined'; + +// TODO: fix naming +export const useGetViewSortsCombined = (viewBarComponentId?: string) => { + const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews); + + const unsavedToUpsertViewSortsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewSortsComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewSortIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewSortIdsComponentFamilyState, + viewBarComponentId, + ); + + const getViewSortsCombined = useRecoilCallback( + ({ snapshot }) => + (viewId: string) => { + const view = views.find((view) => view.id === viewId); + + if (!isDefined(view)) { + throw new Error( + `Cannot get view with id ${viewId}, because it cannot be found in client cache data.`, + ); + } + + const unsavedToUpsertViewSorts = getSnapshotValue( + snapshot, + unsavedToUpsertViewSortsCallbackState({ viewId: view.id }), + ); + + const unsavedToDeleteViewSortIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewSortIdsCallbackState({ viewId: view.id }), + ); + + const combinedViewSorts = getCombinedViewSorts( + view.viewSorts, + unsavedToUpsertViewSorts, + unsavedToDeleteViewSortIds, + ); + + return combinedViewSorts; + }, + [ + views, + unsavedToDeleteViewSortIdsCallbackState, + unsavedToUpsertViewSortsCallbackState, + ], + ); + + return { + getViewSortsCombined, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts index 70d3cd8160c1..1ea911ba9024 100644 --- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts @@ -1,39 +1,46 @@ import { useEffect } from 'react'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { ViewScopeInternalContext } from '@/views/scopes/scope-internal-context/ViewScopeInternalContext'; +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; +import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState'; import { View } from '@/views/types/View'; -import { combinedViewFilters } from '@/views/utils/combinedViewFilters'; -import { combinedViewSorts } from '@/views/utils/combinedViewSorts'; +import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters'; +import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts'; import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews'; import { isDefined } from '~/utils/isDefined'; -export const useGetCurrentView = (viewBarComponentId?: string) => { - const componentId = useAvailableScopeIdOrThrow( - ViewScopeInternalContext, - viewBarComponentId, +export const useGetCurrentView = (viewBarInstanceId?: string) => { + const instanceId = useAvailableComponentInstanceIdOrThrow( + ViewComponentInstanceContext, + viewBarInstanceId, ); const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews); - const { - currentViewIdState, - viewObjectMetadataIdState, - unsavedToUpsertViewFiltersState, - unsavedToDeleteViewFilterIdsState, - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewSortsState, - isCurrentViewKeyIndexState, - } = useViewStates(componentId); - - const currentViewId = useRecoilValue(currentViewIdState); - const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState); - const setIsCurrentViewKeyIndex = useSetRecoilState( - isCurrentViewKeyIndexState, + const currentViewId = useRecoilComponentValueV2( + currentViewIdComponentState, + instanceId, + ); + + const viewObjectMetadataId = useRecoilComponentValueV2( + viewObjectMetadataIdComponentState, + instanceId, + ); + + const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2( + isCurrentViewKeyIndexComponentState, + instanceId, ); const currentViewFromCurrentViewId = views.find( @@ -46,6 +53,8 @@ export const useGetCurrentView = (viewBarComponentId?: string) => { const currentView = currentViewId ? currentViewFromCurrentViewId : indexView; + const viewId = currentViewId ?? indexView?.id; + useEffect(() => { setIsCurrentViewKeyIndex(currentView?.key === 'INDEX'); }, [currentView, setIsCurrentViewKeyIndex]); @@ -55,22 +64,33 @@ export const useGetCurrentView = (viewBarComponentId?: string) => { views, ); - const unsavedToUpsertViewFilters = useRecoilValue( - unsavedToUpsertViewFiltersState, + const unsavedToUpsertViewFilters = useRecoilComponentFamilyValueV2( + unsavedToUpsertViewFiltersComponentFamilyState, + { viewId }, + instanceId, ); - const unsavedToUpsertViewSorts = useRecoilValue( - unsavedToUpsertViewSortsState, + + const unsavedToUpsertViewSorts = useRecoilComponentFamilyValueV2( + unsavedToUpsertViewSortsComponentFamilyState, + { viewId }, + instanceId, ); - const unsavedToDeleteViewFilterIds = useRecoilValue( - unsavedToDeleteViewFilterIdsState, + + const unsavedToDeleteViewFilterIds = useRecoilComponentFamilyValueV2( + unsavedToDeleteViewFilterIdsComponentFamilyState, + { viewId }, + instanceId, ); - const unsavedToDeleteViewSortIds = useRecoilValue( - unsavedToDeleteViewSortIdsState, + + const unsavedToDeleteViewSortIds = useRecoilComponentFamilyValueV2( + unsavedToDeleteViewSortIdsComponentFamilyState, + { viewId }, + instanceId, ); if (!isDefined(currentView)) { return { - componentId, + instanceId, currentViewWithSavedFiltersAndSorts: undefined, currentViewWithCombinedFiltersAndSorts: undefined, viewsOnCurrentObject: viewsOnCurrentObject ?? [], @@ -79,12 +99,12 @@ export const useGetCurrentView = (viewBarComponentId?: string) => { const currentViewWithCombinedFiltersAndSorts = { ...currentView, - viewFilters: combinedViewFilters( + viewFilters: getCombinedViewFilters( currentView.viewFilters, unsavedToUpsertViewFilters, unsavedToDeleteViewFilterIds, ), - viewSorts: combinedViewSorts( + viewSorts: getCombinedViewSorts( currentView.viewSorts, unsavedToUpsertViewSorts, unsavedToDeleteViewSortIds, @@ -92,9 +112,10 @@ export const useGetCurrentView = (viewBarComponentId?: string) => { }; return { - componentId, + instanceId, currentViewWithSavedFiltersAndSorts: currentView, currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject: viewsOnCurrentObject ?? [], + currentViewId, }; }; diff --git a/packages/twenty-front/src/modules/views/hooks/useHandleViews.ts b/packages/twenty-front/src/modules/views/hooks/useHandleViews.ts deleted file mode 100644 index 63dc6732bb04..000000000000 --- a/packages/twenty-front/src/modules/views/hooks/useHandleViews.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { useCallback } from 'react'; -import { useSearchParams } from 'react-router-dom'; -import { useRecoilCallback } from 'recoil'; -import { v4 } from 'uuid'; - -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; -import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; -import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; -import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; -import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; -import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts'; -import { GraphQLView } from '@/views/types/GraphQLView'; -import { View } from '@/views/types/View'; -import { isDefined } from '~/utils/isDefined'; -import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; - -export const useHandleViews = (viewBarComponentId?: string) => { - const { resetCurrentView } = useResetCurrentView(viewBarComponentId); - - const { currentViewIdState, isPersistingViewFieldsState } = - useViewStates(viewBarComponentId); - - const { getViewFromCache } = useGetViewFromCache(); - - const { deleteOneRecord } = useDeleteOneRecord({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const { createOneRecord } = useCreateOneRecord<View>({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const { updateOneRecord } = useUpdateOneRecord({ - objectNameSingular: CoreObjectNameSingular.View, - }); - - const { createViewFieldRecords } = usePersistViewFieldRecords(); - const { saveCurrentViewFilterAndSorts } = - useSaveCurrentViewFiltersAndSorts(viewBarComponentId); - - const [, setSearchParams] = useSearchParams(); - - const removeView = useRecoilCallback( - () => async (viewId: string) => { - await deleteOneRecord(viewId); - }, - [deleteOneRecord], - ); - - const createView = useRecoilCallback( - ({ snapshot, set }) => - async ({ - id, - name, - icon, - kanbanFieldMetadataId, - type, - }: Partial< - Pick< - GraphQLView, - 'id' | 'name' | 'icon' | 'kanbanFieldMetadataId' | 'type' - > - >) => { - const currentViewId = getSnapshotValue(snapshot, currentViewIdState); - - if (!isDefined(currentViewId)) { - return; - } - - const view = await getViewFromCache(currentViewId); - - if (!isDefined(view)) { - return; - } - - set(isPersistingViewFieldsState, true); - - const newView = await createOneRecord({ - id: id ?? v4(), - name: name ?? view.name, - icon: icon ?? view.icon, - key: null, - kanbanFieldMetadataId: - kanbanFieldMetadataId ?? view.kanbanFieldMetadataId, - type: type ?? view.type, - objectMetadataId: view.objectMetadataId, - }); - - if (isUndefinedOrNull(newView)) { - throw new Error('Failed to create view'); - } - - await createViewFieldRecords(view.viewFields, newView); - await saveCurrentViewFilterAndSorts(newView.id); - set(isPersistingViewFieldsState, false); - }, - [ - createOneRecord, - createViewFieldRecords, - currentViewIdState, - getViewFromCache, - isPersistingViewFieldsState, - saveCurrentViewFilterAndSorts, - ], - ); - - const changeViewInUrl = useCallback( - (viewId: string) => { - setSearchParams(() => { - const searchParams = new URLSearchParams(); - searchParams.set('view', viewId); - return searchParams; - }); - }, - [setSearchParams], - ); - - const selectView = useRecoilCallback( - () => async (viewId: string) => { - changeViewInUrl(viewId); - resetCurrentView(); - }, - [changeViewInUrl, resetCurrentView], - ); - - const updateCurrentView = useRecoilCallback( - ({ snapshot }) => - async (view: Partial<GraphQLView>) => { - const currentViewId = snapshot - .getLoadable(currentViewIdState) - .getValue(); - if (isDefined(currentViewId)) { - await updateOneRecord({ - idToUpdate: currentViewId, - updateOneRecordInput: view, - }); - } - }, - [currentViewIdState, updateOneRecord], - ); - - const updateView = useRecoilCallback( - () => async (view: Partial<GraphQLView>) => { - if (isDefined(view.id)) { - await updateOneRecord({ - idToUpdate: view.id, - updateOneRecordInput: view, - }); - } - }, - [updateOneRecord], - ); - - return { - selectView, - updateCurrentView, - updateView, - removeView, - createView, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts b/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts index e81802846868..b7b85cc239b0 100644 --- a/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts +++ b/packages/twenty-front/src/modules/views/hooks/useInitViewBar.ts @@ -1,26 +1,29 @@ -import { useSetRecoilState } from 'recoil'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { availableFieldDefinitionsComponentState } from '@/views/states/availableFieldDefinitionsComponentState'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; +import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; - -export const useInitViewBar = (viewBarComponentId?: string) => { - const { - availableFieldDefinitionsState, - availableSortDefinitionsState, - availableFilterDefinitionsState, - viewObjectMetadataIdState, - } = useViewStates(viewBarComponentId); - - const setAvailableFieldDefinitions = useSetRecoilState( - availableFieldDefinitionsState, +export const useInitViewBar = (viewBarInstanceId?: string) => { + const setAvailableFieldDefinitions = useSetRecoilComponentStateV2( + availableFieldDefinitionsComponentState, + viewBarInstanceId, ); - const setAvailableSortDefinitions = useSetRecoilState( - availableSortDefinitionsState, + + const setAvailableSortDefinitions = useSetRecoilComponentStateV2( + availableSortDefinitionsComponentState, + viewBarInstanceId, ); - const setAvailableFilterDefinitions = useSetRecoilState( - availableFilterDefinitionsState, + + const setAvailableFilterDefinitions = useSetRecoilComponentStateV2( + availableFilterDefinitionsComponentState, + viewBarInstanceId, ); - const setViewObjectMetadataId = useSetRecoilState(viewObjectMetadataIdState); + const setViewObjectMetadataId = useSetRecoilComponentStateV2( + viewObjectMetadataIdComponentState, + viewBarInstanceId, + ); return { setAvailableFieldDefinitions, diff --git a/packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts deleted file mode 100644 index d188580ca355..000000000000 --- a/packages/twenty-front/src/modules/views/hooks/useResetCurrentView.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { useRecoilCallback } from 'recoil'; - -import { useViewStates } from '@/views/hooks/internal/useViewStates'; - -export const useResetCurrentView = (viewBarComponentId?: string) => { - const { - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewSortsState, - unsavedToDeleteViewFilterIdsState, - unsavedToUpsertViewFiltersState, - } = useViewStates(viewBarComponentId); - - const resetCurrentView = useRecoilCallback( - ({ set }) => - async () => { - set(unsavedToDeleteViewFilterIdsState, []); - set(unsavedToDeleteViewSortIdsState, []); - set(unsavedToUpsertViewFiltersState, []); - set(unsavedToUpsertViewSortsState, []); - }, - [ - unsavedToDeleteViewFilterIdsState, - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewFiltersState, - unsavedToUpsertViewSortsState, - ], - ); - - return { - resetCurrentView, - }; -}; diff --git a/packages/twenty-front/src/modules/views/hooks/useResetUnsavedViewStates.ts b/packages/twenty-front/src/modules/views/hooks/useResetUnsavedViewStates.ts new file mode 100644 index 000000000000..f3d3039bec92 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useResetUnsavedViewStates.ts @@ -0,0 +1,52 @@ +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; +import { useRecoilCallback } from 'recoil'; + +export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => { + const setUnsavedToDeleteViewFilterIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewFilterIdsComponentFamilyState, + viewBarInstanceId, + ); + + const setUnsavedToDeleteViewSortIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewSortIdsComponentFamilyState, + viewBarInstanceId, + ); + + const setUnsavedToUpsertViewFiltersCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewFiltersComponentFamilyState, + viewBarInstanceId, + ); + + const unsavedToUpsertViewSortsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewSortsComponentFamilyState, + viewBarInstanceId, + ); + + const resetUnsavedViewStates = useRecoilCallback( + ({ set }) => + (viewId: string) => { + set(setUnsavedToDeleteViewFilterIdsCallbackState({ viewId }), []); + set(setUnsavedToDeleteViewSortIdsCallbackState({ viewId }), []); + set(setUnsavedToUpsertViewFiltersCallbackState({ viewId }), []); + set(unsavedToUpsertViewSortsCallbackState({ viewId }), []); + }, + [ + unsavedToUpsertViewSortsCallbackState, + setUnsavedToUpsertViewFiltersCallbackState, + setUnsavedToDeleteViewSortIdsCallbackState, + setUnsavedToDeleteViewFilterIdsCallbackState, + ], + ); + + return { + resetUnsavedViewStates, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts index 65386abacefc..7d614988140c 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts @@ -1,8 +1,10 @@ import { useRecoilCallback } from 'recoil'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState'; import { ViewField } from '@/views/types/ViewField'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDefined } from '~/utils/isDefined'; @@ -14,21 +16,28 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => { const { getViewFromCache } = useGetViewFromCache(); - const { isPersistingViewFieldsState, currentViewIdState } = - useViewStates(viewBarComponentId); + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2( + isPersistingViewFieldsComponentState, + viewBarComponentId, + ); const saveViewFields = useRecoilCallback( ({ set, snapshot }) => async (viewFieldsToSave: ViewField[]) => { const currentViewId = snapshot - .getLoadable(currentViewIdState) + .getLoadable(currentViewIdCallbackState) .getValue(); if (!currentViewId) { return; } - set(isPersistingViewFieldsState, true); + set(isPersistingViewFieldsCallbackState, true); const view = await getViewFromCache(currentViewId); @@ -85,13 +94,13 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => { updateViewFieldRecords(viewFieldsToUpdate), ]); - set(isPersistingViewFieldsState, false); + set(isPersistingViewFieldsCallbackState, false); }, [ createViewFieldRecords, - currentViewIdState, + currentViewIdCallbackState, getViewFromCache, - isPersistingViewFieldsState, + isPersistingViewFieldsCallbackState, updateViewFieldRecords, ], ); diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts index 6370fe0ca2a4..3b7fdeaebdf0 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts @@ -1,11 +1,16 @@ import { useRecoilCallback } from 'recoil'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords'; import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; -import { useResetCurrentView } from '@/views/hooks/useResetCurrentView'; +import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; @@ -14,13 +19,34 @@ export const useSaveCurrentViewFiltersAndSorts = ( ) => { const { getViewFromCache } = useGetViewFromCache(); - const { - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewSortsState, - unsavedToDeleteViewFilterIdsState, - unsavedToUpsertViewFiltersState, - currentViewIdState, - } = useViewStates(viewBarComponentId); + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const unsavedToDeleteViewSortIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewSortIdsComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToUpsertViewSortsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewSortsComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewFilterIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewFilterIdsComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToUpsertViewFiltersCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewFiltersComponentFamilyState, + viewBarComponentId, + ); const { createViewSortRecords, @@ -34,19 +60,20 @@ export const useSaveCurrentViewFiltersAndSorts = ( deleteViewFilterRecords, } = usePersistViewFilterRecords(); - const { resetCurrentView } = useResetCurrentView(viewBarComponentId); + const { resetUnsavedViewStates } = + useResetUnsavedViewStates(viewBarComponentId); const saveViewSorts = useRecoilCallback( ({ snapshot }) => async (viewId: string) => { const unsavedToDeleteViewSortIds = getSnapshotValue( snapshot, - unsavedToDeleteViewSortIdsState, + unsavedToDeleteViewSortIdsCallbackState({ viewId }), ); const unsavedToUpsertViewSorts = getSnapshotValue( snapshot, - unsavedToUpsertViewSortsState, + unsavedToUpsertViewSortsCallbackState({ viewId }), ); const view = await getViewFromCache(viewId); @@ -76,8 +103,8 @@ export const useSaveCurrentViewFiltersAndSorts = ( createViewSortRecords, deleteViewSortRecords, getViewFromCache, - unsavedToDeleteViewSortIdsState, - unsavedToUpsertViewSortsState, + unsavedToDeleteViewSortIdsCallbackState, + unsavedToUpsertViewSortsCallbackState, updateViewSortRecords, ], ); @@ -87,12 +114,12 @@ export const useSaveCurrentViewFiltersAndSorts = ( async (viewId: string) => { const unsavedToDeleteViewFilterIds = getSnapshotValue( snapshot, - unsavedToDeleteViewFilterIdsState, + unsavedToDeleteViewFilterIdsCallbackState({ viewId }), ); const unsavedToUpsertViewFilters = getSnapshotValue( snapshot, - unsavedToUpsertViewFiltersState, + unsavedToUpsertViewFiltersCallbackState({ viewId }), ); const view = await getViewFromCache(viewId); @@ -123,28 +150,36 @@ export const useSaveCurrentViewFiltersAndSorts = ( createViewFilterRecords, deleteViewFilterRecords, getViewFromCache, - unsavedToDeleteViewFilterIdsState, - unsavedToUpsertViewFiltersState, + unsavedToDeleteViewFilterIdsCallbackState, + unsavedToUpsertViewFiltersCallbackState, updateViewFilterRecords, ], ); const saveCurrentViewFilterAndSorts = useRecoilCallback( ({ snapshot }) => - async (viewId?: string) => { + async (viewIdFromProps?: string) => { const currentViewId = snapshot - .getLoadable(currentViewIdState) + .getLoadable(currentViewIdCallbackState) .getValue(); if (!isDefined(currentViewId)) { return; } - await saveViewFilters(viewId ?? currentViewId); - await saveViewSorts(viewId ?? currentViewId); - resetCurrentView(); + const viewId = viewIdFromProps ?? currentViewId; + + await saveViewFilters(viewId); + await saveViewSorts(viewId); + + resetUnsavedViewStates(viewId); }, - [currentViewIdState, resetCurrentView, saveViewFilters, saveViewSorts], + [ + currentViewIdCallbackState, + resetUnsavedViewStates, + saveViewFilters, + saveViewSorts, + ], ); return { diff --git a/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts index 8deeece5a1a5..778fa6906c6f 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSetRecordCountInCurrentView.ts @@ -1,12 +1,10 @@ -import { useSetRecoilState } from 'recoil'; - -import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState'; export const useSetRecordCountInCurrentView = (viewBarComponentId?: string) => { - const { entityCountInCurrentViewState } = useViewStates(viewBarComponentId); - - const setEntityCountInCurrentView = useSetRecoilState( - entityCountInCurrentViewState, + const setEntityCountInCurrentView = useSetRecoilComponentStateV2( + entityCountInCurrentViewComponentState, + viewBarComponentId, ); return { diff --git a/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts new file mode 100644 index 000000000000..910548d73804 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts @@ -0,0 +1,40 @@ +import { useRecoilCallback } from 'recoil'; + +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { isDefined } from '~/utils/isDefined'; + +export const useUpdateCurrentView = (viewBarComponentId?: string) => { + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const { updateOneRecord } = useUpdateOneRecord({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const updateCurrentView = useRecoilCallback( + ({ snapshot }) => + async (view: Partial<GraphQLView>) => { + const currentViewId = snapshot + .getLoadable(currentViewIdCallbackState) + .getValue(); + + if (isDefined(currentViewId)) { + await updateOneRecord({ + idToUpdate: currentViewId, + updateOneRecordInput: view, + }); + } + }, + [currentViewIdCallbackState, updateOneRecord], + ); + + return { + updateCurrentView, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useUpdateView.ts b/packages/twenty-front/src/modules/views/hooks/useUpdateView.ts new file mode 100644 index 000000000000..d00201e5fd06 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useUpdateView.ts @@ -0,0 +1,27 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; +import { GraphQLView } from '@/views/types/GraphQLView'; +import { useRecoilCallback } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +export const useUpdateView = () => { + const { updateOneRecord } = useUpdateOneRecord({ + objectNameSingular: CoreObjectNameSingular.View, + }); + + const updateView = useRecoilCallback( + () => async (view: Partial<GraphQLView>) => { + if (isDefined(view.id)) { + await updateOneRecord({ + idToUpdate: view.id, + updateOneRecordInput: view, + }); + } + }, + [updateOneRecord], + ); + + return { + updateView, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts new file mode 100644 index 000000000000..fd33eb009583 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts @@ -0,0 +1,131 @@ +import { useRecoilCallback } from 'recoil'; + +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { ViewFilter } from '@/views/types/ViewFilter'; +import { isDefined } from '~/utils/isDefined'; + +export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => { + const unsavedToUpsertViewFiltersCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewFiltersComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewFilterIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewFilterIdsComponentFamilyState, + viewBarComponentId, + ); + + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const { getViewFromCache } = useGetViewFromCache(); + + const upsertCombinedViewFilter = useRecoilCallback( + ({ snapshot, set }) => + async (upsertedFilter: Filter) => { + const currentViewId = getSnapshotValue( + snapshot, + currentViewIdCallbackState, + ); + + const unsavedToUpsertViewFilters = getSnapshotValue( + snapshot, + unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }), + ); + + const unsavedToDeleteViewFilterIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }), + ); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingFilterInCurrentView = currentView.viewFilters.find( + (viewFilter) => + viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId, + ); + + const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find( + (viewFilter) => + viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId, + ); + + if (isDefined(matchingFilterInUnsavedFilters)) { + const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) => + viewFilter.fieldMetadataId === + matchingFilterInUnsavedFilters.fieldMetadataId + ? { ...viewFilter, ...upsertedFilter, id: viewFilter.id } + : viewFilter, + ); + + set( + unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }), + updatedFilters, + ); + return; + } + + if (isDefined(matchingFilterInCurrentView)) { + set( + unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }), + [ + ...unsavedToUpsertViewFilters, + { + ...matchingFilterInCurrentView, + ...upsertedFilter, + id: matchingFilterInCurrentView.id, + }, + ], + ); + set( + unsavedToDeleteViewFilterIdsCallbackState({ + viewId: currentViewId, + }), + unsavedToDeleteViewFilterIds.filter( + (id) => id !== matchingFilterInCurrentView.id, + ), + ); + return; + } + + set( + unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }), + [ + ...unsavedToUpsertViewFilters, + { + ...upsertedFilter, + __typename: 'ViewFilter', + } satisfies ViewFilter, + ], + ); + }, + [ + currentViewIdCallbackState, + getViewFromCache, + unsavedToDeleteViewFilterIdsCallbackState, + unsavedToUpsertViewFiltersCallbackState, + ], + ); + + return { + upsertCombinedViewFilter, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts new file mode 100644 index 000000000000..d455c6f6307e --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts @@ -0,0 +1,123 @@ +import { useRecoilCallback } from 'recoil'; +import { v4 } from 'uuid'; + +import { Sort } from '@/object-record/object-sort-dropdown/types/Sort'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; +import { ViewSort } from '@/views/types/ViewSort'; +import { isDefined } from '~/utils/isDefined'; + +export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => { + const currentViewIdCallbackState = useRecoilComponentCallbackStateV2( + currentViewIdComponentState, + viewBarComponentId, + ); + + const unsavedToUpsertViewSortsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToUpsertViewSortsComponentFamilyState, + viewBarComponentId, + ); + + const unsavedToDeleteViewSortIdsCallbackState = + useRecoilComponentCallbackStateV2( + unsavedToDeleteViewSortIdsComponentFamilyState, + viewBarComponentId, + ); + + const { getViewFromCache } = useGetViewFromCache(); + + const upsertCombinedViewSort = useRecoilCallback( + ({ snapshot, set }) => + async (upsertedSort: Sort) => { + const currentViewId = getSnapshotValue( + snapshot, + currentViewIdCallbackState, + ); + + const unsavedToUpsertViewSorts = getSnapshotValue( + snapshot, + unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), + ); + + const unsavedToDeleteViewSortIds = getSnapshotValue( + snapshot, + unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }), + ); + + if (!currentViewId) { + return; + } + + const currentView = await getViewFromCache(currentViewId); + + if (!currentView) { + return; + } + + const matchingSortInCurrentView = currentView.viewSorts.find( + (viewSort) => + viewSort.fieldMetadataId === upsertedSort.fieldMetadataId, + ); + + const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find( + (viewSort) => + viewSort.fieldMetadataId === upsertedSort.fieldMetadataId, + ); + + if (isDefined(matchingSortInUnsavedSorts)) { + const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) => + viewSort.id === matchingSortInUnsavedSorts.id + ? { ...viewSort, ...upsertedSort } + : viewSort, + ); + + set( + unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), + updatedSorts, + ); + return; + } + + if (isDefined(matchingSortInCurrentView)) { + set( + unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), + [ + ...unsavedToUpsertViewSorts, + { ...matchingSortInCurrentView, ...upsertedSort }, + ], + ); + set( + unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }), + unsavedToDeleteViewSortIds.filter( + (id) => id !== matchingSortInCurrentView.id, + ), + ); + return; + } + + set(unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), [ + ...unsavedToUpsertViewSorts, + { + ...upsertedSort, + id: v4(), + __typename: 'ViewSort', + } satisfies ViewSort, + ]); + }, + [ + currentViewIdCallbackState, + getViewFromCache, + unsavedToDeleteViewSortIdsCallbackState, + unsavedToUpsertViewSortsCallbackState, + ], + ); + + return { + upsertCombinedViewSort, + }; +}; diff --git a/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx b/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx deleted file mode 100644 index e70372fab5a8..000000000000 --- a/packages/twenty-front/src/modules/views/scopes/ViewScope.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { ReactNode } from 'react'; - -import { GraphQLView } from '@/views/types/GraphQLView'; - -import { ViewScopeInitEffect } from './init-effect/ViewScopeInitEffect'; -import { ViewScopeInternalContext } from './scope-internal-context/ViewScopeInternalContext'; - -type ViewScopeProps = { - children: ReactNode; - viewScopeId: string; - onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise<void>; -}; - -export const ViewScope = ({ - children, - viewScopeId, - onCurrentViewChange, -}: ViewScopeProps) => { - return ( - <ViewScopeInternalContext.Provider - value={{ - scopeId: viewScopeId, - }} - > - <ViewScopeInitEffect - viewScopeId={viewScopeId} - onCurrentViewChange={onCurrentViewChange} - /> - {children} - </ViewScopeInternalContext.Provider> - ); -}; diff --git a/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx b/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx deleted file mode 100644 index 330c270d8fd8..000000000000 --- a/packages/twenty-front/src/modules/views/scopes/init-effect/ViewScopeInitEffect.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useEffect } from 'react'; -import { useSetRecoilState } from 'recoil'; - -import { useViewStates } from '@/views/hooks/internal/useViewStates'; -import { GraphQLView } from '@/views/types/GraphQLView'; - -type ViewScopeInitEffectProps = { - viewScopeId: string; - onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise<void>; -}; - -export const ViewScopeInitEffect = ({ - onCurrentViewChange, -}: ViewScopeInitEffectProps) => { - const { onCurrentViewChangeState } = useViewStates(); - - const setOnCurrentViewChange = useSetRecoilState(onCurrentViewChangeState); - - useEffect(() => { - setOnCurrentViewChange(() => onCurrentViewChange); - }, [onCurrentViewChange, setOnCurrentViewChange]); - - return <></>; -}; diff --git a/packages/twenty-front/src/modules/views/scopes/scope-internal-context/ViewScopeInternalContext.ts b/packages/twenty-front/src/modules/views/scopes/scope-internal-context/ViewScopeInternalContext.ts deleted file mode 100644 index d9affe26c251..000000000000 --- a/packages/twenty-front/src/modules/views/scopes/scope-internal-context/ViewScopeInternalContext.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey'; - -type ViewScopeInternalContextProps = ComponentStateKey; - -export const ViewScopeInternalContext = - createScopeInternalContext<ViewScopeInternalContextProps>(); diff --git a/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts b/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts index 9f11648305d5..fcd7b38e1c9f 100644 --- a/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/availableFieldDefinitionsComponentState.ts @@ -1,10 +1,12 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const availableFieldDefinitionsComponentState = createComponentState< +export const availableFieldDefinitionsComponentState = createComponentStateV2< ColumnDefinition<FieldMetadata>[] >({ key: 'availableFieldDefinitionsComponentState', defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts b/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts index 9a3f649ea491..8259d19a6ec9 100644 --- a/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/availableFilterDefinitionsComponentState.ts @@ -1,9 +1,11 @@ import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const availableFilterDefinitionsComponentState = createComponentState< +export const availableFilterDefinitionsComponentState = createComponentStateV2< FilterDefinition[] >({ key: 'availableFilterDefinitionsComponentState', defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts b/packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts index 9281f1d75780..1462b0bb2c02 100644 --- a/packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/availableSortDefinitionsComponentState.ts @@ -1,9 +1,11 @@ import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition'; -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const availableSortDefinitionsComponentState = createComponentState< +export const availableSortDefinitionsComponentState = createComponentStateV2< SortDefinition[] >({ key: 'availableSortDefinitionsComponentState', defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/contexts/ViewComponentInstanceContext.ts b/packages/twenty-front/src/modules/views/states/contexts/ViewComponentInstanceContext.ts new file mode 100644 index 000000000000..b6e8bf87bee7 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/contexts/ViewComponentInstanceContext.ts @@ -0,0 +1,3 @@ +import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext'; + +export const ViewComponentInstanceContext = createComponentInstanceContext(); diff --git a/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts b/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts index 799ba48005b3..40b7ecb61836 100644 --- a/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const currentViewIdComponentState = createComponentState< +export const currentViewIdComponentState = createComponentStateV2< string | undefined >({ key: 'currentViewIdComponentState', defaultValue: undefined, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts b/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts index 5e0f721b65e4..f189084828ac 100644 --- a/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/entityCountInCurrentViewComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const entityCountInCurrentViewComponentState = createComponentState< +export const entityCountInCurrentViewComponentState = createComponentStateV2< number | undefined >({ key: 'entityCountInCurrentViewComponentState', defaultValue: undefined, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts b/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts index ee3252d3680d..e5f78e8ee24f 100644 --- a/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/isCurrentViewIndexComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const isCurrentViewKeyIndexComponentState = - createComponentState<boolean>({ + createComponentStateV2<boolean>({ key: 'isCurrentViewKeyIndexComponentState', defaultValue: true, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts index 60cfdd2c0562..7ddaa5e43d0c 100644 --- a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const isPersistingViewFieldsComponentState = - createComponentState<boolean>({ + createComponentStateV2<boolean>({ key: 'isPersistingViewFieldsComponentState', defaultValue: false, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts b/packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts index 9742ce77e350..26f0f599b94c 100644 --- a/packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/isViewBarExpandedComponentState.ts @@ -1,6 +1,8 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const isViewBarExpandedComponentState = createComponentState<boolean>({ +export const isViewBarExpandedComponentState = createComponentStateV2<boolean>({ key: 'isViewBarExpandedComponentState', defaultValue: true, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts b/packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts deleted file mode 100644 index 085eb03682a8..000000000000 --- a/packages/twenty-front/src/modules/views/states/onCurrentViewChangeComponentState.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; -import { View } from '@/views/types/View'; - -export const onCurrentViewChangeComponentState = createComponentState< - ((view: View | undefined) => void | Promise<void>) | undefined ->({ - key: 'onCurrentViewChangeComponentState', - defaultValue: undefined, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentFamilySelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentFamilySelector.ts new file mode 100644 index 000000000000..51cc6d230fda --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentFamilySelector.ts @@ -0,0 +1,42 @@ +import { createComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState'; +import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState'; +import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState'; +import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState'; + +export const canPersistViewComponentFamilySelector = + createComponentFamilySelectorV2<boolean, { viewId?: string }>({ + key: 'canPersistViewComponentFamilySelector', + get: + ({ familyKey, instanceId }) => + ({ get }) => { + return ( + get( + unsavedToUpsertViewFiltersComponentFamilyState.atomFamily({ + familyKey, + instanceId, + }), + ).length > 0 || + get( + unsavedToUpsertViewSortsComponentFamilyState.atomFamily({ + familyKey, + instanceId, + }), + ).length > 0 || + get( + unsavedToDeleteViewFilterIdsComponentFamilyState.atomFamily({ + familyKey, + instanceId, + }), + ).length > 0 || + get( + unsavedToDeleteViewSortIdsComponentFamilyState.atomFamily({ + familyKey, + instanceId, + }), + ).length > 0 + ); + }, + componentInstanceContext: ViewComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts deleted file mode 100644 index 2d28c5735993..000000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/canPersistViewComponentSelector.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState'; -import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState'; -import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState'; -import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState'; - -export const canPersistViewComponentSelector = selectorFamily({ - key: 'canPersistViewComponentSelector', - get: - ({ scopeId }: { scopeId: string }) => - ({ get }) => { - return ( - get(unsavedToUpsertViewFiltersComponentState({ scopeId })).length > 0 || - get(unsavedToUpsertViewSortsComponentState({ scopeId })).length > 0 || - get(unsavedToDeleteViewFilterIdsComponentState({ scopeId })).length > - 0 || - get(unsavedToDeleteViewSortIdsComponentState({ scopeId })).length > 0 - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts b/packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts deleted file mode 100644 index 5ad2bd408d5c..000000000000 --- a/packages/twenty-front/src/modules/views/states/selectors/canResetViewComponentSelector.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { selectorFamily } from 'recoil'; - -import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState'; -import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState'; -import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState'; -import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState'; - -export const canResetViewComponentSelector = selectorFamily({ - key: 'canResetViewComponentSelector', - get: - ({ scopeId }: { scopeId: string }) => - ({ get }) => { - return ( - get(unsavedToUpsertViewFiltersComponentState({ scopeId })).length === - 0 && - get(unsavedToUpsertViewSortsComponentState({ scopeId })).length === 0 && - get(unsavedToDeleteViewFilterIdsComponentState({ scopeId })).length === - 0 && - get(unsavedToDeleteViewSortIdsComponentState({ scopeId })).length === 0 - ); - }, -}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState.ts b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState.ts new file mode 100644 index 000000000000..7f60aaaefe34 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState.ts @@ -0,0 +1,9 @@ +import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; + +export const unsavedToDeleteViewFilterIdsComponentFamilyState = + createComponentFamilyStateV2<string[], { viewId?: string }>({ + key: 'unsavedToDeleteViewFilterIdsComponentFamilyState', + defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts deleted file mode 100644 index 60b89afbbb1c..000000000000 --- a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewFilterIdsComponentState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const unsavedToDeleteViewFilterIdsComponentState = createComponentState< - string[] ->({ - key: 'unsavedToDeleteViewFilterIdsComponentState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentFamilyState.ts b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentFamilyState.ts new file mode 100644 index 000000000000..428bd4fffb92 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentFamilyState.ts @@ -0,0 +1,9 @@ +import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; + +export const unsavedToDeleteViewSortIdsComponentFamilyState = + createComponentFamilyStateV2<string[], { viewId?: string }>({ + key: 'unsavedToDeleteViewSortIdsComponentFamilyState', + defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts deleted file mode 100644 index bb44082bf807..000000000000 --- a/packages/twenty-front/src/modules/views/states/unsavedToDeleteViewSortIdsComponentState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const unsavedToDeleteViewSortIdsComponentState = createComponentState< - string[] ->({ - key: 'unsavedToDeleteViewSortIdsComponentState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentFamilyState.ts b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentFamilyState.ts new file mode 100644 index 000000000000..bf48b10708cf --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentFamilyState.ts @@ -0,0 +1,10 @@ +import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { ViewFilter } from '../types/ViewFilter'; + +export const unsavedToUpsertViewFiltersComponentFamilyState = + createComponentFamilyStateV2<ViewFilter[], { viewId?: string }>({ + key: 'unsavedToUpsertViewFiltersComponentFamilyState', + defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts deleted file mode 100644 index 108ad0847910..000000000000 --- a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewFiltersComponentState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -import { ViewFilter } from '../types/ViewFilter'; - -export const unsavedToUpsertViewFiltersComponentState = createComponentState< - ViewFilter[] ->({ - key: 'unsavedToUpsertViewFiltersComponentState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentFamilyState.ts b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentFamilyState.ts new file mode 100644 index 000000000000..ebd46fd5ccb0 --- /dev/null +++ b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentFamilyState.ts @@ -0,0 +1,10 @@ +import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { ViewSort } from '../types/ViewSort'; + +export const unsavedToUpsertViewSortsComponentFamilyState = + createComponentFamilyStateV2<ViewSort[], { viewId?: string }>({ + key: 'unsavedToUpsertViewSortsComponentFamilyState', + defaultValue: [], + componentInstanceContext: ViewComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts b/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts deleted file mode 100644 index 57fa5f0b9af9..000000000000 --- a/packages/twenty-front/src/modules/views/states/unsavedToUpsertViewSortsComponentState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -import { ViewSort } from '../types/ViewSort'; - -export const unsavedToUpsertViewSortsComponentState = createComponentState< - ViewSort[] ->({ - key: 'unsavedToUpsertViewSortsComponentState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts b/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts index a20cbb9016fb..56f6b1168d21 100644 --- a/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/viewObjectMetadataIdComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const viewObjectMetadataIdComponentState = createComponentState< +export const viewObjectMetadataIdComponentState = createComponentStateV2< string | undefined >({ key: 'viewObjectMetadataIdComponentState', defaultValue: undefined, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/types/ViewFilterOperand.ts b/packages/twenty-front/src/modules/views/types/ViewFilterOperand.ts index 025d0085d49d..0d6446de9ea4 100644 --- a/packages/twenty-front/src/modules/views/types/ViewFilterOperand.ts +++ b/packages/twenty-front/src/modules/views/types/ViewFilterOperand.ts @@ -4,8 +4,14 @@ export enum ViewFilterOperand { IsNot = 'isNot', LessThan = 'lessThan', GreaterThan = 'greaterThan', + IsBefore = 'isBefore', + IsAfter = 'isAfter', Contains = 'contains', DoesNotContain = 'doesNotContain', IsEmpty = 'isEmpty', IsNotEmpty = 'isNotEmpty', + IsRelative = 'isRelative', + IsInPast = 'isInPast', + IsInFuture = 'isInFuture', + IsToday = 'isToday', } diff --git a/packages/twenty-front/src/modules/views/utils/__tests__/getCombinedViewFilters.test.ts b/packages/twenty-front/src/modules/views/utils/__tests__/getCombinedViewFilters.test.ts new file mode 100644 index 000000000000..95e1b37ae7f1 --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/__tests__/getCombinedViewFilters.test.ts @@ -0,0 +1,112 @@ +// Generate test for getCombinedViewFilters + +import { ViewFilter } from '@/views/types/ViewFilter'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { getCombinedViewFilters } from '../getCombinedViewFilters'; + +describe('getCombinedViewFilters', () => { + it('should return expected combined view filters when additional filters are present', () => { + const viewFilters: ViewFilter[] = [ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]; + const toUpsertViewFilters: ViewFilter[] = [ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]; + const toDeleteViewFilterIds: string[] = []; + + expect( + getCombinedViewFilters( + viewFilters, + toUpsertViewFilters, + toDeleteViewFilterIds, + ), + ).toEqual([ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]); + }); + + it('should return expected combined view filters when additional filters are not present', () => { + const viewFilters: ViewFilter[] = [ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]; + const toUpsertViewFilters: ViewFilter[] = []; + const toDeleteViewFilterIds: string[] = []; + + expect( + getCombinedViewFilters( + viewFilters, + toUpsertViewFilters, + toDeleteViewFilterIds, + ), + ).toEqual([ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]); + }); + + it('should return expected combined view filters when additional filters are present and some filters are to be deleted', () => { + const viewFilters: ViewFilter[] = [ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]; + const toUpsertViewFilters: ViewFilter[] = [ + { + __typename: 'ViewFilter', + id: 'id', + fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482', + value: 'testValue', + displayValue: 'Test Display Value', + operand: ViewFilterOperand.Is, + }, + ]; + const toDeleteViewFilterIds: string[] = ['id']; + + expect( + getCombinedViewFilters( + viewFilters, + toUpsertViewFilters, + toDeleteViewFilterIds, + ), + ).toEqual([]); + }); +}); diff --git a/packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts b/packages/twenty-front/src/modules/views/utils/getCombinedViewFilters.ts similarity index 96% rename from packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts rename to packages/twenty-front/src/modules/views/utils/getCombinedViewFilters.ts index dc205c394822..1e172505dd96 100644 --- a/packages/twenty-front/src/modules/views/utils/combinedViewFilters.ts +++ b/packages/twenty-front/src/modules/views/utils/getCombinedViewFilters.ts @@ -1,6 +1,6 @@ import { ViewFilter } from '@/views/types/ViewFilter'; -export const combinedViewFilters = ( +export const getCombinedViewFilters = ( viewFilters: ViewFilter[], toUpsertViewFilters: ViewFilter[], toDeleteViewFilterIds: string[], diff --git a/packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts b/packages/twenty-front/src/modules/views/utils/getCombinedViewSorts.ts similarity index 96% rename from packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts rename to packages/twenty-front/src/modules/views/utils/getCombinedViewSorts.ts index c0fad726aa99..0fc2396ad239 100644 --- a/packages/twenty-front/src/modules/views/utils/combinedViewSorts.ts +++ b/packages/twenty-front/src/modules/views/utils/getCombinedViewSorts.ts @@ -1,6 +1,6 @@ import { ViewSort } from '@/views/types/ViewSort'; -export const combinedViewSorts = ( +export const getCombinedViewSorts = ( viewSort: ViewSort[], toUpsertViewSorts: ViewSort[], toDeleteViewSortIds: string[], diff --git a/packages/twenty-front/src/modules/views/utils/view-filter-value/computeVariableDateViewFilterValue.ts b/packages/twenty-front/src/modules/views/utils/view-filter-value/computeVariableDateViewFilterValue.ts new file mode 100644 index 000000000000..1b09bc91348b --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/view-filter-value/computeVariableDateViewFilterValue.ts @@ -0,0 +1,10 @@ +import { + VariableDateViewFilterValueDirection, + VariableDateViewFilterValueUnit, +} from '@/views/utils/view-filter-value/resolveDateViewFilterValue'; + +export const computeVariableDateViewFilterValue = ( + direction: VariableDateViewFilterValueDirection, + amount: number | undefined, + unit: VariableDateViewFilterValueUnit, +) => `${direction}_${amount?.toString()}_${unit}`; diff --git a/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveDateViewFilterValue.ts b/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveDateViewFilterValue.ts new file mode 100644 index 000000000000..da940310505c --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveDateViewFilterValue.ts @@ -0,0 +1,190 @@ +import { ViewFilter } from '@/views/types/ViewFilter'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { + addDays, + addMonths, + addWeeks, + addYears, + endOfDay, + endOfMonth, + endOfWeek, + endOfYear, + roundToNearestMinutes, + startOfDay, + startOfMonth, + startOfWeek, + startOfYear, + subDays, + subMonths, + subWeeks, + subYears, +} from 'date-fns'; + +import { z } from 'zod'; + +const variableDateViewFilterValueDirectionSchema = z.enum([ + 'NEXT', + 'THIS', + 'PAST', +]); + +export type VariableDateViewFilterValueDirection = z.infer< + typeof variableDateViewFilterValueDirectionSchema +>; + +const variableDateViewFilterValueAmountSchema = z + .union([z.coerce.number().int().positive(), z.literal('undefined')]) + .transform((val) => (val === 'undefined' ? undefined : val)); + +export const variableDateViewFilterValueUnitSchema = z.enum([ + 'DAY', + 'WEEK', + 'MONTH', + 'YEAR', +]); + +export type VariableDateViewFilterValueUnit = z.infer< + typeof variableDateViewFilterValueUnitSchema +>; + +export const variableDateViewFilterValuePartsSchema = z + .object({ + direction: variableDateViewFilterValueDirectionSchema, + amount: variableDateViewFilterValueAmountSchema, + unit: variableDateViewFilterValueUnitSchema, + }) + .refine((data) => !(data.amount === undefined && data.direction !== 'THIS'), { + message: "Amount cannot be 'undefined' unless direction is 'THIS'", + }); + +const variableDateViewFilterValueSchema = z.string().transform((value) => { + const [direction, amount, unit] = value.split('_'); + + return variableDateViewFilterValuePartsSchema.parse({ + direction, + amount, + unit, + }); +}); + +const addUnit = ( + date: Date, + amount: number, + unit: VariableDateViewFilterValueUnit, +) => { + switch (unit) { + case 'DAY': + return addDays(date, amount); + case 'WEEK': + return addWeeks(date, amount); + case 'MONTH': + return addMonths(date, amount); + case 'YEAR': + return addYears(date, amount); + } +}; + +const subUnit = ( + date: Date, + amount: number, + unit: VariableDateViewFilterValueUnit, +) => { + switch (unit) { + case 'DAY': + return subDays(date, amount); + case 'WEEK': + return subWeeks(date, amount); + case 'MONTH': + return subMonths(date, amount); + case 'YEAR': + return subYears(date, amount); + } +}; + +const startOfUnit = (date: Date, unit: VariableDateViewFilterValueUnit) => { + switch (unit) { + case 'DAY': + return startOfDay(date); + case 'WEEK': + return startOfWeek(date); + case 'MONTH': + return startOfMonth(date); + case 'YEAR': + return startOfYear(date); + } +}; + +const endOfUnit = (date: Date, unit: VariableDateViewFilterValueUnit) => { + switch (unit) { + case 'DAY': + return endOfDay(date); + case 'WEEK': + return endOfWeek(date); + case 'MONTH': + return endOfMonth(date); + case 'YEAR': + return endOfYear(date); + } +}; + +const resolveVariableDateViewFilterValueFromRelativeDate = (relativeDate: { + direction: VariableDateViewFilterValueDirection; + amount?: number; + unit: VariableDateViewFilterValueUnit; +}) => { + const { direction, amount, unit } = relativeDate; + const now = roundToNearestMinutes(new Date()); + + switch (direction) { + case 'NEXT': + if (amount === undefined) throw new Error('Amount is required'); + return { + start: now, + end: addUnit(now, amount, unit), + ...relativeDate, + }; + case 'PAST': + if (amount === undefined) throw new Error('Amount is required'); + return { + start: subUnit(now, amount, unit), + end: now, + ...relativeDate, + }; + case 'THIS': + return { + start: startOfUnit(now, unit), + end: endOfUnit(now, unit), + ...relativeDate, + }; + } +}; + +const resolveVariableDateViewFilterValue = (value?: string | null) => { + if (!value) return null; + + const relativeDate = variableDateViewFilterValueSchema.parse(value); + return resolveVariableDateViewFilterValueFromRelativeDate(relativeDate); +}; + +export type ResolvedDateViewFilterValue<O extends ViewFilterOperand> = + O extends ViewFilterOperand.IsRelative + ? ReturnType<typeof resolveVariableDateViewFilterValue> + : Date | null; + +type PartialViewFilter<O extends ViewFilterOperand> = Pick< + ViewFilter, + 'value' +> & { operand: O }; + +export const resolveDateViewFilterValue = <O extends ViewFilterOperand>( + viewFilter: PartialViewFilter<O>, +): ResolvedDateViewFilterValue<O> => { + if (!viewFilter.value) return null; + + if (viewFilter.operand === ViewFilterOperand.IsRelative) { + return resolveVariableDateViewFilterValue( + viewFilter.value, + ) as ResolvedDateViewFilterValue<O>; + } + return new Date(viewFilter.value) as ResolvedDateViewFilterValue<O>; +}; diff --git a/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveFilterValue.ts b/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveFilterValue.ts new file mode 100644 index 000000000000..310666488f1b --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveFilterValue.ts @@ -0,0 +1,42 @@ +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { resolveNumberViewFilterValue } from '@/views/utils/view-filter-value/resolveNumberViewFilterValue'; +import { + resolveDateViewFilterValue, + ResolvedDateViewFilterValue, +} from './resolveDateViewFilterValue'; + +type ResolvedFilterValue< + T extends FilterType, + O extends ViewFilterOperand, +> = T extends 'DATE' | 'DATE_TIME' + ? ResolvedDateViewFilterValue<O> + : T extends 'NUMBER' + ? ReturnType<typeof resolveNumberViewFilterValue> + : string; + +type PartialFilter<T extends FilterType, O extends ViewFilterOperand> = Pick< + Filter, + 'value' +> & { + definition: { type: T }; + operand: O; +}; + +export const resolveFilterValue = < + T extends FilterType, + O extends ViewFilterOperand, +>( + filter: PartialFilter<T, O>, +) => { + switch (filter.definition.type) { + case 'DATE': + case 'DATE_TIME': + return resolveDateViewFilterValue(filter) as ResolvedFilterValue<T, O>; + case 'NUMBER': + return resolveNumberViewFilterValue(filter) as ResolvedFilterValue<T, O>; + default: + return filter.value as ResolvedFilterValue<T, O>; + } +}; diff --git a/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveNumberViewFilterValue.ts b/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveNumberViewFilterValue.ts new file mode 100644 index 000000000000..4e26ca096332 --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/view-filter-value/resolveNumberViewFilterValue.ts @@ -0,0 +1,7 @@ +import { ViewFilter } from '@/views/types/ViewFilter'; + +export const resolveNumberViewFilterValue = ( + viewFilter: Pick<ViewFilter, 'value'>, +) => { + return viewFilter.value === '' ? null : +viewFilter.value; +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContent.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentCreateMode.tsx similarity index 51% rename from packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContent.tsx rename to packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentCreateMode.tsx index 8a1dc16e26be..1d4fad3080cd 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContent.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentCreateMode.tsx @@ -1,7 +1,6 @@ import styled from '@emotion/styled'; -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; import { Key } from 'ts-key-enum'; -import { IconChevronLeft, IconLayoutKanban, IconTable, IconX } from 'twenty-ui'; +import { IconLayoutKanban, IconTable, IconX } from 'twenty-ui'; import { IconPicker } from '@/ui/input/components/IconPicker'; import { Select } from '@/ui/input/components/Select'; @@ -11,30 +10,26 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope'; import { ViewType } from '@/views/types/ViewType'; -import { ViewPickerCreateOrEditButton } from '@/views/view-picker/components/ViewPickerCreateOrEditButton'; +import { ViewPickerCreateButton } from '@/views/view-picker/components/ViewPickerCreateButton'; +import { ViewPickerIconAndNameContainer } from '@/views/view-picker/components/ViewPickerIconAndNameContainer'; +import { ViewPickerSaveButtonContainer } from '@/views/view-picker/components/ViewPickerSaveButtonContainer'; +import { ViewPickerSelectContainer } from '@/views/view-picker/components/ViewPickerSelectContainer'; import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId'; import { VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerViewTypeDropdownId'; +import { useCreateViewFromCurrentState } from '@/views/view-picker/hooks/useCreateViewFromCurrentState'; import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban'; import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; -import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; - -const StyledIconAndNameContainer = styled.div` - align-items: center; - display: flex; - margin-left: ${({ theme }) => theme.spacing(1)}; - gap: ${({ theme }) => theme.spacing(1)}; -`; - -const StyledSelectContainer = styled.div` - display: flex; - width: calc(100% - ${({ theme }) => theme.spacing(2)}); - margin: ${({ theme }) => theme.spacing(1)}; - color: ${({ theme }) => theme.font.color.light}; - user-select: none; -`; +import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState'; +import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState'; +import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState'; +import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState'; const StyledNoKanbanFieldAvailableContainer = styled.div` color: ${({ theme }) => theme.font.color.light}; @@ -44,40 +39,34 @@ const StyledNoKanbanFieldAvailableContainer = styled.div` width: calc(100% - ${({ theme }) => theme.spacing(4)}); `; -const StyledSaveButtonContainer = styled.div` - display: flex; - padding: ${({ theme }) => theme.spacing(1)}; - width: calc(100% - ${({ theme }) => theme.spacing(2)}); -`; -export const ViewPickerCreateOrEditContent = () => { - const { viewPickerMode, setViewPickerMode } = useViewPickerMode(); - const { - viewPickerInputNameState, - viewPickerSelectedIconState, - viewPickerIsPersistingState, - viewPickerKanbanFieldMetadataIdState, - viewPickerTypeState, - viewPickerIsDirtyState, - } = useViewPickerStates(); - - const [viewPickerInputName, setViewPickerInputName] = useRecoilState( - viewPickerInputNameState, +export const ViewPickerContentCreateMode = () => { + const { setViewPickerMode } = useViewPickerMode(); + + const [viewPickerInputName, setViewPickerInputName] = + useRecoilComponentStateV2(viewPickerInputNameComponentState); + + const [viewPickerSelectedIcon, setViewPickerSelectedIcon] = + useRecoilComponentStateV2(viewPickerSelectedIconComponentState); + + const viewPickerIsPersisting = useRecoilComponentValueV2( + viewPickerIsPersistingComponentState, ); - const [viewPickerSelectedIcon, setViewPickerSelectedIcon] = useRecoilState( - viewPickerSelectedIconState, + const setViewPickerIsDirty = useSetRecoilComponentStateV2( + viewPickerIsDirtyComponentState, ); - const viewPickerIsPersisting = useRecoilValue(viewPickerIsPersistingState); - const setViewPickerIsDirty = useSetRecoilState(viewPickerIsDirtyState); const [viewPickerKanbanFieldMetadataId, setViewPickerKanbanFieldMetadataId] = - useRecoilState(viewPickerKanbanFieldMetadataIdState); + useRecoilComponentStateV2(viewPickerKanbanFieldMetadataIdComponentState); - const [viewPickerType, setViewPickerType] = - useRecoilState(viewPickerTypeState); + const [viewPickerType, setViewPickerType] = useRecoilComponentStateV2( + viewPickerTypeComponentState, + ); const setHotkeyScope = useSetHotkeyScope(); - const { handleCreate, handleUpdate } = useViewPickerPersistView(); + const { createViewFromCurrentState } = useCreateViewFromCurrentState(); + + const { availableFieldsForKanban } = useGetAvailableFieldsForKanban(); useScopedHotkeys( Key.Enter, @@ -85,12 +74,15 @@ export const ViewPickerCreateOrEditContent = () => { if (viewPickerIsPersisting) { return; } - if (viewPickerMode === 'create') { - await handleCreate(); - } - if (viewPickerMode === 'edit') { - await handleUpdate(); + + if ( + viewPickerType === ViewType.Kanban && + availableFieldsForKanban.length === 0 + ) { + return; } + + await createViewFromCurrentState(); }, ViewsHotkeyScope.ListDropdown, ); @@ -100,26 +92,18 @@ export const ViewPickerCreateOrEditContent = () => { setViewPickerSelectedIcon(iconKey); }; - const { availableFieldsForKanban } = useGetAvailableFieldsForKanban(); - const handleClose = async () => { - if (viewPickerMode === 'edit') { - await handleUpdate(); - } setViewPickerMode('list'); }; return ( <> - <DropdownMenuHeader - StartIcon={viewPickerMode === 'create' ? IconX : IconChevronLeft} - onClick={handleClose} - > - {viewPickerMode === 'create' ? 'Create view' : 'Edit view'} + <DropdownMenuHeader StartIcon={IconX} onClick={handleClose}> + Create view </DropdownMenuHeader> <DropdownMenuSeparator /> <DropdownMenuItemsContainer> - <StyledIconAndNameContainer> + <ViewPickerIconAndNameContainer> <IconPicker onChange={onIconChange} selectedIconKey={viewPickerSelectedIcon} @@ -134,33 +118,31 @@ export const ViewPickerCreateOrEditContent = () => { }} autoFocus /> - </StyledIconAndNameContainer> - {viewPickerMode === 'create' && ( - <StyledSelectContainer> - <Select - disableBlur - label="View type" - fullWidth - value={viewPickerType} - onChange={(value) => { - setViewPickerIsDirty(true); - setViewPickerType(value); - }} - options={[ - { value: ViewType.Table, label: 'Table', Icon: IconTable }, - { - value: ViewType.Kanban, - label: 'Kanban', - Icon: IconLayoutKanban, - }, - ]} - dropdownId={VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID} - /> - </StyledSelectContainer> - )} - {viewPickerType === ViewType.Kanban && viewPickerMode === 'create' && ( + </ViewPickerIconAndNameContainer> + <ViewPickerSelectContainer> + <Select + disableBlur + label="View type" + fullWidth + value={viewPickerType} + onChange={(value) => { + setViewPickerIsDirty(true); + setViewPickerType(value); + }} + options={[ + { value: ViewType.Table, label: 'Table', Icon: IconTable }, + { + value: ViewType.Kanban, + label: 'Kanban', + Icon: IconLayoutKanban, + }, + ]} + dropdownId={VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID} + /> + </ViewPickerSelectContainer> + {viewPickerType === ViewType.Kanban && ( <> - <StyledSelectContainer> + <ViewPickerSelectContainer> <Select disableBlur label="Stages" @@ -180,7 +162,7 @@ export const ViewPickerCreateOrEditContent = () => { } dropdownId={VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID} /> - </StyledSelectContainer> + </ViewPickerSelectContainer> {availableFieldsForKanban.length === 0 && ( <StyledNoKanbanFieldAvailableContainer> Set up a Select field on Companies to create a Kanban @@ -191,9 +173,9 @@ export const ViewPickerCreateOrEditContent = () => { </DropdownMenuItemsContainer> <DropdownMenuSeparator /> <DropdownMenuItemsContainer> - <StyledSaveButtonContainer> - <ViewPickerCreateOrEditButton /> - </StyledSaveButtonContainer> + <ViewPickerSaveButtonContainer> + <ViewPickerCreateButton /> + </ViewPickerSaveButtonContainer> </DropdownMenuItemsContainer> </> ); diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEditMode.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEditMode.tsx new file mode 100644 index 000000000000..3246651fb1fe --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEditMode.tsx @@ -0,0 +1,100 @@ +import { Key } from 'ts-key-enum'; +import { IconChevronLeft } from 'twenty-ui'; + +import { IconPicker } from '@/ui/input/components/IconPicker'; +import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; +import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; +import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope'; +import { ViewPickerEditButton } from '@/views/view-picker/components/ViewPickerEditButton'; +import { ViewPickerIconAndNameContainer } from '@/views/view-picker/components/ViewPickerIconAndNameContainer'; +import { ViewPickerSaveButtonContainer } from '@/views/view-picker/components/ViewPickerSaveButtonContainer'; +import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState'; +import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; +import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState'; +import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState'; + +export const ViewPickerContentEditMode = () => { + const { setViewPickerMode } = useViewPickerMode(); + + const [viewPickerInputName, setViewPickerInputName] = + useRecoilComponentStateV2(viewPickerInputNameComponentState); + + const [viewPickerSelectedIcon, setViewPickerSelectedIcon] = + useRecoilComponentStateV2(viewPickerSelectedIconComponentState); + + const viewPickerIsPersisting = useRecoilComponentValueV2( + viewPickerIsPersistingComponentState, + ); + const setViewPickerIsDirty = useSetRecoilComponentStateV2( + viewPickerIsDirtyComponentState, + ); + + const setHotkeyScope = useSetHotkeyScope(); + + const { updateViewFromCurrentState } = useUpdateViewFromCurrentState(); + + useScopedHotkeys( + Key.Enter, + async () => { + if (viewPickerIsPersisting) { + return; + } + + await updateViewFromCurrentState(); + }, + ViewsHotkeyScope.ListDropdown, + ); + + const onIconChange = ({ iconKey }: { iconKey: string }) => { + setViewPickerIsDirty(true); + setViewPickerSelectedIcon(iconKey); + }; + + const handleClose = async () => { + await updateViewFromCurrentState(); + + setViewPickerMode('list'); + }; + + return ( + <> + <DropdownMenuHeader StartIcon={IconChevronLeft} onClick={handleClose}> + Edit view + </DropdownMenuHeader> + <DropdownMenuSeparator /> + <DropdownMenuItemsContainer> + <ViewPickerIconAndNameContainer> + <IconPicker + onChange={onIconChange} + selectedIconKey={viewPickerSelectedIcon} + disableBlur + onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)} + /> + <DropdownMenuInput + value={viewPickerInputName} + onChange={(event) => { + setViewPickerIsDirty(true); + setViewPickerInputName(event.target.value); + }} + autoFocus + /> + </ViewPickerIconAndNameContainer> + </DropdownMenuItemsContainer> + <DropdownMenuSeparator /> + <DropdownMenuItemsContainer> + <ViewPickerSaveButtonContainer> + <ViewPickerEditButton /> + </ViewPickerSaveButtonContainer> + </DropdownMenuItemsContainer> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx new file mode 100644 index 000000000000..78742065cf1e --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx @@ -0,0 +1,90 @@ +import { useEffect } from 'react'; + +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban'; +import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState'; +import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState'; +import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState'; +import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState'; +import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState'; +import { isDefined } from '~/utils/isDefined'; + +export const ViewPickerContentEffect = () => { + const setViewPickerSelectedIcon = useSetRecoilComponentStateV2( + viewPickerSelectedIconComponentState, + ); + const setViewPickerInputName = useSetRecoilComponentStateV2( + viewPickerInputNameComponentState, + ); + + const [viewPickerKanbanFieldMetadataId, setViewPickerKanbanFieldMetadataId] = + useRecoilComponentStateV2(viewPickerKanbanFieldMetadataIdComponentState); + + const setViewPickerType = useSetRecoilComponentStateV2( + viewPickerTypeComponentState, + ); + + const viewPickerReferenceViewId = useRecoilComponentValueV2( + viewPickerReferenceViewIdComponentState, + ); + + const viewPickerIsDirty = useRecoilComponentValueV2( + viewPickerIsDirtyComponentState, + ); + + const viewPickerIsPersisting = useRecoilComponentValueV2( + viewPickerIsPersistingComponentState, + ); + + const { viewsOnCurrentObject } = useGetCurrentView(); + const referenceView = viewsOnCurrentObject.find( + (view) => view.id === viewPickerReferenceViewId, + ); + + const { availableFieldsForKanban } = useGetAvailableFieldsForKanban(); + + useEffect(() => { + if ( + isDefined(referenceView) && + !viewPickerIsPersisting && + !viewPickerIsDirty + ) { + setViewPickerSelectedIcon(referenceView.icon); + setViewPickerInputName(referenceView.name); + setViewPickerType(referenceView.type); + } + }, [ + referenceView, + setViewPickerInputName, + setViewPickerSelectedIcon, + setViewPickerType, + viewPickerIsPersisting, + viewPickerIsDirty, + ]); + + useEffect(() => { + if ( + isDefined(referenceView) && + availableFieldsForKanban.length > 0 && + viewPickerKanbanFieldMetadataId === '' + ) { + setViewPickerKanbanFieldMetadataId( + referenceView.kanbanFieldMetadataId !== '' + ? referenceView.kanbanFieldMetadataId + : availableFieldsForKanban[0].id, + ); + } + }, [ + referenceView, + availableFieldsForKanban, + viewPickerKanbanFieldMetadataId, + setViewPickerKanbanFieldMetadataId, + ]); + + return <></>; +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateButton.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateButton.tsx new file mode 100644 index 000000000000..2fb0cb4f42c4 --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateButton.tsx @@ -0,0 +1,86 @@ +import { Button } from '@/ui/input/button/components/Button'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { ViewType } from '@/views/types/ViewType'; +import { useCreateViewFromCurrentState } from '@/views/view-picker/hooks/useCreateViewFromCurrentState'; +import { useDeleteViewFromCurrentState } from '@/views/view-picker/hooks/useDeleteViewFromCurrentState'; +import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban'; +import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState'; +import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState'; + +export const ViewPickerCreateButton = () => { + const { availableFieldsForKanban, navigateToSelectSettings } = + useGetAvailableFieldsForKanban(); + + const { viewPickerMode } = useViewPickerMode(); + const viewPickerType = useRecoilComponentValueV2( + viewPickerTypeComponentState, + ); + const viewPickerIsPersisting = useRecoilComponentValueV2( + viewPickerIsPersistingComponentState, + ); + const viewPickerKanbanFieldMetadataId = useRecoilComponentValueV2( + viewPickerKanbanFieldMetadataIdComponentState, + ); + + const { createViewFromCurrentState } = useCreateViewFromCurrentState(); + const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState(); + + const handleCreateButtonClick = () => { + createViewFromCurrentState(); + }; + + if (viewPickerMode === 'edit') { + return ( + <Button + title="Delete" + onClick={deleteViewFromCurrentState} + accent="danger" + fullWidth + size="small" + justify="center" + focus={false} + variant="secondary" + disabled={viewPickerIsPersisting} + /> + ); + } + + if ( + viewPickerType === ViewType.Kanban && + availableFieldsForKanban.length === 0 + ) { + return ( + <Button + title="Go to Settings" + onClick={navigateToSelectSettings} + size="small" + accent="blue" + fullWidth + justify="center" + /> + ); + } + + if ( + viewPickerType === ViewType.Table || + viewPickerKanbanFieldMetadataId !== '' + ) { + return ( + <Button + title="Create" + onClick={handleCreateButtonClick} + accent="blue" + fullWidth + size="small" + justify="center" + disabled={ + viewPickerIsPersisting || + (viewPickerType === ViewType.Kanban && + viewPickerKanbanFieldMetadataId === '') + } + /> + ); + } +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContentEffect.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContentEffect.tsx deleted file mode 100644 index 45ba1209c18d..000000000000 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditContentEffect.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { useEffect } from 'react'; -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; - -import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; -import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; -import { isDefined } from '~/utils/isDefined'; - -export const ViewPickerCreateOrEditContentEffect = () => { - const { - viewPickerSelectedIconState, - viewPickerInputNameState, - viewPickerReferenceViewIdState, - viewPickerIsPersistingState, - viewPickerKanbanFieldMetadataIdState, - viewPickerTypeState, - viewPickerIsDirtyState, - } = useViewPickerStates(); - - const setViewPickerSelectedIcon = useSetRecoilState( - viewPickerSelectedIconState, - ); - const setViewPickerInputName = useSetRecoilState(viewPickerInputNameState); - - const [viewPickerKanbanFieldMetadataId, setViewPickerKanbanFieldMetadataId] = - useRecoilState(viewPickerKanbanFieldMetadataIdState); - const setViewPickerType = useSetRecoilState(viewPickerTypeState); - - const viewPickerReferenceViewId = useRecoilValue( - viewPickerReferenceViewIdState, - ); - - const viewPickerIsDirty = useRecoilValue(viewPickerIsDirtyState); - - const viewPickerIsPersisting = useRecoilValue(viewPickerIsPersistingState); - - const { viewsOnCurrentObject } = useGetCurrentView(); - const referenceView = viewsOnCurrentObject.find( - (view) => view.id === viewPickerReferenceViewId, - ); - - const { availableFieldsForKanban } = useGetAvailableFieldsForKanban(); - - useEffect(() => { - if ( - isDefined(referenceView) && - !viewPickerIsPersisting && - !viewPickerIsDirty - ) { - setViewPickerSelectedIcon(referenceView.icon); - setViewPickerInputName(referenceView.name); - setViewPickerType(referenceView.type); - } - }, [ - referenceView, - setViewPickerInputName, - setViewPickerSelectedIcon, - setViewPickerType, - viewPickerIsPersisting, - viewPickerIsDirty, - ]); - - useEffect(() => { - if ( - isDefined(referenceView) && - availableFieldsForKanban.length > 0 && - viewPickerKanbanFieldMetadataId === '' - ) { - setViewPickerKanbanFieldMetadataId( - referenceView.kanbanFieldMetadataId !== '' - ? referenceView.kanbanFieldMetadataId - : availableFieldsForKanban[0].id, - ); - } - }, [ - referenceView, - availableFieldsForKanban, - viewPickerKanbanFieldMetadataId, - setViewPickerKanbanFieldMetadataId, - ]); - - return <></>; -}; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerDropdown.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerDropdown.tsx index a3461683af1c..990a5088c7ef 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerDropdown.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerDropdown.tsx @@ -1,6 +1,5 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { useRecoilValue } from 'recoil'; import { IconChevronDown, IconList, @@ -11,18 +10,19 @@ import { import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState'; import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope'; -import { ViewPickerCreateOrEditContent } from '@/views/view-picker/components/ViewPickerCreateOrEditContent'; -import { ViewPickerCreateOrEditContentEffect } from '@/views/view-picker/components/ViewPickerCreateOrEditContentEffect'; +import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode'; +import { ViewPickerContentEditMode } from '@/views/view-picker/components/ViewPickerContentEditMode'; +import { ViewPickerContentEffect } from '@/views/view-picker/components/ViewPickerContentEffect'; import { ViewPickerListContent } from '@/views/view-picker/components/ViewPickerListContent'; import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId'; +import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState'; import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; -import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView'; import { isDefined } from '~/utils/isDefined'; -import { useViewStates } from '../../hooks/internal/useViewStates'; - const StyledDropdownLabelAdornments = styled.span` align-items: center; color: ${({ theme }) => theme.grayScale.gray35}; @@ -50,14 +50,12 @@ const StyledViewName = styled.span` export const ViewPickerDropdown = () => { const theme = useTheme(); - const { entityCountInCurrentViewState } = useViewStates(); - const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); - const { handleUpdate } = useViewPickerPersistView(); + const { updateViewFromCurrentState } = useUpdateViewFromCurrentState(); - const entityCountInCurrentView = useRecoilValue( - entityCountInCurrentViewState, + const entityCountInCurrentView = useRecoilComponentValueV2( + entityCountInCurrentViewComponentState, ); const { isDropdownOpen: isViewsListDropdownOpen } = useDropdown( @@ -71,7 +69,7 @@ export const ViewPickerDropdown = () => { const handleClickOutside = async () => { if (isViewsListDropdownOpen && viewPickerMode === 'edit') { - await handleUpdate(); + await updateViewFromCurrentState(); } setViewPickerMode('list'); }; @@ -106,8 +104,13 @@ export const ViewPickerDropdown = () => { <ViewPickerListContent /> ) : ( <> - <ViewPickerCreateOrEditContent /> - <ViewPickerCreateOrEditContentEffect /> + {viewPickerMode === 'create-empty' || + viewPickerMode === 'create-from-current' ? ( + <ViewPickerContentCreateMode /> + ) : ( + <ViewPickerContentEditMode /> + )} + <ViewPickerContentEffect /> </> ) } diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditButton.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerEditButton.tsx similarity index 53% rename from packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditButton.tsx rename to packages/twenty-front/src/modules/views/view-picker/components/ViewPickerEditButton.tsx index c54a9daa8dd2..a2f67dcabb16 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerCreateOrEditButton.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerEditButton.tsx @@ -1,36 +1,37 @@ -import { useRecoilValue } from 'recoil'; - import { Button } from '@/ui/input/button/components/Button'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ViewType } from '@/views/types/ViewType'; +import { useCreateViewFromCurrentState } from '@/views/view-picker/hooks/useCreateViewFromCurrentState'; +import { useDeleteViewFromCurrentState } from '@/views/view-picker/hooks/useDeleteViewFromCurrentState'; import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban'; import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; -import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState'; +import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState'; -export const ViewPickerCreateOrEditButton = () => { +export const ViewPickerEditButton = () => { const { availableFieldsForKanban, navigateToSelectSettings } = useGetAvailableFieldsForKanban(); - const { - viewPickerIsPersistingState, - viewPickerKanbanFieldMetadataIdState, - viewPickerTypeState, - } = useViewPickerStates(); - const { viewPickerMode } = useViewPickerMode(); - const viewPickerType = useRecoilValue(viewPickerTypeState); - const viewPickerIsPersisting = useRecoilValue(viewPickerIsPersistingState); - const viewPickerKanbanFieldMetadataId = useRecoilValue( - viewPickerKanbanFieldMetadataIdState, + const viewPickerType = useRecoilComponentValueV2( + viewPickerTypeComponentState, + ); + const viewPickerIsPersisting = useRecoilComponentValueV2( + viewPickerIsPersistingComponentState, + ); + const viewPickerKanbanFieldMetadataId = useRecoilComponentValueV2( + viewPickerKanbanFieldMetadataIdComponentState, ); - const { handleCreate, handleDelete } = useViewPickerPersistView(); + const { createViewFromCurrentState } = useCreateViewFromCurrentState(); + const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState(); if (viewPickerMode === 'edit') { return ( <Button title="Delete" - onClick={handleDelete} + onClick={deleteViewFromCurrentState} accent="danger" fullWidth size="small" @@ -65,7 +66,7 @@ export const ViewPickerCreateOrEditButton = () => { return ( <Button title="Create" - onClick={handleCreate} + onClick={createViewFromCurrentState} accent="blue" fullWidth size="small" diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerIconAndNameContainer.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerIconAndNameContainer.tsx new file mode 100644 index 000000000000..7bfa8e3027a7 --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerIconAndNameContainer.tsx @@ -0,0 +1,10 @@ +import styled from '@emotion/styled'; + +const StyledIconAndNameContainer = styled.div` + align-items: center; + display: flex; + margin-left: ${({ theme }) => theme.spacing(1)}; + gap: ${({ theme }) => theme.spacing(1)}; +`; + +export { StyledIconAndNameContainer as ViewPickerIconAndNameContainer }; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerListContent.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerListContent.tsx index eb7866d8db21..80d3f329a83a 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerListContent.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerListContent.tsx @@ -1,7 +1,6 @@ import styled from '@emotion/styled'; import { DropResult } from '@hello-pangea/dnd'; import { MouseEvent, useCallback } from 'react'; -import { useSetRecoilState } from 'recoil'; import { IconLock, IconPencil, IconPlus, useIcons } from 'twenty-ui'; import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem'; @@ -11,11 +10,13 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItemDraggable'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { useChangeView } from '@/views/hooks/useChangeView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; -import { useHandleViews } from '@/views/hooks/useHandleViews'; +import { useUpdateView } from '@/views/hooks/useUpdateView'; import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId'; import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; +import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState'; import { moveArrayItem } from '~/utils/array/moveArrayItem'; import { isDefined } from '~/utils/isDefined'; @@ -24,29 +25,27 @@ const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)` `; export const ViewPickerListContent = () => { - const { selectView } = useHandleViews(); - const { currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject } = useGetCurrentView(); - const { viewPickerReferenceViewIdState } = useViewPickerStates(); - const setViewPickerReferenceViewId = useSetRecoilState( - viewPickerReferenceViewIdState, + const setViewPickerReferenceViewId = useSetRecoilComponentStateV2( + viewPickerReferenceViewIdComponentState, ); const { setViewPickerMode } = useViewPickerMode(); const { closeDropdown } = useDropdown(VIEW_PICKER_DROPDOWN_ID); - const { updateView } = useHandleViews(); + const { updateView } = useUpdateView(); + const { changeView } = useChangeView(); const handleViewSelect = (viewId: string) => { - selectView(viewId); + changeView(viewId); closeDropdown(); }; const handleAddViewButtonClick = () => { if (isDefined(currentViewWithCombinedFiltersAndSorts?.id)) { setViewPickerReferenceViewId(currentViewWithCombinedFiltersAndSorts.id); - setViewPickerMode('create'); + setViewPickerMode('create-empty'); } }; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSaveButtonContainer.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSaveButtonContainer.tsx new file mode 100644 index 000000000000..6dd2763eeccd --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSaveButtonContainer.tsx @@ -0,0 +1,9 @@ +import styled from '@emotion/styled'; + +const StyledSaveButtonContainer = styled.div` + display: flex; + padding: ${({ theme }) => theme.spacing(1)}; + width: calc(100% - ${({ theme }) => theme.spacing(2)}); +`; + +export { StyledSaveButtonContainer as ViewPickerSaveButtonContainer }; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSelectContainer.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSelectContainer.tsx new file mode 100644 index 000000000000..c72ebc6860f2 --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerSelectContainer.tsx @@ -0,0 +1,11 @@ +import styled from '@emotion/styled'; + +const StyledSelectContainer = styled.div` + display: flex; + width: calc(100% - ${({ theme }) => theme.spacing(2)}); + margin: ${({ theme }) => theme.spacing(1)}; + color: ${({ theme }) => theme.font.color.light}; + user-select: none; +`; + +export { StyledSelectContainer as ViewPickerSelectContainer }; diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts index dc6220b078cc..46fde3f74a19 100644 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts @@ -1,19 +1,18 @@ import { useCallback } from 'react'; -import { useSetRecoilState } from 'recoil'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId'; import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId'; import { VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerViewTypeDropdownId'; import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; export const useCloseAndResetViewPicker = () => { const { setViewPickerMode } = useViewPickerMode(); - const { viewPickerIsPersistingState } = useViewPickerStates(); - const setViewPickerIsPersisting = useSetRecoilState( - viewPickerIsPersistingState, + const setViewPickerIsPersisting = useSetRecoilComponentStateV2( + viewPickerIsPersistingComponentState, ); const { closeDropdown: closeViewPickerDropdown } = useDropdown( diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts new file mode 100644 index 000000000000..c84ec24f29be --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useCreateViewFromCurrentState.ts @@ -0,0 +1,118 @@ +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useChangeView } from '@/views/hooks/useChangeView'; +import { useCreateViewFromCurrentView } from '@/views/hooks/useCreateViewFromCurrentView'; +import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker'; +import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState'; +import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState'; +import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState'; +import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState'; +import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState'; +import { useRecoilCallback } from 'recoil'; +import { v4 } from 'uuid'; + +export const useCreateViewFromCurrentState = (viewBarInstanceId?: string) => { + const { closeAndResetViewPicker } = useCloseAndResetViewPicker(); + + const viewPickerInputNameCallbackState = useRecoilComponentCallbackStateV2( + viewPickerInputNameComponentState, + viewBarInstanceId, + ); + + const viewPickerSelectedIconCallbackState = useRecoilComponentCallbackStateV2( + viewPickerSelectedIconComponentState, + viewBarInstanceId, + ); + + const viewPickerTypeCallbackState = useRecoilComponentCallbackStateV2( + viewPickerTypeComponentState, + viewBarInstanceId, + ); + + const viewPickerKanbanFieldMetadataIdCallbackState = + useRecoilComponentCallbackStateV2( + viewPickerKanbanFieldMetadataIdComponentState, + viewBarInstanceId, + ); + + const viewPickerIsPersistingCallbackState = useRecoilComponentCallbackStateV2( + viewPickerIsPersistingComponentState, + viewBarInstanceId, + ); + + const viewPickerIsDirtyCallbackState = useRecoilComponentCallbackStateV2( + viewPickerIsDirtyComponentState, + viewBarInstanceId, + ); + + const viewPickerModeCallbackState = useRecoilComponentCallbackStateV2( + viewPickerModeComponentState, + viewBarInstanceId, + ); + + const { createViewFromCurrentView } = + useCreateViewFromCurrentView(viewBarInstanceId); + const { changeView } = useChangeView(viewBarInstanceId); + + const createViewFromCurrentState = useRecoilCallback( + ({ snapshot, set }) => + async () => { + const name = getSnapshotValue( + snapshot, + viewPickerInputNameCallbackState, + ); + const iconKey = getSnapshotValue( + snapshot, + viewPickerSelectedIconCallbackState, + ); + const type = getSnapshotValue(snapshot, viewPickerTypeCallbackState); + const kanbanFieldMetadataId = getSnapshotValue( + snapshot, + viewPickerKanbanFieldMetadataIdCallbackState, + ); + + const viewPickerMode = getSnapshotValue( + snapshot, + viewPickerModeCallbackState, + ); + + const shouldCopyFiltersAndSorts = + viewPickerMode === 'create-from-current'; + + const id = v4(); + + set(viewPickerIsPersistingCallbackState, true); + set(viewPickerIsDirtyCallbackState, false); + + await createViewFromCurrentView( + { + id, + name, + icon: iconKey, + type, + kanbanFieldMetadataId, + }, + shouldCopyFiltersAndSorts, + ); + + closeAndResetViewPicker(); + changeView(id); + }, + [ + closeAndResetViewPicker, + createViewFromCurrentView, + changeView, + viewPickerInputNameCallbackState, + viewPickerIsDirtyCallbackState, + viewPickerIsPersistingCallbackState, + viewPickerKanbanFieldMetadataIdCallbackState, + viewPickerSelectedIconCallbackState, + viewPickerTypeCallbackState, + viewPickerModeCallbackState, + ], + ); + + return { createViewFromCurrentState }; +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useDeleteViewFromCurrentState.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useDeleteViewFromCurrentState.ts new file mode 100644 index 000000000000..038fbac49c02 --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useDeleteViewFromCurrentState.ts @@ -0,0 +1,78 @@ +import { useRecoilCallback } from 'recoil'; + +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useChangeView } from '@/views/hooks/useChangeView'; +import { useDeleteView } from '@/views/hooks/useDeleteView'; +import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker'; +import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState'; + +export const useDeleteViewFromCurrentState = (viewBarInstanceId?: string) => { + const { viewsOnCurrentObject, currentViewId } = + useGetCurrentView(viewBarInstanceId); + + const { closeAndResetViewPicker } = useCloseAndResetViewPicker(); + + const viewPickerIsPersistingCallbackState = useRecoilComponentCallbackStateV2( + viewPickerIsPersistingComponentState, + viewBarInstanceId, + ); + + const viewPickerIsDirtyCallbackState = useRecoilComponentCallbackStateV2( + viewPickerIsDirtyComponentState, + viewBarInstanceId, + ); + + const viewPickerReferenceViewIdCallbackState = + useRecoilComponentCallbackStateV2( + viewPickerReferenceViewIdComponentState, + viewBarInstanceId, + ); + + const { changeView } = useChangeView(viewBarInstanceId); + + const { deleteView } = useDeleteView(); + + const deleteViewFromCurrentState = useRecoilCallback( + ({ set, snapshot }) => + async () => { + set(viewPickerIsPersistingCallbackState, true); + closeAndResetViewPicker(); + set(viewPickerIsDirtyCallbackState, false); + + const viewPickerReferenceViewId = getSnapshotValue( + snapshot, + viewPickerReferenceViewIdCallbackState, + ); + + const shouldChangeView = viewPickerReferenceViewId === currentViewId; + + if (shouldChangeView) { + changeView( + viewsOnCurrentObject.filter( + (view) => view.id !== viewPickerReferenceViewId, + )[0].id, + ); + } + + await deleteView(viewPickerReferenceViewId); + }, + [ + currentViewId, + closeAndResetViewPicker, + changeView, + deleteView, + viewPickerIsDirtyCallbackState, + viewPickerIsPersistingCallbackState, + viewPickerReferenceViewIdCallbackState, + viewsOnCurrentObject, + ], + ); + + return { + deleteViewFromCurrentState, + }; +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useGetAvailableFieldsForKanban.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useGetAvailableFieldsForKanban.ts index 1c595472bf6b..23e082c2c73c 100644 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useGetAvailableFieldsForKanban.ts +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useGetAvailableFieldsForKanban.ts @@ -5,14 +5,15 @@ import { useRecoilValue, useSetRecoilState } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; -import { useViewStates } from '@/views/hooks/internal/useViewStates'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isDefined } from '~/utils/isDefined'; export const useGetAvailableFieldsForKanban = () => { - const { viewObjectMetadataIdState } = useViewStates(); - - const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState); + const viewObjectMetadataId = useRecoilComponentValueV2( + viewObjectMetadataIdComponentState, + ); const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const setNavigationMemorizedUrl = useSetRecoilState( navigationMemorizedUrlState, diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useUpdateViewFromCurrentState.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useUpdateViewFromCurrentState.ts new file mode 100644 index 000000000000..d4db3b4a2c94 --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useUpdateViewFromCurrentState.ts @@ -0,0 +1,80 @@ +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useChangeView } from '@/views/hooks/useChangeView'; +import { useUpdateView } from '@/views/hooks/useUpdateView'; +import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker'; +import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState'; +import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; +import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; +import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState'; +import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState'; +import { useRecoilCallback } from 'recoil'; + +export const useUpdateViewFromCurrentState = (viewBarInstanceId?: string) => { + const { closeAndResetViewPicker } = useCloseAndResetViewPicker(); + + const viewPickerInputNameCallbackState = useRecoilComponentCallbackStateV2( + viewPickerInputNameComponentState, + ); + + const viewPickerSelectedIconCallbackState = useRecoilComponentCallbackStateV2( + viewPickerSelectedIconComponentState, + ); + + const viewPickerIsPersistingCallbackState = useRecoilComponentCallbackStateV2( + viewPickerIsPersistingComponentState, + ); + + const viewPickerIsDirtyCallbackState = useRecoilComponentCallbackStateV2( + viewPickerIsDirtyComponentState, + ); + + const viewPickerReferenceViewIdCallbackState = + useRecoilComponentCallbackStateV2(viewPickerReferenceViewIdComponentState); + + const { updateView } = useUpdateView(); + const { changeView } = useChangeView(viewBarInstanceId); + + const updateViewFromCurrentState = useRecoilCallback( + ({ set, snapshot }) => + async () => { + set(viewPickerIsPersistingCallbackState, true); + set(viewPickerIsDirtyCallbackState, false); + closeAndResetViewPicker(); + + const viewPickerReferenceViewId = getSnapshotValue( + snapshot, + viewPickerReferenceViewIdCallbackState, + ); + const viewPickerInputName = getSnapshotValue( + snapshot, + viewPickerInputNameCallbackState, + ); + const viewPickerSelectedIcon = getSnapshotValue( + snapshot, + viewPickerSelectedIconCallbackState, + ); + + await updateView({ + id: viewPickerReferenceViewId, + name: viewPickerInputName, + icon: viewPickerSelectedIcon, + }); + changeView(viewPickerReferenceViewId); + }, + [ + viewPickerIsPersistingCallbackState, + viewPickerIsDirtyCallbackState, + closeAndResetViewPicker, + viewPickerReferenceViewIdCallbackState, + viewPickerInputNameCallbackState, + viewPickerSelectedIconCallbackState, + updateView, + changeView, + ], + ); + + return { + updateViewFromCurrentState, + }; +}; diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerMode.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerMode.ts index d3ef5c01e7b0..ade4ec0e3a5a 100644 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerMode.ts +++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerMode.ts @@ -1,12 +1,11 @@ -import { useRecoilState } from 'recoil'; - -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState'; export const useViewPickerMode = (viewBarComponentId?: string) => { - const { viewPickerModeState } = useViewPickerStates(viewBarComponentId); - - const [viewPickerMode, setViewPickerMode] = - useRecoilState(viewPickerModeState); + const [viewPickerMode, setViewPickerMode] = useRecoilComponentStateV2( + viewPickerModeComponentState, + viewBarComponentId, + ); return { viewPickerMode, diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerPersistView.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerPersistView.ts deleted file mode 100644 index ba9c00398b2c..000000000000 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerPersistView.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { useRecoilCallback } from 'recoil'; -import { v4 } from 'uuid'; - -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; -import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; -import { useHandleViews } from '@/views/hooks/useHandleViews'; -import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker'; -import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates'; - -export const useViewPickerPersistView = () => { - const { - viewPickerInputNameState, - viewPickerSelectedIconState, - viewPickerIsPersistingState, - viewPickerReferenceViewIdState, - viewPickerKanbanFieldMetadataIdState, - viewPickerTypeState, - viewPickerIsDirtyState, - } = useViewPickerStates(); - - const { createView, selectView, removeView, updateView } = useHandleViews(); - - const { viewsOnCurrentObject } = useGetCurrentView(); - - const { closeAndResetViewPicker } = useCloseAndResetViewPicker(); - - const handleCreate = useRecoilCallback( - ({ snapshot, set }) => - async () => { - const name = getSnapshotValue(snapshot, viewPickerInputNameState); - const iconKey = getSnapshotValue(snapshot, viewPickerSelectedIconState); - const type = getSnapshotValue(snapshot, viewPickerTypeState); - const kanbanFieldMetadataId = getSnapshotValue( - snapshot, - viewPickerKanbanFieldMetadataIdState, - ); - const id = v4(); - set(viewPickerIsPersistingState, true); - set(viewPickerIsDirtyState, false); - await createView({ - id, - name, - icon: iconKey, - type, - kanbanFieldMetadataId, - }); - closeAndResetViewPicker(); - selectView(id); - }, - [ - closeAndResetViewPicker, - createView, - selectView, - viewPickerInputNameState, - viewPickerIsDirtyState, - viewPickerIsPersistingState, - viewPickerKanbanFieldMetadataIdState, - viewPickerSelectedIconState, - viewPickerTypeState, - ], - ); - - const handleDelete = useRecoilCallback( - ({ set, snapshot }) => - async () => { - set(viewPickerIsPersistingState, true); - closeAndResetViewPicker(); - set(viewPickerIsDirtyState, false); - const viewPickerReferenceViewId = getSnapshotValue( - snapshot, - viewPickerReferenceViewIdState, - ); - - selectView( - viewsOnCurrentObject.filter( - (view) => view.id !== viewPickerReferenceViewId, - )[0].id, - ); - await removeView(viewPickerReferenceViewId); - }, - [ - closeAndResetViewPicker, - removeView, - selectView, - viewPickerIsDirtyState, - viewPickerIsPersistingState, - viewPickerReferenceViewIdState, - viewsOnCurrentObject, - ], - ); - - const handleUpdate = useRecoilCallback( - ({ set, snapshot }) => - async () => { - set(viewPickerIsPersistingState, true); - set(viewPickerIsDirtyState, false); - closeAndResetViewPicker(); - - const viewPickerReferenceViewId = getSnapshotValue( - snapshot, - viewPickerReferenceViewIdState, - ); - const viewPickerInputName = getSnapshotValue( - snapshot, - viewPickerInputNameState, - ); - const viewPickerSelectedIcon = getSnapshotValue( - snapshot, - viewPickerSelectedIconState, - ); - - await updateView({ - id: viewPickerReferenceViewId, - name: viewPickerInputName, - icon: viewPickerSelectedIcon, - }); - selectView(viewPickerReferenceViewId); - }, - [ - viewPickerIsPersistingState, - viewPickerIsDirtyState, - closeAndResetViewPicker, - viewPickerReferenceViewIdState, - viewPickerInputNameState, - viewPickerSelectedIconState, - updateView, - selectView, - ], - ); - - return { handleCreate, handleDelete, handleUpdate }; -}; diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerStates.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerStates.ts deleted file mode 100644 index 58bfd987cdde..000000000000 --- a/packages/twenty-front/src/modules/views/view-picker/hooks/useViewPickerStates.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; -import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState'; -import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState'; -import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState'; -import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState'; -import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState'; -import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState'; -import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState'; -import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState'; - -import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext'; - -export const useViewPickerStates = (viewComponentId?: string) => { - const componentId = useAvailableScopeIdOrThrow( - ViewScopeInternalContext, - viewComponentId, - ); - - return { - componentId, - viewPickerModeState: extractComponentState( - viewPickerModeComponentState, - componentId, - ), - viewPickerInputNameState: extractComponentState( - viewPickerInputNameComponentState, - componentId, - ), - viewPickerSelectedIconState: extractComponentState( - viewPickerSelectedIconComponentState, - componentId, - ), - viewPickerKanbanFieldMetadataIdState: extractComponentState( - viewPickerKanbanFieldMetadataIdComponentState, - componentId, - ), - viewPickerReferenceViewIdState: extractComponentState( - viewPickerReferenceViewIdComponentState, - componentId, - ), - viewPickerIsPersistingState: extractComponentState( - viewPickerIsPersistingComponentState, - componentId, - ), - viewPickerTypeState: extractComponentState( - viewPickerTypeComponentState, - componentId, - ), - viewPickerIsDirtyState: extractComponentState( - viewPickerIsDirtyComponentState, - componentId, - ), - }; -}; diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerInputNameComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerInputNameComponentState.ts index 35ef6551f923..8aa032b554e1 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerInputNameComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerInputNameComponentState.ts @@ -1,6 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const viewPickerInputNameComponentState = createComponentState<string>({ - key: 'viewPickerInputNameComponentState', - defaultValue: '', -}); +export const viewPickerInputNameComponentState = createComponentStateV2<string>( + { + key: 'viewPickerInputNameComponentState', + defaultValue: '', + componentInstanceContext: ViewComponentInstanceContext, + }, +); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsDirtyComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsDirtyComponentState.ts index a732ae062f6c..a370b3dcfa9d 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsDirtyComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsDirtyComponentState.ts @@ -1,6 +1,8 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; -export const viewPickerIsDirtyComponentState = createComponentState<boolean>({ +export const viewPickerIsDirtyComponentState = createComponentStateV2<boolean>({ key: 'viewPickerIsDirtyComponentState', defaultValue: false, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsPersistingComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsPersistingComponentState.ts index e7e201f8190a..2bbc92786c36 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsPersistingComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerIsPersistingComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const viewPickerIsPersistingComponentState = - createComponentState<boolean>({ + createComponentStateV2<boolean>({ key: 'viewPickerIsPersistingComponentState', defaultValue: false, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState.ts index 2a7ad8117d06..25ac3daa2f69 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const viewPickerKanbanFieldMetadataIdComponentState = - createComponentState<string>({ + createComponentStateV2<string>({ key: 'viewPickerKanbanFieldMetadataIdComponentState', defaultValue: '', + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerModeComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerModeComponentState.ts index b828f4a80214..4a3a8e1b8719 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerModeComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerModeComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; +import { ViewPickerMode } from '@/views/view-picker/types/ViewPickerMode'; -export const viewPickerModeComponentState = createComponentState< - 'list' | 'edit' | 'create' ->({ - key: 'viewEditModeComponentState', - defaultValue: 'list', -}); +export const viewPickerModeComponentState = + createComponentStateV2<ViewPickerMode>({ + key: 'viewPickerModeComponentState', + defaultValue: 'list', + componentInstanceContext: ViewComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerReferenceViewIdComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerReferenceViewIdComponentState.ts index 33d17de9079c..e3a9d6fbd3cc 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerReferenceViewIdComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerReferenceViewIdComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const viewPickerReferenceViewIdComponentState = - createComponentState<string>({ + createComponentStateV2<string>({ key: 'viewPickerReferenceViewIdComponentState', defaultValue: '', + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerSelectedIconComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerSelectedIconComponentState.ts index ae52733e8523..feee0aee3e30 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerSelectedIconComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerSelectedIconComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const viewPickerSelectedIconComponentState = - createComponentState<string>({ + createComponentStateV2<string>({ key: 'viewPickerSelectedIconComponentState', defaultValue: '', + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerTypeComponentState.ts b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerTypeComponentState.ts index b56193372a36..5f440008c344 100644 --- a/packages/twenty-front/src/modules/views/view-picker/states/viewPickerTypeComponentState.ts +++ b/packages/twenty-front/src/modules/views/view-picker/states/viewPickerTypeComponentState.ts @@ -1,7 +1,9 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; +import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; import { ViewType } from '@/views/types/ViewType'; -export const viewPickerTypeComponentState = createComponentState<ViewType>({ +export const viewPickerTypeComponentState = createComponentStateV2<ViewType>({ key: 'viewPickerTypeComponentState', defaultValue: ViewType.Table, + componentInstanceContext: ViewComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/views/view-picker/types/ViewPickerMode.ts b/packages/twenty-front/src/modules/views/view-picker/types/ViewPickerMode.ts new file mode 100644 index 000000000000..cc095b1e3af9 --- /dev/null +++ b/packages/twenty-front/src/modules/views/view-picker/types/ViewPickerMode.ts @@ -0,0 +1,5 @@ +export type ViewPickerMode = + | 'list' + | 'edit' + | 'create-empty' + | 'create-from-current'; diff --git a/packages/twenty-front/src/modules/workflow/components/RecordShowPageWorkflowHeader.tsx b/packages/twenty-front/src/modules/workflow/components/RecordShowPageWorkflowHeader.tsx new file mode 100644 index 000000000000..4afb9839e7ea --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/RecordShowPageWorkflowHeader.tsx @@ -0,0 +1,96 @@ +import { Button } from '@/ui/input/button/components/Button'; +import { useActivateWorkflowVersion } from '@/workflow/hooks/useActivateWorkflowVersion'; +import { useDeactivateWorkflowVersion } from '@/workflow/hooks/useDeactivateWorkflowVersion'; +import { useDeleteOneWorkflowVersion } from '@/workflow/hooks/useDeleteOneWorkflowVersion'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { + IconPlayerPlay, + IconPlayerStop, + IconPower, + IconTrash, + isDefined, +} from 'twenty-ui'; +import { assertWorkflowWithCurrentVersionIsDefined } from '../utils/assertWorkflowWithCurrentVersionIsDefined'; + +export const RecordShowPageWorkflowHeader = ({ + workflowId, +}: { + workflowId: string | undefined; +}) => { + const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId); + + const isWaitingForWorkflowWithCurrentVersion = + !isDefined(workflowWithCurrentVersion) || + !isDefined(workflowWithCurrentVersion.currentVersion); + + const { activateWorkflowVersion } = useActivateWorkflowVersion(); + const { deactivateWorkflowVersion } = useDeactivateWorkflowVersion(); + const { deleteOneWorkflowVersion } = useDeleteOneWorkflowVersion(); + + return ( + <> + <Button + title="Test" + variant="secondary" + Icon={IconPlayerPlay} + disabled={isWaitingForWorkflowWithCurrentVersion} + onClick={() => {}} + /> + + {workflowWithCurrentVersion?.currentVersion?.status === 'DRAFT' && + workflowWithCurrentVersion.versions?.length > 1 ? ( + <Button + title="Discard Draft" + variant="secondary" + Icon={IconTrash} + disabled={isWaitingForWorkflowWithCurrentVersion} + onClick={() => { + assertWorkflowWithCurrentVersionIsDefined( + workflowWithCurrentVersion, + ); + + return deleteOneWorkflowVersion({ + workflowId: workflowWithCurrentVersion.id, + workflowVersionId: workflowWithCurrentVersion.currentVersion.id, + }); + }} + /> + ) : null} + + {workflowWithCurrentVersion?.currentVersion?.status === 'DRAFT' || + workflowWithCurrentVersion?.currentVersion?.status === 'DEACTIVATED' ? ( + <Button + title="Activate" + variant="secondary" + Icon={IconPower} + disabled={isWaitingForWorkflowWithCurrentVersion} + onClick={() => { + assertWorkflowWithCurrentVersionIsDefined( + workflowWithCurrentVersion, + ); + + return activateWorkflowVersion( + workflowWithCurrentVersion.currentVersion.id, + ); + }} + /> + ) : workflowWithCurrentVersion?.currentVersion?.status === 'ACTIVE' ? ( + <Button + title="Deactivate" + variant="secondary" + Icon={IconPlayerStop} + disabled={isWaitingForWorkflowWithCurrentVersion} + onClick={() => { + assertWorkflowWithCurrentVersionIsDefined( + workflowWithCurrentVersion, + ); + + return deactivateWorkflowVersion( + workflowWithCurrentVersion.currentVersion.id, + ); + }} + /> + ) : null} + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStep.tsx b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStep.tsx new file mode 100644 index 000000000000..bc0b4b54d5d6 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStep.tsx @@ -0,0 +1,16 @@ +import { RightDrawerWorkflowEditStepContent } from '@/workflow/components/RightDrawerWorkflowEditStepContent'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { workflowIdState } from '@/workflow/states/workflowIdState'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +export const RightDrawerWorkflowEditStep = () => { + const workflowId = useRecoilValue(workflowIdState); + const workflow = useWorkflowWithCurrentVersion(workflowId); + + if (!isDefined(workflow)) { + return null; + } + + return <RightDrawerWorkflowEditStepContent workflow={workflow} />; +}; diff --git a/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStepContent.tsx b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStepContent.tsx new file mode 100644 index 000000000000..9fb36225678c --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowEditStepContent.tsx @@ -0,0 +1,93 @@ +import { WorkflowEditActionForm } from '@/workflow/components/WorkflowEditActionForm'; +import { WorkflowEditTriggerForm } from '@/workflow/components/WorkflowEditTriggerForm'; +import { TRIGGER_STEP_ID } from '@/workflow/constants/TriggerStepId'; +import { useUpdateWorkflowVersionStep } from '@/workflow/hooks/useUpdateWorkflowVersionStep'; +import { useUpdateWorkflowVersionTrigger } from '@/workflow/hooks/useUpdateWorkflowVersionTrigger'; +import { workflowSelectedNodeState } from '@/workflow/states/workflowSelectedNodeState'; +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; +import { findStepPositionOrThrow } from '@/workflow/utils/findStepPositionOrThrow'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +const getStepDefinitionOrThrow = ({ + stepId, + workflow, +}: { + stepId: string; + workflow: WorkflowWithCurrentVersion; +}) => { + const currentVersion = workflow.currentVersion; + if (!isDefined(currentVersion)) { + throw new Error('Expected to find a current version'); + } + + if (stepId === TRIGGER_STEP_ID) { + if (!isDefined(currentVersion.trigger)) { + return { + type: 'trigger', + definition: undefined, + } as const; + } + + return { + type: 'trigger', + definition: currentVersion.trigger, + } as const; + } + + if (!isDefined(currentVersion.steps)) { + throw new Error( + 'Malformed workflow version: missing steps information; be sure to create at least one step before trying to edit one', + ); + } + + const selectedNodePosition = findStepPositionOrThrow({ + steps: currentVersion.steps, + stepId: stepId, + }); + + return { + type: 'action', + definition: selectedNodePosition.steps[selectedNodePosition.index], + } as const; +}; + +export const RightDrawerWorkflowEditStepContent = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const workflowSelectedNode = useRecoilValue(workflowSelectedNodeState); + if (!isDefined(workflowSelectedNode)) { + throw new Error( + 'Expected a node to be selected. Selecting a node is mandatory to edit it.', + ); + } + + const { updateTrigger } = useUpdateWorkflowVersionTrigger({ workflow }); + const { updateStep } = useUpdateWorkflowVersionStep({ + workflow, + stepId: workflowSelectedNode, + }); + + const stepDefinition = getStepDefinitionOrThrow({ + stepId: workflowSelectedNode, + workflow, + }); + + if (stepDefinition.type === 'trigger') { + return ( + <WorkflowEditTriggerForm + trigger={stepDefinition.definition} + onTriggerUpdate={updateTrigger} + /> + ); + } + + return ( + <WorkflowEditActionForm + action={stepDefinition.definition} + onActionUpdate={updateStep} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectAction.tsx b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectAction.tsx new file mode 100644 index 000000000000..dadc160f4a8a --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectAction.tsx @@ -0,0 +1,16 @@ +import { RightDrawerWorkflowSelectActionContent } from '@/workflow/components/RightDrawerWorkflowSelectActionContent'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { workflowIdState } from '@/workflow/states/workflowIdState'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +export const RightDrawerWorkflowSelectAction = () => { + const workflowId = useRecoilValue(workflowIdState); + const workflow = useWorkflowWithCurrentVersion(workflowId); + + if (!isDefined(workflow)) { + return null; + } + + return <RightDrawerWorkflowSelectActionContent workflow={workflow} />; +}; diff --git a/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectActionContent.tsx b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectActionContent.tsx new file mode 100644 index 000000000000..094cc99e0996 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/RightDrawerWorkflowSelectActionContent.tsx @@ -0,0 +1,41 @@ +import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; +import { ACTIONS } from '@/workflow/constants/Actions'; +import { useCreateStep } from '@/workflow/hooks/useCreateStep'; +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; +import styled from '@emotion/styled'; + +const StyledActionListContainer = styled.div` + display: flex; + flex-direction: column; + height: 100%; + overflow-y: auto; + + padding-block: ${({ theme }) => theme.spacing(1)}; + padding-inline: ${({ theme }) => theme.spacing(2)}; +`; + +export const RightDrawerWorkflowSelectActionContent = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const { createStep } = useCreateStep({ + workflow, + }); + + return ( + <> + <StyledActionListContainer> + {ACTIONS.map((action) => ( + <MenuItem + LeftIcon={action.icon} + text={action.label} + onClick={() => { + return createStep(action.type); + }} + /> + ))} + </StyledActionListContainer> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/Workflow.tsx b/packages/twenty-front/src/modules/workflow/components/Workflow.tsx new file mode 100644 index 000000000000..a9e33c882136 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/Workflow.tsx @@ -0,0 +1,58 @@ +import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; +import { WorkflowDiagramCanvas } from '@/workflow/components/WorkflowDiagramCanvas'; +import { WorkflowEffect } from '@/workflow/components/WorkflowEffect'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { workflowDiagramState } from '@/workflow/states/workflowDiagramState'; +import styled from '@emotion/styled'; +import '@xyflow/react/dist/style.css'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +const StyledFlowContainer = styled.div` + height: 100%; + width: 100%; + position: relative; + + /* Below we reset the default styling of Reactflow */ + .react-flow__node-input, + .react-flow__node-default, + .react-flow__node-output, + .react-flow__node-group { + padding: 0; + } + + --xy-node-border-radius: none; + --xy-node-border: none; + --xy-node-background-color: none; + --xy-node-boxshadow-hover: none; + --xy-node-boxshadow-selected: none; +`; + +export const Workflow = ({ + targetableObject, +}: { + targetableObject: ActivityTargetableObject; +}) => { + const workflowId = targetableObject.id; + + const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId); + const workflowDiagram = useRecoilValue(workflowDiagramState); + + return ( + <> + <WorkflowEffect + workflowId={workflowId} + workflowWithCurrentVersion={workflowWithCurrentVersion} + /> + + <StyledFlowContainer> + {isDefined(workflowDiagram) && isDefined(workflowWithCurrentVersion) ? ( + <WorkflowDiagramCanvas + diagram={workflowDiagram} + workflowWithCurrentVersion={workflowWithCurrentVersion} + /> + ) : null} + </StyledFlowContainer> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx new file mode 100644 index 000000000000..8c05d48baa09 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx @@ -0,0 +1,109 @@ +import { WorkflowDiagramStepNodeData } from '@/workflow/types/WorkflowDiagram'; +import styled from '@emotion/styled'; +import { Handle, Position } from '@xyflow/react'; +import React from 'react'; +import { capitalize } from '~/utils/string/capitalize'; + +type Variant = 'placeholder'; + +const StyledStepNodeContainer = styled.div` + display: flex; + flex-direction: column; + + padding-bottom: 12px; + padding-top: 6px; +`; + +const StyledStepNodeType = styled.div` + background-color: ${({ theme }) => theme.background.tertiary}; + border-radius: ${({ theme }) => theme.border.radius.sm} + ${({ theme }) => theme.border.radius.sm} 0 0; + + color: ${({ theme }) => theme.color.gray50}; + font-size: ${({ theme }) => theme.font.size.xs}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + + padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)}; + position: absolute; + top: 0; + transform: translateY(-100%); + + .selectable.selected &, + .selectable:focus &, + .selectable:focus-visible & { + background-color: ${({ theme }) => theme.color.blue}; + color: ${({ theme }) => theme.font.color.inverted}; + } +`; + +const StyledStepNodeInnerContainer = styled.div<{ variant?: Variant }>` + background-color: ${({ theme }) => theme.background.secondary}; + border: 1px solid ${({ theme }) => theme.border.color.medium}; + border-style: ${({ variant }) => + variant === 'placeholder' ? 'dashed' : null}; + border-radius: ${({ theme }) => theme.border.radius.md}; + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(2)}; + + position: relative; + box-shadow: ${({ variant, theme }) => + variant === 'placeholder' ? 'none' : theme.boxShadow.superHeavy}; + + .selectable.selected &, + .selectable:focus &, + .selectable:focus-visible & { + background-color: ${({ theme }) => theme.color.blue10}; + border-color: ${({ theme }) => theme.color.blue}; + } +`; + +const StyledStepNodeLabel = styled.div<{ variant?: Variant }>` + align-items: center; + display: flex; + font-size: ${({ theme }) => theme.font.size.md}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + column-gap: ${({ theme }) => theme.spacing(2)}; + color: ${({ variant, theme }) => + variant === 'placeholder' ? theme.font.color.extraLight : null}; +`; + +const StyledSourceHandle = styled(Handle)` + background-color: ${({ theme }) => theme.color.gray50}; +`; + +export const StyledTargetHandle = styled(Handle)` + visibility: hidden; +`; + +export const WorkflowDiagramBaseStepNode = ({ + nodeType, + label, + variant, + Icon, +}: { + nodeType: WorkflowDiagramStepNodeData['nodeType']; + label: string; + variant?: Variant; + Icon?: React.ReactNode; +}) => { + return ( + <StyledStepNodeContainer> + {nodeType !== 'trigger' ? ( + <StyledTargetHandle type="target" position={Position.Top} /> + ) : null} + + <StyledStepNodeInnerContainer variant={variant}> + <StyledStepNodeType>{capitalize(nodeType)}</StyledStepNodeType> + + <StyledStepNodeLabel variant={variant}> + {Icon} + + {label} + </StyledStepNodeLabel> + </StyledStepNodeInnerContainer> + + <StyledSourceHandle type="source" position={Position.Bottom} /> + </StyledStepNodeContainer> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvas.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvas.tsx new file mode 100644 index 000000000000..83b9c0c67ad3 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvas.tsx @@ -0,0 +1,109 @@ +import { WorkflowDiagramCanvasEffect } from '@/workflow/components/WorkflowDiagramCanvasEffect'; +import { WorkflowDiagramCreateStepNode } from '@/workflow/components/WorkflowDiagramCreateStepNode'; +import { WorkflowDiagramEmptyTrigger } from '@/workflow/components/WorkflowDiagramEmptyTrigger'; +import { WorkflowDiagramStepNode } from '@/workflow/components/WorkflowDiagramStepNode'; +import { WorkflowVersionStatusTag } from '@/workflow/components/WorkflowVersionStatusTag'; +import { workflowDiagramState } from '@/workflow/states/workflowDiagramState'; +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; +import { + WorkflowDiagram, + WorkflowDiagramEdge, + WorkflowDiagramNode, +} from '@/workflow/types/WorkflowDiagram'; +import { getOrganizedDiagram } from '@/workflow/utils/getOrganizedDiagram'; +import styled from '@emotion/styled'; +import { + applyEdgeChanges, + applyNodeChanges, + Background, + EdgeChange, + NodeChange, + ReactFlow, +} from '@xyflow/react'; +import '@xyflow/react/dist/style.css'; +import { useMemo } from 'react'; +import { useSetRecoilState } from 'recoil'; +import { GRAY_SCALE, isDefined } from 'twenty-ui'; + +const StyledStatusTagContainer = styled.div` + left: 0; + top: 0; + position: absolute; + padding: ${({ theme }) => theme.spacing(2)}; +`; + +export const WorkflowDiagramCanvas = ({ + diagram, + workflowWithCurrentVersion, +}: { + diagram: WorkflowDiagram; + workflowWithCurrentVersion: WorkflowWithCurrentVersion; +}) => { + const { nodes, edges } = useMemo( + () => getOrganizedDiagram(diagram), + [diagram], + ); + + const setWorkflowDiagram = useSetRecoilState(workflowDiagramState); + + const handleNodesChange = ( + nodeChanges: Array<NodeChange<WorkflowDiagramNode>>, + ) => { + setWorkflowDiagram((diagram) => { + if (isDefined(diagram) === false) { + throw new Error( + 'It must be impossible for the nodes to be updated if the diagram is not defined yet. Be sure the diagram is rendered only when defined.', + ); + } + + return { + ...diagram, + nodes: applyNodeChanges(nodeChanges, diagram.nodes), + }; + }); + }; + + const handleEdgesChange = ( + edgeChanges: Array<EdgeChange<WorkflowDiagramEdge>>, + ) => { + setWorkflowDiagram((diagram) => { + if (isDefined(diagram) === false) { + throw new Error( + 'It must be impossible for the edges to be updated if the diagram is not defined yet. Be sure the diagram is rendered only when defined.', + ); + } + + return { + ...diagram, + edges: applyEdgeChanges(edgeChanges, diagram.edges), + }; + }); + }; + + return ( + <> + <ReactFlow + nodeTypes={{ + default: WorkflowDiagramStepNode, + 'create-step': WorkflowDiagramCreateStepNode, + 'empty-trigger': WorkflowDiagramEmptyTrigger, + }} + fitView + nodes={nodes.map((node) => ({ ...node, draggable: false }))} + edges={edges} + onNodesChange={handleNodesChange} + onEdgesChange={handleEdgesChange} + > + <WorkflowDiagramCanvasEffect /> + + <Background color={GRAY_SCALE.gray25} size={2} /> + </ReactFlow> + + <StyledStatusTagContainer> + <WorkflowVersionStatusTag + versionStatus={workflowWithCurrentVersion.currentVersion.status} + /> + </StyledStatusTagContainer> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEffect.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEffect.tsx new file mode 100644 index 000000000000..4f6bfde09488 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEffect.tsx @@ -0,0 +1,79 @@ +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; +import { useStartNodeCreation } from '@/workflow/hooks/useStartNodeCreation'; +import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/states/workflowDiagramTriggerNodeSelectionState'; +import { workflowSelectedNodeState } from '@/workflow/states/workflowSelectedNodeState'; +import { + WorkflowDiagramEdge, + WorkflowDiagramNode, +} from '@/workflow/types/WorkflowDiagram'; +import { + OnSelectionChangeParams, + useOnSelectionChange, + useReactFlow, +} from '@xyflow/react'; +import { useCallback, useEffect } from 'react'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +export const WorkflowDiagramCanvasEffect = () => { + const reactflow = useReactFlow<WorkflowDiagramNode, WorkflowDiagramEdge>(); + + const { startNodeCreation } = useStartNodeCreation(); + + const { openRightDrawer, closeRightDrawer } = useRightDrawer(); + const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState); + + const workflowDiagramTriggerNodeSelection = useRecoilValue( + workflowDiagramTriggerNodeSelectionState, + ); + + const handleSelectionChange = useCallback( + ({ nodes }: OnSelectionChangeParams) => { + const selectedNode = nodes[0] as WorkflowDiagramNode; + const isClosingStep = isDefined(selectedNode) === false; + + if (isClosingStep) { + closeRightDrawer(); + + return; + } + + const isCreateStepNode = selectedNode.type === 'create-step'; + if (isCreateStepNode) { + if (selectedNode.data.nodeType !== 'create-step') { + throw new Error('Expected selected node to be a create step node.'); + } + + startNodeCreation(selectedNode.data.parentNodeId); + + return; + } + + setWorkflowSelectedNode(selectedNode.id); + openRightDrawer(RightDrawerPages.WorkflowStepEdit); + }, + [ + closeRightDrawer, + openRightDrawer, + setWorkflowSelectedNode, + startNodeCreation, + ], + ); + + useOnSelectionChange({ + onChange: handleSelectionChange, + }); + + useEffect(() => { + if (!isDefined(workflowDiagramTriggerNodeSelection)) { + return; + } + + reactflow.updateNode(workflowDiagramTriggerNodeSelection, { + selected: true, + }); + }, [reactflow, workflowDiagramTriggerNodeSelection]); + + return null; +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx new file mode 100644 index 000000000000..27706668b4b1 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx @@ -0,0 +1,18 @@ +import { IconButton } from '@/ui/input/button/components/IconButton'; +import styled from '@emotion/styled'; +import { Handle, Position } from '@xyflow/react'; +import { IconPlus } from 'twenty-ui'; + +export const StyledTargetHandle = styled(Handle)` + visibility: hidden; +`; + +export const WorkflowDiagramCreateStepNode = () => { + return ( + <> + <StyledTargetHandle type="target" position={Position.Top} /> + + <IconButton Icon={IconPlus} /> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramEmptyTrigger.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramEmptyTrigger.tsx new file mode 100644 index 000000000000..a355733219ab --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramEmptyTrigger.tsx @@ -0,0 +1,30 @@ +import { WorkflowDiagramBaseStepNode } from '@/workflow/components/WorkflowDiagramBaseStepNode'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { IconPlaylistAdd } from 'twenty-ui'; + +const StyledStepNodeLabelIconContainer = styled.div` + align-items: center; + background: ${({ theme }) => theme.background.transparent.light}; + border-radius: ${({ theme }) => theme.spacing(1)}; + display: flex; + justify-content: center; + padding: ${({ theme }) => theme.spacing(1)}; +`; + +export const WorkflowDiagramEmptyTrigger = () => { + const theme = useTheme(); + + return ( + <WorkflowDiagramBaseStepNode + label="Add a Trigger" + nodeType="trigger" + variant="placeholder" + Icon={ + <StyledStepNodeLabelIconContainer> + <IconPlaylistAdd size={16} color={theme.font.color.tertiary} /> + </StyledStepNodeLabelIconContainer> + } + /> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNode.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNode.tsx new file mode 100644 index 000000000000..0c0e6ce945ea --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNode.tsx @@ -0,0 +1,54 @@ +import { WorkflowDiagramBaseStepNode } from '@/workflow/components/WorkflowDiagramBaseStepNode'; +import { WorkflowDiagramStepNodeData } from '@/workflow/types/WorkflowDiagram'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { IconCode, IconPlaylistAdd } from 'twenty-ui'; + +const StyledStepNodeLabelIconContainer = styled.div` + align-items: center; + background: ${({ theme }) => theme.background.transparent.light}; + border-radius: ${({ theme }) => theme.spacing(1)}; + display: flex; + justify-content: center; + padding: ${({ theme }) => theme.spacing(1)}; +`; + +export const WorkflowDiagramStepNode = ({ + data, +}: { + data: WorkflowDiagramStepNodeData; +}) => { + const theme = useTheme(); + + const renderStepIcon = () => { + switch (data.nodeType) { + case 'trigger': { + return ( + <StyledStepNodeLabelIconContainer> + <IconPlaylistAdd + size={theme.icon.size.sm} + color={theme.font.color.tertiary} + /> + </StyledStepNodeLabelIconContainer> + ); + } + case 'action': { + return ( + <StyledStepNodeLabelIconContainer> + <IconCode size={theme.icon.size.sm} color={theme.color.orange} /> + </StyledStepNodeLabelIconContainer> + ); + } + } + + return null; + }; + + return ( + <WorkflowDiagramBaseStepNode + nodeType={data.nodeType} + label={data.label} + Icon={renderStepIcon()} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowEditActionForm.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowEditActionForm.tsx new file mode 100644 index 000000000000..015952309d11 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowEditActionForm.tsx @@ -0,0 +1,103 @@ +import { useGetManyServerlessFunctions } from '@/settings/serverless-functions/hooks/useGetManyServerlessFunctions'; +import { Select, SelectOption } from '@/ui/input/components/Select'; +import { WorkflowAction } from '@/workflow/types/Workflow'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { IconCode, isDefined } from 'twenty-ui'; + +const StyledTriggerHeader = styled.div` + background-color: ${({ theme }) => theme.background.secondary}; + border-bottom: 1px solid ${({ theme }) => theme.border.color.medium}; + display: flex; + flex-direction: column; + padding: ${({ theme }) => theme.spacing(6)}; +`; + +const StyledTriggerHeaderTitle = styled.p` + color: ${({ theme }) => theme.font.color.primary}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + font-size: ${({ theme }) => theme.font.size.xl}; + + margin: ${({ theme }) => theme.spacing(3)} 0; +`; + +const StyledTriggerHeaderType = styled.p` + color: ${({ theme }) => theme.font.color.tertiary}; + margin: 0; +`; + +const StyledTriggerHeaderIconContainer = styled.div` + align-self: flex-start; + display: flex; + justify-content: center; + align-items: center; + background-color: ${({ theme }) => theme.background.transparent.light}; + border-radius: ${({ theme }) => theme.border.radius.xs}; + padding: ${({ theme }) => theme.spacing(1)}; +`; + +const StyledTriggerSettings = styled.div` + padding: ${({ theme }) => theme.spacing(6)}; + display: flex; + flex-direction: column; + row-gap: ${({ theme }) => theme.spacing(4)}; +`; + +export const WorkflowEditActionForm = ({ + action, + onActionUpdate, +}: { + action: WorkflowAction; + onActionUpdate: (trigger: WorkflowAction) => void; +}) => { + const theme = useTheme(); + + const { serverlessFunctions } = useGetManyServerlessFunctions(); + + const availableFunctions: Array<SelectOption<string>> = [ + { label: 'None', value: '' }, + ...serverlessFunctions + .filter((serverlessFunction) => + isDefined(serverlessFunction.latestVersion), + ) + .map((serverlessFunction) => ({ + label: serverlessFunction.name, + value: serverlessFunction.id, + })), + ]; + + return ( + <> + <StyledTriggerHeader> + <StyledTriggerHeaderIconContainer> + <IconCode color={theme.color.orange} /> + </StyledTriggerHeaderIconContainer> + + <StyledTriggerHeaderTitle> + Code - Serverless Function + </StyledTriggerHeaderTitle> + + <StyledTriggerHeaderType>Code</StyledTriggerHeaderType> + </StyledTriggerHeader> + + <StyledTriggerSettings> + <Select + dropdownId="workflow-edit-action-function" + label="Function" + fullWidth + value={action.settings.serverlessFunctionId} + options={availableFunctions} + onChange={(updatedFunction) => { + onActionUpdate({ + ...action, + settings: { + ...action.settings, + serverlessFunctionId: updatedFunction, + }, + }); + }} + /> + </StyledTriggerSettings> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowEditTriggerForm.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowEditTriggerForm.tsx new file mode 100644 index 000000000000..9a3960428162 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowEditTriggerForm.tsx @@ -0,0 +1,154 @@ +import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; +import { Select, SelectOption } from '@/ui/input/components/Select'; +import { OBJECT_EVENT_TRIGGERS } from '@/workflow/constants/ObjectEventTriggers'; +import { WorkflowTrigger } from '@/workflow/types/Workflow'; +import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { IconPlaylistAdd, isDefined } from 'twenty-ui'; + +const StyledTriggerHeader = styled.div` + background-color: ${({ theme }) => theme.background.secondary}; + border-bottom: 1px solid ${({ theme }) => theme.border.color.medium}; + display: flex; + flex-direction: column; + padding: ${({ theme }) => theme.spacing(6)}; +`; + +const StyledTriggerHeaderTitle = styled.p` + color: ${({ theme }) => theme.font.color.primary}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + font-size: ${({ theme }) => theme.font.size.xl}; + + margin: ${({ theme }) => theme.spacing(3)} 0; +`; + +const StyledTriggerHeaderType = styled.p` + color: ${({ theme }) => theme.font.color.tertiary}; + margin: 0; +`; + +const StyledTriggerHeaderIconContainer = styled.div` + align-self: flex-start; + display: flex; + justify-content: center; + align-items: center; + background-color: ${({ theme }) => theme.background.transparent.light}; + border-radius: ${({ theme }) => theme.border.radius.xs}; + padding: ${({ theme }) => theme.spacing(1)}; +`; + +const StyledTriggerSettings = styled.div` + padding: ${({ theme }) => theme.spacing(6)}; + display: flex; + flex-direction: column; + row-gap: ${({ theme }) => theme.spacing(4)}; +`; + +export const WorkflowEditTriggerForm = ({ + trigger, + onTriggerUpdate, +}: { + trigger: WorkflowTrigger | undefined; + onTriggerUpdate: (trigger: WorkflowTrigger) => void; +}) => { + const theme = useTheme(); + + const { activeObjectMetadataItems } = useFilteredObjectMetadataItems(); + + const triggerEvent = isDefined(trigger) + ? splitWorkflowTriggerEventName(trigger.settings.eventName) + : undefined; + + const availableMetadata: Array<SelectOption<string>> = + activeObjectMetadataItems.map((item) => ({ + label: item.labelPlural, + value: item.nameSingular, + })); + const recordTypeMetadata = isDefined(triggerEvent) + ? activeObjectMetadataItems.find( + (item) => item.nameSingular === triggerEvent.objectType, + ) + : undefined; + + const selectedEvent = isDefined(triggerEvent) + ? OBJECT_EVENT_TRIGGERS.find( + (availableEvent) => availableEvent.value === triggerEvent.event, + ) + : undefined; + + return ( + <> + <StyledTriggerHeader> + <StyledTriggerHeaderIconContainer> + <IconPlaylistAdd color={theme.font.color.tertiary} /> + </StyledTriggerHeaderIconContainer> + + <StyledTriggerHeaderTitle> + {isDefined(recordTypeMetadata) && isDefined(selectedEvent) + ? `When a ${recordTypeMetadata.labelSingular} is ${selectedEvent.label}` + : '-'} + </StyledTriggerHeaderTitle> + + <StyledTriggerHeaderType> + {isDefined(selectedEvent) + ? `Trigger . Record is ${selectedEvent.label}` + : '-'} + </StyledTriggerHeaderType> + </StyledTriggerHeader> + + <StyledTriggerSettings> + <Select + dropdownId="workflow-edit-trigger-record-type" + label="Record Type" + fullWidth + value={triggerEvent?.objectType} + options={availableMetadata} + onChange={(updatedRecordType) => { + onTriggerUpdate( + isDefined(trigger) && isDefined(triggerEvent) + ? { + ...trigger, + settings: { + ...trigger.settings, + eventName: `${updatedRecordType}.${triggerEvent.event}`, + }, + } + : { + type: 'DATABASE_EVENT', + settings: { + eventName: `${updatedRecordType}.${OBJECT_EVENT_TRIGGERS[0].value}`, + }, + }, + ); + }} + /> + <Select + dropdownId="workflow-edit-trigger-event-type" + label="Event type" + fullWidth + value={triggerEvent?.event} + options={OBJECT_EVENT_TRIGGERS} + onChange={(updatedEvent) => { + onTriggerUpdate( + isDefined(trigger) && isDefined(triggerEvent) + ? { + ...trigger, + settings: { + ...trigger.settings, + eventName: `${triggerEvent.objectType}.${updatedEvent}`, + }, + } + : { + type: 'DATABASE_EVENT', + settings: { + eventName: `${availableMetadata[0].value}.${updatedEvent}`, + }, + }, + ); + }} + /> + </StyledTriggerSettings> + </> + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowEffect.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowEffect.tsx new file mode 100644 index 000000000000..6171f2d64b15 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowEffect.tsx @@ -0,0 +1,42 @@ +import { workflowDiagramState } from '@/workflow/states/workflowDiagramState'; +import { workflowIdState } from '@/workflow/states/workflowIdState'; +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; +import { addCreateStepNodes } from '@/workflow/utils/addCreateStepNodes'; +import { getWorkflowVersionDiagram } from '@/workflow/utils/getWorkflowVersionDiagram'; +import { useEffect } from 'react'; +import { useSetRecoilState } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +type WorkflowEffectProps = { + workflowId: string; + workflowWithCurrentVersion: WorkflowWithCurrentVersion | undefined; +}; + +export const WorkflowEffect = ({ + workflowId, + workflowWithCurrentVersion, +}: WorkflowEffectProps) => { + const setWorkflowId = useSetRecoilState(workflowIdState); + const setWorkflowDiagram = useSetRecoilState(workflowDiagramState); + + useEffect(() => { + setWorkflowId(workflowId); + }, [setWorkflowId, workflowId]); + + useEffect(() => { + const currentVersion = workflowWithCurrentVersion?.currentVersion; + if (!isDefined(currentVersion)) { + setWorkflowDiagram(undefined); + + return; + } + + const lastWorkflowDiagram = getWorkflowVersionDiagram(currentVersion); + const workflowDiagramWithCreateStepNodes = + addCreateStepNodes(lastWorkflowDiagram); + + setWorkflowDiagram(workflowDiagramWithCreateStepNodes); + }, [setWorkflowDiagram, workflowWithCurrentVersion?.currentVersion]); + + return null; +}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagram.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagram.tsx deleted file mode 100644 index 090d074ad131..000000000000 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagram.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { WorkflowShowPageDiagramCreateStepNode } from '@/workflow/components/WorkflowShowPageDiagramCreateStepNode.tsx'; -import { WorkflowShowPageDiagramStepNode } from '@/workflow/components/WorkflowShowPageDiagramStepNode'; -import { showPageWorkflowDiagramState } from '@/workflow/states/showPageWorkflowDiagramState'; -import { - WorkflowDiagram, - WorkflowDiagramEdge, - WorkflowDiagramNode, -} from '@/workflow/types/WorkflowDiagram'; -import { getOrganizedDiagram } from '@/workflow/utils/getOrganizedDiagram'; -import { - applyEdgeChanges, - applyNodeChanges, - Background, - EdgeChange, - NodeChange, - ReactFlow, -} from '@xyflow/react'; -import '@xyflow/react/dist/style.css'; -import { useMemo } from 'react'; -import { useSetRecoilState } from 'recoil'; -import { GRAY_SCALE, isDefined } from 'twenty-ui'; - -export const WorkflowShowPageDiagram = ({ - diagram, -}: { - diagram: WorkflowDiagram; -}) => { - const { nodes, edges } = useMemo( - () => getOrganizedDiagram(diagram), - [diagram], - ); - - const setShowPageWorkflowDiagram = useSetRecoilState( - showPageWorkflowDiagramState, - ); - - const handleNodesChange = ( - nodeChanges: Array<NodeChange<WorkflowDiagramNode>>, - ) => { - setShowPageWorkflowDiagram((diagram) => { - if (isDefined(diagram) === false) { - throw new Error( - 'It must be impossible for the nodes to be updated if the diagram is not defined yet. Be sure the diagram is rendered only when defined.', - ); - } - - return { - ...diagram, - nodes: applyNodeChanges(nodeChanges, diagram.nodes), - }; - }); - }; - - const handleEdgesChange = ( - edgeChanges: Array<EdgeChange<WorkflowDiagramEdge>>, - ) => { - setShowPageWorkflowDiagram((diagram) => { - if (isDefined(diagram) === false) { - throw new Error( - 'It must be impossible for the edges to be updated if the diagram is not defined yet. Be sure the diagram is rendered only when defined.', - ); - } - - return { - ...diagram, - edges: applyEdgeChanges(edgeChanges, diagram.edges), - }; - }); - }; - - return ( - <ReactFlow - nodeTypes={{ - default: WorkflowShowPageDiagramStepNode, - 'create-step': WorkflowShowPageDiagramCreateStepNode, - }} - fitView - nodes={nodes.map((node) => ({ ...node, draggable: false }))} - edges={edges} - onNodesChange={handleNodesChange} - onEdgesChange={handleEdgesChange} - > - <Background color={GRAY_SCALE.gray25} size={2} /> - </ReactFlow> - ); -}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagramCreateStepNode.tsx.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagramCreateStepNode.tsx.tsx deleted file mode 100644 index a799480e81ff..000000000000 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageDiagramCreateStepNode.tsx.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { IconButton } from '@/ui/input/button/components/IconButton'; -import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; -import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; -import styled from '@emotion/styled'; -import { Handle, Position } from '@xyflow/react'; -import { IconPlus } from 'twenty-ui'; - -export const StyledTargetHandle = styled(Handle)` - visibility: hidden; -`; - -export const WorkflowShowPageDiagramCreateStepNode = () => { - const { openRightDrawer } = useRightDrawer(); - - const handleCreateStepNodeButtonClick = () => { - openRightDrawer(RightDrawerPages.Workflow); - }; - - return ( - <div> - <StyledTargetHandle type="target" position={Position.Top} /> - - <IconButton Icon={IconPlus} onClick={handleCreateStepNodeButtonClick} /> - </div> - ); -}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageEffect.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageEffect.tsx deleted file mode 100644 index 6d41e5d7fd4b..000000000000 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowShowPageEffect.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; -import { showPageWorkflowDiagramState } from '@/workflow/states/showPageWorkflowDiagramState'; -import { showPageWorkflowErrorState } from '@/workflow/states/showPageWorkflowErrorState'; -import { showPageWorkflowLoadingState } from '@/workflow/states/showPageWorkflowLoadingState'; -import { Workflow } from '@/workflow/types/Workflow'; -import { addCreateStepNodes } from '@/workflow/utils/addCreateStepNodes'; -import { getWorkflowLastDiagramVersion } from '@/workflow/utils/getWorkflowLastDiagramVersion'; -import { useEffect } from 'react'; -import { useSetRecoilState } from 'recoil'; -import { isDefined } from 'twenty-ui'; - -type WorkflowShowPageEffectProps = { - workflowId: string; -}; - -export const WorkflowShowPageEffect = ({ - workflowId, -}: WorkflowShowPageEffectProps) => { - const { - record: workflow, - loading, - error, - } = useFindOneRecord<Workflow>({ - objectNameSingular: CoreObjectNameSingular.Workflow, - objectRecordId: workflowId, - recordGqlFields: { - id: true, - name: true, - versions: true, - publishedVersionId: true, - }, - }); - - const setCurrentWorkflowData = useSetRecoilState( - showPageWorkflowDiagramState, - ); - const setCurrentWorkflowLoading = useSetRecoilState( - showPageWorkflowLoadingState, - ); - const setCurrentWorkflowError = useSetRecoilState(showPageWorkflowErrorState); - - useEffect(() => { - const flowLastVersion = getWorkflowLastDiagramVersion(workflow); - const flowWithCreateStepNodes = addCreateStepNodes(flowLastVersion); - - setCurrentWorkflowData( - isDefined(workflow) ? flowWithCreateStepNodes : undefined, - ); - }, [setCurrentWorkflowData, workflow]); - - useEffect(() => { - setCurrentWorkflowLoading(loading); - }, [loading, setCurrentWorkflowLoading]); - - useEffect(() => { - setCurrentWorkflowError(error); - }, [error, setCurrentWorkflowError]); - - return null; -}; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowVersionStatusTag.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowVersionStatusTag.tsx new file mode 100644 index 000000000000..a917d8055d37 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowVersionStatusTag.tsx @@ -0,0 +1,22 @@ +import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; +import { Tag } from 'twenty-ui'; + +export const WorkflowVersionStatusTag = ({ + versionStatus, +}: { + versionStatus: WorkflowVersionStatus; +}) => { + if (versionStatus === 'ACTIVE') { + return <Tag color="green" text="Active" />; + } + + if (versionStatus === 'DRAFT') { + return <Tag color="yellow" text="Draft" />; + } + + if (versionStatus === 'ARCHIVED') { + return <Tag color="gray" text="Archived" />; + } + + return <Tag color="gray" text="Deactivated" />; +}; diff --git a/packages/twenty-front/src/modules/workflow/components/__stories__/RecordShowPageWorkflowHeader.stories.tsx b/packages/twenty-front/src/modules/workflow/components/__stories__/RecordShowPageWorkflowHeader.stories.tsx new file mode 100644 index 000000000000..663924fb7cce --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/__stories__/RecordShowPageWorkflowHeader.stories.tsx @@ -0,0 +1,666 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { graphql, HttpResponse } from 'msw'; +import { ComponentDecorator } from 'twenty-ui'; + +import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader'; +import { expect, within } from '@storybook/test'; +import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; +import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +const meta: Meta<typeof RecordShowPageWorkflowHeader> = { + title: 'Modules/Workflow/RecordShowPageWorkflowHeader', + component: RecordShowPageWorkflowHeader, + decorators: [ + ComponentDecorator, + ObjectMetadataItemsDecorator, + SnackBarDecorator, + ], + parameters: { + container: { width: 728 }, + }, +}; + +export default meta; +type Story = StoryObj<typeof RecordShowPageWorkflowHeader>; + +const blankInitialVersionWorkflowId = '78fd5184-08f4-47b7-bb60-adb541608f65'; + +export const BlankInitialVersion: Story = { + args: { + workflowId: blankInitialVersionWorkflowId, + }, + parameters: { + msw: { + handlers: [ + graphql.query('FindManyWorkflows', () => { + return HttpResponse.json({ + data: { + workflows: { + __typename: 'WorkflowConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + endCursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + }, + edges: [ + { + __typename: 'WorkflowEdge', + cursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + node: { + __typename: 'Workflow', + id: blankInitialVersionWorkflowId, + }, + }, + ], + }, + }, + }); + }), + graphql.query('FindOneWorkflow', () => { + return HttpResponse.json({ + data: { + workflow: { + __typename: 'Workflow', + id: blankInitialVersionWorkflowId, + name: '1231 qqerrt', + statuses: null, + lastPublishedVersionId: '', + deletedAt: null, + updatedAt: '2024-09-19T10:10:04.505Z', + position: 0, + createdAt: '2024-09-19T10:10:04.505Z', + favorites: { + __typename: 'FavoriteConnection', + edges: [], + }, + eventListeners: { + __typename: 'WorkflowEventListenerConnection', + edges: [], + }, + runs: { + __typename: 'WorkflowRunConnection', + edges: [], + }, + versions: { + __typename: 'WorkflowVersionConnection', + edges: [ + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:04.725Z', + status: 'DRAFT', + name: 'v1', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f0', + trigger: null, + deletedAt: null, + workflowId: blankInitialVersionWorkflowId, + }, + }, + ], + }, + }, + }, + }); + }), + graphql.query('FindManyWorkflowVersions', () => { + return HttpResponse.json({ + data: { + workflowVersions: { + __typename: 'WorkflowVersionConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + endCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + }, + edges: [ + { + __typename: 'WorkflowVersionEdge', + cursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:04.725Z', + status: 'DRAFT', + name: 'v1', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f0', + trigger: null, + deletedAt: null, + workflowId: blankInitialVersionWorkflowId, + }, + }, + ], + }, + }, + }); + }), + ...graphqlMocks.handlers, + ], + }, + }, + play: async () => { + const canvas = within(document.body); + + expect(await canvas.findByText('Test')).toBeVisible(); + expect(await canvas.findByText('Activate')).toBeVisible(); + expect(canvas.queryByText('Discard Draft')).not.toBeInTheDocument(); + }, +}; + +const activeVersionWorkflowId = 'ca177fb1-7780-4911-8b1f-ef0a245fbd61'; + +export const ActiveVersion: Story = { + args: { + workflowId: activeVersionWorkflowId, + }, + parameters: { + msw: { + handlers: [ + graphql.query('FindManyWorkflows', () => { + return HttpResponse.json({ + data: { + workflows: { + __typename: 'WorkflowConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJwb3NpdGlvbiI6LTEsImlkIjoiN2JlM2E4MmMtNDRiNy00MTUwLWEyZTgtNDA4ODcxNDZmNGQ0In0=', + endCursor: + 'eyJwb3NpdGlvbiI6LTEsImlkIjoiN2JlM2E4MmMtNDRiNy00MTUwLWEyZTgtNDA4ODcxNDZmNGQ0In0=', + }, + edges: [ + { + __typename: 'WorkflowEdge', + cursor: + 'eyJwb3NpdGlvbiI6LTEsImlkIjoiN2JlM2E4MmMtNDRiNy00MTUwLWEyZTgtNDA4ODcxNDZmNGQ0In0=', + node: { + __typename: 'Workflow', + id: activeVersionWorkflowId, + }, + }, + ], + }, + }, + }); + }), + graphql.query('FindOneWorkflow', () => { + return HttpResponse.json({ + data: { + workflow: { + __typename: 'Workflow', + name: 'test qqqq', + lastPublishedVersionId: 'b57e577a-ae55-4de2-ba08-fe361dcc1a57', + id: activeVersionWorkflowId, + deletedAt: null, + statuses: null, + createdAt: '2024-09-20T10:18:59.977Z', + updatedAt: '2024-09-20T16:59:37.212Z', + position: -1, + runs: { + __typename: 'WorkflowRunConnection', + edges: [], + }, + favorites: { + __typename: 'FavoriteConnection', + edges: [], + }, + eventListeners: { + __typename: 'WorkflowEventListenerConnection', + edges: [], + }, + versions: { + __typename: 'WorkflowVersionConnection', + edges: [ + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-20T16:59:37.212Z', + status: 'ARCHIVED', + deletedAt: null, + steps: [ + { + id: '93c41c1d-eff3-4c91-ac61-f56cc1a0df8a', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + ], + workflowId: activeVersionWorkflowId, + trigger: { + type: 'DATABASE_EVENT', + settings: { + eventName: 'note.created', + }, + }, + name: 'v1', + id: '394cd0b5-bd48-41d7-a110-a92cafaf171d', + createdAt: '2024-09-20T10:19:00.141Z', + }, + }, + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-20T17:01:15.637Z', + status: 'DRAFT', + deletedAt: null, + steps: [ + { + id: '93c41c1d-eff3-4c91-ac61-f56cc1a0df8a', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + { + id: '4177d57d-35dc-4eb1-a467-07e25cb31da0', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + { + id: '0cc392d9-5f28-4d92-90a0-08180f264e68', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + ], + workflowId: activeVersionWorkflowId, + trigger: { + type: 'DATABASE_EVENT', + settings: { + eventName: 'note.created', + }, + }, + name: 'v3', + id: '5eae34ef-9d62-4a9e-b827-3eb927481728', + createdAt: '2024-09-20T17:01:15.637Z', + }, + }, + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-20T17:00:16.097Z', + status: 'ACTIVE', + deletedAt: null, + steps: [ + { + id: '93c41c1d-eff3-4c91-ac61-f56cc1a0df8a', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + { + id: '4177d57d-35dc-4eb1-a467-07e25cb31da0', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + ], + workflowId: activeVersionWorkflowId, + trigger: { + type: 'DATABASE_EVENT', + settings: { + eventName: 'note.created', + }, + }, + name: 'v2', + id: 'b57e577a-ae55-4de2-ba08-fe361dcc1a57', + createdAt: '2024-09-20T16:59:35.755Z', + }, + }, + ], + }, + }, + }, + }); + }), + graphql.query('FindManyWorkflowVersions', () => { + return HttpResponse.json({ + data: { + workflowVersions: { + __typename: 'WorkflowVersionConnection', + totalCount: 3, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: true, + hasPreviousPage: false, + startCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTIwVDE3OjAxOjE1LjYzN1oiLCJpZCI6IjVlYWUzNGVmLTlkNjItNGE5ZS1iODI3LTNlYjkyNzQ4MTcyOCJ9', + endCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTIwVDE3OjAxOjE1LjYzN1oiLCJpZCI6IjVlYWUzNGVmLTlkNjItNGE5ZS1iODI3LTNlYjkyNzQ4MTcyOCJ9', + }, + edges: [ + { + __typename: 'WorkflowVersionEdge', + cursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTIwVDE3OjAxOjE1LjYzN1oiLCJpZCI6IjVlYWUzNGVmLTlkNjItNGE5ZS1iODI3LTNlYjkyNzQ4MTcyOCJ9', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-20T17:01:15.637Z', + status: 'ACTIVE', + deletedAt: null, + steps: [ + { + id: '93c41c1d-eff3-4c91-ac61-f56cc1a0df8a', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + { + id: '4177d57d-35dc-4eb1-a467-07e25cb31da0', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + { + id: '0cc392d9-5f28-4d92-90a0-08180f264e68', + name: 'Code', + type: 'CODE', + valid: false, + settings: { + errorHandlingOptions: { + retryOnFailure: { + value: false, + }, + continueOnFailure: { + value: false, + }, + }, + serverlessFunctionId: '', + }, + }, + ], + workflowId: activeVersionWorkflowId, + trigger: { + type: 'DATABASE_EVENT', + settings: { + eventName: 'note.created', + }, + }, + name: 'v3', + id: '5eae34ef-9d62-4a9e-b827-3eb927481728', + createdAt: '2024-09-20T17:01:15.637Z', + }, + }, + ], + }, + }, + }); + }), + ...graphqlMocks.handlers, + ], + }, + }, + play: async () => { + const canvas = within(document.body); + + expect(await canvas.findByText('Test')).toBeVisible(); + expect(await canvas.findByText('Deactivate')).toBeVisible(); + }, +}; + +const draftVersionWithPreviousActiveVersionWorkflowId = + '89c00f14-4ebd-4675-a098-cdf59eee372b'; + +export const DraftVersionWithPreviousActiveVersion: Story = { + args: { + workflowId: draftVersionWithPreviousActiveVersionWorkflowId, + }, + parameters: { + msw: { + handlers: [ + graphql.query('FindManyWorkflows', () => { + return HttpResponse.json({ + data: { + workflows: { + __typename: 'WorkflowConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + endCursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + }, + edges: [ + { + __typename: 'WorkflowEdge', + cursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + node: { + __typename: 'Workflow', + id: draftVersionWithPreviousActiveVersionWorkflowId, + }, + }, + ], + }, + }, + }); + }), + graphql.query('FindOneWorkflow', () => { + return HttpResponse.json({ + data: { + workflow: { + __typename: 'Workflow', + id: draftVersionWithPreviousActiveVersionWorkflowId, + name: '1231 qqerrt', + statuses: null, + lastPublishedVersionId: '', + deletedAt: null, + updatedAt: '2024-09-19T10:10:04.505Z', + position: 0, + createdAt: '2024-09-19T10:10:04.505Z', + favorites: { + __typename: 'FavoriteConnection', + edges: [], + }, + eventListeners: { + __typename: 'WorkflowEventListenerConnection', + edges: [], + }, + runs: { + __typename: 'WorkflowRunConnection', + edges: [], + }, + versions: { + __typename: 'WorkflowVersionConnection', + edges: [ + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:04.725Z', + status: 'ACTIVE', + name: 'v1', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f0', + trigger: null, + deletedAt: null, + workflowId: + draftVersionWithPreviousActiveVersionWorkflowId, + }, + }, + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:05.725Z', + status: 'DRAFT', + name: 'v2', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f1', + trigger: null, + deletedAt: null, + workflowId: + draftVersionWithPreviousActiveVersionWorkflowId, + }, + }, + ], + }, + }, + }, + }); + }), + graphql.query('FindManyWorkflowVersions', () => { + return HttpResponse.json({ + data: { + workflowVersions: { + __typename: 'WorkflowVersionConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + endCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + }, + edges: [ + { + __typename: 'WorkflowVersionEdge', + cursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:05.725Z', + status: 'DRAFT', + name: 'v2', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f1', + trigger: null, + deletedAt: null, + workflowId: + draftVersionWithPreviousActiveVersionWorkflowId, + }, + }, + ], + }, + }, + }); + }), + ...graphqlMocks.handlers, + ], + }, + }, + play: async () => { + const canvas = within(document.body); + + expect(await canvas.findByText('Test')).toBeVisible(); + expect(await canvas.findByText('Discard Draft')).toBeVisible(); + }, +}; diff --git a/packages/twenty-front/src/modules/workflow/components/__stories__/WorkflowVersionStatusTag.stories.tsx b/packages/twenty-front/src/modules/workflow/components/__stories__/WorkflowVersionStatusTag.stories.tsx new file mode 100644 index 000000000000..0ea2cd94ca8d --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/__stories__/WorkflowVersionStatusTag.stories.tsx @@ -0,0 +1,43 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { CatalogDecorator, CatalogStory, ComponentDecorator } from 'twenty-ui'; + +import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; +import { WorkflowVersionStatusTag } from '../WorkflowVersionStatusTag'; + +const meta: Meta<typeof WorkflowVersionStatusTag> = { + title: 'Modules/Workflow/WorkflowVersionStatusTag', + component: WorkflowVersionStatusTag, +}; + +export default meta; +type Story = StoryObj<typeof WorkflowVersionStatusTag>; + +export const Default: Story = { + args: { + versionStatus: 'DRAFT', + }, + decorators: [ComponentDecorator], +}; + +export const Catalog: CatalogStory<Story, typeof WorkflowVersionStatusTag> = { + argTypes: { + versionStatus: { table: { disable: true } }, + }, + parameters: { + catalog: { + dimensions: [ + { + name: 'version status', + values: [ + 'DRAFT', + 'ACTIVE', + 'DEACTIVATED', + 'ARCHIVED', + ] satisfies WorkflowVersionStatus[], + props: (versionStatus: WorkflowVersionStatus) => ({ versionStatus }), + }, + ], + }, + }, + decorators: [CatalogDecorator], +}; diff --git a/packages/twenty-front/src/modules/workflow/constants/Actions.ts b/packages/twenty-front/src/modules/workflow/constants/Actions.ts new file mode 100644 index 000000000000..53c988420e59 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/constants/Actions.ts @@ -0,0 +1,14 @@ +import { WorkflowStepType } from '@/workflow/types/Workflow'; +import { IconComponent, IconSettingsAutomation } from 'twenty-ui'; + +export const ACTIONS: Array<{ + label: string; + type: WorkflowStepType; + icon: IconComponent; +}> = [ + { + label: 'Serverless Function', + type: 'CODE', + icon: IconSettingsAutomation, + }, +]; diff --git a/packages/twenty-front/src/modules/workflow/constants/ObjectEventTriggers.ts b/packages/twenty-front/src/modules/workflow/constants/ObjectEventTriggers.ts new file mode 100644 index 000000000000..bd204f7c8fd5 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/constants/ObjectEventTriggers.ts @@ -0,0 +1,16 @@ +import { SelectOption } from '@/ui/input/components/Select'; + +export const OBJECT_EVENT_TRIGGERS: Array<SelectOption<string>> = [ + { + label: 'Created', + value: 'created', + }, + { + label: 'Updated', + value: 'updated', + }, + { + label: 'Deleted', + value: 'deleted', + }, +]; diff --git a/packages/twenty-front/src/modules/workflow/constants/TriggerStepId.ts b/packages/twenty-front/src/modules/workflow/constants/TriggerStepId.ts new file mode 100644 index 000000000000..2325548eb18e --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/constants/TriggerStepId.ts @@ -0,0 +1 @@ +export const TRIGGER_STEP_ID = 'trigger'; diff --git a/packages/twenty-front/src/modules/workflow/graphql/activateWorkflowVersion.ts b/packages/twenty-front/src/modules/workflow/graphql/activateWorkflowVersion.ts new file mode 100644 index 000000000000..d81597546dea --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/graphql/activateWorkflowVersion.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const ACTIVATE_WORKFLOW_VERSION = gql` + mutation ActivateWorkflowVersion($workflowVersionId: String!) { + activateWorkflowVersion(workflowVersionId: $workflowVersionId) + } +`; diff --git a/packages/twenty-front/src/modules/workflow/graphql/deactivateWorkflowVersion.ts b/packages/twenty-front/src/modules/workflow/graphql/deactivateWorkflowVersion.ts new file mode 100644 index 000000000000..8cd8950d6d9f --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/graphql/deactivateWorkflowVersion.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const DEACTIVATE_WORKFLOW_VERSION = gql` + mutation DeactivateWorkflowVersion($workflowVersionId: String!) { + deactivateWorkflowVersion(workflowVersionId: $workflowVersionId) + } +`; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useActivateWorkflowVersion.tsx b/packages/twenty-front/src/modules/workflow/hooks/useActivateWorkflowVersion.tsx new file mode 100644 index 000000000000..230b7be35b29 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useActivateWorkflowVersion.tsx @@ -0,0 +1,45 @@ +import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient'; +import { ApolloClient, useApolloClient, useMutation } from '@apollo/client'; + +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery'; +import { ACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/activateWorkflowVersion'; +import { + ActivateWorkflowVersionMutation, + ActivateWorkflowVersionMutationVariables, +} from '~/generated/graphql'; + +export const useActivateWorkflowVersion = () => { + const apolloClient = useApolloClient(); + + const apolloMetadataClient = useApolloMetadataClient(); + const [mutate] = useMutation< + ActivateWorkflowVersionMutation, + ActivateWorkflowVersionMutationVariables + >(ACTIVATE_WORKFLOW_VERSION, { + client: apolloMetadataClient ?? ({} as ApolloClient<any>), + }); + + const { findOneRecordQuery: findOneWorkflowVersionQuery } = + useFindOneRecordQuery({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const activateWorkflowVersion = async (workflowVersionId: string) => { + await mutate({ + variables: { + workflowVersionId, + }, + }); + + await apolloClient.query({ + query: findOneWorkflowVersionQuery, + variables: { + objectRecordId: workflowVersionId, + }, + fetchPolicy: 'network-only', + }); + }; + + return { activateWorkflowVersion }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useCreateNewWorkflowVersion.tsx b/packages/twenty-front/src/modules/workflow/hooks/useCreateNewWorkflowVersion.tsx new file mode 100644 index 000000000000..3935f1fe9198 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useCreateNewWorkflowVersion.tsx @@ -0,0 +1,30 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; +import { WorkflowVersion } from '@/workflow/types/Workflow'; + +export const useCreateNewWorkflowVersion = ({ + workflowId, +}: { + workflowId: string; +}) => { + const { createOneRecord: createOneWorkflowVersion } = + useCreateOneRecord<WorkflowVersion>({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const createNewWorkflowVersion = ( + workflowVersionData: Pick< + WorkflowVersion, + 'name' | 'status' | 'trigger' | 'steps' + >, + ) => { + return createOneWorkflowVersion({ + workflowId, + ...workflowVersionData, + }); + }; + + return { + createNewWorkflowVersion, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useCreateStep.tsx b/packages/twenty-front/src/modules/workflow/hooks/useCreateStep.tsx new file mode 100644 index 000000000000..6a11b1f42d52 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useCreateStep.tsx @@ -0,0 +1,101 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; +import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion'; +import { workflowCreateStepFromParentStepIdState } from '@/workflow/states/workflowCreateStepFromParentStepIdState'; +import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/states/workflowDiagramTriggerNodeSelectionState'; +import { + WorkflowStep, + WorkflowStepType, + WorkflowVersion, + WorkflowWithCurrentVersion, +} from '@/workflow/types/Workflow'; +import { getStepDefaultDefinition } from '@/workflow/utils/getStepDefaultDefinition'; +import { insertStep } from '@/workflow/utils/insertStep'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +export const useCreateStep = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const workflowCreateStepFromParentStepId = useRecoilValue( + workflowCreateStepFromParentStepIdState, + ); + + const setWorkflowDiagramTriggerNodeSelection = useSetRecoilState( + workflowDiagramTriggerNodeSelectionState, + ); + + const { updateOneRecord: updateOneWorkflowVersion } = + useUpdateOneRecord<WorkflowVersion>({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const { createNewWorkflowVersion } = useCreateNewWorkflowVersion({ + workflowId: workflow.id, + }); + + const insertNodeAndSave = async ({ + parentNodeId, + nodeToAdd, + }: { + parentNodeId: string; + nodeToAdd: WorkflowStep; + }) => { + const currentVersion = workflow.currentVersion; + if (!isDefined(currentVersion)) { + throw new Error("Can't add a node when there is no current version."); + } + + const updatedSteps = insertStep({ + steps: currentVersion.steps ?? [], + parentStepId: parentNodeId, + stepToAdd: nodeToAdd, + }); + + if (workflow.currentVersion.status === 'DRAFT') { + await updateOneWorkflowVersion({ + idToUpdate: currentVersion.id, + updateOneRecordInput: { + steps: updatedSteps, + }, + }); + + return; + } + + await createNewWorkflowVersion({ + name: `v${workflow.versions.length + 1}`, + status: 'DRAFT', + trigger: workflow.currentVersion.trigger, + steps: updatedSteps, + }); + }; + + const createStep = async (newStepType: WorkflowStepType) => { + if (!isDefined(workflowCreateStepFromParentStepId)) { + throw new Error('Select a step to create a new step from first.'); + } + + const newStep = getStepDefaultDefinition(newStepType); + + await insertNodeAndSave({ + parentNodeId: workflowCreateStepFromParentStepId, + nodeToAdd: newStep, + }); + + /** + * After the step has been created, select it. + * As the `insertNodeAndSave` function mutates the cached workflow before resolving, + * we are sure that the new node will have been created at this stage. + * + * Selecting the node will cause a right drawer to open in order to edit the step. + */ + setWorkflowDiagramTriggerNodeSelection(newStep.id); + }; + + return { + createStep, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useDeactivateWorkflowVersion.tsx b/packages/twenty-front/src/modules/workflow/hooks/useDeactivateWorkflowVersion.tsx new file mode 100644 index 000000000000..2ebd34f67453 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useDeactivateWorkflowVersion.tsx @@ -0,0 +1,45 @@ +import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient'; +import { ApolloClient, useApolloClient, useMutation } from '@apollo/client'; + +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery'; +import { DEACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/deactivateWorkflowVersion'; +import { + ActivateWorkflowVersionMutation, + ActivateWorkflowVersionMutationVariables, +} from '~/generated/graphql'; + +export const useDeactivateWorkflowVersion = () => { + const apolloClient = useApolloClient(); + + const apolloMetadataClient = useApolloMetadataClient(); + const [mutate] = useMutation< + ActivateWorkflowVersionMutation, + ActivateWorkflowVersionMutationVariables + >(DEACTIVATE_WORKFLOW_VERSION, { + client: apolloMetadataClient ?? ({} as ApolloClient<any>), + }); + + const { findOneRecordQuery: findOneWorkflowVersionQuery } = + useFindOneRecordQuery({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const deactivateWorkflowVersion = async (workflowVersionId: string) => { + await mutate({ + variables: { + workflowVersionId, + }, + }); + + await apolloClient.query({ + query: findOneWorkflowVersionQuery, + variables: { + objectRecordId: workflowVersionId, + }, + fetchPolicy: 'network-only', + }); + }; + + return { deactivateWorkflowVersion }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useDeleteOneWorkflowVersion.tsx b/packages/twenty-front/src/modules/workflow/hooks/useDeleteOneWorkflowVersion.tsx new file mode 100644 index 000000000000..7997b14e3afe --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useDeleteOneWorkflowVersion.tsx @@ -0,0 +1,37 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; +import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery'; +import { useApolloClient } from '@apollo/client'; + +export const useDeleteOneWorkflowVersion = () => { + const apolloClient = useApolloClient(); + + const { findOneRecordQuery: findOneWorkflowRecordQuery } = + useFindOneRecordQuery({ + objectNameSingular: CoreObjectNameSingular.Workflow, + }); + + const { deleteOneRecord } = useDeleteOneRecord({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const deleteOneWorkflowVersion = async ({ + workflowId, + workflowVersionId, + }: { + workflowId: string; + workflowVersionId: string; + }) => { + await deleteOneRecord(workflowVersionId); + + await apolloClient.query({ + query: findOneWorkflowRecordQuery, + variables: { + objectRecordId: workflowId, + }, + fetchPolicy: 'network-only', + }); + }; + + return { deleteOneWorkflowVersion }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useStartNodeCreation.tsx b/packages/twenty-front/src/modules/workflow/hooks/useStartNodeCreation.tsx new file mode 100644 index 000000000000..54e479cfb604 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useStartNodeCreation.tsx @@ -0,0 +1,29 @@ +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; +import { workflowCreateStepFromParentStepIdState } from '@/workflow/states/workflowCreateStepFromParentStepIdState'; +import { useCallback } from 'react'; +import { useSetRecoilState } from 'recoil'; + +export const useStartNodeCreation = () => { + const { openRightDrawer } = useRightDrawer(); + const setWorkflowCreateStepFromParentStepId = useSetRecoilState( + workflowCreateStepFromParentStepIdState, + ); + + /** + * This function is used in a context where dependencies shouldn't change much. + * That's why its wrapped in a `useCallback` hook. Removing memoization might break the app unexpectedly. + */ + const startNodeCreation = useCallback( + (parentNodeId: string) => { + setWorkflowCreateStepFromParentStepId(parentNodeId); + + openRightDrawer(RightDrawerPages.WorkflowStepSelectAction); + }, + [openRightDrawer, setWorkflowCreateStepFromParentStepId], + ); + + return { + startNodeCreation, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionStep.tsx b/packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionStep.tsx new file mode 100644 index 000000000000..91d9cd491baf --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionStep.tsx @@ -0,0 +1,61 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; +import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion'; +import { + WorkflowStep, + WorkflowVersion, + WorkflowWithCurrentVersion, +} from '@/workflow/types/Workflow'; +import { replaceStep } from '@/workflow/utils/replaceStep'; +import { isDefined } from 'twenty-ui'; + +export const useUpdateWorkflowVersionStep = ({ + workflow, + stepId, +}: { + workflow: WorkflowWithCurrentVersion; + stepId: string; +}) => { + const { updateOneRecord: updateOneWorkflowVersion } = + useUpdateOneRecord<WorkflowVersion>({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const { createNewWorkflowVersion } = useCreateNewWorkflowVersion({ + workflowId: workflow.id, + }); + + const updateStep = async (updatedStep: WorkflowStep) => { + if (!isDefined(workflow.currentVersion)) { + throw new Error('Can not update an undefined workflow version.'); + } + + const updatedSteps = replaceStep({ + steps: workflow.currentVersion.steps ?? [], + stepId, + stepToReplace: updatedStep, + }); + + if (workflow.currentVersion.status === 'DRAFT') { + await updateOneWorkflowVersion({ + idToUpdate: workflow.currentVersion.id, + updateOneRecordInput: { + steps: updatedSteps, + }, + }); + + return; + } + + await createNewWorkflowVersion({ + name: `v${workflow.versions.length + 1}`, + status: 'DRAFT', + trigger: workflow.currentVersion.trigger, + steps: updatedSteps, + }); + }; + + return { + updateStep, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionTrigger.tsx b/packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionTrigger.tsx new file mode 100644 index 000000000000..ba9e28367287 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useUpdateWorkflowVersionTrigger.tsx @@ -0,0 +1,52 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; +import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion'; +import { + WorkflowTrigger, + WorkflowVersion, + WorkflowWithCurrentVersion, +} from '@/workflow/types/Workflow'; +import { isDefined } from 'twenty-ui'; + +export const useUpdateWorkflowVersionTrigger = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const { updateOneRecord: updateOneWorkflowVersion } = + useUpdateOneRecord<WorkflowVersion>({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + }); + + const { createNewWorkflowVersion } = useCreateNewWorkflowVersion({ + workflowId: workflow.id, + }); + + const updateTrigger = async (updatedTrigger: WorkflowTrigger) => { + if (!isDefined(workflow.currentVersion)) { + throw new Error('Can not update an undefined workflow version.'); + } + + if (workflow.currentVersion.status === 'DRAFT') { + await updateOneWorkflowVersion({ + idToUpdate: workflow.currentVersion.id, + updateOneRecordInput: { + trigger: updatedTrigger, + }, + }); + + return; + } + + await createNewWorkflowVersion({ + name: `v${workflow.versions.length + 1}`, + status: 'DRAFT', + trigger: updatedTrigger, + steps: workflow.currentVersion.steps, + }); + }; + + return { + updateTrigger, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.tsx b/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.tsx new file mode 100644 index 000000000000..fc87a6a6ec2d --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.tsx @@ -0,0 +1,62 @@ +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; +import { + Workflow, + WorkflowVersion, + WorkflowWithCurrentVersion, +} from '@/workflow/types/Workflow'; +import { useMemo } from 'react'; +import { isDefined } from 'twenty-ui'; + +export const useWorkflowWithCurrentVersion = ( + workflowId: string | undefined, +): WorkflowWithCurrentVersion | undefined => { + const { record: workflow } = useFindOneRecord<Workflow>({ + objectNameSingular: CoreObjectNameSingular.Workflow, + objectRecordId: workflowId, + recordGqlFields: { + id: true, + name: true, + statuses: true, + versions: { + totalCount: true, + }, + }, + skip: !isDefined(workflowId), + }); + + const { + records: mostRecentWorkflowVersions, + loading: loadingMostRecentWorkflowVersions, + } = useFindManyRecords<WorkflowVersion>({ + objectNameSingular: CoreObjectNameSingular.WorkflowVersion, + filter: { + workflowId: { + eq: workflowId, + }, + }, + orderBy: [ + { + createdAt: 'DescNullsLast', + }, + ], + limit: 1, + skip: !isDefined(workflowId), + }); + + const workflowWithCurrentVersion = useMemo(() => { + if (!isDefined(workflow) || loadingMostRecentWorkflowVersions) { + return undefined; + } + + const currentVersion = mostRecentWorkflowVersions?.[0]; + + return { + ...workflow, + currentVersion, + }; + }, [loadingMostRecentWorkflowVersions, mostRecentWorkflowVersions, workflow]); + + return workflowWithCurrentVersion; +}; diff --git a/packages/twenty-front/src/modules/workflow/states/workflowCreateStepFromParentStepIdState.ts b/packages/twenty-front/src/modules/workflow/states/workflowCreateStepFromParentStepIdState.ts new file mode 100644 index 000000000000..4e64010b9630 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/workflowCreateStepFromParentStepIdState.ts @@ -0,0 +1,8 @@ +import { createState } from 'twenty-ui'; + +export const workflowCreateStepFromParentStepIdState = createState< + string | undefined +>({ + key: 'workflowCreateStepFromParentStepId', + defaultValue: undefined, +}); diff --git a/packages/twenty-front/src/modules/workflow/states/workflowDiagramState.ts b/packages/twenty-front/src/modules/workflow/states/workflowDiagramState.ts new file mode 100644 index 000000000000..5f51bf85c61c --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/workflowDiagramState.ts @@ -0,0 +1,7 @@ +import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram'; +import { createState } from 'twenty-ui'; + +export const workflowDiagramState = createState<WorkflowDiagram | undefined>({ + key: 'workflowDiagramState', + defaultValue: undefined, +}); diff --git a/packages/twenty-front/src/modules/workflow/states/workflowDiagramTriggerNodeSelectionState.ts b/packages/twenty-front/src/modules/workflow/states/workflowDiagramTriggerNodeSelectionState.ts new file mode 100644 index 000000000000..91630a30046e --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/workflowDiagramTriggerNodeSelectionState.ts @@ -0,0 +1,8 @@ +import { createState } from 'twenty-ui'; + +export const workflowDiagramTriggerNodeSelectionState = createState< + string | undefined +>({ + key: 'workflowDiagramTriggerNodeSelectionState', + defaultValue: undefined, +}); diff --git a/packages/twenty-front/src/modules/workflow/states/workflowIdState.ts b/packages/twenty-front/src/modules/workflow/states/workflowIdState.ts new file mode 100644 index 000000000000..112729ea4166 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/workflowIdState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const workflowIdState = createState<string | undefined>({ + key: 'workflowIdState', + defaultValue: undefined, +}); diff --git a/packages/twenty-front/src/modules/workflow/states/workflowSelectedNodeState.ts b/packages/twenty-front/src/modules/workflow/states/workflowSelectedNodeState.ts new file mode 100644 index 000000000000..d920489d673d --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/workflowSelectedNodeState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const workflowSelectedNodeState = createState<string | undefined>({ + key: 'workflowSelectedNodeState', + defaultValue: undefined, +}); diff --git a/packages/twenty-front/src/modules/workflow/types/Workflow.ts b/packages/twenty-front/src/modules/workflow/types/Workflow.ts index ea5d39d1ec86..45500e219e7f 100644 --- a/packages/twenty-front/src/modules/workflow/types/Workflow.ts +++ b/packages/twenty-front/src/modules/workflow/types/Workflow.ts @@ -13,7 +13,7 @@ export type WorkflowCodeSettingsType = WorkflowBaseSettingsType & { serverlessFunctionId: string; }; -export type WorkflowActionType = 'CODE_ACTION'; +export type WorkflowActionType = 'CODE'; type CommonWorkflowAction = { id: string; @@ -22,7 +22,7 @@ type CommonWorkflowAction = { }; type WorkflowCodeAction = CommonWorkflowAction & { - type: 'CODE_ACTION'; + type: 'CODE'; settings: WorkflowCodeSettingsType; }; @@ -30,6 +30,8 @@ export type WorkflowAction = WorkflowCodeAction; export type WorkflowStep = WorkflowAction; +export type WorkflowStepType = WorkflowStep['type']; + export type WorkflowTriggerType = 'DATABASE_EVENT'; type BaseTrigger = { @@ -46,14 +48,23 @@ export type WorkflowDatabaseEventTrigger = BaseTrigger & { export type WorkflowTrigger = WorkflowDatabaseEventTrigger; +export type WorkflowStatus = 'DRAFT' | 'ACTIVE' | 'DEACTIVATED'; + +export type WorkflowVersionStatus = + | 'DRAFT' + | 'ACTIVE' + | 'DEACTIVATED' + | 'ARCHIVED'; + export type WorkflowVersion = { id: string; name: string; createdAt: string; updatedAt: string; workflowId: string; - trigger: WorkflowTrigger; - steps: Array<WorkflowStep>; + trigger: WorkflowTrigger | null; + steps: Array<WorkflowStep> | null; + status: WorkflowVersionStatus; __typename: 'WorkflowVersion'; }; @@ -62,5 +73,10 @@ export type Workflow = { id: string; name: string; versions: Array<WorkflowVersion>; - publishedVersionId: string; + lastPublishedVersionId: string; + statuses: Array<WorkflowStatus> | null; +}; + +export type WorkflowWithCurrentVersion = Workflow & { + currentVersion: WorkflowVersion; }; diff --git a/packages/twenty-front/src/modules/workflow/types/WorkflowDiagram.ts b/packages/twenty-front/src/modules/workflow/types/WorkflowDiagram.ts index f97d5027ed0c..237daab24b93 100644 --- a/packages/twenty-front/src/modules/workflow/types/WorkflowDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/types/WorkflowDiagram.ts @@ -13,7 +13,10 @@ export type WorkflowDiagramStepNodeData = { label: string; }; -export type WorkflowDiagramCreateStepNodeData = Record<string, never>; +export type WorkflowDiagramCreateStepNodeData = { + nodeType: 'create-step'; + parentNodeId: string; +}; export type WorkflowDiagramNodeData = | WorkflowDiagramStepNodeData diff --git a/packages/twenty-front/src/modules/workflow/utils/__tests__/addCreateStepNodes.test.ts b/packages/twenty-front/src/modules/workflow/utils/__tests__/addCreateStepNodes.test.ts index e3326c795be0..d0f46dde3576 100644 --- a/packages/twenty-front/src/modules/workflow/utils/__tests__/addCreateStepNodes.test.ts +++ b/packages/twenty-front/src/modules/workflow/utils/__tests__/addCreateStepNodes.test.ts @@ -14,7 +14,7 @@ describe('addCreateStepNodes', () => { { id: 'step1', name: 'Step 1', - type: 'CODE_ACTION', + type: 'CODE', valid: true, settings: { errorHandlingOptions: { @@ -27,7 +27,7 @@ describe('addCreateStepNodes', () => { { id: 'step2', name: 'Step 2', - type: 'CODE_ACTION', + type: 'CODE', valid: true, settings: { errorHandlingOptions: { diff --git a/packages/twenty-front/src/modules/workflow/utils/__tests__/generateWorkflowDiagram.test.ts b/packages/twenty-front/src/modules/workflow/utils/__tests__/generateWorkflowDiagram.test.ts index 0716aa29bb83..ee4643fcb20b 100644 --- a/packages/twenty-front/src/modules/workflow/utils/__tests__/generateWorkflowDiagram.test.ts +++ b/packages/twenty-front/src/modules/workflow/utils/__tests__/generateWorkflowDiagram.test.ts @@ -18,7 +18,7 @@ describe('generateWorkflowDiagram', () => { expect(result.nodes[0]).toMatchObject({ data: { - label: trigger.settings.eventName, + label: 'Company is Created', nodeType: 'trigger', }, }); @@ -35,7 +35,7 @@ describe('generateWorkflowDiagram', () => { { id: 'step1', name: 'Step 1', - type: 'CODE_ACTION', + type: 'CODE', valid: true, settings: { errorHandlingOptions: { @@ -48,7 +48,7 @@ describe('generateWorkflowDiagram', () => { { id: 'step2', name: 'Step 2', - type: 'CODE_ACTION', + type: 'CODE', valid: true, settings: { errorHandlingOptions: { @@ -70,8 +70,10 @@ describe('generateWorkflowDiagram', () => { const stepNodes = result.nodes.slice(1); for (const [index, step] of steps.entries()) { - expect(stepNodes[index].data.nodeType).toBe('action'); - expect(stepNodes[index].data.label).toBe(step.name); + expect(stepNodes[index].data).toEqual({ + nodeType: 'action', + label: step.name, + }); } }); @@ -86,7 +88,7 @@ describe('generateWorkflowDiagram', () => { { id: 'step1', name: 'Step 1', - type: 'CODE_ACTION', + type: 'CODE', valid: true, settings: { errorHandlingOptions: { @@ -99,7 +101,7 @@ describe('generateWorkflowDiagram', () => { { id: 'step2', name: 'Step 2', - type: 'CODE_ACTION', + type: 'CODE', valid: true, settings: { errorHandlingOptions: { diff --git a/packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowLastDiagramVersion.test.ts b/packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowLastDiagramVersion.test.ts deleted file mode 100644 index 20c41c085bb1..000000000000 --- a/packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowLastDiagramVersion.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Workflow } from '@/workflow/types/Workflow'; -import { getWorkflowLastDiagramVersion } from '../getWorkflowLastDiagramVersion'; - -describe('getWorkflowLastDiagramVersion', () => { - it('returns an empty diagram if the provided workflow is undefined', () => { - const result = getWorkflowLastDiagramVersion(undefined); - - expect(result).toEqual({ nodes: [], edges: [] }); - }); - - it('returns an empty diagram if the provided workflow has no versions', () => { - const result = getWorkflowLastDiagramVersion({ - __typename: 'Workflow', - id: 'aa', - name: 'aa', - publishedVersionId: '', - versions: [], - }); - - expect(result).toEqual({ nodes: [], edges: [] }); - }); - - it('returns the diagram for the last version', () => { - const workflow: Workflow = { - __typename: 'Workflow', - id: 'aa', - name: 'aa', - publishedVersionId: '', - versions: [ - { - __typename: 'WorkflowVersion', - createdAt: '', - id: '1', - name: '', - steps: [], - trigger: { - settings: { eventName: 'company.created' }, - type: 'DATABASE_EVENT', - }, - updatedAt: '', - workflowId: '', - }, - { - __typename: 'WorkflowVersion', - createdAt: '', - id: '1', - name: '', - steps: [ - { - id: 'step-1', - name: '', - settings: { - errorHandlingOptions: { - retryOnFailure: { value: true }, - continueOnFailure: { value: false }, - }, - serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', - }, - type: 'CODE_ACTION', - valid: true, - }, - ], - trigger: { - settings: { eventName: 'company.created' }, - type: 'DATABASE_EVENT', - }, - updatedAt: '', - workflowId: '', - }, - ], - }; - - const result = getWorkflowLastDiagramVersion(workflow); - - // Corresponds to the trigger + 1 step - expect(result.nodes).toHaveLength(2); - expect(result.edges).toHaveLength(1); - }); -}); diff --git a/packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowVersionDiagram.test.ts b/packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowVersionDiagram.test.ts new file mode 100644 index 000000000000..907524a725e7 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/__tests__/getWorkflowVersionDiagram.test.ts @@ -0,0 +1,101 @@ +import { getWorkflowVersionDiagram } from '../getWorkflowVersionDiagram'; + +describe('getWorkflowVersionDiagram', () => { + it('returns an empty diagram if the provided workflow version', () => { + const result = getWorkflowVersionDiagram(undefined); + + expect(result).toEqual({ nodes: [], edges: [] }); + }); + + it('returns a diagram with an empty-trigger node if the provided workflow version has no trigger', () => { + const result = getWorkflowVersionDiagram({ + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [], + trigger: null, + updatedAt: '', + workflowId: '', + }); + + expect(result).toEqual({ + nodes: [ + { + data: {}, + id: 'trigger', + position: { x: 0, y: 0 }, + type: 'empty-trigger', + }, + ], + edges: [], + }); + }); + + it('returns a diagram with an empty-trigger node if the provided workflow version has no steps', () => { + const result = getWorkflowVersionDiagram({ + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: null, + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + }); + + expect(result).toEqual({ + nodes: [ + { + data: { + label: 'Company is Created', + nodeType: 'trigger', + }, + id: 'trigger', + position: { x: 0, y: 0 }, + }, + ], + edges: [], + }); + }); + + it('returns the diagram for the last version', () => { + const result = getWorkflowVersionDiagram({ + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [ + { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + ], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + }); + + // Corresponds to the trigger + 1 step + expect(result.nodes).toHaveLength(2); + expect(result.edges).toHaveLength(1); + }); +}); diff --git a/packages/twenty-front/src/modules/workflow/utils/__tests__/insertStep.test.ts b/packages/twenty-front/src/modules/workflow/utils/__tests__/insertStep.test.ts new file mode 100644 index 000000000000..ba93aa6c341e --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/__tests__/insertStep.test.ts @@ -0,0 +1,221 @@ +import { WorkflowStep, WorkflowVersion } from '@/workflow/types/Workflow'; +import { insertStep } from '../insertStep'; + +describe('insertStep', () => { + it('returns a deep copy of the provided steps array instead of mutating it', () => { + const workflowVersionInitial = { + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + } satisfies WorkflowVersion; + const stepToAdd: WorkflowStep = { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }; + + const stepsUpdated = insertStep({ + steps: workflowVersionInitial.steps, + stepToAdd, + parentStepId: undefined, + }); + + expect(workflowVersionInitial.steps).not.toBe(stepsUpdated); + }); + + it('adds the step when the steps array is empty', () => { + const workflowVersionInitial = { + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + } satisfies WorkflowVersion; + const stepToAdd: WorkflowStep = { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }; + + const stepsUpdated = insertStep({ + steps: workflowVersionInitial.steps, + stepToAdd, + parentStepId: undefined, + }); + + const expectedUpdatedSteps: Array<WorkflowStep> = [stepToAdd]; + expect(stepsUpdated).toEqual(expectedUpdatedSteps); + }); + + it('adds the step at the end of a non-empty steps array', () => { + const workflowVersionInitial = { + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [ + { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + { + id: 'step-2', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + ], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + } satisfies WorkflowVersion; + const stepToAdd: WorkflowStep = { + id: 'step-3', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }; + + const stepsUpdated = insertStep({ + steps: workflowVersionInitial.steps, + stepToAdd, + parentStepId: workflowVersionInitial.steps[1].id, // Note the selected step. + }); + + const expectedUpdatedSteps: Array<WorkflowStep> = [ + workflowVersionInitial.steps[0], + workflowVersionInitial.steps[1], + stepToAdd, + ]; + expect(stepsUpdated).toEqual(expectedUpdatedSteps); + }); + + it('adds the step in the middle of a non-empty steps array', () => { + const workflowVersionInitial = { + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [ + { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + { + id: 'step-2', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + ], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + } satisfies WorkflowVersion; + const stepToAdd: WorkflowStep = { + id: 'step-3', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }; + + const stepsUpdated = insertStep({ + steps: workflowVersionInitial.steps, + stepToAdd, + parentStepId: workflowVersionInitial.steps[0].id, // Note the selected step. + }); + + const expectedUpdatedSteps: Array<WorkflowStep> = [ + workflowVersionInitial.steps[0], + stepToAdd, + workflowVersionInitial.steps[1], + ]; + expect(stepsUpdated).toEqual(expectedUpdatedSteps); + }); +}); diff --git a/packages/twenty-front/src/modules/workflow/utils/__tests__/replaceStep.test.ts b/packages/twenty-front/src/modules/workflow/utils/__tests__/replaceStep.test.ts new file mode 100644 index 000000000000..93286c59013e --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/__tests__/replaceStep.test.ts @@ -0,0 +1,127 @@ +import { WorkflowStep, WorkflowVersion } from '@/workflow/types/Workflow'; +import { replaceStep } from '../replaceStep'; + +describe('replaceStep', () => { + it('returns a deep copy of the provided steps array instead of mutating it', () => { + const stepToBeReplaced = { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'first', + }, + type: 'CODE', + valid: true, + } satisfies WorkflowStep; + const workflowVersionInitial = { + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [stepToBeReplaced], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + } satisfies WorkflowVersion; + + const stepsUpdated = replaceStep({ + steps: workflowVersionInitial.steps, + stepToReplace: { + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'second', + }, + }, + stepId: stepToBeReplaced.id, + }); + + expect(workflowVersionInitial.steps).not.toBe(stepsUpdated); + }); + + it('replaces a step in a non-empty steps array', () => { + const stepToBeReplaced: WorkflowStep = { + id: 'step-2', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }; + const workflowVersionInitial = { + __typename: 'WorkflowVersion', + status: 'ACTIVE', + createdAt: '', + id: '1', + name: '', + steps: [ + { + id: 'step-1', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + stepToBeReplaced, + { + id: 'step-3', + name: '', + settings: { + errorHandlingOptions: { + retryOnFailure: { value: true }, + continueOnFailure: { value: false }, + }, + serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997', + }, + type: 'CODE', + valid: true, + }, + ], + trigger: { + settings: { eventName: 'company.created' }, + type: 'DATABASE_EVENT', + }, + updatedAt: '', + workflowId: '', + } satisfies WorkflowVersion; + + const updatedStepName = "that's another name"; + const stepsUpdated = replaceStep({ + stepId: stepToBeReplaced.id, + steps: workflowVersionInitial.steps, + stepToReplace: { + name: updatedStepName, + }, + }); + + const expectedUpdatedSteps: Array<WorkflowStep> = [ + workflowVersionInitial.steps[0], + { + ...stepToBeReplaced, + name: updatedStepName, + }, + workflowVersionInitial.steps[2], + ]; + expect(stepsUpdated).toEqual(expectedUpdatedSteps); + }); +}); diff --git a/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts b/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts index 9d2941adb274..381d05889874 100644 --- a/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts +++ b/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts @@ -18,7 +18,10 @@ export const addCreateStepNodes = ({ nodes, edges }: WorkflowDiagram) => { const newCreateStepNode: WorkflowDiagramNode = { id: v4(), type: 'create-step', - data: {}, + data: { + nodeType: 'create-step', + parentNodeId: node.id, + }, position: { x: 0, y: 0 }, }; diff --git a/packages/twenty-front/src/modules/workflow/utils/assertWorkflowWithCurrentVersionIsDefined.tsx b/packages/twenty-front/src/modules/workflow/utils/assertWorkflowWithCurrentVersionIsDefined.tsx new file mode 100644 index 000000000000..c7849dd6cbd4 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/assertWorkflowWithCurrentVersionIsDefined.tsx @@ -0,0 +1,15 @@ +import { + Workflow, + WorkflowVersion, + WorkflowWithCurrentVersion, +} from '@/workflow/types/Workflow'; +import { isDefined } from 'twenty-ui'; + +// eslint-disable-next-line prefer-arrow/prefer-arrow-functions +export function assertWorkflowWithCurrentVersionIsDefined( + workflow: WorkflowWithCurrentVersion | undefined, +): asserts workflow is Workflow & { currentVersion: WorkflowVersion } { + if (!isDefined(workflow) || !isDefined(workflow.currentVersion)) { + throw new Error('Expected workflow and its current version to be defined'); + } +} diff --git a/packages/twenty-front/src/modules/workflow/utils/findStepPositionOrThrow.ts b/packages/twenty-front/src/modules/workflow/utils/findStepPositionOrThrow.ts new file mode 100644 index 000000000000..bf10df7783fc --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/findStepPositionOrThrow.ts @@ -0,0 +1,41 @@ +import { TRIGGER_STEP_ID } from '@/workflow/constants/TriggerStepId'; +import { WorkflowStep } from '@/workflow/types/Workflow'; +import { isDefined } from 'twenty-ui'; + +/** + * This function returns the reference of the array where the step should be positioned + * and at which index. + */ +export const findStepPositionOrThrow = ({ + steps, + stepId, +}: { + steps: Array<WorkflowStep>; + stepId: string | undefined; +}): { steps: Array<WorkflowStep>; index: number } => { + if (!isDefined(stepId) || stepId === TRIGGER_STEP_ID) { + return { + steps, + index: 0, + }; + } + + for (const [index, step] of steps.entries()) { + if (step.id === stepId) { + return { + steps, + index, + }; + } + + // TODO: When condition will have been implemented, put recursivity here. + // if (step.type === "CONDITION") { + // return findNodePosition({ + // workflowSteps: step.conditions, + // stepId, + // }) + // } + } + + throw new Error(`Couldn't locate the step. Unreachable step id: ${stepId}.`); +}; diff --git a/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts b/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts index 6bb95f23cbba..4d0aa8995ae5 100644 --- a/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts @@ -1,17 +1,21 @@ +import { TRIGGER_STEP_ID } from '@/workflow/constants/TriggerStepId'; import { WorkflowStep, WorkflowTrigger } from '@/workflow/types/Workflow'; import { WorkflowDiagram, WorkflowDiagramEdge, WorkflowDiagramNode, } from '@/workflow/types/WorkflowDiagram'; +import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; import { MarkerType } from '@xyflow/react'; +import { isDefined } from 'twenty-ui'; import { v4 } from 'uuid'; +import { capitalize } from '~/utils/string/capitalize'; export const generateWorkflowDiagram = ({ trigger, steps, }: { - trigger: WorkflowTrigger; + trigger: WorkflowTrigger | undefined; steps: Array<WorkflowStep>; }): WorkflowDiagram => { const nodes: Array<WorkflowDiagramNode> = []; @@ -24,7 +28,7 @@ export const generateWorkflowDiagram = ({ xPos: number, yPos: number, ) => { - const nodeId = v4(); + const nodeId = step.id; nodes.push({ id: nodeId, data: { @@ -47,29 +51,39 @@ export const generateWorkflowDiagram = ({ }, }); - // Recursively generate flow for the next action if it exists - if (step.type !== 'CODE_ACTION') { - // processNode(action.nextAction, nodeId, xPos + 150, yPos + 100); - - throw new Error('Other types as code actions are not supported yet.'); - } - return nodeId; }; // Start with the trigger node - const triggerNodeId = v4(); - nodes.push({ - id: triggerNodeId, - data: { - nodeType: 'trigger', - label: trigger.settings.eventName, - }, - position: { - x: 0, - y: 0, - }, - }); + const triggerNodeId = TRIGGER_STEP_ID; + + if (isDefined(trigger)) { + const triggerEvent = splitWorkflowTriggerEventName( + trigger.settings.eventName, + ); + + nodes.push({ + id: triggerNodeId, + data: { + nodeType: 'trigger', + label: `${capitalize(triggerEvent.objectType)} is ${capitalize(triggerEvent.event)}`, + }, + position: { + x: 0, + y: 0, + }, + }); + } else { + nodes.push({ + id: triggerNodeId, + type: 'empty-trigger', + data: {} as any, + position: { + x: 0, + y: 0, + }, + }); + } let lastStepId = triggerNodeId; diff --git a/packages/twenty-front/src/modules/workflow/utils/getOrganizedDiagram.ts b/packages/twenty-front/src/modules/workflow/utils/getOrganizedDiagram.ts index 0aa687d71054..a5d549c71ad6 100644 --- a/packages/twenty-front/src/modules/workflow/utils/getOrganizedDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/utils/getOrganizedDiagram.ts @@ -1,9 +1,6 @@ import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram'; import Dagre from '@dagrejs/dagre'; -/** - * Set the position of the nodes in the diagram. The positions are computed with a layouting algorithm. - */ export const getOrganizedDiagram = ( diagram: WorkflowDiagram, ): WorkflowDiagram => { diff --git a/packages/twenty-front/src/modules/workflow/utils/getStepDefaultDefinition.ts b/packages/twenty-front/src/modules/workflow/utils/getStepDefaultDefinition.ts new file mode 100644 index 000000000000..9cb8b27e86ff --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/getStepDefaultDefinition.ts @@ -0,0 +1,33 @@ +import { WorkflowStep, WorkflowStepType } from '@/workflow/types/Workflow'; +import { v4 } from 'uuid'; + +export const getStepDefaultDefinition = ( + type: WorkflowStepType, +): WorkflowStep => { + const newStepId = v4(); + + switch (type) { + case 'CODE': { + return { + id: newStepId, + name: 'Code', + type: 'CODE', + valid: false, + settings: { + serverlessFunctionId: '', + errorHandlingOptions: { + continueOnFailure: { + value: false, + }, + retryOnFailure: { + value: false, + }, + }, + }, + }; + } + default: { + throw new Error(`Unknown type: ${type}`); + } + } +}; diff --git a/packages/twenty-front/src/modules/workflow/utils/getWorkflowLastDiagramVersion.ts b/packages/twenty-front/src/modules/workflow/utils/getWorkflowLastDiagramVersion.ts deleted file mode 100644 index 448ed7fec4b6..000000000000 --- a/packages/twenty-front/src/modules/workflow/utils/getWorkflowLastDiagramVersion.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Workflow } from '@/workflow/types/Workflow'; -import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram'; -import { generateWorkflowDiagram } from '@/workflow/utils/generateWorkflowDiagram'; -import { isDefined } from 'twenty-ui'; - -const EMPTY_DIAGRAM: WorkflowDiagram = { - nodes: [], - edges: [], -}; - -export const getWorkflowLastDiagramVersion = ( - workflow: Workflow | undefined, -): WorkflowDiagram => { - if (!isDefined(workflow)) { - return EMPTY_DIAGRAM; - } - - const lastVersion = workflow.versions.at(-1); - if (!isDefined(lastVersion) || !isDefined(lastVersion.trigger)) { - return EMPTY_DIAGRAM; - } - - return generateWorkflowDiagram({ - trigger: lastVersion.trigger, - steps: lastVersion.steps, - }); -}; diff --git a/packages/twenty-front/src/modules/workflow/utils/getWorkflowVersionDiagram.ts b/packages/twenty-front/src/modules/workflow/utils/getWorkflowVersionDiagram.ts new file mode 100644 index 000000000000..e119b1d2c5c9 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/getWorkflowVersionDiagram.ts @@ -0,0 +1,22 @@ +import { WorkflowVersion } from '@/workflow/types/Workflow'; +import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram'; +import { generateWorkflowDiagram } from '@/workflow/utils/generateWorkflowDiagram'; +import { isDefined } from 'twenty-ui'; + +const EMPTY_DIAGRAM: WorkflowDiagram = { + nodes: [], + edges: [], +}; + +export const getWorkflowVersionDiagram = ( + workflowVersion: WorkflowVersion | undefined, +): WorkflowDiagram => { + if (!isDefined(workflowVersion)) { + return EMPTY_DIAGRAM; + } + + return generateWorkflowDiagram({ + trigger: workflowVersion.trigger ?? undefined, + steps: workflowVersion.steps ?? [], + }); +}; diff --git a/packages/twenty-front/src/modules/workflow/utils/insertStep.ts b/packages/twenty-front/src/modules/workflow/utils/insertStep.ts new file mode 100644 index 000000000000..1a6abbd54113 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/insertStep.ts @@ -0,0 +1,27 @@ +import { WorkflowStep } from '@/workflow/types/Workflow'; +import { findStepPositionOrThrow } from '@/workflow/utils/findStepPositionOrThrow'; + +export const insertStep = ({ + steps: stepsInitial, + stepToAdd, + parentStepId, +}: { + steps: Array<WorkflowStep>; + parentStepId: string | undefined; + stepToAdd: WorkflowStep; +}): Array<WorkflowStep> => { + const steps = structuredClone(stepsInitial); + + const parentStepPosition = findStepPositionOrThrow({ + steps, + stepId: parentStepId, + }); + + parentStepPosition.steps.splice( + parentStepPosition.index + 1, // The "+ 1" means that we add the step after its parent and not before. + 0, + stepToAdd, + ); + + return steps; +}; diff --git a/packages/twenty-front/src/modules/workflow/utils/replaceStep.ts b/packages/twenty-front/src/modules/workflow/utils/replaceStep.ts new file mode 100644 index 000000000000..b08e2d33cf03 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/replaceStep.ts @@ -0,0 +1,26 @@ +import { WorkflowStep } from '@/workflow/types/Workflow'; +import { findStepPositionOrThrow } from '@/workflow/utils/findStepPositionOrThrow'; + +export const replaceStep = ({ + steps: stepsInitial, + stepId, + stepToReplace, +}: { + steps: Array<WorkflowStep>; + stepId: string; + stepToReplace: Partial<Omit<WorkflowStep, 'id'>>; +}) => { + const steps = structuredClone(stepsInitial); + + const parentStepPosition = findStepPositionOrThrow({ + steps, + stepId, + }); + + parentStepPosition.steps[parentStepPosition.index] = { + ...parentStepPosition.steps[parentStepPosition.index], + ...stepToReplace, + }; + + return steps; +}; diff --git a/packages/twenty-front/src/modules/workflow/utils/splitWorkflowTriggerEventName.ts b/packages/twenty-front/src/modules/workflow/utils/splitWorkflowTriggerEventName.ts new file mode 100644 index 000000000000..282f1b969268 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/splitWorkflowTriggerEventName.ts @@ -0,0 +1,8 @@ +export const splitWorkflowTriggerEventName = (eventName: string) => { + const [objectType, event] = eventName.split('.'); + + return { + objectType, + event, + }; +}; diff --git a/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/deleteWorkspaceInvitation.ts b/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/deleteWorkspaceInvitation.ts new file mode 100644 index 000000000000..0b2b2510ee25 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/deleteWorkspaceInvitation.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const DELETE_WORKSPACE_INVITATION = gql` + mutation DeleteWorkspaceInvitation($appTokenId: String!) { + deleteWorkspaceInvitation(appTokenId: $appTokenId) + } +`; diff --git a/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/resendWorkspaceInvitation.ts b/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/resendWorkspaceInvitation.ts new file mode 100644 index 000000000000..43cd10049219 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/resendWorkspaceInvitation.ts @@ -0,0 +1,17 @@ +import { gql } from '@apollo/client'; + +export const RESEND_WORKSPACE_INVITATION = gql` + mutation ResendWorkspaceInvitation($appTokenId: String!) { + resendWorkspaceInvitation(appTokenId: $appTokenId) { + success + errors + result { + ... on WorkspaceInvitation { + id + email + expiresAt + } + } + } + } +`; diff --git a/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/sendInvitations.ts b/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/sendInvitations.ts new file mode 100644 index 000000000000..a66579febf29 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/graphql/mutations/sendInvitations.ts @@ -0,0 +1,17 @@ +import { gql } from '@apollo/client'; + +export const SEND_INVITATIONS = gql` + mutation SendInvitations($emails: [String!]!) { + sendInvitations(emails: $emails) { + success + errors + result { + ... on WorkspaceInvitation { + id + email + expiresAt + } + } + } + } +`; diff --git a/packages/twenty-front/src/modules/workspace-invitation/graphql/queries/getWorkspaceInvitations.ts b/packages/twenty-front/src/modules/workspace-invitation/graphql/queries/getWorkspaceInvitations.ts new file mode 100644 index 000000000000..dbb3f8b79127 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/graphql/queries/getWorkspaceInvitations.ts @@ -0,0 +1,11 @@ +import { gql } from '@apollo/client'; + +export const GET_WORKSPACE_INVITATIONS = gql` + query GetWorkspaceInvitations { + findWorkspaceInvitations { + id + email + expiresAt + } + } +`; diff --git a/packages/twenty-front/src/modules/workspace-invitation/hooks/useCreateWorkspaceInvitation.ts b/packages/twenty-front/src/modules/workspace-invitation/hooks/useCreateWorkspaceInvitation.ts new file mode 100644 index 000000000000..6894f9b700e4 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/hooks/useCreateWorkspaceInvitation.ts @@ -0,0 +1,26 @@ +import { useSetRecoilState } from 'recoil'; +import { useSendInvitationsMutation } from '~/generated/graphql'; +import { SendInvitationsMutationVariables } from '../../../generated/graphql'; +import { workspaceInvitationsState } from '../states/workspaceInvitationsStates'; + +export const useCreateWorkspaceInvitation = () => { + const [sendInvitationsMutation] = useSendInvitationsMutation(); + + const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState); + + const sendInvitation = async (emails: SendInvitationsMutationVariables) => { + return await sendInvitationsMutation({ + variables: emails, + onCompleted: (data) => { + setWorkspaceInvitations((workspaceInvitations) => [ + ...workspaceInvitations, + ...data.sendInvitations.result, + ]); + }, + }); + }; + + return { + sendInvitation, + }; +}; diff --git a/packages/twenty-front/src/modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation.ts b/packages/twenty-front/src/modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation.ts new file mode 100644 index 000000000000..5731548c1db8 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation.ts @@ -0,0 +1,34 @@ +import { useSetRecoilState } from 'recoil'; +import { + DeleteWorkspaceInvitationMutationVariables, + useDeleteWorkspaceInvitationMutation, +} from '~/generated/graphql'; +import { workspaceInvitationsState } from '../states/workspaceInvitationsStates'; + +export const useDeleteWorkspaceInvitation = () => { + const [deleteWorkspaceInvitationMutation] = + useDeleteWorkspaceInvitationMutation(); + + const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState); + + const deleteWorkspaceInvitation = async ({ + appTokenId, + }: DeleteWorkspaceInvitationMutationVariables) => { + return await deleteWorkspaceInvitationMutation({ + variables: { + appTokenId, + }, + onCompleted: () => { + setWorkspaceInvitations((workspaceInvitations) => + workspaceInvitations.filter( + (workspaceInvitation) => workspaceInvitation.id !== appTokenId, + ), + ); + }, + }); + }; + + return { + deleteWorkspaceInvitation, + }; +}; diff --git a/packages/twenty-front/src/modules/workspace-invitation/hooks/useResendWorkspaceInvitation.ts b/packages/twenty-front/src/modules/workspace-invitation/hooks/useResendWorkspaceInvitation.ts new file mode 100644 index 000000000000..acda3cffd662 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/hooks/useResendWorkspaceInvitation.ts @@ -0,0 +1,35 @@ +import { useSetRecoilState } from 'recoil'; +import { + ResendWorkspaceInvitationMutationVariables, + useResendWorkspaceInvitationMutation, +} from '~/generated/graphql'; +import { workspaceInvitationsState } from '../states/workspaceInvitationsStates'; + +export const useResendWorkspaceInvitation = () => { + const [resendWorkspaceInvitationMutation] = + useResendWorkspaceInvitationMutation(); + + const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState); + + const resendInvitation = async ({ + appTokenId, + }: ResendWorkspaceInvitationMutationVariables) => { + return await resendWorkspaceInvitationMutation({ + variables: { + appTokenId, + }, + onCompleted: (data) => { + setWorkspaceInvitations((workspaceInvitations) => [ + ...data.resendWorkspaceInvitation.result, + ...workspaceInvitations.filter( + (workspaceInvitation) => workspaceInvitation.id !== appTokenId, + ), + ]); + }, + }); + }; + + return { + resendInvitation, + }; +}; diff --git a/packages/twenty-front/src/modules/workspace-invitation/states/workspaceInvitationsStates.ts b/packages/twenty-front/src/modules/workspace-invitation/states/workspaceInvitationsStates.ts new file mode 100644 index 000000000000..8f550a1ad2cf --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-invitation/states/workspaceInvitationsStates.ts @@ -0,0 +1,9 @@ +import { createState } from 'twenty-ui'; +import { WorkspaceInvitation } from '@/workspace-member/types/WorkspaceMember'; + +export const workspaceInvitationsState = createState< + Omit<WorkspaceInvitation, '__typename'>[] +>({ + key: 'workspaceInvitationsState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/workspace-member/grapqhql/mutations/addUserToWorkspaceByInviteToken.ts b/packages/twenty-front/src/modules/workspace-member/grapqhql/mutations/addUserToWorkspaceByInviteToken.ts new file mode 100644 index 000000000000..4850c10596e4 --- /dev/null +++ b/packages/twenty-front/src/modules/workspace-member/grapqhql/mutations/addUserToWorkspaceByInviteToken.ts @@ -0,0 +1,9 @@ +import { gql } from '@apollo/client'; + +export const ADD_USER_TO_WORKSPACE_BY_INVITE_TOKEN = gql` + mutation AddUserToWorkspaceByInviteToken($inviteToken: String!) { + addUserToWorkspaceByInviteToken(inviteToken: $inviteToken) { + id + } + } +`; diff --git a/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts b/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts index 46365c93497f..ded69618f0fa 100644 --- a/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts +++ b/packages/twenty-front/src/modules/workspace-member/types/WorkspaceMember.ts @@ -24,3 +24,10 @@ export type WorkspaceMember = { dateFormat?: WorkspaceMemberDateFormatEnum | null; timeFormat?: WorkspaceMemberTimeFormatEnum | null; }; + +export type WorkspaceInvitation = { + __typename: 'WorkspaceInvitation'; + id: string; + email: string; + expiresAt: string; +}; diff --git a/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx b/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx index 3bb6bbc0248f..4c007b5180b2 100644 --- a/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx +++ b/packages/twenty-front/src/modules/workspace/components/WorkspaceInviteTeam.tsx @@ -1,9 +1,9 @@ -import { useEffect } from 'react'; -import { Controller, useForm } from 'react-hook-form'; import styled from '@emotion/styled'; import { zodResolver } from '@hookform/resolvers/zod'; +import { useEffect } from 'react'; +import { Controller, useForm } from 'react-hook-form'; import { Key } from 'ts-key-enum'; -import { IconMail, IconSend } from 'twenty-ui'; +import { IconSend } from 'twenty-ui'; import { z } from 'zod'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; @@ -11,12 +11,13 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { Button } from '@/ui/input/button/components/Button'; import { TextInput } from '@/ui/input/components/TextInput'; import { sanitizeEmailList } from '@/workspace/utils/sanitizeEmailList'; -import { useSendInviteLinkMutation } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; +import { useCreateWorkspaceInvitation } from '../../workspace-invitation/hooks/useCreateWorkspaceInvitation'; const StyledContainer = styled.div` display: flex; flex-direction: row; + padding-bottom: ${({ theme }) => theme.spacing(3)}; `; const StyledLinkContainer = styled.div` @@ -69,26 +70,40 @@ type FormInput = { export const WorkspaceInviteTeam = () => { const { enqueueSnackBar } = useSnackBar(); - const [sendInviteLink] = useSendInviteLinkMutation(); + const { sendInvitation } = useCreateWorkspaceInvitation(); - const { reset, handleSubmit, control, formState } = useForm<FormInput>({ - mode: 'onSubmit', - resolver: zodResolver(validationSchema()), - defaultValues: { - emails: '', + const { reset, handleSubmit, control, formState, watch } = useForm<FormInput>( + { + mode: 'onSubmit', + resolver: zodResolver(validationSchema()), + defaultValues: { + emails: '', + }, }, - }); + ); + const isEmailsEmpty = !watch('emails'); - const submit = handleSubmit(async (data) => { - const emailsList = sanitizeEmailList(data.emails.split(',')); - const result = await sendInviteLink({ variables: { emails: emailsList } }); - if (isDefined(result.errors)) { - throw result.errors; + const submit = handleSubmit(async ({ emails }) => { + const emailsList = sanitizeEmailList(emails.split(',')); + const { data } = await sendInvitation({ emails: emailsList }); + if (isDefined(data) && data.sendInvitations.result.length > 0) { + enqueueSnackBar( + `${data.sendInvitations.result.length} invitations sent`, + { + variant: SnackBarVariant.Success, + duration: 2000, + }, + ); + return; + } + if (isDefined(data) && !data.sendInvitations.success) { + data.sendInvitations.errors.forEach((error) => { + enqueueSnackBar(error, { + variant: SnackBarVariant.Error, + duration: 5000, + }); + }); } - enqueueSnackBar('Invite link sent to email addresses', { - variant: SnackBarVariant.Success, - duration: 2000, - }); }); const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { @@ -97,7 +112,7 @@ export const WorkspaceInviteTeam = () => { } }; - const { isSubmitSuccessful } = formState; + const { isSubmitSuccessful, errors } = formState; useEffect(() => { if (isSubmitSuccessful) { @@ -116,7 +131,6 @@ export const WorkspaceInviteTeam = () => { return ( <TextInput placeholder="tim@apple.com, jony.ive@apple.dev" - LeftIcon={IconMail} value={value} onChange={onChange} error={error?.message} @@ -133,6 +147,7 @@ export const WorkspaceInviteTeam = () => { accent="blue" title="Invite" type="submit" + disabled={isEmailsEmpty || !!errors.emails} /> </StyledContainer> </form> diff --git a/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx b/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx deleted file mode 100644 index 6ed05ce15f39..000000000000 --- a/packages/twenty-front/src/modules/workspace/components/WorkspaceMemberCard.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import styled from '@emotion/styled'; -import { Avatar, OverflowingTextWithTooltip } from 'twenty-ui'; - -import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; - -const StyledContainer = styled.div` - background: ${({ theme }) => theme.background.secondary}; - border: 1px solid ${({ theme }) => theme.border.color.medium}; - border-radius: ${({ theme }) => theme.spacing(2)}; - display: flex; - flex-direction: row; - margin-bottom: ${({ theme }) => theme.spacing(0)}; - margin-top: ${({ theme }) => theme.spacing(4)}; - padding: ${({ theme }) => theme.spacing(3)}; -`; - -const StyledContent = styled.div` - display: flex; - flex: 1; - flex-direction: column; - justify-content: center; - margin-left: ${({ theme }) => theme.spacing(3)}; - overflow: auto; -`; - -const StyledEmailText = styled.span` - color: ${({ theme }) => theme.font.color.tertiary}; -`; - -type WorkspaceMemberCardProps = { - workspaceMember: WorkspaceMember; - accessory?: React.ReactNode; -}; - -export const WorkspaceMemberCard = ({ - workspaceMember, - accessory, -}: WorkspaceMemberCardProps) => ( - <StyledContainer> - <Avatar - avatarUrl={workspaceMember.avatarUrl} - placeholderColorSeed={workspaceMember.id} - placeholder={workspaceMember.name.firstName || ''} - type="squared" - size="xl" - /> - <StyledContent> - <OverflowingTextWithTooltip - text={ - workspaceMember.name.firstName + ' ' + workspaceMember.name.lastName - } - /> - <StyledEmailText>{workspaceMember.userEmail}</StyledEmailText> - </StyledContent> - {accessory} - </StyledContainer> -); diff --git a/packages/twenty-front/src/modules/workspace/graphql/mutations/sendInviteLink.ts b/packages/twenty-front/src/modules/workspace/graphql/mutations/sendInviteLink.ts deleted file mode 100644 index c34f4734c4b9..000000000000 --- a/packages/twenty-front/src/modules/workspace/graphql/mutations/sendInviteLink.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const SEND_INVITE_LINK = gql` - mutation SendInviteLink($emails: [String!]!) { - sendInviteLink(emails: $emails) { - success - } - } -`; diff --git a/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts b/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts index e1dd39384ad7..409723f1655e 100644 --- a/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts +++ b/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts @@ -1,5 +1,4 @@ export type FeatureFlagKey = - | 'IS_BLOCKLIST_ENABLED' | 'IS_EVENT_OBJECT_ENABLED' | 'IS_AIRTABLE_INTEGRATION_ENABLED' | 'IS_POSTGRESQL_INTEGRATION_ENABLED' @@ -9,4 +8,5 @@ export type FeatureFlagKey = | 'IS_CRM_MIGRATION_ENABLED' | 'IS_FREE_ACCESS_ENABLED' | 'IS_MESSAGE_THREAD_SUBSCRIBER_ENABLED' - | 'IS_WORKFLOW_ENABLED'; + | 'IS_WORKFLOW_ENABLED' + | 'IS_WORKSPACE_FAVORITE_ENABLED'; diff --git a/packages/twenty-front/src/pages/auth/Invite.tsx b/packages/twenty-front/src/pages/auth/Invite.tsx index be677ecb5a56..7a80c3139d84 100644 --- a/packages/twenty-front/src/pages/auth/Invite.tsx +++ b/packages/twenty-front/src/pages/auth/Invite.tsx @@ -13,8 +13,12 @@ import { Loader } from '@/ui/feedback/loader/components/Loader'; import { MainButton } from '@/ui/input/button/components/MainButton'; import { useWorkspaceSwitching } from '@/ui/navigation/navigation-drawer/hooks/useWorkspaceSwitching'; import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn'; -import { useAddUserToWorkspaceMutation } from '~/generated/graphql'; +import { + useAddUserToWorkspaceMutation, + useAddUserToWorkspaceByInviteTokenMutation, +} from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; +import { useSearchParams } from 'react-router-dom'; const StyledContentContainer = styled.div` margin-bottom: ${({ theme }) => theme.spacing(8)}; @@ -24,26 +28,40 @@ const StyledContentContainer = styled.div` export const Invite = () => { const { workspace: workspaceFromInviteHash, workspaceInviteHash } = useWorkspaceFromInviteHash(); + const { form } = useSignInUpForm(); const currentWorkspace = useRecoilValue(currentWorkspaceState); const [addUserToWorkspace] = useAddUserToWorkspaceMutation(); + const [addUserToWorkspaceByInviteToken] = + useAddUserToWorkspaceByInviteTokenMutation(); const { switchWorkspace } = useWorkspaceSwitching(); + const [searchParams] = useSearchParams(); + const workspaceInviteToken = searchParams.get('inviteToken'); const title = useMemo(() => { return `Join ${workspaceFromInviteHash?.displayName ?? ''} team`; }, [workspaceFromInviteHash?.displayName]); const handleUserJoinWorkspace = async () => { - if ( - !(isDefined(workspaceInviteHash) && isDefined(workspaceFromInviteHash)) + if (isDefined(workspaceInviteToken) && isDefined(workspaceFromInviteHash)) { + await addUserToWorkspaceByInviteToken({ + variables: { + inviteToken: workspaceInviteToken, + }, + }); + } else if ( + isDefined(workspaceInviteHash) && + isDefined(workspaceFromInviteHash) ) { + await addUserToWorkspace({ + variables: { + inviteHash: workspaceInviteHash, + }, + }); + } else { return; } - await addUserToWorkspace({ - variables: { - inviteHash: workspaceInviteHash, - }, - }); + await switchWorkspace(workspaceFromInviteHash.id); }; diff --git a/packages/twenty-front/src/pages/auth/__stories__/Invite.stories.tsx b/packages/twenty-front/src/pages/auth/__stories__/Invite.stories.tsx index c90f7c968807..3d35bb0b14e5 100644 --- a/packages/twenty-front/src/pages/auth/__stories__/Invite.stories.tsx +++ b/packages/twenty-front/src/pages/auth/__stories__/Invite.stories.tsx @@ -33,7 +33,7 @@ const meta: Meta<PageDecoratorArgs> = { findWorkspaceFromInviteHash: { __typename: 'Workspace', id: '20202020-91f0-46d0-acab-cb5afef3cc3b', - displayName: 'Funnelmink dev', + displayName: 'Twenty dev', logo: null, allowImpersonation: false, }, @@ -73,7 +73,9 @@ export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Join Funnelmink dev team'); + await canvas.findByText('Join Twenty dev team', undefined, { + timeout: 5000, + }); const continueWithEmailButton = await canvas.findByText( 'Continue With Email', diff --git a/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx b/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx index ea98157a1e4a..79bf50e0a327 100644 --- a/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx +++ b/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx @@ -1,7 +1,7 @@ import { getOperationName } from '@apollo/client/utilities'; import { Meta, StoryObj } from '@storybook/react'; import { within } from '@storybook/test'; -import { graphql, HttpResponse } from 'msw'; +import { HttpResponse, graphql } from 'msw'; import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser'; import { @@ -65,6 +65,8 @@ export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Reset Password'); + await canvas.findByText('Reset Password', undefined, { + timeout: 3000, + }); }, }; diff --git a/packages/twenty-front/src/pages/not-found/__stories__/NotFound.stories.tsx b/packages/twenty-front/src/pages/not-found/__stories__/NotFound.stories.tsx index 914814e01acd..81a468927489 100644 --- a/packages/twenty-front/src/pages/not-found/__stories__/NotFound.stories.tsx +++ b/packages/twenty-front/src/pages/not-found/__stories__/NotFound.stories.tsx @@ -1,23 +1,17 @@ import { Meta, StoryObj } from '@storybook/react'; import { within } from '@storybook/test'; -import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; -import { HelmetProviderDecorator } from '~/testing/decorators/HelmetProviderDecorator'; -import { PageDecoratorArgs } from '~/testing/decorators/PageDecorator'; -import { RelationPickerDecorator } from '~/testing/decorators/RelationPickerDecorator'; -import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; +import { + PageDecorator, + PageDecoratorArgs, +} from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; import { NotFound } from '../NotFound'; const meta: Meta<PageDecoratorArgs> = { title: 'Pages/NotFound/Default', component: NotFound, - decorators: [ - HelmetProviderDecorator, - ComponentWithRouterDecorator, - SnackBarDecorator, - RelationPickerDecorator, - ], + decorators: [PageDecorator], args: { routePath: '/toto-not-found', }, diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 2df55058eb82..edb11865dcda 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -1,16 +1,18 @@ import styled from '@emotion/styled'; import { useParams } from 'react-router-dom'; -import { v4 } from 'uuid'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; +import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer'; import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader'; -import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2'; -import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode'; +import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext'; +import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick'; +import { useCreateNewTableRecord } from '@/object-record/record-table/hooks/useCreateNewTableRecords'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; +import { useRecoilCallback } from 'recoil'; import { capitalize } from '~/utils/string/capitalize'; const StyledIndexContainer = styled.div` @@ -23,35 +25,55 @@ export const RecordIndexPage = () => { const objectNamePlural = useParams().objectNamePlural ?? ''; const recordIndexId = objectNamePlural ?? ''; - const setHotkeyScope = useSetHotkeyScope(); - const { setSelectedTableCellEditMode } = useSelectedTableCellEditMode({ - scopeId: recordIndexId, + const { objectNameSingular } = useObjectNameSingularFromPlural({ + objectNamePlural, }); - const { setPendingRecordId } = useRecordTable({ - recordTableId: recordIndexId, + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular, }); - const handleAddButtonClick = async () => { - setPendingRecordId(v4()); - setSelectedTableCellEditMode(-1, 0); - setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes); + const { createNewTableRecord } = useCreateNewTableRecord(recordIndexId); + + const handleCreateRecord = () => { + createNewTableRecord(); }; + const { handleIndexIdentifierClick } = useHandleIndexIdentifierClick({ + objectMetadataItem, + recordIndexId, + }); + + const handleIndexRecordsLoaded = useRecoilCallback( + ({ set }) => + () => { + // TODO: find a better way to reset this state ? + set(lastShowPageRecordIdState, null); + }, + [], + ); + return ( <PageContainer> - <PageTitle title={`${capitalize(objectNamePlural)}`} /> - <RecordIndexPageHeader createRecord={handleAddButtonClick} /> - <PageBody> - <StyledIndexContainer> - <RecordIndexContainer - recordIndexId={recordIndexId} - objectNamePlural={objectNamePlural} - createRecord={handleAddButtonClick} - /> - </StyledIndexContainer> - </PageBody> + <RecordIndexRootPropsContext.Provider + value={{ + recordIndexId, + objectNamePlural, + objectNameSingular, + onIndexRecordsLoaded: handleIndexRecordsLoaded, + onIndexIdentifierClick: handleIndexIdentifierClick, + onCreateRecord: handleCreateRecord, + }} + > + <PageTitle title={`${capitalize(objectNamePlural)}`} /> + <RecordIndexPageHeader /> + <PageBody> + <StyledIndexContainer> + <RecordIndexContainer /> + </StyledIndexContainer> + </PageBody> + </RecordIndexRootPropsContext.Provider> </PageContainer> ); }; diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx index 30e73dad46ea..3f697c21f07a 100644 --- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx @@ -1,16 +1,16 @@ import { useParams } from 'react-router-dom'; import { TimelineActivityContext } from '@/activities/timelineActivities/contexts/TimelineActivityContext'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage'; import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton'; -import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton'; -import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton'; import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; +import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader'; +import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader'; import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader'; export const RecordShowPage = () => { @@ -46,22 +46,21 @@ export const RecordShowPage = () => { headerIcon={headerIcon} > <> - <PageFavoriteButton - isFavorite={isFavorite} - onClick={handleFavoriteButtonClick} - /> - <ShowPageAddButton - key="add" - activityTargetObject={{ - id: record?.id ?? '0', - targetObjectNameSingular: objectMetadataItem?.nameSingular, - }} - /> - <ShowPageMoreButton - key="more" - recordId={record?.id ?? '0'} - objectNameSingular={objectNameSingular} - /> + {objectNameSingular === CoreObjectNameSingular.Workflow ? ( + <RecordShowPageWorkflowHeader + workflowId={parameters.objectRecordId} + /> + ) : ( + <RecordShowPageBaseHeader + {...{ + isFavorite, + handleFavoriteButtonClick, + record, + objectMetadataItem, + objectNameSingular, + }} + /> + )} </> </RecordShowPageHeader> <PageBody> diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPageBaseHeader.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPageBaseHeader.tsx new file mode 100644 index 000000000000..a7577114c092 --- /dev/null +++ b/packages/twenty-front/src/pages/object-record/RecordShowPageBaseHeader.tsx @@ -0,0 +1,40 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton'; +import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton'; +import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton'; + +export const RecordShowPageBaseHeader = ({ + isFavorite, + handleFavoriteButtonClick, + record, + objectMetadataItem, + objectNameSingular, +}: { + isFavorite: boolean; + handleFavoriteButtonClick: () => void; + record: ObjectRecord | undefined; + objectMetadataItem: ObjectMetadataItem; + objectNameSingular: string; +}) => { + return ( + <> + <PageFavoriteButton + isFavorite={isFavorite} + onClick={handleFavoriteButtonClick} + /> + <ShowPageAddButton + key="add" + activityTargetObject={{ + id: record?.id ?? '0', + targetObjectNameSingular: objectMetadataItem.nameSingular, + }} + /> + <ShowPageMoreButton + key="more" + recordId={record?.id ?? '0'} + objectNameSingular={objectNameSingular} + /> + </> + ); +}; diff --git a/packages/twenty-front/src/pages/object-record/__stories__/RecordIndexPage.stories.tsx b/packages/twenty-front/src/pages/object-record/__stories__/RecordIndexPage.stories.tsx index 465b931c6108..76b559961c5a 100644 --- a/packages/twenty-front/src/pages/object-record/__stories__/RecordIndexPage.stories.tsx +++ b/packages/twenty-front/src/pages/object-record/__stories__/RecordIndexPage.stories.tsx @@ -32,9 +32,7 @@ export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('People'); - await canvas.findAllByText('Companies'); - await canvas.findByText('Opportunities'); - await canvas.findByText('My Customs'); + await canvas.findByText('People', undefined, { timeout: 3000 }); + await canvas.findByText('Linkedin'); }, }; diff --git a/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx b/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx index 62e6f4112f08..5f1b8c02129d 100644 --- a/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx +++ b/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx @@ -89,8 +89,8 @@ export const Default: Story = { // await canvas.findAllByText(peopleMock[0].name.firstName); expect( - await canvas.findByText('Funnelmink', undefined, { - timeout: 3000, + await canvas.findByText('Twenty', undefined, { + timeout: 5000, }), ).toBeInTheDocument(); expect( diff --git a/packages/twenty-front/src/pages/onboarding/InviteTeam.tsx b/packages/twenty-front/src/pages/onboarding/InviteTeam.tsx index 53a7b212494c..63cd583ec04a 100644 --- a/packages/twenty-front/src/pages/onboarding/InviteTeam.tsx +++ b/packages/twenty-front/src/pages/onboarding/InviteTeam.tsx @@ -1,3 +1,6 @@ +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { zodResolver } from '@hookform/resolvers/zod'; import { useCallback } from 'react'; import { Controller, @@ -5,9 +8,6 @@ import { useFieldArray, useForm, } from 'react-hook-form'; -import { useTheme } from '@emotion/react'; -import styled from '@emotion/styled'; -import { zodResolver } from '@hookform/resolvers/zod'; import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { IconCopy } from 'twenty-ui'; @@ -27,11 +27,9 @@ import { MainButton } from '@/ui/input/button/components/MainButton'; import { TextInputV2 } from '@/ui/input/components/TextInputV2'; import { AnimatedTranslation } from '@/ui/utilities/animation/components/AnimatedTranslation'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; -import { - OnboardingStatus, - useSendInviteLinkMutation, -} from '~/generated/graphql'; +import { OnboardingStatus } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; +import { useCreateWorkspaceInvitation } from '../../modules/workspace-invitation/hooks/useCreateWorkspaceInvitation'; const StyledAnimatedContainer = styled.div` display: flex; @@ -65,7 +63,8 @@ type FormInput = z.infer<typeof validationSchema>; export const InviteTeam = () => { const theme = useTheme(); const { enqueueSnackBar } = useSnackBar(); - const [sendInviteLink] = useSendInviteLinkMutation(); + const { sendInvitation } = useCreateWorkspaceInvitation(); + const setNextOnboardingStatus = useSetNextOnboardingStatus(); const currentUser = useRecoilValue(currentUserState); const currentWorkspace = useRecoilValue(currentWorkspaceState); @@ -102,15 +101,15 @@ export const InviteTeam = () => { const getPlaceholder = (emailIndex: number) => { if (emailIndex === 0) { - return 'tim@apple.dev'; + return 'tim@apple.com'; } if (emailIndex === 1) { - return 'craig@apple.dev'; + return 'phil@apple.com'; } if (emailIndex === 2) { - return 'mike@apple.dev'; + return 'jony@apple.com'; } - return 'phil@apple.dev'; + return 'craig@apple.com'; }; const copyInviteLink = () => { @@ -134,7 +133,7 @@ export const InviteTeam = () => { .filter((email) => email.length > 0), ), ); - const result = await sendInviteLink({ variables: { emails } }); + const result = await sendInvitation({ emails }); setNextOnboardingStatus(); @@ -148,7 +147,7 @@ export const InviteTeam = () => { }); } }, - [enqueueSnackBar, sendInviteLink, setNextOnboardingStatus], + [enqueueSnackBar, sendInvitation, setNextOnboardingStatus], ); useScopedHotkeys( diff --git a/packages/twenty-front/src/pages/onboarding/__stories__/ChooseYourPlan.stories.tsx b/packages/twenty-front/src/pages/onboarding/__stories__/ChooseYourPlan.stories.tsx index b42177fedd01..952a6e501c12 100644 --- a/packages/twenty-front/src/pages/onboarding/__stories__/ChooseYourPlan.stories.tsx +++ b/packages/twenty-front/src/pages/onboarding/__stories__/ChooseYourPlan.stories.tsx @@ -1,7 +1,7 @@ import { getOperationName } from '@apollo/client/utilities'; import { Meta, StoryObj } from '@storybook/react'; import { within } from '@storybook/testing-library'; -import { graphql, HttpResponse } from 'msw'; +import { HttpResponse, graphql } from 'msw'; import { AppPath } from '@/types/AppPath'; import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser'; @@ -13,7 +13,6 @@ import { } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; import { mockedOnboardingUserData } from '~/testing/mock-data/users'; -import { sleep } from '~/utils/sleep'; const meta: Meta<PageDecoratorArgs> = { title: 'Pages/Onboarding/ChooseYourPlan', @@ -70,8 +69,9 @@ export type Story = StoryObj<typeof ChooseYourPlan>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - sleep(100); - await canvas.findByText('Choose your Plan'); + await canvas.findByText('Choose your Plan', undefined, { + timeout: 3000, + }); }, }; diff --git a/packages/twenty-front/src/pages/settings/Releases.tsx b/packages/twenty-front/src/pages/settings/Releases.tsx index 2ecd949d7e09..60845a1b8c5f 100644 --- a/packages/twenty-front/src/pages/settings/Releases.tsx +++ b/packages/twenty-front/src/pages/settings/Releases.tsx @@ -3,18 +3,16 @@ import React, { useEffect, useState } from 'react'; import rehypeStringify from 'rehype-stringify'; import remarkParse from 'remark-parse'; import remarkRehype from 'remark-rehype'; -import { H1Title, IconRocket } from 'twenty-ui'; +import { IconRocket } from 'twenty-ui'; import { unified } from 'unified'; import { visit } from 'unist-util-visit'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -const StyledH1Title = styled(H1Title)` - margin-bottom: 0; -`; - type ReleaseNote = { slug: string; date: string; @@ -85,7 +83,7 @@ export const Releases = () => { const [releases, setReleases] = useState<ReleaseNote[]>([]); useEffect(() => { - fetch('https://funnelmink.com/api/releases').then(async (res) => { + fetch('https://twenty.com/api/releases').then(async (res) => { const json = await res.json(); for (const release of json) { release.html = String( @@ -108,9 +106,20 @@ export const Releases = () => { }, []); return ( - <SubMenuTopBarContainer Icon={IconRocket} title="Releases"> + <SubMenuTopBarContainer + Icon={IconRocket} + title="Releases" + links={[ + { + children: 'Others', + href: getSettingsPagePath(SettingsPath.Releases), + }, + { + children: 'Releases', + }, + ]} + > <SettingsPageContainer> - <StyledH1Title title="Releases" /> <ScrollWrapper contextProviderName="releases"> <StyledReleaseContainer> {releases.map((release) => ( diff --git a/packages/twenty-front/src/pages/settings/SettingsBilling.tsx b/packages/twenty-front/src/pages/settings/SettingsBilling.tsx index e184ec40c883..ee057b7114a7 100644 --- a/packages/twenty-front/src/pages/settings/SettingsBilling.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsBilling.tsx @@ -14,7 +14,9 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage'; import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; +import { SettingsPath } from '@/types/SettingsPath'; import { Info } from '@/ui/display/info/components/Info'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; @@ -140,7 +142,17 @@ export const SettingsBilling = () => { }; return ( - <SubMenuTopBarContainer Icon={IconCurrencyDollar} title="Billing"> + <SubMenuTopBarContainer + Icon={IconCurrencyDollar} + title="Billing" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Billing' }, + ]} + > <SettingsPageContainer> <StyledH1Title title="Billing" /> <SettingsBillingCoverImage /> diff --git a/packages/twenty-front/src/pages/settings/SettingsProfile.tsx b/packages/twenty-front/src/pages/settings/SettingsProfile.tsx index 07202b6fa42f..86b0e5637320 100644 --- a/packages/twenty-front/src/pages/settings/SettingsProfile.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsProfile.tsx @@ -6,11 +6,23 @@ import { DeleteAccount } from '@/settings/profile/components/DeleteAccount'; import { EmailField } from '@/settings/profile/components/EmailField'; import { NameFields } from '@/settings/profile/components/NameFields'; import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; export const SettingsProfile = () => ( - <SubMenuTopBarContainer Icon={IconUserCircle} title="Profile"> + <SubMenuTopBarContainer + Icon={IconUserCircle} + title="Profile" + links={[ + { + children: 'User', + href: getSettingsPagePath(SettingsPath.ProfilePage), + }, + { children: 'Profile' }, + ]} + > <SettingsPageContainer> <Section> <H2Title title="Picture" /> diff --git a/packages/twenty-front/src/pages/settings/SettingsWorkspace.tsx b/packages/twenty-front/src/pages/settings/SettingsWorkspace.tsx index b9d7f3cd6f82..35b90896203f 100644 --- a/packages/twenty-front/src/pages/settings/SettingsWorkspace.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsWorkspace.tsx @@ -2,14 +2,26 @@ import { H2Title, IconSettings } from 'twenty-ui'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { DeleteWorkspace } from '@/settings/profile/components/DeleteWorkspace'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { NameField } from '@/settings/workspace/components/NameField'; import { ToggleImpersonate } from '@/settings/workspace/components/ToggleImpersonate'; import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; export const SettingsWorkspace = () => ( - <SubMenuTopBarContainer Icon={IconSettings} title="General"> + <SubMenuTopBarContainer + Icon={IconSettings} + title="General" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'General' }, + ]} + > <SettingsPageContainer> <Section> <H2Title title="Picture" /> diff --git a/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx b/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx index 2408fd380d6b..0079fb888501 100644 --- a/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsWorkspaceMembers.tsx @@ -1,7 +1,17 @@ import styled from '@emotion/styled'; import { useState } from 'react'; -import { useRecoilValue } from 'recoil'; -import { H2Title, IconTrash, IconUsers } from 'twenty-ui'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { + H2Title, + IconTrash, + IconUsers, + IconReload, + IconMail, + StyledText, + Avatar, +} from 'twenty-ui'; +import { isNonEmptyArray } from '@sniptt/guards'; +import { useTheme } from '@emotion/react'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; @@ -9,6 +19,8 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { IconButton } from '@/ui/input/button/components/IconButton'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; @@ -16,7 +28,19 @@ import { Section } from '@/ui/layout/section/components/Section'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink'; import { WorkspaceInviteTeam } from '@/workspace/components/WorkspaceInviteTeam'; -import { WorkspaceMemberCard } from '@/workspace/components/WorkspaceMemberCard'; +import { useGetWorkspaceInvitationsQuery } from '~/generated/graphql'; +import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { Table } from '@/ui/layout/table/components/Table'; +import { TableHeader } from '@/ui/layout/table/components/TableHeader'; +import { workspaceInvitationsState } from '../../modules/workspace-invitation/states/workspaceInvitationsStates'; +import { TableRow } from '../../modules/ui/layout/table/components/TableRow'; +import { TableCell } from '../../modules/ui/layout/table/components/TableCell'; +import { Status } from '../../modules/ui/display/status/components/Status'; +import { formatDistanceToNow } from 'date-fns'; +import { useResendWorkspaceInvitation } from '../../modules/workspace-invitation/hooks/useResendWorkspaceInvitation'; +import { isDefined } from '~/utils/isDefined'; +import { useDeleteWorkspaceInvitation } from '../../modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation'; const StyledButtonContainer = styled.div` align-items: center; @@ -25,7 +49,17 @@ const StyledButtonContainer = styled.div` margin-left: ${({ theme }) => theme.spacing(3)}; `; +const StyledTable = styled(Table)` + margin-top: ${({ theme }) => theme.spacing(0.5)}; +`; + +const StyledTableHeaderRow = styled(Table)` + margin-bottom: ${({ theme }) => theme.spacing(1.5)}; +`; + export const SettingsWorkspaceMembers = () => { + const { enqueueSnackBar } = useSnackBar(); + const theme = useTheme(); const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false); const [workspaceMemberToDelete, setWorkspaceMemberToDelete] = useState< string | undefined @@ -37,6 +71,10 @@ export const SettingsWorkspaceMembers = () => { const { deleteOneRecord: deleteOneWorkspaceMember } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.WorkspaceMember, }); + + const { resendInvitation } = useResendWorkspaceInvitation(); + const { deleteWorkspaceInvitation } = useDeleteWorkspaceInvitation(); + const currentWorkspace = useRecoilValue(currentWorkspaceState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); @@ -45,21 +83,65 @@ export const SettingsWorkspaceMembers = () => { setIsConfirmationModalOpen(false); }; + const workspaceInvitations = useRecoilValue(workspaceInvitationsState); + const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState); + + useGetWorkspaceInvitationsQuery({ + onError: (error: Error) => { + enqueueSnackBar(error.message, { + variant: SnackBarVariant.Error, + }); + }, + onCompleted: (data) => { + setWorkspaceInvitations(data?.findWorkspaceInvitations ?? []); + }, + }); + + const handleRemoveWorkspaceInvitation = async (appTokenId: string) => { + const result = await deleteWorkspaceInvitation({ appTokenId }); + if (isDefined(result.errors)) { + enqueueSnackBar('Error deleting invitation', { + variant: SnackBarVariant.Error, + duration: 2000, + }); + } + }; + + const handleResendWorkspaceInvitation = async (appTokenId: string) => { + const result = await resendInvitation({ appTokenId }); + if (isDefined(result.errors)) { + enqueueSnackBar('Error resending invitation', { + variant: SnackBarVariant.Error, + duration: 2000, + }); + } + }; + + const getExpiresAtText = (expiresAt: string) => { + const expiresAtDate = new Date(expiresAt); + return expiresAtDate < new Date() + ? 'Expired' + : formatDistanceToNow(new Date(expiresAt)); + }; + return ( - <SubMenuTopBarContainer Icon={IconUsers} title="Members"> + <SubMenuTopBarContainer + Icon={IconUsers} + title="Members" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Members' }, + ]} + > <SettingsPageContainer> - <Section> - <H2Title - title="Invite by email" - description="Send an invite email to your team" - /> - <WorkspaceInviteTeam /> - </Section> {currentWorkspace?.inviteHash && ( <Section> <H2Title - title="Or send an invite link" - description="Copy and send an invite link directly" + title="Invite by link" + description="Share this link to invite users to join your workspace" /> <WorkspaceInviteLink inviteLink={`${window.location.origin}/invite/${currentWorkspace?.inviteHash}`} @@ -71,27 +153,125 @@ export const SettingsWorkspaceMembers = () => { title="Members" description="Manage the members of your space here" /> - {workspaceMembers?.map((member) => ( - <WorkspaceMemberCard - key={member.id} - workspaceMember={member as WorkspaceMember} - accessory={ - currentWorkspaceMember?.id !== member.id && ( - <StyledButtonContainer> - <IconButton - onClick={() => { - setIsConfirmationModalOpen(true); - setWorkspaceMemberToDelete(member.id); - }} - variant="tertiary" - size="medium" - Icon={IconTrash} + <Table> + <StyledTableHeaderRow> + <TableRow> + <TableHeader>Name</TableHeader> + <TableHeader>Email</TableHeader> + <TableHeader align={'right'}></TableHeader> + </TableRow> + </StyledTableHeaderRow> + {workspaceMembers?.map((workspaceMember) => ( + <StyledTable key={workspaceMember.id}> + <TableRow> + <TableCell> + <StyledText + PrefixComponent={ + <Avatar + avatarUrl={workspaceMember.avatarUrl} + placeholderColorSeed={workspaceMember.id} + placeholder={workspaceMember.name.firstName ?? ''} + type="rounded" + size="sm" + /> + } + text={ + workspaceMember.name.firstName + + ' ' + + workspaceMember.name.lastName + } /> - </StyledButtonContainer> - ) - } - /> - ))} + </TableCell> + <TableCell> + <StyledText + text={workspaceMember.userEmail} + color={theme.font.color.secondary} + /> + </TableCell> + <TableCell align={'right'}> + {currentWorkspaceMember?.id !== workspaceMember.id && ( + <StyledButtonContainer> + <IconButton + onClick={() => { + setIsConfirmationModalOpen(true); + setWorkspaceMemberToDelete(workspaceMember.id); + }} + variant="tertiary" + size="medium" + Icon={IconTrash} + /> + </StyledButtonContainer> + )} + </TableCell> + </TableRow> + </StyledTable> + ))} + </Table> + </Section> + <Section> + <H2Title + title="Invite by email" + description="Send an invite email to your team" + /> + <WorkspaceInviteTeam /> + {isNonEmptyArray(workspaceInvitations) && ( + <Table> + <StyledTableHeaderRow> + <TableRow gridAutoColumns={`1fr 1fr ${theme.spacing(22)}`}> + <TableHeader>Email</TableHeader> + <TableHeader align={'right'}>Expires in</TableHeader> + <TableHeader></TableHeader> + </TableRow> + </StyledTableHeaderRow> + {workspaceInvitations?.map((workspaceInvitation) => ( + <StyledTable key={workspaceInvitation.id}> + <TableRow gridAutoColumns={`1fr 1fr ${theme.spacing(22)}`}> + <TableCell> + <StyledText + PrefixComponent={ + <IconMail + size={theme.icon.size.md} + stroke={theme.icon.stroke.sm} + /> + } + text={workspaceInvitation.email} + /> + </TableCell> + <TableCell align={'right'}> + <Status + color={'gray'} + text={getExpiresAtText(workspaceInvitation.expiresAt)} + /> + </TableCell> + <TableCell align={'right'}> + <StyledButtonContainer> + <IconButton + onClick={() => { + handleResendWorkspaceInvitation( + workspaceInvitation.id, + ); + }} + variant="tertiary" + size="medium" + Icon={IconReload} + /> + <IconButton + onClick={() => { + handleRemoveWorkspaceInvitation( + workspaceInvitation.id, + ); + }} + variant="tertiary" + size="medium" + Icon={IconTrash} + /> + </StyledButtonContainer> + </TableCell> + </TableRow> + </StyledTable> + ))} + </Table> + )} </Section> </SettingsPageContainer> <ConfirmationModal diff --git a/packages/twenty-front/src/pages/settings/__stories__/SettingsAppearance.stories.tsx b/packages/twenty-front/src/pages/settings/__stories__/SettingsAppearance.stories.tsx index 5ad191a10a57..1aa66449abcc 100644 --- a/packages/twenty-front/src/pages/settings/__stories__/SettingsAppearance.stories.tsx +++ b/packages/twenty-front/src/pages/settings/__stories__/SettingsAppearance.stories.tsx @@ -6,8 +6,11 @@ import { } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { userEvent, within } from '@storybook/test'; import { SettingsAppearance } from '../profile/appearance/components/SettingsAppearance'; +Date.now = () => new Date('2022-06-13T12:33:37.000Z').getTime(); + const meta: Meta<PageDecoratorArgs> = { title: 'Pages/Settings/SettingsAppearance', component: SettingsAppearance, @@ -15,6 +18,7 @@ const meta: Meta<PageDecoratorArgs> = { args: { routePath: '/settings/appearance' }, parameters: { msw: graphqlMocks, + date: new Date(2021, 1, 1), }, }; @@ -22,4 +26,72 @@ export default meta; export type Story = StoryObj<typeof SettingsAppearance>; -export const Default: Story = {}; +export const Default: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await canvas.findByText('Appearance', undefined, { + timeout: 3000, + }); + + await canvas.findByText('Date and time'); + }, +}; + +export const DateTimeSettingsTimezone: Story = { + play: async () => { + const canvas = within(document.body); + + await canvas.findByText('Date and time'); + + const timezoneSelect = await canvas.findByText( + '(GMT-04:00) Eastern Daylight Time - New York', + ); + + userEvent.click(timezoneSelect); + + const systemSettingsOptions = await canvas.findByText( + '(GMT-11:00) Niue Time', + ); + + userEvent.click(systemSettingsOptions); + + await canvas.findByText('(GMT-11:00) Niue Time'); + }, +}; + +export const DateTimeSettingsDateFormat: Story = { + play: async () => { + const canvas = within(document.body); + + await canvas.findByText('Date and time'); + + const timeFormatSelect = await canvas.findByText('13 Jun, 2022'); + + userEvent.click(timeFormatSelect); + + const timeFormatOptions = await canvas.findByText('Jun 13, 2022'); + + userEvent.click(timeFormatOptions); + + await canvas.findByText('Jun 13, 2022'); + }, +}; + +export const DateTimeSettingsTimeFormat: Story = { + play: async () => { + const canvas = within(document.body); + + await canvas.findByText('Date and time'); + + const timeFormatSelect = await canvas.findByText('24h (08:33)'); + + userEvent.click(timeFormatSelect); + + const timeFormatOptions = await canvas.findByText('12h (8:33 AM)'); + + userEvent.click(timeFormatOptions); + + await canvas.findByText('12h (8:33 AM)'); + }, +}; diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx index c9fa96c6c404..ed1ad2713231 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx @@ -12,9 +12,10 @@ import { SettingsAccountsBlocklistSection } from '@/settings/accounts/components import { SettingsAccountsConnectedAccountsListCard } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsListCard'; import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; export const SettingsAccounts = () => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); @@ -33,10 +34,18 @@ export const SettingsAccounts = () => { recordGqlFields: generateDepthOneRecordGqlFields({ objectMetadataItem }), }); - const isBlocklistEnabled = useIsFeatureEnabled('IS_BLOCKLIST_ENABLED'); - return ( - <SubMenuTopBarContainer Icon={IconAt} title="Account"> + <SubMenuTopBarContainer + Icon={IconAt} + title="Account" + links={[ + { + children: 'User', + href: getSettingsPagePath(SettingsPath.ProfilePage), + }, + { children: 'Account' }, + ]} + > <SettingsPageContainer> {loading ? ( <SettingsAccountLoader /> @@ -52,7 +61,7 @@ export const SettingsAccounts = () => { loading={loading} /> </Section> - {isBlocklistEnabled && <SettingsAccountsBlocklistSection />} + <SettingsAccountsBlocklistSection /> <SettingsAccountsSettingsSection /> </> )} diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx index f2e93d234ecc..ff4a6cd6ac29 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsCalendars.tsx @@ -4,24 +4,24 @@ import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { IconCalendarEvent } from 'twenty-ui'; export const SettingsAccountsCalendars = () => { return ( <SubMenuTopBarContainer Icon={IconCalendarEvent} - title={ - <Breadcrumb - links={[ - { - children: 'Accounts', - href: getSettingsPagePath(SettingsPath.Accounts), - }, - { children: 'Calendars' }, - ]} - /> - } + title="Calendars" + links={[ + { + children: 'User', + href: getSettingsPagePath(SettingsPath.ProfilePage), + }, + { + children: 'Accounts', + href: getSettingsPagePath(SettingsPath.Accounts), + }, + { children: 'Calendars' }, + ]} > <SettingsPageContainer> <Section> diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx index 11af16608aef..6e2d574b95d4 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmails.tsx @@ -1,21 +1,26 @@ import { SettingsAccountsMessageChannelsContainer } from '@/settings/accounts/components/SettingsAccountsMessageChannelsContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { IconMail } from 'twenty-ui'; export const SettingsAccountsEmails = () => ( <SubMenuTopBarContainer Icon={IconMail} - title={ - <Breadcrumb - links={[ - { children: 'Accounts', href: '/settings/accounts' }, - { children: 'Emails' }, - ]} - /> - } + title="Emails" + links={[ + { + children: 'User', + href: getSettingsPagePath(SettingsPath.ProfilePage), + }, + { + children: 'Accounts', + href: getSettingsPagePath(SettingsPath.Accounts), + }, + { children: 'Emails' }, + ]} > <SettingsPageContainer> <Section> diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsNewAccount.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsNewAccount.tsx index 69465ef5e579..440ebedb93a9 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsNewAccount.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsNewAccount.tsx @@ -1,21 +1,26 @@ import { SettingsNewAccountSection } from '@/settings/accounts/components/SettingsNewAccountSection'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { IconAt } from 'twenty-ui'; export const SettingsNewAccount = () => { return ( <SubMenuTopBarContainer Icon={IconAt} - title={ - <Breadcrumb - links={[ - { children: 'Accounts', href: '/settings/accounts' }, - { children: `New` }, - ]} - /> - } + title="New Account" + links={[ + { + children: 'User', + href: getSettingsPagePath(SettingsPath.ProfilePage), + }, + { + children: 'Accounts', + href: getSettingsPagePath(SettingsPath.Accounts), + }, + { children: `New` }, + ]} > <SettingsPageContainer> <SettingsNewAccountSection /> diff --git a/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccounts.stories.tsx b/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccounts.stories.tsx index 747a43b24a25..402d9408cd73 100644 --- a/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccounts.stories.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/__stories__/SettingsAccounts.stories.tsx @@ -30,6 +30,8 @@ export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Connected accounts'); + await canvas.findByText('Connected accounts', undefined, { + timeout: 3000, + }); }, }; diff --git a/packages/twenty-front/src/pages/settings/crm-migration/SettingsCRMMigration.tsx b/packages/twenty-front/src/pages/settings/crm-migration/SettingsCRMMigration.tsx index 4b6c98be095f..5794ee4ae4e0 100644 --- a/packages/twenty-front/src/pages/settings/crm-migration/SettingsCRMMigration.tsx +++ b/packages/twenty-front/src/pages/settings/crm-migration/SettingsCRMMigration.tsx @@ -6,9 +6,10 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { useRecoilValue } from 'recoil'; const REVERT_PUBLIC_KEY = 'pk_live_a87fee8c-28c7-494f-99a3-996ff89f9918'; @@ -18,7 +19,14 @@ export const SettingsCRMMigration = () => { return ( <SubMenuTopBarContainer Icon={IconSettings} - title={<Breadcrumb links={[{ children: 'Migrate' }]} />} + title="Migrate" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Migrate' }, + ]} actionButton={<SettingsReadDocumentationButton />} > <SettingsPageContainer> diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx index 0b40a39d8723..f3ddd5440865 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx @@ -7,7 +7,6 @@ import { z } from 'zod'; import { useCreateOneObjectMetadataItem } from '@/object-metadata/hooks/useCreateOneObjectMetadataItem'; import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; -import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsDataModelObjectAboutForm, @@ -20,7 +19,6 @@ import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/Snac import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; const newObjectFormSchema = settingsDataModelObjectAboutFormSchema; @@ -72,17 +70,18 @@ export const SettingsNewObject = () => { <FormProvider {...formConfig}> <SubMenuTopBarContainer Icon={IconHierarchy2} - title={ - <Breadcrumb - links={[ - { - children: 'Objects', - href: settingsObjectsPagePath, - }, - { children: 'New' }, - ]} - /> - } + title="New Object" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Objects', + href: settingsObjectsPagePath, + }, + { children: 'New' }, + ]} actionButton={ <SaveAndCancelButtons isSaveDisabled={!canSave} @@ -93,7 +92,6 @@ export const SettingsNewObject = () => { } > <SettingsPageContainer> - <SettingsHeaderContainer></SettingsHeaderContainer> <Section> <H2Title title="About" diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPageContent.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPageContent.tsx index f7ca61f50492..c69c27507c54 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPageContent.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPageContent.tsx @@ -8,7 +8,6 @@ import { SettingsPath } from '@/types/SettingsPath'; import { Button } from '@/ui/input/button/components/Button'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink'; import styled from '@emotion/styled'; import { isNonEmptyArray } from '@sniptt/guards'; @@ -49,14 +48,15 @@ export const SettingsObjectDetailPageContent = ({ return ( <SubMenuTopBarContainer Icon={IconHierarchy2} - title={ - <Breadcrumb - links={[ - { children: 'Objects', href: '/settings/objects' }, - { children: objectMetadataItem.labelPlural }, - ]} - /> - } + title={objectMetadataItem.labelPlural} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Objects', href: '/settings/objects' }, + { children: objectMetadataItem.labelPlural }, + ]} > <SettingsPageContainer> <Section> diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectEdit.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectEdit.tsx index a5f7aca0c9e6..3596f9831b68 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectEdit.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectEdit.tsx @@ -13,7 +13,6 @@ import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdat import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; -import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsDataModelObjectAboutForm, @@ -30,7 +29,6 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { Button } from '@/ui/input/button/components/Button'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { isRequiredByFunnelmink } from '~/funnelmink/funnelmink-front-constants'; const objectEditFormSchema = z @@ -111,35 +109,36 @@ export const SettingsObjectEdit = () => { <FormProvider {...formConfig}> <SubMenuTopBarContainer Icon={IconHierarchy2} - title={ - <Breadcrumb - links={[ - { - children: 'Objects', - href: settingsObjectsPagePath, - }, - { - children: activeObjectMetadataItem.labelPlural, - href: `${settingsObjectsPagePath}/${objectSlug}`, - }, - { children: 'Edit' }, - ]} - /> + title="Edit" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Objects', + href: settingsObjectsPagePath, + }, + { + children: activeObjectMetadataItem.labelPlural, + href: `${settingsObjectsPagePath}/${objectSlug}`, + }, + { children: 'Edit Object' }, + ]} + actionButton={ + activeObjectMetadataItem.isCustom && ( + <SaveAndCancelButtons + isSaveDisabled={!canSave} + isCancelDisabled={isSubmitting} + onCancel={() => + navigate(`${settingsObjectsPagePath}/${objectSlug}`) + } + onSave={formConfig.handleSubmit(handleSave)} + /> + ) } > <SettingsPageContainer> - <SettingsHeaderContainer> - {activeObjectMetadataItem.isCustom && ( - <SaveAndCancelButtons - isSaveDisabled={!canSave} - isCancelDisabled={isSubmitting} - onCancel={() => - navigate(`${settingsObjectsPagePath}/${objectSlug}`) - } - onSave={formConfig.handleSubmit(handleSave)} - /> - )} - </SettingsHeaderContainer> <Section> <H2Title title="About" diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx index a05e522a3bfc..dd11d6dbb845 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx @@ -1,12 +1,16 @@ import { useApolloClient } from '@apollo/client'; -import styled from '@emotion/styled'; import { zodResolver } from '@hookform/resolvers/zod'; import omit from 'lodash.omit'; import pick from 'lodash.pick'; import { useEffect } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { useNavigate, useParams } from 'react-router-dom'; -import { H2Title, IconArchive, IconHierarchy2 } from 'twenty-ui'; +import { + H2Title, + IconArchive, + IconArchiveOff, + IconHierarchy2, +} from 'twenty-ui'; import { z } from 'zod'; import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem'; @@ -22,17 +26,19 @@ import { RecordFieldValueSelectorContextProvider } from '@/object-record/record- import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { FIELD_NAME_MAXIMUM_LENGTH } from '@/settings/data-model/constants/FieldNameMaximumLength'; -import { SettingsDataModelFieldAboutForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm'; +import { SettingsDataModelFieldDescriptionForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm'; +import { SettingsDataModelFieldIconLabelForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm'; import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard'; -import { SettingsDataModelFieldTypeSelect } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect'; import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema'; +import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { Button } from '@/ui/input/button/components/Button'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isDefined } from '~/utils/isDefined'; @@ -40,12 +46,6 @@ type SettingsDataModelFieldEditFormValues = z.infer< ReturnType<typeof settingsFieldFormSchema> >; -const StyledSettingsObjectFieldTypeSelect = styled( - SettingsDataModelFieldTypeSelect, -)` - margin-bottom: ${({ theme }) => theme.spacing(4)}; -`; - const canPersistFieldMetadataItemUpdate = ( fieldMetadataItem: FieldMetadataItem, ) => { @@ -61,16 +61,15 @@ export const SettingsObjectFieldEdit = () => { const { enqueueSnackBar } = useSnackBar(); const { objectSlug = '', fieldSlug = '' } = useParams(); - const { findActiveObjectMetadataItemBySlug } = - useFilteredObjectMetadataItems(); + const { findObjectMetadataItemBySlug } = useFilteredObjectMetadataItems(); + + const objectMetadataItem = findObjectMetadataItemBySlug(objectSlug); - const activeObjectMetadataItem = - findActiveObjectMetadataItemBySlug(objectSlug); + const { deactivateMetadataField, activateMetadataField } = + useFieldMetadataItem(); - const { deactivateMetadataField } = useFieldMetadataItem(); - const activeMetadataField = activeObjectMetadataItem?.fields.find( - (metadataField) => - metadataField.isActive && getFieldSlug(metadataField) === fieldSlug, + const fieldMetadataItem = objectMetadataItem?.fields.find( + (fieldMetadataItem) => getFieldSlug(fieldMetadataItem) === fieldSlug, ); const getRelationMetadata = useGetRelationMetadata(); @@ -79,11 +78,11 @@ export const SettingsObjectFieldEdit = () => { const apolloClient = useApolloClient(); const { findManyRecordsQuery } = useFindManyRecordsQuery({ - objectNameSingular: activeObjectMetadataItem?.nameSingular || '', + objectNameSingular: objectMetadataItem?.nameSingular || '', }); const refetchRecords = async () => { - if (!activeObjectMetadataItem) return; + if (!objectMetadataItem) return; await apolloClient.query({ query: findManyRecordsQuery, fetchPolicy: 'network-only', @@ -93,22 +92,30 @@ export const SettingsObjectFieldEdit = () => { const formConfig = useForm<SettingsDataModelFieldEditFormValues>({ mode: 'onTouched', resolver: zodResolver(settingsFieldFormSchema()), + values: { + icon: fieldMetadataItem?.icon ?? 'Icon', + type: fieldMetadataItem?.type as SettingsSupportedFieldType, + label: fieldMetadataItem?.label ?? '', + description: fieldMetadataItem?.description, + }, }); useEffect(() => { - if (!activeObjectMetadataItem || !activeMetadataField) { + if (!objectMetadataItem || !fieldMetadataItem) { navigate(AppPath.NotFound); } - }, [activeMetadataField, activeObjectMetadataItem, navigate]); - - if (!activeObjectMetadataItem || !activeMetadataField) return null; + }, [fieldMetadataItem, objectMetadataItem, navigate]); const { isDirty, isValid, isSubmitting } = formConfig.formState; const canSave = isDirty && isValid && !isSubmitting; + if (!isDefined(objectMetadataItem) || !isDefined(fieldMetadataItem)) { + return null; + } + const isLabelIdentifier = isLabelIdentifierField({ - fieldMetadataItem: activeMetadataField, - objectMetadataItem: activeObjectMetadataItem, + fieldMetadataItem: fieldMetadataItem, + objectMetadataItem: objectMetadataItem, }); const handleSave = async ( @@ -124,7 +131,7 @@ export const SettingsObjectFieldEdit = () => { ) { const { relationFieldMetadataItem } = getRelationMetadata({ - fieldMetadataItem: activeMetadataField, + fieldMetadataItem: fieldMetadataItem, }) ?? {}; if (isDefined(relationFieldMetadataItem)) { @@ -144,7 +151,7 @@ export const SettingsObjectFieldEdit = () => { ); await updateOneFieldMetadataItem({ - fieldMetadataIdToUpdate: activeMetadataField.id, + fieldMetadataIdToUpdate: fieldMetadataItem.id, updatePayload: formattedInput, }); } @@ -160,12 +167,17 @@ export const SettingsObjectFieldEdit = () => { }; const handleDeactivate = async () => { - await deactivateMetadataField(activeMetadataField); + await deactivateMetadataField(fieldMetadataItem); + navigate(`/settings/objects/${objectSlug}`); + }; + + const handleActivate = async () => { + await activateMetadataField(fieldMetadataItem); navigate(`/settings/objects/${objectSlug}`); }; const shouldDisplaySaveAndCancel = - canPersistFieldMetadataItemUpdate(activeMetadataField); + canPersistFieldMetadataItemUpdate(fieldMetadataItem); return ( <RecordFieldValueSelectorContextProvider> @@ -173,18 +185,24 @@ export const SettingsObjectFieldEdit = () => { <FormProvider {...formConfig}> <SubMenuTopBarContainer Icon={IconHierarchy2} - title={ - <Breadcrumb - links={[ - { children: 'Objects', href: '/settings/objects' }, - { - children: activeObjectMetadataItem.labelPlural, - href: `/settings/objects/${objectSlug}`, - }, - { children: activeMetadataField.label }, - ]} - /> - } + title={fieldMetadataItem?.label} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Objects', + href: '/settings/objects', + }, + { + children: objectMetadataItem.labelPlural, + href: `/settings/objects/${objectSlug}`, + }, + { + children: fieldMetadataItem.label, + }, + ]} actionButton={ shouldDisplaySaveAndCancel && ( <SaveAndCancelButtons @@ -199,32 +217,30 @@ export const SettingsObjectFieldEdit = () => { <SettingsPageContainer> <Section> <H2Title - title="Name and description" - description="The name and description of this field" + title="Icon and Name" + description="The name and icon of this field" /> - <SettingsDataModelFieldAboutForm - disabled={!activeMetadataField.isCustom} - fieldMetadataItem={activeMetadataField} + <SettingsDataModelFieldIconLabelForm + disabled={!fieldMetadataItem.isCustom} + fieldMetadataItem={fieldMetadataItem} maxLength={FIELD_NAME_MAXIMUM_LENGTH} /> </Section> <Section> - <H2Title - title="Type and values" - description="The field's type and values." + <H2Title title="Values" description="The values of this field" /> + <SettingsDataModelFieldSettingsFormCard + fieldMetadataItem={fieldMetadataItem} + objectMetadataItem={objectMetadataItem} /> - <StyledSettingsObjectFieldTypeSelect - disabled - fieldMetadataItem={activeMetadataField} - excludedFieldTypes={[ - FieldMetadataType.Link, - FieldMetadataType.Email, - ]} + </Section> + <Section> + <H2Title + title="Description" + description="The description of this field" /> - <SettingsDataModelFieldSettingsFormCard - disableCurrencyForm - fieldMetadataItem={activeMetadataField} - objectMetadataItem={activeObjectMetadataItem} + <SettingsDataModelFieldDescriptionForm + disabled={!fieldMetadataItem.isCustom} + fieldMetadataItem={fieldMetadataItem} /> </Section> {!isLabelIdentifier && ( @@ -234,10 +250,17 @@ export const SettingsObjectFieldEdit = () => { description="Deactivate this field" /> <Button - Icon={IconArchive} - title="Deactivate" + Icon={ + fieldMetadataItem.isActive ? IconArchive : IconArchiveOff + } + variant="secondary" + title={fieldMetadataItem.isActive ? 'Deactivate' : 'Activate'} size="small" - onClick={handleDeactivate} + onClick={ + fieldMetadataItem.isActive + ? handleDeactivate + : handleActivate + } /> </Section> )} diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx index 5830df05c91b..534ebc6ee5fd 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldTable.tsx @@ -78,6 +78,7 @@ const SETTINGS_OBJECT_DETAIL_TABLE_METADATA_CUSTOM: TableMetadata<SettingsObject }; const StyledSearchInput = styled(TextInput)` + padding-bottom: ${({ theme }) => theme.spacing(2)}; width: 100%; `; export type SettingsObjectFieldTableProps = { diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx index f2e18dc14f6a..d608e79967b7 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; -import { H2Title, IconPlus, IconSettings } from 'twenty-ui'; +import { H2Title, IconHierarchy2, IconPlus } from 'twenty-ui'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; @@ -9,11 +9,12 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem'; import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; +import { SettingsPath } from '@/types/SettingsPath'; import { Button } from '@/ui/input/button/components/Button'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { useRecoilState } from 'recoil'; import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable'; @@ -85,19 +86,19 @@ export const SettingsObjectNewFieldStep1 = () => { return ( <SubMenuTopBarContainer - Icon={IconSettings} - title={ - <Breadcrumb - links={[ - { children: 'Objects', href: '/settings/objects' }, - { - children: activeObjectMetadataItem.labelPlural, - href: `/settings/objects/${objectSlug}`, - }, - { children: 'New Field' }, - ]} - /> - } + Icon={IconHierarchy2} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Objects', href: '/settings/objects' }, + { + children: activeObjectMetadataItem.labelPlural, + href: `/settings/objects/${objectSlug}`, + }, + { children: 'New Field' }, + ]} actionButton={ !activeObjectMetadataItem.isRemote && ( <SaveAndCancelButtons diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx index 5a0ab678d23c..90a1e4d1020e 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx @@ -1,13 +1,3 @@ -import { useApolloClient } from '@apollo/client'; -import styled from '@emotion/styled'; -import { zodResolver } from '@hookform/resolvers/zod'; -import pick from 'lodash.pick'; -import { useEffect, useState } from 'react'; -import { FormProvider, useForm } from 'react-hook-form'; -import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; -import { H2Title, IconSettings } from 'twenty-ui'; -import { z } from 'zod'; - import { useCreateOneRelationMetadataItem } from '@/object-metadata/hooks/useCreateOneRelationMetadataItem'; import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; @@ -15,10 +5,11 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; -import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { SettingsDataModelNewFieldBreadcrumbDropDown } from '@/settings/data-model/components/SettingsDataModelNewFieldBreadcrumbDropDown'; import { FIELD_NAME_MAXIMUM_LENGTH } from '@/settings/data-model/constants/FieldNameMaximumLength'; -import { SettingsDataModelFieldAboutForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm'; +import { SettingsDataModelFieldDescriptionForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm'; +import { SettingsDataModelFieldIconLabelForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm'; import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard'; import { SettingsDataModelFieldTypeSelect } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect'; import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema'; @@ -28,9 +19,17 @@ import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/Snac import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { View } from '@/views/types/View'; import { ViewType } from '@/views/types/ViewType'; +import { useApolloClient } from '@apollo/client'; +import styled from '@emotion/styled'; +import { zodResolver } from '@hookform/resolvers/zod'; +import pick from 'lodash.pick'; +import { useEffect, useState } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import { H1Title, H1TitleFontColor, H2Title, IconHierarchy2 } from 'twenty-ui'; +import { z } from 'zod'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; @@ -39,12 +38,10 @@ type SettingsDataModelNewFieldFormValues = z.infer< ReturnType<typeof settingsFieldFormSchema> >; -const StyledSettingsObjectFieldTypeSelect = styled( - SettingsDataModelFieldTypeSelect, -)` - margin-bottom: ${({ theme }) => theme.spacing(4)}; +const StyledH1Title = styled(H1Title)` + margin-bottom: 0; + padding-top: ${({ theme }) => theme.spacing(3)}; `; - export const SettingsObjectNewFieldStep2 = () => { const navigate = useNavigate(); const { objectSlug = '' } = useParams(); @@ -52,6 +49,7 @@ export const SettingsObjectNewFieldStep2 = () => { const fieldType = searchParams.get('fieldType') as SettingsSupportedFieldType; const { enqueueSnackBar } = useSnackBar(); + const [isConfigureStep, setIsConfigureStep] = useState(false); const { findActiveObjectMetadataItemBySlug } = useFilteredObjectMetadataItems(); @@ -168,6 +166,7 @@ export const SettingsObjectNewFieldStep2 = () => { FieldMetadataType.RichText, FieldMetadataType.Actor, FieldMetadataType.Email, + FieldMetadataType.Phone, ] as const ).filter(isDefined); @@ -176,57 +175,97 @@ export const SettingsObjectNewFieldStep2 = () => { <FormProvider // eslint-disable-next-line react/jsx-props-no-spreading {...formConfig} > - <SubMenuTopBarContainer Icon={IconSettings} title="Settings"> - <SettingsPageContainer> - <SettingsHeaderContainer> - <Breadcrumb - links={[ - { children: 'Objects', href: '/settings/objects' }, - { - children: activeObjectMetadataItem.labelPlural, - href: `/settings/objects/${objectSlug}`, - }, - { children: 'New Field' }, - ]} - /> - {!activeObjectMetadataItem.isRemote && ( - <SaveAndCancelButtons - isSaveDisabled={!canSave} - isCancelDisabled={isSubmitting} - onCancel={() => navigate(`/settings/objects/${objectSlug}`)} - onSave={formConfig.handleSubmit(handleSave)} + <SubMenuTopBarContainer + Icon={IconHierarchy2} + links={[ + { + children: 'Objects', + href: '/settings/objects', + }, + { + children: activeObjectMetadataItem.labelPlural, + href: `/settings/objects/${objectSlug}`, + }, + { + children: ( + <SettingsDataModelNewFieldBreadcrumbDropDown + isConfigureStep={isConfigureStep} + onBreadcrumbClick={setIsConfigureStep} /> - )} - </SettingsHeaderContainer> - <Section> - <H2Title - title="Name and description" - description="The name and description of this field" - /> - <SettingsDataModelFieldAboutForm - maxLength={FIELD_NAME_MAXIMUM_LENGTH} - /> - </Section> - <Section> - <H2Title - title="Type and values" - description="The field's type and values." + ), + }, + ]} + actionButton={ + !activeObjectMetadataItem.isRemote && ( + <SaveAndCancelButtons + isSaveDisabled={!canSave} + isCancelDisabled={isSubmitting} + onCancel={() => { + if (!isConfigureStep) { + navigate(`/settings/objects/${objectSlug}`); + } else { + setIsConfigureStep(false); + } + }} + onSave={formConfig.handleSubmit(handleSave)} /> - <StyledSettingsObjectFieldTypeSelect + ) + } + > + <SettingsPageContainer> + <StyledH1Title + title={ + !isConfigureStep + ? '1. Select a field type' + : '2. Configure field' + } + fontColor={H1TitleFontColor.Primary} + /> + + {!isConfigureStep ? ( + <SettingsDataModelFieldTypeSelect excludedFieldTypes={excludedFieldTypes} fieldMetadataItem={{ type: fieldType, }} + onFieldTypeSelect={() => setIsConfigureStep(true)} /> - <SettingsDataModelFieldSettingsFormCard - fieldMetadataItem={{ - icon: formConfig.watch('icon'), - label: formConfig.watch('label') || 'Employees', - type: formConfig.watch('type'), - }} - objectMetadataItem={activeObjectMetadataItem} - /> - </Section> + ) : ( + <> + <Section> + <H2Title + title="Icon and Name" + description="The name and icon of this field" + /> + <SettingsDataModelFieldIconLabelForm + maxLength={FIELD_NAME_MAXIMUM_LENGTH} + /> + </Section> + <Section> + <H2Title + title="Values" + description="The values of this field" + /> + + <SettingsDataModelFieldSettingsFormCard + isCreatingField + fieldMetadataItem={{ + icon: formConfig.watch('icon'), + label: formConfig.watch('label') || 'Employees', + type: formConfig.watch('type'), + }} + objectMetadataItem={activeObjectMetadataItem} + /> + </Section> + <Section> + <H2Title + title="Description" + description="The description of this field" + /> + <SettingsDataModelFieldDescriptionForm /> + </Section> + </> + )} </SettingsPageContainer> </SubMenuTopBarContainer> </FormProvider> diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectOverview.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectOverview.tsx index a33ed73e4764..6adcb2a9db59 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectOverview.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectOverview.tsx @@ -1,24 +1,25 @@ import { ReactFlowProvider } from 'reactflow'; import { SettingsDataModelOverview } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverview'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { IconHierarchy2 } from 'twenty-ui'; export const SettingsObjectOverview = () => { return ( <SubMenuTopBarContainer Icon={IconHierarchy2} - title={ - <Breadcrumb - links={[ - { children: 'Data model', href: '/settings/objects' }, - { - children: 'Overview', - }, - ]} - /> - } + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Objects', href: '/settings/objects' }, + { + children: 'Overview', + }, + ]} > <ReactFlowProvider> <SettingsDataModelOverview /> diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx index 3c13d55167db..c31af9513c48 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx @@ -42,6 +42,7 @@ const StyledIconChevronRight = styled(IconChevronRight)` color: ${({ theme }) => theme.font.color.tertiary}; `; const StyledSearchInput = styled(TextInput)` + padding-bottom: ${({ theme }) => theme.spacing(2)}; width: 100%; `; export const SettingsObjects = () => { @@ -144,6 +145,15 @@ export const SettingsObjects = () => { /> </UndecoratedLink> } + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Objects', + }, + ]} > <SettingsPageContainer> <> diff --git a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx index d64afb769f19..f1521a96d910 100644 --- a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx @@ -34,6 +34,6 @@ export const StandardObject: Story = { export const CustomObject: Story = { args: { - routeParams: { ':objectSlug': 'listings' }, + routeParams: { ':objectSlug': 'my-custom-objects' }, }, }; diff --git a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx index d54dd9f4db04..752bfcc713d4 100644 --- a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx @@ -30,7 +30,6 @@ export type Story = StoryObj<typeof SettingsObjectNewFieldStep1>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Settings'); await canvas.findByText('Objects'); await canvas.findByText('Companies'); await canvas.findByText('Check deactivated fields'); diff --git a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx index 0329f1110342..ccd81beaf145 100644 --- a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx @@ -30,9 +30,18 @@ export type Story = StoryObj<typeof SettingsObjectNewFieldStep2>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Settings'); await canvas.findByText('Objects'); - await canvas.findByText('Name and description'); + await canvas.findByText('1. Select a field type'); + + const searchInput = await canvas.findByPlaceholderText('Search a type'); + + await userEvent.type(searchInput, 'Num'); + + const numberTypeButton = await canvas.findByText('Number'); + + await userEvent.click(numberTypeButton); + + await canvas.findByText('2. Configure field'); const employeeInput = await canvas.findByPlaceholderText('Employees'); await userEvent.type(employeeInput, 'Test'); @@ -42,7 +51,6 @@ export const Default: Story = { ); await userEvent.type(descriptionInput, 'Test description'); - await canvas.findByText('Type and values'); const saveButton = await canvas.findByText('Save'); diff --git a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjects.stories.tsx b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjects.stories.tsx index 4782f9f232cf..67fceaa131eb 100644 --- a/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjects.stories.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/__stories__/SettingsObjects.stories.tsx @@ -6,7 +6,6 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; -import { sleep } from '~/utils/sleep'; import { SettingsObjects } from '../SettingsObjects'; @@ -28,11 +27,6 @@ export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await sleep(1000); - - await canvas.getByRole('heading', { - level: 2, - name: 'Objects', - }); + await canvas.findByText('Existing objects', undefined, { timeout: 5000 }); }, }; diff --git a/packages/twenty-front/src/pages/settings/developers/SettingsDevelopers.tsx b/packages/twenty-front/src/pages/settings/developers/SettingsDevelopers.tsx index c551fda4572c..4cb6cf888713 100644 --- a/packages/twenty-front/src/pages/settings/developers/SettingsDevelopers.tsx +++ b/packages/twenty-front/src/pages/settings/developers/SettingsDevelopers.tsx @@ -5,6 +5,8 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain import { SettingsApiKeysTable } from '@/settings/developers/components/SettingsApiKeysTable'; import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton'; import { SettingsWebhooksTable } from '@/settings/developers/components/SettingsWebhooksTable'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { Button } from '@/ui/input/button/components/Button'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; @@ -21,6 +23,13 @@ export const SettingsDevelopers = () => { Icon={IconCode} title="Developers" actionButton={<SettingsReadDocumentationButton />} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Developers' }, + ]} > <SettingsPageContainer> <Section> diff --git a/packages/twenty-front/src/pages/settings/developers/__stories__/SettingsDevelopers.stories.tsx b/packages/twenty-front/src/pages/settings/developers/__stories__/SettingsDevelopers.stories.tsx index ebe8d272f505..40b3b8ae69cc 100644 --- a/packages/twenty-front/src/pages/settings/developers/__stories__/SettingsDevelopers.stories.tsx +++ b/packages/twenty-front/src/pages/settings/developers/__stories__/SettingsDevelopers.stories.tsx @@ -7,7 +7,6 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; -import { sleep } from '~/utils/sleep'; const meta: Meta<PageDecoratorArgs> = { title: 'Pages/Settings/Developers/SettingsDevelopers', @@ -26,8 +25,9 @@ export type Story = StoryObj<typeof SettingsDevelopers>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await sleep(100); - await canvas.findByText('API keys'); + await canvas.findByText('API keys', undefined, { + timeout: 3000, + }); }, }; diff --git a/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysDetail.stories.tsx b/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysDetail.stories.tsx index 4428ce4e1bd5..37c96a2a5ed4 100644 --- a/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysDetail.stories.tsx +++ b/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysDetail.stories.tsx @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/react'; -import { userEvent, within } from '@storybook/test'; +import { fireEvent, userEvent, within } from '@storybook/test'; import { HttpResponse, graphql } from 'msw'; import { SettingsDevelopersApiKeyDetail } from '~/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail'; @@ -50,24 +50,26 @@ export type Story = StoryObj<typeof SettingsDevelopersApiKeyDetail>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Settings'); - await canvas.findByText('sfsfdsf API Key'); + await canvas.findByText('sfsfdsf API Key', undefined, { timeout: 3000 }); }, }; export const RegenerateApiKey: Story = { - play: async ({ canvasElement, step }) => { - const canvas = within(canvasElement); - await canvas.findByText('Settings'); + play: async ({ step }) => { + const canvas = within(document.body); + await canvas.findByText('sfsfdsf API Key', undefined, { timeout: 3000 }); await userEvent.click(await canvas.findByText('Regenerate Key')); await canvas.findByText('Cancel'); - const confirmationInput = await canvas.findByPlaceholderText('yes'); - await userEvent.click(confirmationInput); - await userEvent.keyboard('y'); - await userEvent.keyboard('e'); - await userEvent.keyboard('s'); + + const confirmationInput = await canvas.findByTestId( + 'confirmation-modal-input', + ); + + fireEvent.change(confirmationInput, { + target: { value: 'yes' }, + }); const confirmButton = await canvas.findByTestId( 'confirmation-modal-confirm-button', @@ -83,16 +85,18 @@ export const RegenerateApiKey: Story = { export const DeleteApiKey: Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await canvas.findByText('Settings'); + await canvas.findByText('sfsfdsf API Key', undefined, { timeout: 3000 }); await userEvent.click(await canvas.findByText('Delete')); await canvas.findByText('Cancel'); - const confirmationInput = await canvas.findByPlaceholderText('yes'); - await userEvent.click(confirmationInput); - await userEvent.keyboard('y'); - await userEvent.keyboard('e'); - await userEvent.keyboard('s'); + const confirmationInput = await canvas.findByTestId( + 'confirmation-modal-input', + ); + + fireEvent.change(confirmationInput, { + target: { value: 'yes' }, + }); const confirmButton = await canvas.findByTestId( 'confirmation-modal-confirm-button', diff --git a/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysNew.stories.tsx b/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysNew.stories.tsx index ec5630ab87b8..9b13c2679043 100644 --- a/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysNew.stories.tsx +++ b/packages/twenty-front/src/pages/settings/developers/__stories__/api-keys/SettingsDevelopersApiKeysNew.stories.tsx @@ -25,8 +25,7 @@ export type Story = StoryObj<typeof SettingsDevelopersApiKeysNew>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await canvas.findByText('Settings'); - await canvas.findByText('New API Key'); + await canvas.findByText('New Key'); await canvas.findByText('Name'); await canvas.findByText('Expiration Date'); diff --git a/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx b/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx index 21919f09a4f5..107ce698d43d 100644 --- a/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx +++ b/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx @@ -17,12 +17,15 @@ import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTo import { ApiKey } from '@/settings/developers/types/api-key/ApiKey'; import { computeNewExpirationDate } from '@/settings/developers/utils/compute-new-expiration-date'; import { formatExpiration } from '@/settings/developers/utils/format-expiration'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; +import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { Button } from '@/ui/input/button/components/Button'; import { TextInput } from '@/ui/input/components/TextInput'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { useGenerateApiKeyTokenMutation } from '~/generated/graphql'; const StyledInfo = styled.span` @@ -40,9 +43,11 @@ const StyledInputContainer = styled.div` `; export const SettingsDevelopersApiKeyDetail = () => { + const { enqueueSnackBar } = useSnackBar(); const [isRegenerateKeyModalOpen, setIsRegenerateKeyModalOpen] = useState(false); const [isDeleteApiKeyModalOpen, setIsDeleteApiKeyModalOpen] = useState(false); + const [isLoading, setIsLoading] = useState(false); const navigate = useNavigate(); const { apiKeyId = '' } = useParams(); @@ -65,14 +70,25 @@ export const SettingsDevelopersApiKeyDetail = () => { setApiKeyName(record.name); }, }); + const developerPath = getSettingsPagePath(SettingsPath.Developers); const deleteIntegration = async (redirect = true) => { - await updateApiKey?.({ - idToUpdate: apiKeyId, - updateOneRecordInput: { revokedAt: DateTime.now().toString() }, - }); - if (redirect) { - navigate('/settings/developers'); + setIsLoading(true); + + try { + await updateApiKey?.({ + idToUpdate: apiKeyId, + updateOneRecordInput: { revokedAt: DateTime.now().toString() }, + }); + if (redirect) { + navigate(developerPath); + } + } catch (err) { + enqueueSnackBar(`Error deleting api key: ${err}`, { + variant: SnackBarVariant.Error, + }); + } finally { + setIsLoading(false); } }; @@ -100,20 +116,28 @@ export const SettingsDevelopersApiKeyDetail = () => { token: tokenData.data?.generateApiKeyToken.token, }; }; - const regenerateApiKey = async () => { - if (isNonEmptyString(apiKeyData?.name)) { - const newExpiresAt = computeNewExpirationDate( - apiKeyData?.expiresAt, - apiKeyData?.createdAt, - ); - const apiKey = await createIntegration(apiKeyData?.name, newExpiresAt); - await deleteIntegration(false); + setIsLoading(true); + try { + if (isNonEmptyString(apiKeyData?.name)) { + const newExpiresAt = computeNewExpirationDate( + apiKeyData?.expiresAt, + apiKeyData?.createdAt, + ); + const apiKey = await createIntegration(apiKeyData?.name, newExpiresAt); + await deleteIntegration(false); - if (isNonEmptyString(apiKey?.token)) { - setApiKeyToken(apiKey.token); - navigate(`/settings/developers/api-keys/${apiKey.id}`); + if (isNonEmptyString(apiKey?.token)) { + setApiKeyToken(apiKey.token); + navigate(`/settings/developers/api-keys/${apiKey.id}`); + } } + } catch (err) { + enqueueSnackBar(`Error regenerating api key: ${err}`, { + variant: SnackBarVariant.Error, + }); + } finally { + setIsLoading(false); } }; @@ -122,21 +146,22 @@ export const SettingsDevelopersApiKeyDetail = () => { {apiKeyData?.name && ( <SubMenuTopBarContainer Icon={IconCode} - title={ - <Breadcrumb - links={[ - { children: 'Developers', href: '/settings/developers' }, - { children: `${apiKeyName} API Key` }, - ]} - /> - } + title={apiKeyData?.name} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Developers', href: developerPath }, + { children: `${apiKeyName} API Key` }, + ]} > <SettingsPageContainer> <Section> {apiKeyToken ? ( <> <H2Title - title="Api Key" + title="API Key" description="Copy this key as it will only be visible this one time" /> <ApiKeyInput apiKey={apiKeyToken} /> @@ -147,8 +172,8 @@ export const SettingsDevelopersApiKeyDetail = () => { ) : ( <> <H2Title - title="Api Key" - description="Regenerate an Api key" + title="API Key" + description="Regenerate an API key" /> <StyledInputContainer> <Button @@ -179,7 +204,7 @@ export const SettingsDevelopersApiKeyDetail = () => { <Section> <H2Title title="Expiration" - description="When the key will be diasbled" + description="When the key will be disabled" /> <TextInput placeholder="E.g. backoffice integration" @@ -213,7 +238,7 @@ export const SettingsDevelopersApiKeyDetail = () => { confirmationValue="yes" isOpen={isDeleteApiKeyModalOpen} setIsOpen={setIsDeleteApiKeyModalOpen} - title="Delete Api key" + title="Delete API key" subtitle={ <> Please type "yes" to confirm you want to delete this API Key. Be @@ -222,13 +247,14 @@ export const SettingsDevelopersApiKeyDetail = () => { } onConfirmClick={deleteIntegration} deleteButtonText="Delete" + loading={isLoading} /> <ConfirmationModal confirmationPlaceholder="yes" confirmationValue="yes" isOpen={isRegenerateKeyModalOpen} setIsOpen={setIsRegenerateKeyModalOpen} - title="Regenerate an Api key" + title="Regenerate an API key" subtitle={ <> If you’ve lost this key, you can regenerate it, but be aware that @@ -238,6 +264,7 @@ export const SettingsDevelopersApiKeyDetail = () => { } onConfirmClick={regenerateApiKey} deleteButtonText="Regenerate key" + loading={isLoading} /> </> ); diff --git a/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx b/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx index 7a2207125022..5e4ebe5cf740 100644 --- a/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx +++ b/packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeysNew.tsx @@ -10,11 +10,12 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain import { EXPIRATION_DATES } from '@/settings/developers/constants/ExpirationDates'; import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTokenState'; import { ApiKey } from '@/settings/developers/types/api-key/ApiKey'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { Select } from '@/ui/input/components/Select'; import { TextInput } from '@/ui/input/components/TextInput'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { useSetRecoilState } from 'recoil'; import { Key } from 'ts-key-enum'; import { useGenerateApiKeyTokenMutation } from '~/generated/graphql'; @@ -65,14 +66,18 @@ export const SettingsDevelopersApiKeysNew = () => { return ( <SubMenuTopBarContainer Icon={IconCode} - title={ - <Breadcrumb - links={[ - { children: 'Developers', href: '/settings/developers' }, - { children: 'New API Key' }, - ]} - /> - } + title="New key" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Developers', + href: getSettingsPagePath(SettingsPath.Developers), + }, + { children: 'New Key' }, + ]} actionButton={ <SaveAndCancelButtons isSaveDisabled={!canSave} diff --git a/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail.tsx b/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail.tsx index 174561f6a9f2..a45227408fb5 100644 --- a/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail.tsx +++ b/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail.tsx @@ -11,6 +11,8 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { Webhook } from '@/settings/developers/types/webhook/Webhook'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { Button } from '@/ui/input/button/components/Button'; import { Select } from '@/ui/input/components/Select'; import { TextArea } from '@/ui/input/components/TextArea'; @@ -18,7 +20,6 @@ import { TextInput } from '@/ui/input/components/TextInput'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; const StyledFilterRow = styled.div` display: flex; @@ -55,9 +56,11 @@ export const SettingsDevelopersWebhooksDetail = () => { objectNameSingular: CoreObjectNameSingular.Webhook, }); + const developerPath = getSettingsPagePath(SettingsPath.Developers); + const deleteWebhook = () => { deleteOneWebhook(webhookId); - navigate('/settings/developers'); + navigate(developerPath); }; const fieldTypeOptions = [ @@ -81,124 +84,119 @@ export const SettingsDevelopersWebhooksDetail = () => { description: description, }, }); - navigate('/settings/developers'); + navigate(developerPath); }; + if (!webhookData?.targetUrl) { + return <></>; + } + return ( - <> - {webhookData?.targetUrl && ( - <SubMenuTopBarContainer - Icon={IconCode} - title={ - <Breadcrumb - links={[ - { children: 'Developers', href: '/settings/developers' }, - { children: 'Webhook' }, - ]} + <SubMenuTopBarContainer + Icon={IconCode} + title={webhookData.targetUrl} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Developers', + href: developerPath, + }, + { children: 'Webhook' }, + ]} + actionButton={ + <SaveAndCancelButtons + isSaveDisabled={!isDirty} + onCancel={() => { + navigate(developerPath); + }} + onSave={handleSave} + /> + } + > + <SettingsPageContainer> + <Section> + <H2Title + title="Endpoint URL" + description="We will send POST requests to this endpoint for every new event" + /> + <TextInput + placeholder="URL" + value={webhookData.targetUrl} + disabled + fullWidth + /> + </Section> + <Section> + <H2Title title="Description" description="An optional description" /> + <TextArea + placeholder="Write a description" + minRows={4} + value={description} + onChange={(description) => { + setDescription(description); + setIsDirty(true); + }} + /> + </Section> + <Section> + <H2Title + title="Filters" + description="Select the event you wish to send to this endpoint" + /> + <StyledFilterRow> + <Select + fullWidth + dropdownId="object-webhook-type-select" + value={operationObjectSingularName} + onChange={(objectSingularName) => { + setIsDirty(true); + setOperationObjectSingularName(objectSingularName); + }} + options={fieldTypeOptions} /> - } - actionButton={ - <SaveAndCancelButtons - isSaveDisabled={!isDirty} - onCancel={() => { - navigate('/settings/developers'); + <Select + fullWidth + dropdownId="operation-webhook-type-select" + value={operationAction} + onChange={(operationAction) => { + setIsDirty(true); + setOperationAction(operationAction); }} - onSave={handleSave} + options={[ + { value: '*', label: 'All Actions' }, + { value: 'create', label: 'Create' }, + { value: 'update', label: 'Update' }, + { value: 'delete', label: 'Delete' }, + ]} /> - } - > - <SettingsPageContainer> - <Section> - <H2Title - title="Endpoint URL" - description="We will send POST requests to this endpoint for every new event" - /> - <TextInput - placeholder="URL" - value={webhookData.targetUrl} - disabled - fullWidth - /> - </Section> - <Section> - <H2Title - title="Description" - description="An optional description" - /> - <TextArea - placeholder="Write a description" - minRows={4} - value={description} - onChange={(description) => { - setDescription(description); - setIsDirty(true); - }} - /> - </Section> - <Section> - <H2Title - title="Filters" - description="Select the event you wish to send to this endpoint" - /> - <StyledFilterRow> - <Select - fullWidth - dropdownId="object-webhook-type-select" - value={operationObjectSingularName} - onChange={(objectSingularName) => { - setIsDirty(true); - setOperationObjectSingularName(objectSingularName); - }} - options={fieldTypeOptions} - /> - <Select - fullWidth - dropdownId="operation-webhook-type-select" - value={operationAction} - onChange={(operationAction) => { - setIsDirty(true); - setOperationAction(operationAction); - }} - options={[ - { value: '*', label: 'All Actions' }, - { value: 'create', label: 'Create' }, - { value: 'update', label: 'Update' }, - { value: 'delete', label: 'Delete' }, - ]} - /> - </StyledFilterRow> - </Section> - <Section> - <H2Title - title="Danger zone" - description="Delete this integration" - /> - <Button - accent="danger" - variant="secondary" - title="Delete" - Icon={IconTrash} - onClick={() => setIsDeleteWebhookModalOpen(true)} - /> - <ConfirmationModal - confirmationPlaceholder="yes" - confirmationValue="yes" - isOpen={isDeleteWebhookModalOpen} - setIsOpen={setIsDeleteWebhookModalOpen} - title="Delete webhook" - subtitle={ - <> - Please type "yes" to confirm you want to delete this - webhook. - </> - } - onConfirmClick={deleteWebhook} - deleteButtonText="Delete webhook" - /> - </Section> - </SettingsPageContainer> - </SubMenuTopBarContainer> - )} - </> + </StyledFilterRow> + </Section> + <Section> + <H2Title title="Danger zone" description="Delete this integration" /> + <Button + accent="danger" + variant="secondary" + title="Delete" + Icon={IconTrash} + onClick={() => setIsDeleteWebhookModalOpen(true)} + /> + <ConfirmationModal + confirmationPlaceholder="yes" + confirmationValue="yes" + isOpen={isDeleteWebhookModalOpen} + setIsOpen={setIsDeleteWebhookModalOpen} + title="Delete webhook" + subtitle={ + <>Please type "yes" to confirm you want to delete this webhook.</> + } + onConfirmClick={deleteWebhook} + deleteButtonText="Delete webhook" + /> + </Section> + </SettingsPageContainer> + </SubMenuTopBarContainer> ); }; diff --git a/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew.tsx b/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew.tsx index 2e9f06e10d3e..7b75bd09f0fe 100644 --- a/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew.tsx +++ b/packages/twenty-front/src/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew.tsx @@ -1,16 +1,18 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { H2Title, IconCode } from 'twenty-ui'; +import { H2Title, IconCode, isDefined } from 'twenty-ui'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { Webhook } from '@/settings/developers/types/webhook/Webhook'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { TextInput } from '@/ui/input/components/TextInput'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; +import { isValidUrl } from '~/utils/url/isValidUrl'; export const SettingsDevelopersWebhooksNew = () => { const navigate = useNavigate(); @@ -21,9 +23,18 @@ export const SettingsDevelopersWebhooksNew = () => { targetUrl: '', operation: '*.*', }); + const [isTargetUrlValid, setIsTargetUrlValid] = useState(true); + const { createOneRecord: createOneWebhook } = useCreateOneRecord<Webhook>({ objectNameSingular: CoreObjectNameSingular.Webhook, }); + + const handleValidate = async (value: string) => { + const trimmedUrl = value.trim(); + + setIsTargetUrlValid(isValidUrl(trimmedUrl)); + }; + const handleSave = async () => { const newWebhook = await createOneWebhook?.(formValues); @@ -32,23 +43,45 @@ export const SettingsDevelopersWebhooksNew = () => { } navigate(`/settings/developers/webhooks/${newWebhook.id}`); }; - const canSave = !!formValues.targetUrl && createOneWebhook; + + const canSave = + !!formValues.targetUrl && isTargetUrlValid && isDefined(createOneWebhook); + + // TODO: refactor use useScopedHotkeys + const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { + if (e.key === 'Enter' && canSave) { + handleSave(); + } + }; + + const handleChange = (value: string) => { + setFormValues((prevState) => ({ + ...prevState, + targetUrl: value, + })); + handleValidate(value); + }; + return ( <SubMenuTopBarContainer Icon={IconCode} - title={ - <Breadcrumb - links={[ - { children: 'Developers', href: '/settings/developers' }, - { children: 'New webhook' }, - ]} - /> - } + title="New Webhook" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Developers', + href: getSettingsPagePath(SettingsPath.Developers), + }, + { children: 'New Webhook' }, + ]} actionButton={ <SaveAndCancelButtons isSaveDisabled={!canSave} onCancel={() => { - navigate('/settings/developers'); + navigate(getSettingsPagePath(SettingsPath.Developers)); }} onSave={handleSave} /> @@ -63,17 +96,9 @@ export const SettingsDevelopersWebhooksNew = () => { <TextInput placeholder="URL" value={formValues.targetUrl} - onKeyDown={(e) => { - if (e.key === 'Enter') { - handleSave(); - } - }} - onChange={(value) => { - setFormValues((prevState) => ({ - ...prevState, - targetUrl: value, - })); - }} + error={!isTargetUrlValid ? 'Please enter a valid URL' : undefined} + onKeyDown={handleKeyDown} + onChange={handleChange} fullWidth /> </Section> diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx index 430848d7615b..2136ae1ae858 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx @@ -13,7 +13,6 @@ import { AppPath } from '@/types/AppPath'; import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; export const SettingsIntegrationDatabase = () => { const { databaseKey = '' } = useParams(); @@ -44,17 +43,18 @@ export const SettingsIntegrationDatabase = () => { return ( <SubMenuTopBarContainer Icon={IconSettings} - title={ - <Breadcrumb - links={[ - { - children: 'Integrations', - href: getSettingsPagePath(SettingsPath.Integrations), - }, - { children: integration.text }, - ]} - /> - } + title={integration.text} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Integrations', + href: getSettingsPagePath(SettingsPath.Integrations), + }, + { children: integration.text }, + ]} > <SettingsPageContainer> <SettingsIntegrationPreview diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationEditDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationEditDatabaseConnection.tsx index 7600c2a89cd0..5203f01de89e 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationEditDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationEditDatabaseConnection.tsx @@ -2,21 +2,26 @@ import { IconSettings } from 'twenty-ui'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsIntegrationEditDatabaseConnectionContainer } from '@/settings/integrations/database-connection/components/SettingsIntegrationEditDatabaseConnectionContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; export const SettingsIntegrationEditDatabaseConnection = () => { return ( <SubMenuTopBarContainer Icon={IconSettings} - title={ - <Breadcrumb - links={[ - // TODO - { children: 'Edit connection' }, - ]} - /> - } + title="Edit connection" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Integrations', + href: getSettingsPagePath(SettingsPath.Integrations), + }, + { children: 'Edit connection' }, + ]} > <SettingsPageContainer> <SettingsIntegrationEditDatabaseConnectionContainer /> diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx index 4763e02e664f..1440bd66100b 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx @@ -23,7 +23,6 @@ import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/Snac import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { CreateRemoteServerInput } from '~/generated-metadata/graphql'; const createRemoteServerInputPostgresSchema = @@ -133,21 +132,22 @@ export const SettingsIntegrationNewDatabaseConnection = () => { return ( <SubMenuTopBarContainer Icon={IconSettings} - title={ - <Breadcrumb - links={[ - { - children: 'Integrations', - href: settingsIntegrationsPagePath, - }, - { - children: integration.text, - href: `${settingsIntegrationsPagePath}/${databaseKey}`, - }, - { children: 'New' }, - ]} - /> - } + title="New" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Integrations', + href: settingsIntegrationsPagePath, + }, + { + children: integration.text, + href: `${settingsIntegrationsPagePath}/${databaseKey}`, + }, + { children: 'New' }, + ]} actionButton={ <SaveAndCancelButtons isSaveDisabled={!canSave} diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection.tsx index 297c6fc76ea8..04fe78e64422 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection.tsx @@ -2,11 +2,27 @@ import { IconSettings } from 'twenty-ui'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsIntegrationDatabaseConnectionShowContainer } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionShowContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; export const SettingsIntegrationShowDatabaseConnection = () => { return ( - <SubMenuTopBarContainer Icon={IconSettings} title="Settings"> + <SubMenuTopBarContainer + Icon={IconSettings} + title="Database Connection" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Integrations', + href: getSettingsPagePath(SettingsPath.Integrations), + }, + { children: 'Database Connection' }, + ]} + > <SettingsPageContainer> <SettingsIntegrationDatabaseConnectionShowContainer /> </SettingsPageContainer> diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrations.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrations.tsx index cd12fb14eae3..acc3c5cc6777 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrations.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrations.tsx @@ -1,6 +1,8 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsIntegrationGroup } from '@/settings/integrations/components/SettingsIntegrationGroup'; import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { IconApps } from 'twenty-ui'; @@ -8,7 +10,17 @@ export const SettingsIntegrations = () => { const integrationCategories = useSettingsIntegrationCategories(); return ( - <SubMenuTopBarContainer Icon={IconApps} title="Integrations"> + <SubMenuTopBarContainer + Icon={IconApps} + title="Integrations" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { children: 'Integrations' }, + ]} + > <SettingsPageContainer> {integrationCategories.map((group) => ( <SettingsIntegrationGroup key={group.key} integrationGroup={group} /> diff --git a/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx b/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx index 8adb6d719d10..fd04905356c8 100644 --- a/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx @@ -35,6 +35,6 @@ export const Default: Story = { const canvas = within(canvasElement); sleep(100); - await canvas.findByText('Edit Connection'); + await canvas.findByText('Edit Connection', undefined, { timeout: 3000 }); }, }; diff --git a/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationNewDatabaseConnection.stories.tsx b/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationNewDatabaseConnection.stories.tsx index 5f95eacb238b..c28749873556 100644 --- a/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationNewDatabaseConnection.stories.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationNewDatabaseConnection.stories.tsx @@ -7,7 +7,6 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; -import { sleep } from '~/utils/sleep'; const meta: Meta<PageDecoratorArgs> = { title: 'Pages/Settings/Integrations/SettingsIntegrationNewDatabaseConnection', @@ -29,8 +28,9 @@ export type Story = StoryObj<typeof SettingsIntegrationNewDatabaseConnection>; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - sleep(100); - await canvas.findByText('Connect a new database'); + await canvas.findByText('Connect a new database', undefined, { + timeout: 3000, + }); }, }; diff --git a/packages/twenty-front/src/pages/settings/profile/appearance/components/SettingsAppearance.tsx b/packages/twenty-front/src/pages/settings/profile/appearance/components/SettingsAppearance.tsx index efa1036b0acf..f3fe094bcb15 100644 --- a/packages/twenty-front/src/pages/settings/profile/appearance/components/SettingsAppearance.tsx +++ b/packages/twenty-front/src/pages/settings/profile/appearance/components/SettingsAppearance.tsx @@ -1,6 +1,8 @@ import { H2Title, IconColorSwatch } from 'twenty-ui'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { ColorSchemePicker } from '@/ui/input/color-scheme/components/ColorSchemePicker'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; @@ -11,10 +13,20 @@ export const SettingsAppearance = () => { const { colorScheme, setColorScheme } = useColorScheme(); return ( - <SubMenuTopBarContainer Icon={IconColorSwatch} title="Appearance"> + <SubMenuTopBarContainer + Icon={IconColorSwatch} + title="Experience" + links={[ + { + children: 'User', + href: getSettingsPagePath(SettingsPath.ProfilePage), + }, + { children: 'Experience' }, + ]} + > <SettingsPageContainer> <Section> - <H2Title title="Theme" /> + <H2Title title="Appearance" /> <ColorSchemePicker value={colorScheme} onChange={setColorScheme} /> </Section> <Section> diff --git a/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionDetail.tsx b/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionDetail.tsx index fa3d01bbd8a6..efd06b555139 100644 --- a/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionDetail.tsx +++ b/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionDetail.tsx @@ -4,26 +4,26 @@ import { SettingsServerlessFunctionSettingsTab } from '@/settings/serverless-fun import { SettingsServerlessFunctionTestTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTab'; import { SettingsServerlessFunctionTestTabEffect } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTabEffect'; import { useExecuteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useExecuteOneServerlessFunction'; +import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode'; +import { usePublishOneServerlessFunction } from '@/settings/serverless-functions/hooks/usePublishOneServerlessFunction'; import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState'; import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction'; -import { usePublishOneServerlessFunction } from '@/settings/serverless-functions/hooks/usePublishOneServerlessFunction'; import { settingsServerlessFunctionInputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionInputState'; import { settingsServerlessFunctionOutputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionOutputState'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; +import { SettingsPath } from '@/types/SettingsPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; import { TabList } from '@/ui/layout/tab/components/TabList'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; +import { useState } from 'react'; import { useParams } from 'react-router-dom'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { IconCode, IconFunction, IconSettings, IconTestPipe } from 'twenty-ui'; +import { usePreventOverlapCallback } from '~/hooks/usePreventOverlapCallback'; import { isDefined } from '~/utils/isDefined'; -import { useDebouncedCallback } from 'use-debounce'; -import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode'; -import { useState } from 'react'; -import isEmpty from 'lodash.isempty'; const TAB_LIST_COMPONENT_ID = 'serverless-function-detail'; @@ -53,9 +53,6 @@ export const SettingsServerlessFunctionDetail = () => { const save = async () => { try { - if (isEmpty(formValues.name)) { - return; - } await updateOneServerlessFunction({ id: serverlessFunctionId, name: formValues.name, @@ -72,10 +69,10 @@ export const SettingsServerlessFunctionDetail = () => { } }; - const handleSave = useDebouncedCallback(save, 500); + const handleSave = usePreventOverlapCallback(save, 1000); const onChange = (key: string) => { - return async (value: string | undefined) => { + return async (value: string) => { setFormValues((prevState) => ({ ...prevState, [key]: value, @@ -208,14 +205,18 @@ export const SettingsServerlessFunctionDetail = () => { !loading && ( <SubMenuTopBarContainer Icon={IconFunction} - title={ - <Breadcrumb - links={[ - { children: 'Functions', href: '/settings/functions' }, - { children: `${formValues.name}` }, - ]} - /> - } + title={formValues.name} + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Functions', + href: getSettingsPagePath(SettingsPath.ServerlessFunctions), + }, + { children: `${formValues.name}` }, + ]} > <SettingsPageContainer> <Section> diff --git a/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctions.tsx b/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctions.tsx index ff44358c0d62..00dcabb77bdc 100644 --- a/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctions.tsx +++ b/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctions.tsx @@ -1,4 +1,3 @@ -import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsServerlessFunctionsTable } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsTable'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; @@ -6,7 +5,6 @@ import { SettingsPath } from '@/types/SettingsPath'; import { Button } from '@/ui/input/button/components/Button'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; import { Section } from '@/ui/layout/section/components/Section'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink'; import { IconFunction, IconPlus } from 'twenty-ui'; @@ -27,11 +25,17 @@ export const SettingsServerlessFunctions = () => { /> </UndecoratedLink> } + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Functions', + }, + ]} > <SettingsPageContainer> - <SettingsHeaderContainer> - <Breadcrumb links={[{ children: 'Functions' }]} /> - </SettingsHeaderContainer> <Section> <SettingsServerlessFunctionsTable /> </Section> diff --git a/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionsNew.tsx b/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionsNew.tsx index 9acdead88f6d..24308d53a3d1 100644 --- a/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionsNew.tsx +++ b/packages/twenty-front/src/pages/settings/serverless-functions/SettingsServerlessFunctionsNew.tsx @@ -1,7 +1,6 @@ import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; -import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { useNavigate } from 'react-router-dom'; import { SettingsServerlessFunctionNewForm } from '@/settings/serverless-functions/components/SettingsServerlessFunctionNewForm'; @@ -46,7 +45,7 @@ export const SettingsServerlessFunctionsNew = () => { }; const onChange = (key: string) => { - return (value: string | undefined) => { + return (value: string) => { setFormValues((prevState) => ({ ...prevState, [key]: value, @@ -81,14 +80,18 @@ export const SettingsServerlessFunctionsNew = () => { return ( <SubMenuTopBarContainer Icon={IconFunction} - title={ - <Breadcrumb - links={[ - { children: 'Functions', href: '/settings/functions' }, - { children: 'New' }, - ]} - /> - } + title="New Function" + links={[ + { + children: 'Workspace', + href: getSettingsPagePath(SettingsPath.Workspace), + }, + { + children: 'Functions', + href: getSettingsPagePath(SettingsPath.ServerlessFunctions), + }, + { children: 'New' }, + ]} actionButton={ <SaveAndCancelButtons isSaveDisabled={!canSave} @@ -108,3 +111,5 @@ export const SettingsServerlessFunctionsNew = () => { </SubMenuTopBarContainer> ); }; + +export default SettingsServerlessFunctionsNew; diff --git a/packages/twenty-front/src/pages/settings/serverless-functions/__stories__/SettingsServerlessFunctions.stories.tsx b/packages/twenty-front/src/pages/settings/serverless-functions/__stories__/SettingsServerlessFunctions.stories.tsx index eb1474a8b126..bc6a68db1784 100644 --- a/packages/twenty-front/src/pages/settings/serverless-functions/__stories__/SettingsServerlessFunctions.stories.tsx +++ b/packages/twenty-front/src/pages/settings/serverless-functions/__stories__/SettingsServerlessFunctions.stories.tsx @@ -1,12 +1,12 @@ -import { SettingsServerlessFunctions } from '~/pages/settings/serverless-functions/SettingsServerlessFunctions'; -import { graphqlMocks } from '~/testing/graphqlMocks'; import { Meta, StoryObj } from '@storybook/react'; +import { within } from '@storybook/test'; +import { SettingsServerlessFunctions } from '~/pages/settings/serverless-functions/SettingsServerlessFunctions'; import { PageDecorator, PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; import { sleep } from '~/utils/sleep'; -import { within } from '@storybook/test'; const meta: Meta<PageDecoratorArgs> = { title: 'Pages/Settings/ServerlessFunctions/SettingsServerlessFunctions', @@ -26,7 +26,6 @@ export const Default: Story = { const canvas = within(canvasElement); await sleep(100); - await canvas.findByText('Functions'); await canvas.findByText('Add your first Function'); }, }; diff --git a/packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx b/packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx deleted file mode 100644 index 0a5125ef9081..000000000000 --- a/packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { PageBody } from '@/ui/layout/page/PageBody'; -import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; -import { WorkflowShowPageDiagram } from '@/workflow/components/WorkflowShowPageDiagram'; -import { WorkflowShowPageEffect } from '@/workflow/components/WorkflowShowPageEffect'; -import { WorkflowShowPageHeader } from '@/workflow/components/WorkflowShowPageHeader'; -import { showPageWorkflowDiagramState } from '@/workflow/states/showPageWorkflowDiagramState'; -import styled from '@emotion/styled'; -import '@xyflow/react/dist/style.css'; -import { useParams } from 'react-router-dom'; -import { useRecoilValue } from 'recoil'; -import { IconSettingsAutomation } from 'twenty-ui'; - -const StyledFlowContainer = styled.div` - height: 100%; - width: 100%; - - /* Below we reset the default styling of Reactflow */ - .react-flow__node-input, - .react-flow__node-default, - .react-flow__node-output, - .react-flow__node-group { - padding: 0; - } - - --xy-node-border-radius: none; - --xy-node-border: none; - --xy-node-background-color: none; - --xy-node-boxshadow-hover: none; - --xy-node-boxshadow-selected: none; -`; - -export const WorkflowShowPage = () => { - const parameters = useParams<{ - workflowId: string; - }>(); - - const workflowName = 'Test Workflow'; - - const showPageWorkflowDiagram = useRecoilValue(showPageWorkflowDiagramState); - - if (parameters.workflowId === undefined) { - return null; - } - - return ( - <PageContainer> - <WorkflowShowPageEffect workflowId={parameters.workflowId} /> - - <PageTitle title={workflowName} /> - <WorkflowShowPageHeader - workflowName={workflowName} - headerIcon={IconSettingsAutomation} - /> - <PageBody> - <StyledFlowContainer> - {showPageWorkflowDiagram === undefined ? null : ( - <WorkflowShowPageDiagram diagram={showPageWorkflowDiagram} /> - )} - </StyledFlowContainer> - </PageBody> - </PageContainer> - ); -}; diff --git a/packages/twenty-front/src/testing/decorators/PageDecorator.tsx b/packages/twenty-front/src/testing/decorators/PageDecorator.tsx index 19453453c664..7125e4326dc6 100644 --- a/packages/twenty-front/src/testing/decorators/PageDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/PageDecorator.tsx @@ -12,7 +12,6 @@ import { import { RecoilRoot } from 'recoil'; import { ClientConfigProviderEffect } from '@/client-config/components/ClientConfigProviderEffect'; -import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider'; import { ApolloMetadataClientMockedProvider } from '@/object-metadata/hooks/__mocks__/ApolloMetadataClientProvider'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; import { UserProviderEffect } from '@/users/components/UserProviderEffect'; @@ -21,7 +20,9 @@ import { DefaultLayout } from '~/modules/ui/layout/page/DefaultLayout'; import { UserProvider } from '~/modules/users/components/UserProvider'; import { mockedApolloClient } from '~/testing/mockedApolloClient'; +import { RecoilDebugObserverEffect } from '@/debug/components/RecoilDebugObserver'; import { PrefetchDataProvider } from '@/prefetch/components/PrefetchDataProvider'; +import { IconsProvider } from 'twenty-ui'; import { FullHeightStorybookLayout } from '../FullHeightStorybookLayout'; export type PageDecoratorArgs = { @@ -63,6 +64,7 @@ const ApolloStorybookDevLogEffect = () => { const Providers = () => { return ( <RecoilRoot> + <RecoilDebugObserverEffect /> <ApolloProvider client={mockedApolloClient}> <ApolloStorybookDevLogEffect /> <ApolloMetadataClientMockedProvider> @@ -73,11 +75,11 @@ const Providers = () => { <FullHeightStorybookLayout> <HelmetProvider> <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> - <ObjectMetadataItemsProvider> + <IconsProvider> <PrefetchDataProvider> <Outlet /> </PrefetchDataProvider> - </ObjectMetadataItemsProvider> + </IconsProvider> </SnackBarProviderScope> </HelmetProvider> </FullHeightStorybookLayout> diff --git a/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx b/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx new file mode 100644 index 000000000000..11774aba44bf --- /dev/null +++ b/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx @@ -0,0 +1,39 @@ +import { Decorator } from '@storybook/react'; +import { useRecoilValue } from 'recoil'; + +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; +import { isDefined } from 'twenty-ui'; + +export const RecordTableDecorator: Decorator = (Story) => { + const objectMetadataItems = useRecoilValue(objectMetadataItemsState); + + const personObjectMetadataItem = objectMetadataItems.find( + (objectMetadataItem) => objectMetadataItem.nameSingular === 'person', + ); + + if (!isDefined(personObjectMetadataItem)) { + return <Story />; + } + + return ( + <RecordTableContext.Provider + value={{ + objectNameSingular: personObjectMetadataItem?.nameSingular, + objectMetadataItem: personObjectMetadataItem, + onCellMouseEnter: () => {}, + onCloseTableCell: () => {}, + onOpenTableCell: () => {}, + onContextMenu: () => {}, + onMoveFocus: () => {}, + onMoveSoftFocusToCell: () => {}, + onUpsertRecord: () => {}, + recordTableId: 'persons', + viewBarId: 'view-bar', + visibleTableColumns: [], + }} + > + <Story /> + </RecordTableContext.Provider> + ); +}; diff --git a/packages/twenty-front/src/testing/graphqlMocks.ts b/packages/twenty-front/src/testing/graphqlMocks.ts index 7c16b15a04e9..c5d319b460b7 100644 --- a/packages/twenty-front/src/testing/graphqlMocks.ts +++ b/packages/twenty-front/src/testing/graphqlMocks.ts @@ -416,6 +416,133 @@ export const graphqlMocks = { }, }); }), + graphql.query('FindManyWorkflows', () => { + return HttpResponse.json({ + data: { + workflows: { + __typename: 'WorkflowConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + endCursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + }, + edges: [ + { + __typename: 'WorkflowEdge', + cursor: + 'eyJpZCI6IjIwMGMxNTA4LWYxMDItNGJiOS1hZjMyLWVkYTU1MjM5YWU2MSJ9', + node: { + __typename: 'Workflow', + id: '200c1508-f102-4bb9-af32-eda55239ae61', + }, + }, + ], + }, + }, + }); + }), + graphql.query('FindOneWorkflow', () => { + return HttpResponse.json({ + data: { + workflow: { + __typename: 'Workflow', + id: '200c1508-f102-4bb9-af32-eda55239ae61', + name: '1231 qqerrt', + statuses: null, + lastPublishedVersionId: '', + deletedAt: null, + updatedAt: '2024-09-19T10:10:04.505Z', + position: 0, + createdAt: '2024-09-19T10:10:04.505Z', + favorites: { + __typename: 'FavoriteConnection', + edges: [], + }, + eventListeners: { + __typename: 'WorkflowEventListenerConnection', + edges: [], + }, + runs: { + __typename: 'WorkflowRunConnection', + edges: [], + }, + versions: { + __typename: 'WorkflowVersionConnection', + edges: [ + { + __typename: 'WorkflowVersionEdge', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:04.725Z', + status: 'DRAFT', + name: 'v1', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f0', + trigger: { + type: 'DATABASE_EVENT', + settings: { + eventName: 'note.created', + }, + }, + deletedAt: null, + workflowId: '200c1508-f102-4bb9-af32-eda55239ae61', + }, + }, + ], + }, + }, + }, + }); + }), + graphql.query('FindManyWorkflowVersions', () => { + return HttpResponse.json({ + data: { + workflowVersions: { + __typename: 'WorkflowVersionConnection', + totalCount: 1, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + endCursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + }, + edges: [ + { + __typename: 'WorkflowVersionEdge', + cursor: + 'eyJjcmVhdGVkQXQiOiIyMDI0LTA5LTE5VDEwOjEwOjA0LjcyNVoiLCJpZCI6ImY2MTg4NDNhLTI2YmUtNGE1NC1hNjBmLWY0Y2U4OGE1OTRmMCJ9', + node: { + __typename: 'WorkflowVersion', + updatedAt: '2024-09-19T10:13:12.075Z', + steps: null, + createdAt: '2024-09-19T10:10:04.725Z', + status: 'DRAFT', + name: 'v1', + id: 'f618843a-26be-4a54-a60f-f4ce88a594f0', + trigger: { + type: 'DATABASE_EVENT', + settings: { + eventName: 'note.created', + }, + }, + deletedAt: null, + workflowId: '200c1508-f102-4bb9-af32-eda55239ae61', + }, + }, + ], + }, + }, + }); + }), http.get('https://chat-assets.frontapp.com/v1/chat.bundle.js', () => { return HttpResponse.text( ` diff --git a/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx b/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx index 35d4a861f5b6..abd11cab1832 100644 --- a/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx +++ b/packages/twenty-front/src/testing/jest/JestObjectMetadataItemSetter.tsx @@ -2,7 +2,7 @@ import { ReactNode, useEffect, useState } from 'react'; import { useSetRecoilState } from 'recoil'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/objectMetadataItems'; export const JestObjectMetadataItemSetter = ({ children, @@ -12,7 +12,7 @@ export const JestObjectMetadataItemSetter = ({ const setObjectMetadataItems = useSetRecoilState(objectMetadataItemsState); const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { - setObjectMetadataItems(getObjectMetadataItemsMock()); + setObjectMetadataItems(generatedMockObjectMetadataItems); setIsLoaded(true); }, [setObjectMetadataItems]); diff --git a/packages/twenty-front/src/testing/jest/getJestHookWrapper.tsx b/packages/twenty-front/src/testing/jest/getJestHookWrapper.tsx index d16f71bebb5d..3c8f21553323 100644 --- a/packages/twenty-front/src/testing/jest/getJestHookWrapper.tsx +++ b/packages/twenty-front/src/testing/jest/getJestHookWrapper.tsx @@ -1,8 +1,9 @@ -import { ReactNode } from 'react'; import { MockedProvider, MockedResponse } from '@apollo/client/testing'; +import { ReactNode } from 'react'; import { MutableSnapshot, RecoilRoot } from 'recoil'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; +import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter'; export const getJestHookWrapper = ({ apolloMocks, @@ -17,7 +18,9 @@ export const getJestHookWrapper = ({ <RecoilRoot initializeState={onInitializeRecoilSnapshot}> <SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager"> <MockedProvider mocks={apolloMocks} addTypename={false}> - {children} + <JestObjectMetadataItemSetter> + {children} + </JestObjectMetadataItemSetter> </MockedProvider> </SnackBarProviderScope> </RecoilRoot> diff --git a/packages/twenty-front/src/testing/mock-data/config.ts b/packages/twenty-front/src/testing/mock-data/config.ts index 656dcbb80b76..1ed65869a7ca 100644 --- a/packages/twenty-front/src/testing/mock-data/config.ts +++ b/packages/twenty-front/src/testing/mock-data/config.ts @@ -13,10 +13,6 @@ export const mockedClientConfig: ClientConfig = { microsoft: false, __typename: 'AuthProviders', }, - telemetry: { - enabled: false, - __typename: 'Telemetry', - }, support: { supportDriver: 'front', supportFrontChatId: null, diff --git a/packages/twenty-front/src/testing/mock-data/generated/mock-metadata-query-result.ts b/packages/twenty-front/src/testing/mock-data/generated/mock-metadata-query-result.ts new file mode 100644 index 000000000000..c30b74ec2344 --- /dev/null +++ b/packages/twenty-front/src/testing/mock-data/generated/mock-metadata-query-result.ts @@ -0,0 +1,16986 @@ +import { ObjectMetadataItemsQuery } from '~/generated-metadata/graphql'; + +// This file is not designed to be manually edited. +// It's an extract from the dev seeded environment metadata call +// TODO: automate the generation of this file +// ⚠️ WARNING ⚠️: Be sure to activate the workflow feature flag (IsWorkflowEnabled) before updating that mock. +export const mockedStandardObjectMetadataQueryResult: ObjectMetadataItemsQuery = + { + objects: { + __typename: 'ObjectConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjM2', + }, + edges: [ + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'f8c3e3e7-8392-469f-9f3c-b0972910bec0', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'webhook', + namePlural: 'webhooks', + labelSingular: 'Webhook', + labelPlural: 'Webhooks', + description: 'A webhook', + icon: 'IconRobot', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'a8876650-a7b6-4a9f-95b4-9ec1d6c232cc', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjY=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ed0dfa31-8e2f-4b23-87e4-8fa55eb16729', + type: 'TEXT', + name: 'operation', + label: 'Operation', + description: 'Webhook operation', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '814795ef-6f2d-4798-a6f9-4e1c87c68d43', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1c802ccf-c0ae-4b04-8c1e-f77417e6c3f8', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6f210155-9cdc-48c6-9803-e20f63512024', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5fa54f64-3363-4a21-89ca-30d4816d8c77', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a8876650-a7b6-4a9f-95b4-9ec1d6c232cc', + type: 'TEXT', + name: 'targetUrl', + label: 'Target Url', + description: 'Webhook target url', + icon: 'IconLink', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'afae3f60-bfeb-4faf-a899-b0eb0fefac51', + type: 'TEXT', + name: 'description', + label: 'Description', + description: null, + icon: 'IconInfo', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + labelSingular: 'Task Target', + labelPlural: 'Task Targets', + description: 'An task target', + icon: 'IconCheckbox', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '400c9e53-283b-42d8-a69f-5010fb75d977', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEz', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ad82920a-857a-4357-8e4a-ed70961ba5d8', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '89662f00-b57c-49f6-aa48-d1c84f5fd7c7', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'TaskTarget person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '19270b1d-73b4-4aa9-8106-c1c81351ec53', + type: 'UUID', + name: 'rocketId', + label: 'Rocket ID (foreign key)', + description: 'TaskTarget Rocket id foreign key', + icon: null, + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.610Z', + updatedAt: '2024-09-25T13:45:42.610Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0c796ac5-0592-455f-9a0a-66ad53c6e4cf', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'TaskTarget company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dadac630-f64e-4d3d-9923-78ca579373f3', + type: 'RELATION', + name: 'rocket', + label: 'Rocket', + description: 'TaskTarget Rocket', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.612Z', + updatedAt: '2024-09-25T13:45:42.612Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '140a67f3-988e-4d60-b24c-8a4fcb4ea6e9', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'dadac630-f64e-4d3d-9923-78ca579373f3', + name: 'rocket', + }, + targetObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '83515891-eb29-472e-9cde-4a1d42b6855d', + name: 'taskTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0fcdebbb-a332-45ec-ab46-c30d5d7f9ef0', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '37882bc2-c8d8-4cc5-bc13-4b820cc05b83', + type: 'UUID', + name: 'taskId', + label: 'Task id (foreign key)', + description: 'TaskTarget task id foreign key', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'da63ddb4-7c19-49f0-bf90-ac2cc9486ae7', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '26cc6ba3-cff7-4b84-bf78-71823187a824', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'TaskTarget person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c0c28147-9606-4d8f-9c27-688f19c00dc4', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '26cc6ba3-cff7-4b84-bf78-71823187a824', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'b328a712-5dc3-457a-aa56-8631f1b57248', + name: 'taskTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e4414119-6f9c-465a-9ee2-95d1fc5eec01', + type: 'UUID', + name: 'opportunityId', + label: 'Opportunity id (foreign key)', + description: 'TaskTarget opportunity id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '598688a1-9766-439d-abd3-c0a47c8f36a3', + type: 'RELATION', + name: 'opportunity', + label: 'Opportunity', + description: 'TaskTarget opportunity', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8cdbd838-30d2-4062-94aa-0fa93376635c', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '598688a1-9766-439d-abd3-c0a47c8f36a3', + name: 'opportunity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '9e7b7d2f-02fb-426b-8e3e-392225f5b6b3', + name: 'taskTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'cd7f57e8-a67f-4be9-a971-b5609cb0fb83', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'TaskTarget company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '309200d8-c547-47a7-82a5-25915056db15', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'cd7f57e8-a67f-4be9-a971-b5609cb0fb83', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd69eb854-c043-43d9-a40e-65a0649fd1a9', + name: 'taskTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '400c9e53-283b-42d8-a69f-5010fb75d977', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ec532542-a4dc-4722-99c3-fca6366db597', + type: 'RELATION', + name: 'task', + label: 'Task', + description: 'TaskTarget task', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '81926481-abaa-4b04-900e-2170694cc034', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'ec532542-a4dc-4722-99c3-fca6366db597', + name: 'task', + }, + targetObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + targetFieldMetadata: { + __typename: 'field', + id: '80932806-6350-4941-a291-4d1430275d65', + name: 'taskTargets', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + labelSingular: 'Note Target', + labelPlural: 'Note Targets', + description: 'A note target', + icon: 'IconCheckbox', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'e6a5a8b1-ebef-4e01-ba22-a5f86d894eb5', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEz', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '26c57af1-5c70-4a9d-974f-e54c6a77a2b4', + type: 'RELATION', + name: 'rocket', + label: 'Rocket', + description: 'NoteTarget Rocket', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.605Z', + updatedAt: '2024-09-25T13:45:42.605Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '9cbf4ccc-cff9-4439-86c9-6f8c01970442', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '26c57af1-5c70-4a9d-974f-e54c6a77a2b4', + name: 'rocket', + }, + targetObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '75f64c23-e9a5-4ada-8dc6-3c2c2ea27280', + name: 'noteTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '434d1fd2-e6e0-4de7-9b15-706398e34d2d', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '06fcb5e2-b2f7-4118-a9f0-34558429b72c', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4b6aaf36-4247-4bbb-b26d-64987b02f805', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'NoteTarget company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '706df621-2977-49c9-a05f-38a6d4389011', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '4b6aaf36-4247-4bbb-b26d-64987b02f805', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: '531c4b2e-94a0-46f4-9395-277c3239413d', + name: 'noteTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c9bbd140-d9ab-4557-bd77-b446cd80774b', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'NoteTarget person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b86fd021-b648-4a1e-b02e-080f0b280303', + type: 'UUID', + name: 'rocketId', + label: 'Rocket ID (foreign key)', + description: 'NoteTarget Rocket id foreign key', + icon: null, + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.602Z', + updatedAt: '2024-09-25T13:45:42.602Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'cd3a9c3d-a29e-4b27-9fdb-0e8959f21f10', + type: 'UUID', + name: 'opportunityId', + label: 'Opportunity id (foreign key)', + description: 'NoteTarget opportunity id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e6a5a8b1-ebef-4e01-ba22-a5f86d894eb5', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9d568132-6cbc-4e87-95e8-7c2509549391', + type: 'RELATION', + name: 'note', + label: 'Note', + description: 'NoteTarget note', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e512fc88-2b02-4ba4-a118-ead545db5a63', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '9d568132-6cbc-4e87-95e8-7c2509549391', + name: 'note', + }, + targetObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'bef43ac8-834a-4a86-8bfb-5bed6cd94a57', + name: 'noteTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6f80afcd-8ed7-4bf9-a987-9de3d1cddc81', + type: 'RELATION', + name: 'opportunity', + label: 'Opportunity', + description: 'NoteTarget opportunity', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c6d4a2d6-1baf-49c3-87a8-2516c098b717', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '6f80afcd-8ed7-4bf9-a987-9de3d1cddc81', + name: 'opportunity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '78f1d502-397e-4cce-b096-a525b2d373e2', + name: 'noteTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dc63ee78-06ac-4312-b223-1d41a7ea2af4', + type: 'UUID', + name: 'noteId', + label: 'Note id (foreign key)', + description: 'NoteTarget note id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '646f3b4b-0fad-495a-a90d-136593464c7f', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'NoteTarget company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2b9481a9-c605-45d0-8aad-801a19c4b92c', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '77508442-f0de-4809-b690-3c998edfc0b5', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'NoteTarget person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '4bde4058-4875-4a16-9cc3-4e387121a875', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '77508442-f0de-4809-b690-3c998edfc0b5', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: '0f7b1621-5da6-439a-927f-948fd2dd6f29', + name: 'noteTargets', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'ee346c8e-6ca8-4142-852e-2d9180e80176', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'messageChannelMessageAssociation', + namePlural: 'messageChannelMessageAssociations', + labelSingular: 'Message Channel Message Association', + labelPlural: 'Message Channel Message Associations', + description: 'Message Synced with a Message Channel', + icon: 'IconMessage', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'f3eafb28-947a-4c7a-9464-24fa5549fb03', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEw', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '27e79204-ba19-4791-8110-ec2bdc523e07', + type: 'TEXT', + name: 'messageThreadExternalId', + label: 'Thread External Id', + description: 'Thread id from the messaging provider', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1d9f0c85-c16f-41e9-9241-2acd90781cdd', + type: 'RELATION', + name: 'message', + label: 'Message Id', + description: 'Message Id', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'f9f525c4-c303-48a0-aaeb-23dcb0ef41bb', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'ee346c8e-6ca8-4142-852e-2d9180e80176', + nameSingular: 'messageChannelMessageAssociation', + namePlural: 'messageChannelMessageAssociations', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '1d9f0c85-c16f-41e9-9241-2acd90781cdd', + name: 'message', + }, + targetObjectMetadata: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + nameSingular: 'message', + namePlural: 'messages', + }, + targetFieldMetadata: { + __typename: 'field', + id: '86a6dca6-5ad5-4576-b8f4-4be343e573de', + name: 'messageChannelMessageAssociations', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '72a85b74-9803-4279-9f74-dafb833847fb', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6cb121b9-32d1-44fe-af26-324d73ffe0ac', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9491ddd2-aea5-47fe-bd93-09fb6969b20c', + type: 'TEXT', + name: 'messageExternalId', + label: 'Message External Id', + description: 'Message id from the messaging provider', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f3eafb28-947a-4c7a-9464-24fa5549fb03', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dbfff493-11a0-4866-9ef6-e4e8418a661a', + type: 'UUID', + name: 'messageChannelId', + label: 'Message Channel Id id (foreign key)', + description: 'Message Channel Id id foreign key', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '95488a9d-6473-47e8-aa62-a04d49238a2f', + type: 'UUID', + name: 'messageId', + label: 'Message Id id (foreign key)', + description: 'Message Id id foreign key', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f4582d66-df12-4499-8ede-ab347427241b', + type: 'RELATION', + name: 'messageChannel', + label: 'Message Channel Id', + description: 'Message Channel Id', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '9047ee65-1739-4228-8e3a-255bbaf7b374', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'ee346c8e-6ca8-4142-852e-2d9180e80176', + nameSingular: 'messageChannelMessageAssociation', + namePlural: 'messageChannelMessageAssociations', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f4582d66-df12-4499-8ede-ab347427241b', + name: 'messageChannel', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ec7f4695-2b0a-49c8-881d-73f046aba063', + nameSingular: 'messageChannel', + namePlural: 'messageChannels', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'a3c22a32-9c6c-4294-abc4-7b3f9b6d8816', + name: 'messageChannelMessageAssociations', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7bf79a5a-f5b7-495e-a336-4ddf85a5b2f7', + type: 'SELECT', + name: 'direction', + label: 'Direction', + description: 'Message Direction', + icon: 'IconDirection', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'INCOMING'", + options: [ + { + id: '8b272ab7-bc81-4896-bba3-c222e087e7fb', + color: 'green', + label: 'Incoming', + value: 'INCOMING', + position: 0, + }, + { + id: 'c57aa860-fdf0-455f-97ee-4a0bf7e31202', + color: 'blue', + label: 'Outgoing', + value: 'OUTGOING', + position: 1, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a18edc4a-1b58-4a78-8de4-9564479b09cc', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + labelSingular: 'Message Participant', + labelPlural: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '8dcde658-c38a-4659-8546-89c60465d36e', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEy', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ea62fcb2-2161-47db-9151-19011419ac66', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e2f2b624-93bf-4d16-8517-bf66e43cabc4', + type: 'RELATION', + name: 'message', + label: 'Message', + description: 'Message', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7048eb73-25bf-4170-9ac0-41b7f8dec24b', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'e2f2b624-93bf-4d16-8517-bf66e43cabc4', + name: 'message', + }, + targetObjectMetadata: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + nameSingular: 'message', + namePlural: 'messages', + }, + targetFieldMetadata: { + __typename: 'field', + id: '606cef74-d9c3-4abc-b6ae-bb778f518e49', + name: 'messageParticipants', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b92e3ff7-e5e0-4fec-b36e-cb496e2b57ae', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ef5a67e6-88dd-4c92-a9be-7ab0605804e7', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f3db188f-7329-40bc-9978-e30e5c07d962', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'Person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8c36bb62-2757-4c24-88da-160a6a9e56d6', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f3db188f-7329-40bc-9978-e30e5c07d962', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: '779bdf5a-a28d-48be-8d02-b6ca93851829', + name: 'messageParticipants', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '26c81156-529d-4bec-b5fb-f92e991907b5', + type: 'UUID', + name: 'messageId', + label: 'Message id (foreign key)', + description: 'Message id foreign key', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aa502069-91c1-4eeb-bc8e-b22240564fe1', + type: 'TEXT', + name: 'displayName', + label: 'Display Name', + description: 'Display Name', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd205df4f-f9de-4f61-9a85-40f340a4de23', + type: 'RELATION', + name: 'workspaceMember', + label: 'Workspace Member', + description: 'Workspace member', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'fa25f857-7b30-4cd7-87c6-7910bde2d050', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd205df4f-f9de-4f61-9a85-40f340a4de23', + name: 'workspaceMember', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd82db237-ca6d-4bee-8d69-dfa0f753707b', + name: 'messageParticipants', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0cf35f0a-eb64-47ef-88a4-55b92ca57c64', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'Person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e8550477-6034-45f4-8370-5a1cd75f7a55', + type: 'UUID', + name: 'workspaceMemberId', + label: 'Workspace Member id (foreign key)', + description: 'Workspace member id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8dcde658-c38a-4659-8546-89c60465d36e', + type: 'TEXT', + name: 'handle', + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '56ff0ed7-7916-4610-834c-a7c0657fa9e7', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7a8597e3-bbce-4ff5-9f6e-9bf3c7fd43fa', + type: 'SELECT', + name: 'role', + label: 'Role', + description: 'Role', + icon: 'IconAt', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'from'", + options: [ + { + id: 'c6cd481c-59fd-4107-bcb7-f09474785c06', + color: 'green', + label: 'From', + value: 'from', + position: 0, + }, + { + id: '8957abb3-924b-4cb5-af08-8b96269ce502', + color: 'blue', + label: 'To', + value: 'to', + position: 1, + }, + { + id: '9e814524-6b58-4395-bdd4-3ce29218cd80', + color: 'orange', + label: 'Cc', + value: 'cc', + position: 2, + }, + { + id: '3efb003f-644d-4a71-abfa-565932918a16', + color: 'red', + label: 'Bcc', + value: 'bcc', + position: 3, + }, + ], + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'ec7f4695-2b0a-49c8-881d-73f046aba063', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'messageChannel', + namePlural: 'messageChannels', + labelSingular: 'Message Channel', + labelPlural: 'Message Channels', + description: 'Message Channels', + icon: 'IconMessage', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '7ca7d194-3cdc-4ff9-a90f-6bfaedba8280', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjIw', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9061081a-eed9-49b8-99ab-9a7b8ce7a355', + type: 'BOOLEAN', + name: 'isContactAutoCreationEnabled', + label: 'Is Contact Auto Creation Enabled', + description: 'Is Contact Auto Creation Enabled', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'df104a7c-39e5-491d-8bde-6e3f75a3156b', + type: 'DATE_TIME', + name: 'syncedAt', + label: 'Last sync date', + description: 'Last sync date', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '751ef307-be5e-4451-9434-e2bae8861873', + type: 'BOOLEAN', + name: 'excludeNonProfessionalEmails', + label: 'Exclude non professional emails', + description: 'Exclude non professional emails', + icon: 'IconBriefcase', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9a8520ed-6577-46b0-a732-1a08aafb0160', + type: 'SELECT', + name: 'visibility', + label: 'Visibility', + description: 'Visibility', + icon: 'IconEyeglass', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'SHARE_EVERYTHING'", + options: [ + { + id: 'b4ebf1ba-0434-4697-b851-d171b7d34cdf', + color: 'green', + label: 'Metadata', + value: 'METADATA', + position: 0, + }, + { + id: '6081348d-23da-44a6-8b16-57fc550e24c6', + color: 'blue', + label: 'Subject', + value: 'SUBJECT', + position: 1, + }, + { + id: '6cd27613-6217-4aac-9c62-5c956a187786', + color: 'orange', + label: 'Share Everything', + value: 'SHARE_EVERYTHING', + position: 2, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2f7f7ea2-c5d0-47bc-bb0e-e3afc6d82b91', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dafc931d-0466-4c83-91b3-72be3fdee12f', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '97ba10a8-da33-4d1f-a9c6-964f814f5fd7', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a3c22a32-9c6c-4294-abc4-7b3f9b6d8816', + type: 'RELATION', + name: 'messageChannelMessageAssociations', + label: 'Message Channel Association', + description: 'Messages from the channel.', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '9047ee65-1739-4228-8e3a-255bbaf7b374', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'ec7f4695-2b0a-49c8-881d-73f046aba063', + nameSingular: 'messageChannel', + namePlural: 'messageChannels', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'a3c22a32-9c6c-4294-abc4-7b3f9b6d8816', + name: 'messageChannelMessageAssociations', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ee346c8e-6ca8-4142-852e-2d9180e80176', + nameSingular: 'messageChannelMessageAssociation', + namePlural: 'messageChannelMessageAssociations', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f4582d66-df12-4499-8ede-ab347427241b', + name: 'messageChannel', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c1686e5a-1af6-45d9-a9f8-d2ecaef71526', + type: 'RELATION', + name: 'connectedAccount', + label: 'Connected Account', + description: 'Connected Account', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '37d43107-c5ad-4d15-bd29-2bc6986f75d8', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'ec7f4695-2b0a-49c8-881d-73f046aba063', + nameSingular: 'messageChannel', + namePlural: 'messageChannels', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c1686e5a-1af6-45d9-a9f8-d2ecaef71526', + name: 'connectedAccount', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + }, + targetFieldMetadata: { + __typename: 'field', + id: '178f1e8a-cbbf-448e-95f3-d1262d9ff33d', + name: 'messageChannels', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7eaa0427-04b4-4cf8-9676-4e28c88a0fa8', + type: 'DATE_TIME', + name: 'syncStageStartedAt', + label: 'Sync stage started at', + description: 'Sync stage started at', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '290318a3-e994-4dee-8dd1-6bebe92043af', + type: 'SELECT', + name: 'syncStatus', + label: 'Sync status', + description: 'Sync status', + icon: 'IconStatusChange', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: [ + { + id: 'a875b66f-c31a-4bdb-b75a-0b1454f1fb2e', + color: 'yellow', + label: 'Ongoing', + value: 'ONGOING', + position: 1, + }, + { + id: '37d8441e-8649-4986-abc4-457a0e804635', + color: 'blue', + label: 'Not Synced', + value: 'NOT_SYNCED', + position: 2, + }, + { + id: '45b1f6c8-ed8e-4f54-a3fb-40ce6ab035a8', + color: 'green', + label: 'Active', + value: 'ACTIVE', + position: 3, + }, + { + id: '350b5cff-abbd-4232-bd82-35f904e8a9fc', + color: 'red', + label: 'Failed Insufficient Permissions', + value: 'FAILED_INSUFFICIENT_PERMISSIONS', + position: 4, + }, + { + id: '850bbb80-49bb-48bb-986f-e72351f80014', + color: 'red', + label: 'Failed Unknown', + value: 'FAILED_UNKNOWN', + position: 5, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7238d6c1-c54c-4787-aa4f-79294220acdc', + type: 'BOOLEAN', + name: 'isSyncEnabled', + label: 'Is Sync Enabled', + description: 'Is Sync Enabled', + icon: 'IconRefresh', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9416f68a-84cb-4b1f-805b-e58fb009cc44', + type: 'TEXT', + name: 'syncCursor', + label: 'Last sync cursor', + description: 'Last sync cursor', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '09ec080b-c8fe-432f-aff1-c151861c3ec7', + type: 'SELECT', + name: 'contactAutoCreationPolicy', + label: 'Contact auto creation policy', + description: + 'Automatically create People records when receiving or sending emails', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'SENT'", + options: [ + { + id: '1a097274-4e65-4488-ac6b-0756f80c97c5', + color: 'green', + label: 'Sent and Received', + value: 'SENT_AND_RECEIVED', + position: 0, + }, + { + id: '1968f899-3858-431b-8d5a-8802ba7c9862', + color: 'blue', + label: 'Sent', + value: 'SENT', + position: 1, + }, + { + id: '6e98f8e3-e57c-4292-ba26-61a03d131fef', + color: 'red', + label: 'None', + value: 'NONE', + position: 2, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd30ddf0c-769a-4480-a9cf-fea5867f9eea', + type: 'BOOLEAN', + name: 'excludeGroupEmails', + label: 'Exclude group emails', + description: 'Exclude group emails', + icon: 'IconUsersGroup', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '839a7a90-3b1a-4f76-8207-5a0779ca909d', + type: 'SELECT', + name: 'type', + label: 'Type', + description: 'Channel Type', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'email'", + options: [ + { + id: '214b0bc6-38b6-4cd6-9dbd-190619598d8e', + color: 'green', + label: 'Email', + value: 'email', + position: 0, + }, + { + id: '47d7521c-7ad5-42c0-9f80-11f39efcef82', + color: 'blue', + label: 'SMS', + value: 'sms', + position: 1, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b0026844-d54e-4fe2-af36-ed7ac7be1833', + type: 'UUID', + name: 'connectedAccountId', + label: 'Connected Account id (foreign key)', + description: 'Connected Account id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7ca7d194-3cdc-4ff9-a90f-6bfaedba8280', + type: 'TEXT', + name: 'handle', + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5f87d969-7dae-4a25-8b11-9577aa11285e', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aafcc52e-d761-4b6a-97a6-1bc097e2ccd2', + type: 'SELECT', + name: 'syncStage', + label: 'Sync stage', + description: 'Sync stage', + icon: 'IconStatusChange', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'FULL_MESSAGE_LIST_FETCH_PENDING'", + options: [ + { + id: '84df43eb-72c8-433b-a861-b98db7d2d224', + color: 'blue', + label: 'Full messages list fetch pending', + value: 'FULL_MESSAGE_LIST_FETCH_PENDING', + position: 0, + }, + { + id: '562abf2a-c19f-4782-bc2d-5a9e8707fc45', + color: 'blue', + label: 'Partial messages list fetch pending', + value: 'PARTIAL_MESSAGE_LIST_FETCH_PENDING', + position: 1, + }, + { + id: 'fd47b29d-9d01-4f3e-8503-63649665a966', + color: 'orange', + label: 'Messages list fetch ongoing', + value: 'MESSAGE_LIST_FETCH_ONGOING', + position: 2, + }, + { + id: '23e113b3-0f82-47c6-b668-54955bb05baa', + color: 'blue', + label: 'Messages import pending', + value: 'MESSAGES_IMPORT_PENDING', + position: 3, + }, + { + id: '3d751a1f-d1cb-43ca-801f-3b3248a39b96', + color: 'orange', + label: 'Messages import ongoing', + value: 'MESSAGES_IMPORT_ONGOING', + position: 4, + }, + { + id: '16478389-d2b5-47f7-af2e-239d25f6d0d4', + color: 'red', + label: 'Failed', + value: 'FAILED', + position: 5, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '33180dbd-4124-43eb-84c3-17e32b4848e4', + type: 'NUMBER', + name: 'throttleFailureCount', + label: 'Throttle Failure Count', + description: 'Throttle Failure Count', + icon: 'IconX', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 0, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + labelSingular: 'Connected Account', + labelPlural: 'Connected Accounts', + description: 'A connected account', + icon: 'IconAt', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '762d59c0-f7e9-410f-b5dc-df66d764de0d', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE0', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8ca32bd7-4999-4562-9e41-698a458944ea', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '236195db-49d1-4386-99b9-4518ab7586f2', + type: 'RELATION', + name: 'accountOwner', + label: 'Account Owner', + description: 'Account Owner', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'ee186212-93d2-4f15-b74c-c703bedbd396', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '236195db-49d1-4386-99b9-4518ab7586f2', + name: 'accountOwner', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: '13531c23-42ca-4b1e-a6e3-3fcfad74a3e9', + name: 'connectedAccounts', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '919dadd4-8dda-479f-a8a7-b4ed89eafae5', + type: 'RELATION', + name: 'calendarChannels', + label: 'Calendar Channels', + description: 'Calendar Channels', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7fe521fe-1b22-4354-92ba-8164ce5c9b5d', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '919dadd4-8dda-479f-a8a7-b4ed89eafae5', + name: 'calendarChannels', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'c8993ad6-46d5-4ab0-88f5-d407625c0c75', + nameSingular: 'calendarChannel', + namePlural: 'calendarChannels', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c933e11e-7820-42e4-a589-389c2f314add', + name: 'connectedAccount', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '75c78041-39ca-4b46-bcff-6ed0af05248e', + type: 'TEXT', + name: 'handleAliases', + label: 'Handle Aliases', + description: 'Handle Aliases', + icon: 'IconMail', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd3f821eb-c8b1-48a5-aebb-1bfe23c4128e', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6f74d250-76f0-4eff-8e27-d1a12782517d', + type: 'TEXT', + name: 'lastSyncHistoryId', + label: 'Last sync history ID', + description: 'Last sync history ID', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fd6c04f4-8dba-47ac-a597-90300eb1a079', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8f7d7528-83a8-442e-b0b6-958f52a1de5e', + type: 'DATE_TIME', + name: 'authFailedAt', + label: 'Auth failed at', + description: 'Auth failed at', + icon: 'IconX', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '762d59c0-f7e9-410f-b5dc-df66d764de0d', + type: 'TEXT', + name: 'handle', + label: 'handle', + description: + 'The account handle (email, username, phone number, etc.)', + icon: 'IconMail', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f45f5e44-f88a-490c-b112-df2465b612a3', + type: 'TEXT', + name: 'refreshToken', + label: 'Refresh Token', + description: 'Messaging provider refresh token', + icon: 'IconKey', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2aa282f3-5542-47e8-adf3-4384e9ce5d10', + type: 'UUID', + name: 'accountOwnerId', + label: 'Account Owner id (foreign key)', + description: 'Account Owner id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5f411e82-b626-4456-896c-d5a326e5e02a', + type: 'TEXT', + name: 'accessToken', + label: 'Access Token', + description: 'Messaging provider access token', + icon: 'IconKey', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c21734fd-6539-410f-bc1a-e91a3177b9c9', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5b0a8a38-9d02-4e06-8f07-2f76f0ab70eb', + type: 'TEXT', + name: 'provider', + label: 'provider', + description: 'The account provider', + icon: 'IconSettings', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '178f1e8a-cbbf-448e-95f3-d1262d9ff33d', + type: 'RELATION', + name: 'messageChannels', + label: 'Message Channels', + description: 'Message Channels', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '37d43107-c5ad-4d15-bd29-2bc6986f75d8', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '178f1e8a-cbbf-448e-95f3-d1262d9ff33d', + name: 'messageChannels', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ec7f4695-2b0a-49c8-881d-73f046aba063', + nameSingular: 'messageChannel', + namePlural: 'messageChannels', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c1686e5a-1af6-45d9-a9f8-d2ecaef71526', + name: 'connectedAccount', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'opportunity', + namePlural: 'opportunities', + labelSingular: 'Opportunity', + labelPlural: 'Opportunities', + description: 'An opportunity', + icon: 'IconTargetArrow', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '6d5401c0-d456-42c4-85d4-9666900615ef', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE5', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9e7b7d2f-02fb-426b-8e3e-392225f5b6b3', + type: 'RELATION', + name: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the opportunity', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8cdbd838-30d2-4062-94aa-0fa93376635c', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '9e7b7d2f-02fb-426b-8e3e-392225f5b6b3', + name: 'taskTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '598688a1-9766-439d-abd3-c0a47c8f36a3', + name: 'opportunity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '78f1d502-397e-4cce-b096-a525b2d373e2', + type: 'RELATION', + name: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the opportunity', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c6d4a2d6-1baf-49c3-87a8-2516c098b717', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '78f1d502-397e-4cce-b096-a525b2d373e2', + name: 'noteTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '6f80afcd-8ed7-4bf9-a987-9de3d1cddc81', + name: 'opportunity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c692555c-020e-46a4-b537-c9c4c7d3cd32', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6d32aa8b-28c0-4e35-b45e-9643fd8e1c33', + type: 'CURRENCY', + name: 'amount', + label: 'Amount', + description: 'Opportunity amount', + icon: 'IconCurrencyDollar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + amountMicros: null, + currencyCode: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c859b99c-2554-483d-8ffe-4d29cb9c8459', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'Opportunity company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '06717b0b-194c-46e4-9394-f2ef37bdee90', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c859b99c-2554-483d-8ffe-4d29cb9c8459', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: '8421d3d3-d5ac-4065-a431-95780fda2ce7', + name: 'opportunities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7ad6853d-d1e9-46a8-a77a-38eeae27e1d6', + type: 'RELATION', + name: 'pointOfContact', + label: 'Point of Contact', + description: 'Opportunity point of contact', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c80603a0-f9b4-47c0-ba4d-7a1c5d0735e8', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '7ad6853d-d1e9-46a8-a77a-38eeae27e1d6', + name: 'pointOfContact', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f926708e-cc19-4e5f-8684-d14a1a1bc7df', + name: 'pointOfContactForOpportunities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f6c45230-619b-4432-82fd-e5bed0c4e8f4', + type: 'SELECT', + name: 'stage', + label: 'Stage', + description: 'Opportunity stage', + icon: 'IconProgressCheck', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'NEW'", + options: [ + { + id: '2bf53bd1-c267-4389-bd53-60d91d623e52', + color: 'red', + label: 'New', + value: 'NEW', + position: 0, + }, + { + id: 'b2c9d73a-2c6d-4bd9-a159-f72554ee8b68', + color: 'purple', + label: 'Screening', + value: 'SCREENING', + position: 1, + }, + { + id: 'e42a14ea-6a05-4ca8-8096-e61cf21aa94e', + color: 'sky', + label: 'Meeting', + value: 'MEETING', + position: 2, + }, + { + id: 'a90f6256-246d-4897-b86e-bfd30aec941b', + color: 'turquoise', + label: 'Proposal', + value: 'PROPOSAL', + position: 3, + }, + { + id: '3ac0a9b3-259a-4876-9912-6f4fd4aa5a9f', + color: 'yellow', + label: 'Customer', + value: 'CUSTOMER', + position: 4, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5d3ca5b4-9468-4061-8c6b-ef03a9b123df', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the opportunity', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'aeb1d35c-771a-4226-a11a-4dbe1228fa7c', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '5d3ca5b4-9468-4061-8c6b-ef03a9b123df', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '1d3858e1-e4aa-484f-b422-8bbefa9409c8', + name: 'opportunity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3bc37e42-10f2-4501-94e4-760a7c3fa38e', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Opportunity record position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9019bf90-efbc-4499-a87b-0624bda5a559', + type: 'RELATION', + name: 'timelineActivities', + label: 'Timeline Activities', + description: + 'Timeline Activities linked to the opportunity.', + icon: 'IconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8d8d083e-b9a2-4de2-a368-2422a4df4a83', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '9019bf90-efbc-4499-a87b-0624bda5a559', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '88a829b3-6d66-4e53-b1ad-ed02e544e4d2', + name: 'opportunity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c7472787-44e9-4641-9901-cc4909ca031d', + type: 'DATE_TIME', + name: 'closeDate', + label: 'Close date', + description: 'Opportunity close date', + icon: 'IconCalendarEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '01e75534-627f-4a49-bc28-c08170a71085', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6d5401c0-d456-42c4-85d4-9666900615ef', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'The opportunity name', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aa651efa-1576-4edc-9599-070666a76dda', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the opportunity', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'ca5b3017-82e4-4d9f-94c1-c73a37b56e0b', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'aa651efa-1576-4edc-9599-070666a76dda', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'fa9d964c-3d30-4d8b-bc57-9b382053e9e3', + name: 'opportunity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b8eb99bd-3485-44bb-8483-f0c600af4e92', + type: 'UUID', + name: 'pointOfContactId', + label: 'Point of Contact id (foreign key)', + description: 'Opportunity point of contact id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '55fd22aa-80df-4c0b-b5ee-f19163d10a82', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'Opportunity company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd487fe61-e181-4077-ba4e-9c7b466085ad', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bf11e668-6598-42ee-8c81-563641403ba9', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2e77023d-fdeb-454d-9368-ab638a68a0bb', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ac708d8f-abd4-436f-aec7-9a8c4ec2cd28', + type: 'RELATION', + name: 'activityTargets', + label: 'Activities', + description: 'Activities tied to the opportunity', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '842709df-7276-45b0-8c07-cc44b1f575c6', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'ac708d8f-abd4-436f-aec7-9a8c4ec2cd28', + name: 'activityTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c2708db4-5c1e-482b-bdd4-bd620612c15f', + name: 'opportunity', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + labelSingular: 'Activity Target', + labelPlural: 'Activity Targets', + description: 'An activity target', + icon: 'IconCheckbox', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '86438a20-0beb-4e73-93d9-cf91bfe9ac3f', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEz', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4a2da98e-6880-47be-8673-165e1d77a910', + type: 'RELATION', + name: 'rocket', + label: 'Rocket', + description: 'ActivityTarget Rocket', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.577Z', + updatedAt: '2024-09-25T13:45:42.577Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '624c8a51-ba95-409f-bd54-72c85bb1bb2d', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '4a2da98e-6880-47be-8673-165e1d77a910', + name: 'rocket', + }, + targetObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '9aed4be2-3434-489f-a8a3-384311ee585e', + name: 'activityTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '03aab98d-e16c-48fb-91e7-bffc2300402d', + type: 'UUID', + name: 'opportunityId', + label: 'Opportunity id (foreign key)', + description: 'ActivityTarget opportunity id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e1d06322-0658-4c45-9c9b-8a42750c8751', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'ActivityTarget company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '08d38bf1-1b43-416a-915d-1d5718a829a7', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'e1d06322-0658-4c45-9c9b-8a42750c8751', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'e2e632fe-1c08-4c12-9aba-88f8595bf5be', + name: 'activityTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ca812263-7b62-4e7f-8f31-bed3de2d4a94', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '984d38ae-335d-41fb-ac29-9029ff43c4c6', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'ActivityTarget company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b2531e1e-39ad-46c8-af56-853fe1cc7dd6', + type: 'RELATION', + name: 'activity', + label: 'Activity', + description: 'ActivityTarget activity', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'bb02c0cb-18dc-4af7-ae59-d105c515bddc', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'b2531e1e-39ad-46c8-af56-853fe1cc7dd6', + name: 'activity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '1dc0b9af-181a-4f2c-bd01-9c4bf355b9de', + name: 'activityTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '26d681d7-4ef2-40eb-bd0c-7e0b7d6d6cb0', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'ActivityTarget person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dc9c8fec-55d2-40b6-9fcd-d441024be60f', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '08806161-5d03-4777-8825-b5cff93de042', + type: 'UUID', + name: 'activityId', + label: 'Activity id (foreign key)', + description: 'ActivityTarget activity id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9ff04b9e-f87c-44df-82ed-518748ca0d81', + type: 'UUID', + name: 'rocketId', + label: 'Rocket ID (foreign key)', + description: 'ActivityTarget Rocket id foreign key', + icon: null, + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.575Z', + updatedAt: '2024-09-25T13:45:42.575Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '86438a20-0beb-4e73-93d9-cf91bfe9ac3f', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2f2ed506-e96e-48d3-8225-45a9c0b55e76', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '867aff40-ddf5-4af8-a3f5-6359ab91eb2c', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'ActivityTarget person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '22f8c2a7-9887-4642-821c-6fefaab56aed', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '867aff40-ddf5-4af8-a3f5-6359ab91eb2c', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: '23c64ee1-4935-4a25-b401-afc08a0967fd', + name: 'activityTargets', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c2708db4-5c1e-482b-bdd4-bd620612c15f', + type: 'RELATION', + name: 'opportunity', + label: 'Opportunity', + description: 'ActivityTarget opportunity', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '842709df-7276-45b0-8c07-cc44b1f575c6', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c2708db4-5c1e-482b-bdd4-bd620612c15f', + name: 'opportunity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'ac708d8f-abd4-436f-aec7-9a8c4ec2cd28', + name: 'activityTargets', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'activity', + namePlural: 'activities', + labelSingular: 'Activity', + labelPlural: 'Activities', + description: 'An activity', + icon: 'IconCheckbox', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '7314a7d0-f318-4aa0-b8f3-db1953139d3f', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE2', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'eb926345-9d3c-4815-a044-bf1085b31cdc', + type: 'UUID', + name: 'assigneeId', + label: 'Assignee id (foreign key)', + description: 'Activity assignee id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7314a7d0-f318-4aa0-b8f3-db1953139d3f', + type: 'TEXT', + name: 'title', + label: 'Title', + description: 'Activity title', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3e63dfad-08ba-422f-88e5-0c1ebffd6496', + type: 'RELATION', + name: 'author', + label: 'Author', + description: 'Activity author', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'dd13169a-0cc9-44c1-9e12-4d66e31dcfc0', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '3e63dfad-08ba-422f-88e5-0c1ebffd6496', + name: 'author', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f76b3faa-0bc6-45ed-9654-0421171a1f1a', + name: 'authoredActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5ceb1884-c3ff-4a31-9629-3ef599b1a461', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ffdb396b-200a-4dc5-a3aa-e2c23b180ac0', + type: 'TEXT', + name: 'body', + label: 'Body', + description: 'Activity body', + icon: 'IconList', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0f1cfe74-f960-44f9-91f3-fc9d25a4b96b', + type: 'RELATION', + name: 'comments', + label: 'Comments', + description: 'Activity comments', + icon: 'IconComment', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'a3bdce1c-b0a8-4961-8a06-b7dc8355e879', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '0f1cfe74-f960-44f9-91f3-fc9d25a4b96b', + name: 'comments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '7610fd21-9f3e-44d2-bdf9-f30e442ead53', + nameSingular: 'comment', + namePlural: 'comments', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'e48bc6a2-211c-46aa-9f22-1859aedac28e', + name: 'activity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '248b356d-5a70-458d-a10b-92d70512497b', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2f1f7b1a-2c98-42ca-8f6c-784406d7bad8', + type: 'UUID', + name: 'authorId', + label: 'Author id (foreign key)', + description: 'Activity author id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '799c1e27-3fa5-4411-bfa2-a1f494d2434a', + type: 'DATE_TIME', + name: 'reminderAt', + label: 'Reminder Date', + description: 'Activity reminder date', + icon: 'IconCalendarEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dd5354bb-dd0a-4426-ac75-87e9ab171dc4', + type: 'RELATION', + name: 'assignee', + label: 'Assignee', + description: 'Activity assignee', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'bd41ada4-a132-4297-8f7f-e622a090f243', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'dd5354bb-dd0a-4426-ac75-87e9ab171dc4', + name: 'assignee', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'e32f7a81-d208-4c14-afb4-a4befc938670', + name: 'assignedActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd7b4584a-d0ed-49f8-b14c-198036b60fe8', + type: 'DATE_TIME', + name: 'dueAt', + label: 'Due Date', + description: 'Activity due date', + icon: 'IconCalendarEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9b8808d3-be01-4595-9b20-ebb9553cd7db', + type: 'DATE_TIME', + name: 'completedAt', + label: 'Completion Date', + description: 'Activity completion date', + icon: 'IconCheck', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd0341ced-bdb0-4629-a816-d402df827bd7', + type: 'TEXT', + name: 'type', + label: 'Type', + description: 'Activity type', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'Note'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1dc0b9af-181a-4f2c-bd01-9c4bf355b9de', + type: 'RELATION', + name: 'activityTargets', + label: 'Targets', + description: 'Activity targets', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'bb02c0cb-18dc-4af7-ae59-d105c515bddc', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '1dc0b9af-181a-4f2c-bd01-9c4bf355b9de', + name: 'activityTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'b2531e1e-39ad-46c8-af56-853fe1cc7dd6', + name: 'activity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b31fdd11-115b-4405-8265-c03329338f0c', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bfa2ab3d-a55b-41ca-906b-9d497aee7ba8', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Activity attachments', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e954bb33-50a5-4f94-85c3-be141fa17f70', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'bfa2ab3d-a55b-41ca-906b-9d497aee7ba8', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: '3669c8b2-ba73-4e9b-be61-10a2023955fd', + name: 'activity', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '33b0ccb9-19fc-42d6-b7af-87bc4411692e', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + labelSingular: 'Calendar event participant', + labelPlural: 'Calendar event participants', + description: 'Calendar event participants', + icon: 'IconCalendar', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'c97d9e28-d807-4fff-ba2c-c72f99087f89', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEz', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e166c79b-99c1-4fb4-9575-5cf7e7f4811f', + type: 'BOOLEAN', + name: 'isOrganizer', + label: 'Is Organizer', + description: 'Is Organizer', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: false, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '34f2ac5d-bb7e-446c-ab52-18e722345a24', + type: 'UUID', + name: 'workspaceMemberId', + label: 'Workspace Member id (foreign key)', + description: 'Workspace Member id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0c215138-fc5b-4be2-8c37-0acc7cb4e5a1', + type: 'SELECT', + name: 'responseStatus', + label: 'Response Status', + description: 'Response Status', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'NEEDS_ACTION'", + options: [ + { + id: '0896acf3-8f3e-4b7f-ba24-e102e68a9c30', + color: 'orange', + label: 'Needs Action', + value: 'NEEDS_ACTION', + position: 0, + }, + { + id: '6eefa8a1-3a90-4fb2-afd1-b46b73598c6a', + color: 'red', + label: 'Declined', + value: 'DECLINED', + position: 1, + }, + { + id: 'ec2aea9f-55c8-44b2-b98e-b861a075edf2', + color: 'yellow', + label: 'Tentative', + value: 'TENTATIVE', + position: 2, + }, + { + id: '96ae698f-1bae-43e2-8ec2-5fc928de9959', + color: 'green', + label: 'Accepted', + value: 'ACCEPTED', + position: 3, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '16b867dd-9fb1-43ab-8254-2478004b30b3', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fdfea59a-624c-4af3-9901-1f86d1972b23', + type: 'TEXT', + name: 'displayName', + label: 'Display Name', + description: 'Display Name', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2f77bc8e-26dc-40b1-964a-f0748feb193a', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'Person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7aced498-e104-4898-939c-187937ea7bca', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '2f77bc8e-26dc-40b1-964a-f0748feb193a', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'aa5e7931-e042-45d5-af4a-e4c22979a3b7', + name: 'calendarEventParticipants', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '597d153f-8724-4d61-8863-8bfae905721f', + type: 'RELATION', + name: 'calendarEvent', + label: 'Event ID', + description: 'Event ID', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '089a99c0-0893-4288-ad62-ac723007a426', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '597d153f-8724-4d61-8863-8bfae905721f', + name: 'calendarEvent', + }, + targetObjectMetadata: { + __typename: 'object', + id: '75c685e2-f612-415f-a81c-6ca8eda30c8d', + nameSingular: 'calendarEvent', + namePlural: 'calendarEvents', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'bc8be6a6-4707-498a-9e79-8ffb86e92a43', + name: 'calendarEventParticipants', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '83d94e19-f9f3-47bb-a277-6935af6ae69d', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'Person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'cc27c5b5-44cc-4f19-a56e-8ce172e2ab37', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '22c34bd1-550b-4b5c-a2a4-fbb475a4420b', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7b7792da-246d-4015-855a-ea029f0b8a02', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7794c913-c52f-4c06-921e-2b391b63e51e', + type: 'UUID', + name: 'calendarEventId', + label: 'Event ID id (foreign key)', + description: 'Event ID id foreign key', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '30fd4e8a-2089-4443-ac06-5cd53d9a3fcf', + type: 'RELATION', + name: 'workspaceMember', + label: 'Workspace Member', + description: 'Workspace Member', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'd23fa3d8-e4ce-4cc9-a949-cafbd231d563', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '30fd4e8a-2089-4443-ac06-5cd53d9a3fcf', + name: 'workspaceMember', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: '7370da8c-294f-4671-91e5-7f87f4dccc1e', + name: 'calendarEventParticipants', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c97d9e28-d807-4fff-ba2c-c72f99087f89', + type: 'TEXT', + name: 'handle', + label: 'Handle', + description: 'Handle', + icon: 'IconMail', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'cd90b6c9-4f22-4c62-a107-dc396e5396ed', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'auditLog', + namePlural: 'auditLogs', + labelSingular: 'Audit Log', + labelPlural: 'Audit Logs', + description: 'An audit log of actions performed in the system', + icon: 'IconIconTimelineEvent', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '0383ac8e-6138-4e06-a828-bfc391e53d01', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEx', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e8a5a86c-b1ce-4db1-8d51-d5b01d2b361b', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '09a753b7-a5f9-4810-ae2f-389982f593c3', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7881aa82-a7ed-4090-923d-f1c0cf16a486', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7f1d2847-9f16-457f-a57c-de36c401286a', + type: 'UUID', + name: 'recordId', + label: 'Record id', + description: 'Record id', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1db6f800-bb46-45a2-a324-cfe52362ed9a', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '785dc6cb-77dc-4bdd-be44-60ad8f1f45da', + type: 'UUID', + name: 'workspaceMemberId', + label: 'Workspace Member id (foreign key)', + description: 'Event workspace member id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3d6dc314-877d-4aaa-88bd-364dc50f780b', + type: 'RELATION', + name: 'workspaceMember', + label: 'Workspace Member', + description: 'Event workspace member', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '07071415-1159-4913-9dee-81b8f9b8cdb4', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'cd90b6c9-4f22-4c62-a107-dc396e5396ed', + nameSingular: 'auditLog', + namePlural: 'auditLogs', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '3d6dc314-877d-4aaa-88bd-364dc50f780b', + name: 'workspaceMember', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: '85df4525-aed1-4e46-b718-b5bc963da41d', + name: 'auditLogs', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '80fe2b13-5cb0-48a0-9341-aec08481628f', + type: 'RAW_JSON', + name: 'context', + label: 'Event context', + description: + 'Json object to provide context (user, device, workspace, etc.)', + icon: 'IconListDetails', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0383ac8e-6138-4e06-a828-bfc391e53d01', + type: 'TEXT', + name: 'name', + label: 'Event name', + description: 'Event name/type', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f4f0343a-8241-492a-8156-18d40c75f46a', + type: 'RAW_JSON', + name: 'properties', + label: 'Event details', + description: 'Json value for event details', + icon: 'IconListDetails', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a8282a28-724f-487b-a9fa-f0d10c919237', + type: 'TEXT', + name: 'objectName', + label: 'Object name', + description: 'Object name', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd85abbad-9616-456f-978c-4cced740490c', + type: 'TEXT', + name: 'objectMetadataId', + label: 'Object metadata id', + description: 'Object metadata id', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'c8993ad6-46d5-4ab0-88f5-d407625c0c75', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'calendarChannel', + namePlural: 'calendarChannels', + labelSingular: 'Calendar Channel', + labelPlural: 'Calendar Channels', + description: 'Calendar Channels', + icon: 'IconCalendar', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '93658b38-cb56-4d2b-93f8-3a4c7714f7c4', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE2', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '818ec7cd-9181-4c72-ad99-c19b00fde065', + type: 'TEXT', + name: 'syncCursor', + label: 'Sync Cursor', + description: + 'Sync Cursor. Used for syncing events from the calendar provider', + icon: 'IconReload', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '93658b38-cb56-4d2b-93f8-3a4c7714f7c4', + type: 'TEXT', + name: 'handle', + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'af61423d-0891-4e91-b6d3-2f7ed6363916', + type: 'UUID', + name: 'connectedAccountId', + label: 'Connected Account id (foreign key)', + description: 'Connected Account id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e921674b-2e9f-4f19-a067-920685cf9164', + type: 'SELECT', + name: 'visibility', + label: 'Visibility', + description: 'Visibility', + icon: 'IconEyeglass', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'SHARE_EVERYTHING'", + options: [ + { + id: '862f57cb-ef30-47e4-a520-396f1036f245', + color: 'green', + label: 'Metadata', + value: 'METADATA', + position: 0, + }, + { + id: '4e9e36e1-e402-4453-80ca-832f0e2e07a6', + color: 'orange', + label: 'Share Everything', + value: 'SHARE_EVERYTHING', + position: 1, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0abc3baf-2797-4f88-8565-a3ffa4468b55', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e567e960-f3c8-4ef0-b810-d8a4bc6a4f7d', + type: 'BOOLEAN', + name: 'isSyncEnabled', + label: 'Is Sync Enabled', + description: 'Is Sync Enabled', + icon: 'IconRefresh', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bb3531fe-a008-4505-820b-0cb2c365b05d', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd9a353c7-25ba-403f-8157-0d8bee911cec', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd1596020-b595-4bf9-b3c1-782f9b49f41b', + type: 'RELATION', + name: 'calendarChannelEventAssociations', + label: 'Calendar Channel Event Associations', + description: 'Calendar Channel Event Associations', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'da686bc9-04d2-4665-b0ce-2bfa306c1087', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'c8993ad6-46d5-4ab0-88f5-d407625c0c75', + nameSingular: 'calendarChannel', + namePlural: 'calendarChannels', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd1596020-b595-4bf9-b3c1-782f9b49f41b', + name: 'calendarChannelEventAssociations', + }, + targetObjectMetadata: { + __typename: 'object', + id: '97548143-02cb-4372-8e0e-416793d65a38', + nameSingular: 'calendarChannelEventAssociation', + namePlural: 'calendarChannelEventAssociations', + }, + targetFieldMetadata: { + __typename: 'field', + id: '906e35f2-e2d1-45d5-8326-cb7712a19e60', + name: 'calendarChannel', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd757fd20-3568-411f-a2ba-ec2f7b30dc55', + type: 'SELECT', + name: 'syncStatus', + label: 'Sync status', + description: 'Sync status', + icon: 'IconStatusChange', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: [ + { + id: 'b630226e-bf35-4598-be4d-292eb96c2a37', + color: 'yellow', + label: 'Ongoing', + value: 'ONGOING', + position: 1, + }, + { + id: '53e06d7a-d579-47cc-925c-2f2c869503cc', + color: 'blue', + label: 'Not Synced', + value: 'NOT_SYNCED', + position: 2, + }, + { + id: '3285bfab-5312-493b-b907-58b2000e9406', + color: 'green', + label: 'Active', + value: 'ACTIVE', + position: 3, + }, + { + id: '224383b8-e2fb-4ccd-8b63-6ec929eb134c', + color: 'red', + label: 'Failed Insufficient Permissions', + value: 'FAILED_INSUFFICIENT_PERMISSIONS', + position: 4, + }, + { + id: '9177a080-60f6-44cf-982a-9f6c40871588', + color: 'red', + label: 'Failed Unknown', + value: 'FAILED_UNKNOWN', + position: 5, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '529b36bb-42d1-4361-ac0a-e683557cc879', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8d7cb56f-29f1-40ad-90cf-4497bee669a1', + type: 'SELECT', + name: 'contactAutoCreationPolicy', + label: 'Contact auto creation policy', + description: + 'Automatically create records for people you participated with in an event.', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'AS_PARTICIPANT_AND_ORGANIZER'", + options: [ + { + id: 'd8da75a6-19b3-4ecd-902c-72646a7d01a3', + color: 'green', + label: 'As Participant and Organizer', + value: 'AS_PARTICIPANT_AND_ORGANIZER', + position: 0, + }, + { + id: 'f5b362bf-5dd0-4742-894c-b9393dd97550', + color: 'orange', + label: 'As Participant', + value: 'AS_PARTICIPANT', + position: 1, + }, + { + id: 'e3bd7054-2e28-453a-a21a-e2245858cae9', + color: 'blue', + label: 'As Organizer', + value: 'AS_ORGANIZER', + position: 2, + }, + { + id: '3ef1eec3-ba71-4440-a700-012652a2b6e8', + color: 'red', + label: 'None', + value: 'NONE', + position: 3, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c933e11e-7820-42e4-a589-389c2f314add', + type: 'RELATION', + name: 'connectedAccount', + label: 'Connected Account', + description: 'Connected Account', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7fe521fe-1b22-4354-92ba-8164ce5c9b5d', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'c8993ad6-46d5-4ab0-88f5-d407625c0c75', + nameSingular: 'calendarChannel', + namePlural: 'calendarChannels', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c933e11e-7820-42e4-a589-389c2f314add', + name: 'connectedAccount', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + }, + targetFieldMetadata: { + __typename: 'field', + id: '919dadd4-8dda-479f-a8a7-b4ed89eafae5', + name: 'calendarChannels', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '01e23a9d-d8b7-47c6-a1f8-7e012ae9f54a', + type: 'DATE_TIME', + name: 'syncStageStartedAt', + label: 'Sync stage started at', + description: 'Sync stage started at', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9c5f7d31-5b5e-4af1-9918-859ce66b6c08', + type: 'SELECT', + name: 'syncStage', + label: 'Sync stage', + description: 'Sync stage', + icon: 'IconStatusChange', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING'", + options: [ + { + id: '0eede3ef-23ee-49ff-8e08-39d85dc33558', + color: 'blue', + label: 'Full calendar event list fetch pending', + value: 'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING', + position: 0, + }, + { + id: 'b6c4a65e-df0e-40dc-a038-dcd7038ab32e', + color: 'blue', + label: 'Partial calendar event list fetch pending', + value: 'PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING', + position: 1, + }, + { + id: '5c7302cb-02e0-4335-be97-71b8571e0374', + color: 'orange', + label: 'Calendar event list fetch ongoing', + value: 'CALENDAR_EVENT_LIST_FETCH_ONGOING', + position: 2, + }, + { + id: 'e087a4ad-717a-40e6-9139-57b5aaab9fb9', + color: 'blue', + label: 'Calendar events import pending', + value: 'CALENDAR_EVENTS_IMPORT_PENDING', + position: 3, + }, + { + id: '2b18f762-4d31-40e1-b10b-e1a57f8fb54c', + color: 'orange', + label: 'Calendar events import ongoing', + value: 'CALENDAR_EVENTS_IMPORT_ONGOING', + position: 4, + }, + { + id: '0fd50f39-d60f-47a7-a988-37948fdbbfaa', + color: 'red', + label: 'Failed', + value: 'FAILED', + position: 5, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0c81da27-4ff4-4bf4-8937-9a8ee627e46c', + type: 'NUMBER', + name: 'throttleFailureCount', + label: 'Throttle Failure Count', + description: 'Throttle Failure Count', + icon: 'IconX', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 0, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5c73b1cc-ddda-46a8-a517-f0bb5f0c5f60', + type: 'BOOLEAN', + name: 'isContactAutoCreationEnabled', + label: 'Is Contact Auto Creation Enabled', + description: 'Is Contact Auto Creation Enabled', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'b5cd74c7-a68f-4ccb-be66-24604d10a315', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'messageThread', + namePlural: 'messageThreads', + labelSingular: 'Message Thread', + labelPlural: 'Message Threads', + description: 'Message Thread', + icon: 'IconMessage', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '823a20db-9431-422c-b0a1-4f559b992651', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjQ=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0cc37cbd-c7ce-4898-b34d-5da7736e7b54', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '537e956c-58bb-4ed4-8127-beb0f2d04dd2', + type: 'RELATION', + name: 'messages', + label: 'Messages', + description: 'Messages from the thread.', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '30c65174-8905-4a32-9239-c5659a1acc9e', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b5cd74c7-a68f-4ccb-be66-24604d10a315', + nameSingular: 'messageThread', + namePlural: 'messageThreads', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '537e956c-58bb-4ed4-8127-beb0f2d04dd2', + name: 'messages', + }, + targetObjectMetadata: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + nameSingular: 'message', + namePlural: 'messages', + }, + targetFieldMetadata: { + __typename: 'field', + id: '11f38fa4-e7b8-4275-b0b2-59688cb2eed8', + name: 'messageThread', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '728f4580-9220-4130-9a25-c56669ad0e43', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fe0508ef-6e8e-4422-b822-67899af4aa58', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '823a20db-9431-422c-b0a1-4f559b992651', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'company', + namePlural: 'companies', + labelSingular: 'Company', + labelPlural: 'Companies', + description: 'A company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '3b52848e-e419-4361-8fbc-3d4ed19f1956', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjI3', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7011922c-2271-4960-81eb-b9f9ae3ae00c', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '37abc2ae-9f44-4bc0-8277-e3ddfd54738c', + type: 'RELATION', + name: 'people', + label: 'People', + description: 'People linked to the company.', + icon: 'IconUsers', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'd9add14d-13bd-4bb7-abab-06d4fdc78a3e', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '37abc2ae-9f44-4bc0-8277-e3ddfd54738c', + name: 'people', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: '504f7e23-1476-422b-ac1d-5d86d3d33022', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c264b8c8-1260-410b-aa34-d69b14bba19b', + type: 'LINKS', + name: 'domainName', + label: 'Domain Name', + description: + 'The company website URL. We use this url to fetch the company icon', + icon: 'IconLink', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '73c7c0bc-a328-488f-b357-fd9dc332ab75', + type: 'BOOLEAN', + name: 'visaSponsorship', + label: 'Visa Sponsorship', + description: "Company's Visa Sponsorship Policy", + icon: 'IconBrandVisa', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:41.908Z', + updatedAt: '2024-09-25T13:45:41.908Z', + defaultValue: false, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b08a8600-2c4f-4e8a-8f32-6ffe7041e569', + type: 'ADDRESS', + name: 'address', + label: 'Address', + description: 'Address of the company', + icon: 'IconMap', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + addressLat: null, + addressLng: null, + addressCity: "''", + addressState: "''", + addressCountry: "''", + addressStreet1: "''", + addressStreet2: "''", + addressPostcode: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '107fd869-fa4a-4ca5-b6b1-a918ec78851e', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Company record position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2f0ab2d8-3cdf-49d1-a8be-ef204e871968', + type: 'NUMBER', + name: 'employees', + label: 'Employees', + description: 'Number of employees in the company', + icon: 'IconUsers', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9677b321-e8fc-4d1b-9d7f-145a5dea0001', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the company', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '48f0a4f6-84e3-48e9-8444-72109a32f149', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '9677b321-e8fc-4d1b-9d7f-145a5dea0001', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '7155582f-4bbc-4643-be0c-38165b8a282f', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8a21fcb9-5ee7-498c-a09d-1d3137be0540', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '300545a5-6ca7-487a-8374-a662bab5d717', + type: 'UUID', + name: 'accountOwnerId', + label: 'Account Owner id (foreign key)', + description: + 'Your team member responsible for managing the company account id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e41f22fd-ecd5-4b28-a2ed-a04d2a017c19', + type: 'CURRENCY', + name: 'annualRecurringRevenue', + label: 'ARR', + description: + 'Annual Recurring Revenue: The actual or estimated annual revenue of the company', + icon: 'IconMoneybag', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + amountMicros: null, + currencyCode: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '24cc7f7b-e8d3-4c12-a3c5-caa5ccf61523', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8421d3d3-d5ac-4065-a431-95780fda2ce7', + type: 'RELATION', + name: 'opportunities', + label: 'Opportunities', + description: 'Opportunities linked to the company.', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '06717b0b-194c-46e4-9394-f2ef37bdee90', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '8421d3d3-d5ac-4065-a431-95780fda2ce7', + name: 'opportunities', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c859b99c-2554-483d-8ffe-4d29cb9c8459', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2395970c-d0a2-43df-9f55-58299e930b34', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the company', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'ed757882-8668-407f-8fb8-314b68aa58f8', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '2395970c-d0a2-43df-9f55-58299e930b34', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: '1433d739-29ed-450c-8216-6afea26d21fb', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3b52848e-e419-4361-8fbc-3d4ed19f1956', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'The company name', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5f23c37a-9971-4060-a861-19f030848b90', + type: 'LINKS', + name: 'xLink', + label: 'X', + description: 'The company Twitter/X account', + icon: 'IconBrandX', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c5103301-686a-4c1f-86d1-69e32a4a34ae', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '81907e01-90e3-412a-9aa5-9ae8352b679d', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f8393bb6-05c2-44d7-bff8-4a7671b43f15', + type: 'RELATION', + name: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the company', + icon: 'IconIconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'b8909cf8-5b9d-4512-8fdf-d6fc4b450191', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f8393bb6-05c2-44d7-bff8-4a7671b43f15', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '145c8790-abd1-49fb-9857-650da78c6717', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4882e808-7cd2-487f-911f-ab2d9353e60d', + type: 'RELATION', + name: 'accountOwner', + label: 'Account Owner', + description: + 'Your team member responsible for managing the company account', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '39f43faa-8471-4440-88d5-d6bc2c8e49fd', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '4882e808-7cd2-487f-911f-ab2d9353e60d', + name: 'accountOwner', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'bb548a08-0706-4021-833d-e527c23e2a48', + name: 'accountOwnerForCompanies', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a8cf3568-4d04-43cf-b8c2-2070a7eb0e4e', + type: 'MULTI_SELECT', + name: 'workPolicy', + label: 'Work Policy', + description: "Company's Work Policy", + icon: 'IconHome', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:41.780Z', + updatedAt: '2024-09-25T13:45:41.780Z', + defaultValue: null, + options: [ + { + id: '3d8e885e-9481-41f3-b90e-1264020e731e', + color: 'green', + label: 'On-Site', + value: 'ON_SITE', + position: 0, + }, + { + id: '8b05941b-9ed0-4f76-a97c-6647d0d54976', + color: 'turquoise', + label: 'Hybrid', + value: 'HYBRID', + position: 1, + }, + { + id: '97561fec-643d-4477-a6ae-f213b86a047d', + color: 'sky', + label: 'Remote Work', + value: 'REMOTE_WORK', + position: 2, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd69eb854-c043-43d9-a40e-65a0649fd1a9', + type: 'RELATION', + name: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the company', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '309200d8-c547-47a7-82a5-25915056db15', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd69eb854-c043-43d9-a40e-65a0649fd1a9', + name: 'taskTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'cd7f57e8-a67f-4be9-a971-b5609cb0fb83', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '531c4b2e-94a0-46f4-9395-277c3239413d', + type: 'RELATION', + name: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the company', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '706df621-2977-49c9-a05f-38a6d4389011', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '531c4b2e-94a0-46f4-9395-277c3239413d', + name: 'noteTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '4b6aaf36-4247-4bbb-b26d-64987b02f805', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'de10d71e-4cfa-4322-b967-761871e69bc0', + type: 'LINKS', + name: 'introVideo', + label: 'Intro Video', + description: "Company's Intro Video", + icon: 'IconVideo', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:41.643Z', + updatedAt: '2024-09-25T13:45:41.643Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e2e632fe-1c08-4c12-9aba-88f8595bf5be', + type: 'RELATION', + name: 'activityTargets', + label: 'Activities', + description: 'Activities tied to the company', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '08d38bf1-1b43-416a-915d-1d5718a829a7', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'e2e632fe-1c08-4c12-9aba-88f8595bf5be', + name: 'activityTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'e1d06322-0658-4c45-9c9b-8a42750c8751', + name: 'company', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '16838104-8adf-45a3-93bf-e97551240b66', + type: 'LINKS', + name: 'linkedinLink', + label: 'Linkedin', + description: 'The company Linkedin account', + icon: 'IconBrandLinkedin', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '195db745-305e-40f0-b740-d071c5c19214', + type: 'TEXT', + name: 'tagline', + label: 'Tagline', + description: "Company's Tagline", + icon: 'IconAdCircle', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:41.458Z', + updatedAt: '2024-09-25T13:45:41.458Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2d8e886a-3ebf-474c-8c7a-909e9d7fcc6f', + type: 'BOOLEAN', + name: 'idealCustomerProfile', + label: 'ICP', + description: + 'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you', + icon: 'IconTarget', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: false, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '97548143-02cb-4372-8e0e-416793d65a38', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'calendarChannelEventAssociation', + namePlural: 'calendarChannelEventAssociations', + labelSingular: 'Calendar Channel Event Association', + labelPlural: 'Calendar Channel Event Associations', + description: 'Calendar Channel Event Associations', + icon: 'IconCalendar', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '8505bc8b-e978-401a-8983-f1f1e64aa26d', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjg=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c496110c-239a-4dd4-bdbd-022ca4fdc62c', + type: 'RELATION', + name: 'calendarEvent', + label: 'Event ID', + description: 'Event ID', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '81106456-6209-4373-b7fd-e1ed6b6c26a5', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '97548143-02cb-4372-8e0e-416793d65a38', + nameSingular: 'calendarChannelEventAssociation', + namePlural: 'calendarChannelEventAssociations', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c496110c-239a-4dd4-bdbd-022ca4fdc62c', + name: 'calendarEvent', + }, + targetObjectMetadata: { + __typename: 'object', + id: '75c685e2-f612-415f-a81c-6ca8eda30c8d', + nameSingular: 'calendarEvent', + namePlural: 'calendarEvents', + }, + targetFieldMetadata: { + __typename: 'field', + id: '52db308a-e428-4efd-95ed-2b0e19cbdc92', + name: 'calendarChannelEventAssociations', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8505bc8b-e978-401a-8983-f1f1e64aa26d', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '18e21e78-56c2-492a-8082-f1e8ceb72e14', + type: 'UUID', + name: 'calendarChannelId', + label: 'Channel ID id (foreign key)', + description: 'Channel ID id foreign key', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b61d8723-b739-42b6-b23d-b82e09b34669', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '97a0be23-ba2e-4af3-8503-d4c27c293a37', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '906e35f2-e2d1-45d5-8326-cb7712a19e60', + type: 'RELATION', + name: 'calendarChannel', + label: 'Channel ID', + description: 'Channel ID', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'da686bc9-04d2-4665-b0ce-2bfa306c1087', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '97548143-02cb-4372-8e0e-416793d65a38', + nameSingular: 'calendarChannelEventAssociation', + namePlural: 'calendarChannelEventAssociations', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '906e35f2-e2d1-45d5-8326-cb7712a19e60', + name: 'calendarChannel', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'c8993ad6-46d5-4ab0-88f5-d407625c0c75', + nameSingular: 'calendarChannel', + namePlural: 'calendarChannels', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd1596020-b595-4bf9-b3c1-782f9b49f41b', + name: 'calendarChannelEventAssociations', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aa298945-e331-40de-a6db-855b58b99d05', + type: 'TEXT', + name: 'eventExternalId', + label: 'Event external ID', + description: 'Event external ID', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0ec16ef5-2331-4a1e-b429-0e4fc3d9576f', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2c765e90-ce86-4f6b-a528-94e38b5aaf54', + type: 'UUID', + name: 'calendarEventId', + label: 'Event ID id (foreign key)', + description: 'Event ID id foreign key', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '82209518-55fb-4fbd-acdd-f7c5a9d587f4', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'apiKey', + namePlural: 'apiKeys', + labelSingular: 'Api Key', + labelPlural: 'Api Keys', + description: 'An api key', + icon: 'IconRobot', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '78eec6b7-ab9c-4dee-ac64-2b9e40b467f6', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjY=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '78eec6b7-ab9c-4dee-ac64-2b9e40b467f6', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'ApiKey name', + icon: 'IconLink', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd2653ce4-585b-4a38-9e09-4ae8e2afae51', + type: 'DATE_TIME', + name: 'expiresAt', + label: 'Expiration date', + description: 'ApiKey expiration date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9e5cd8cb-e800-4b25-a9e6-cfb6d51623c6', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '68704d45-b248-4e41-a07b-21d5874663bb', + type: 'DATE_TIME', + name: 'revokedAt', + label: 'Revocation date', + description: 'ApiKey revocation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '77ef9f04-627b-4708-b400-076629ed9f20', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dc4892f0-a890-4a49-90ae-5a7999665785', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bbe022a1-426f-40c2-ad1d-8294ef127c0b', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'favorite', + namePlural: 'favorites', + labelSingular: 'Favorite', + labelPlural: 'Favorites', + description: 'A favorite', + icon: 'IconHeart', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'a1555234-ff28-4a04-871c-31008b39e442', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjIy', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9d2499b3-403c-473f-b61f-61bbea97afeb', + type: 'UUID', + name: 'noteId', + label: 'Note id (foreign key)', + description: 'Favorite note id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0d232853-5ae9-43f3-ac4a-248c50e2a64e', + type: 'UUID', + name: 'taskId', + label: 'Task id (foreign key)', + description: 'Favorite task id foreign key', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8e506212-1b66-4981-95d6-f0ac83f5d869', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'Favorite person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '001dae2b-80e6-4e2d-b5fe-ee0349e940d7', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '8e506212-1b66-4981-95d6-f0ac83f5d869', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c188f5b7-2259-4207-87d2-5232ec775029', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dc005581-351b-4fa0-9b39-da5bbe2554b7', + type: 'RELATION', + name: 'task', + label: 'Task', + description: 'Favorite task', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c349fbab-ecda-4dd6-bf3f-b60a4118db25', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'dc005581-351b-4fa0-9b39-da5bbe2554b7', + name: 'task', + }, + targetObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + targetFieldMetadata: { + __typename: 'field', + id: '1d53ad9c-bdf4-4660-b4b6-e79162d13c39', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '86e97af0-ec16-4937-b5b6-e4531027be82', + type: 'UUID', + name: 'rocketId', + label: 'Rocket ID (foreign key)', + description: 'Favorite Rocket id foreign key', + icon: null, + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.584Z', + updatedAt: '2024-09-25T13:45:42.584Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c33a0768-3f55-4c7b-aa1a-07aeacf3fb85', + type: 'UUID', + name: 'viewId', + label: 'View id (foreign key)', + description: 'Favorite view id foreign key', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'afc385d4-22d1-4f83-a67a-46450df368e9', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '90a28b04-0214-424f-afad-172b7cd28073', + type: 'UUID', + name: 'workflowId', + label: 'Workflow id (foreign key)', + description: 'Favorite workflow id foreign key', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6a245087-243d-450b-9f00-c951d417d4ef', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'Favorite person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '14e0bf40-d4eb-4893-a5f2-3df3ce749996', + type: 'UUID', + name: 'workspaceMemberId', + label: 'Workspace Member id (foreign key)', + description: 'Favorite workspace member id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0ecb3679-5ff7-4b55-9ed3-9927bc9e184b', + type: 'RELATION', + name: 'note', + label: 'Note', + description: 'Favorite note', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'aeec4288-a886-4c86-8f42-1be726bd4fb4', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '0ecb3679-5ff7-4b55-9ed3-9927bc9e184b', + name: 'note', + }, + targetObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f115229b-f5b3-4623-ac80-f8bf3df5e077', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3a561744-45bd-45a6-af94-bfb4d4f508fe', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '46ff8942-360f-4837-9a83-007739c8ba05', + type: 'RELATION', + name: 'view', + label: 'View', + description: 'Favorite view', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'a081c61b-9c8f-4e93-820e-a6c11cb51950', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '46ff8942-360f-4837-9a83-007739c8ba05', + name: 'view', + }, + targetObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + targetFieldMetadata: { + __typename: 'field', + id: '61fe3c78-ab04-4a83-9a40-8560f7285abe', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6e104959-9dfb-42a7-80da-0ddb0dab12f9', + type: 'UUID', + name: 'opportunityId', + label: 'Opportunity id (foreign key)', + description: 'Favorite opportunity id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f112f2a8-4f21-454d-b3a7-fcd85f0eab72', + type: 'NUMBER', + name: 'position', + label: 'Position', + description: 'Favorite position', + icon: 'IconList', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 0, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e4102fb0-c6e3-47e8-a810-71e0b6453705', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a1555234-ff28-4a04-871c-31008b39e442', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '10509b5e-71c0-49e8-9cb8-d0ff7ee8691b', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'Favorite company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'eed525bd-edf3-4030-9f09-8ff68226a6a0', + type: 'RELATION', + name: 'workflow', + label: 'Workflow', + description: 'Favorite workflow', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '892e8ce6-83f8-4dbd-8c0d-eb5bb7db71f6', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'eed525bd-edf3-4030-9f09-8ff68226a6a0', + name: 'workflow', + }, + targetObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + targetFieldMetadata: { + __typename: 'field', + id: '141281c7-5b28-41d4-99bd-31c1e4c88e9b', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5b559e4c-eb75-4a1e-b904-a486d2328b24', + type: 'RELATION', + name: 'workspaceMember', + label: 'Workspace Member', + description: 'Favorite workspace member', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '4549947d-17e5-497b-898e-cf42e1ad3d99', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '5b559e4c-eb75-4a1e-b904-a486d2328b24', + name: 'workspaceMember', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'ac76a0ff-f5c1-4127-b354-0b3ce2b3696b', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7155582f-4bbc-4643-be0c-38165b8a282f', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'Favorite company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '48f0a4f6-84e3-48e9-8444-72109a32f149', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '7155582f-4bbc-4643-be0c-38165b8a282f', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: '9677b321-e8fc-4d1b-9d7f-145a5dea0001', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '11e6c0a0-e1fa-4931-a705-8725a79afe24', + type: 'RELATION', + name: 'rocket', + label: 'Rocket', + description: 'Favorite Rocket', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.587Z', + updatedAt: '2024-09-25T13:45:42.587Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '2d9dcc60-3d44-4ea4-ac02-146fdbdeac22', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '11e6c0a0-e1fa-4931-a705-8725a79afe24', + name: 'rocket', + }, + targetObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '79da64bc-eea3-476e-801b-f08c86a8c337', + name: 'favorites', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1d3858e1-e4aa-484f-b422-8bbefa9409c8', + type: 'RELATION', + name: 'opportunity', + label: 'Opportunity', + description: 'Favorite opportunity', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'aeb1d35c-771a-4226-a11a-4dbe1228fa7c', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '1d3858e1-e4aa-484f-b422-8bbefa9409c8', + name: 'opportunity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '5d3ca5b4-9468-4061-8c6b-ef03a9b123df', + name: 'favorites', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '7610fd21-9f3e-44d2-bdf9-f30e442ead53', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'comment', + namePlural: 'comments', + labelSingular: 'Comment', + labelPlural: 'Comments', + description: 'A comment', + icon: 'IconMessageCircle', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '8f985123-68d4-4e8a-b75b-85a75f0f071e', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjg=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '974ab999-a946-409f-820c-aa2e2c21f3ce', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '70a9b04f-0d11-41a1-bce8-e7ac8bb0ed5d', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'da1dda8a-b7b6-4166-b11b-740a8414706b', + type: 'UUID', + name: 'authorId', + label: 'Author id (foreign key)', + description: 'Comment author id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3b07941b-15b6-4468-8e2f-52abf7ff36b3', + type: 'TEXT', + name: 'body', + label: 'Body', + description: 'Comment body', + icon: 'IconLink', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8f985123-68d4-4e8a-b75b-85a75f0f071e', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e48bc6a2-211c-46aa-9f22-1859aedac28e', + type: 'RELATION', + name: 'activity', + label: 'Activity', + description: 'Comment activity', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'a3bdce1c-b0a8-4961-8a06-b7dc8355e879', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '7610fd21-9f3e-44d2-bdf9-f30e442ead53', + nameSingular: 'comment', + namePlural: 'comments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'e48bc6a2-211c-46aa-9f22-1859aedac28e', + name: 'activity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '0f1cfe74-f960-44f9-91f3-fc9d25a4b96b', + name: 'comments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c39eb95c-2e9f-4fd3-abc3-103986dd21bb', + type: 'UUID', + name: 'activityId', + label: 'Activity id (foreign key)', + description: 'Comment activity id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '571e3b8c-0c80-4292-93b1-c73b4d976b05', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b1ead0df-5b1c-4c00-b0c5-05a67ec37327', + type: 'RELATION', + name: 'author', + label: 'Author', + description: 'Comment author', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '00facee3-c07f-443c-8eca-4a8f4d8bec0d', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '7610fd21-9f3e-44d2-bdf9-f30e442ead53', + nameSingular: 'comment', + namePlural: 'comments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'b1ead0df-5b1c-4c00-b0c5-05a67ec37327', + name: 'author', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f74a56bf-9230-4452-b6a0-099ba9f7de0d', + name: 'authoredComments', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '75c685e2-f612-415f-a81c-6ca8eda30c8d', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'calendarEvent', + namePlural: 'calendarEvents', + labelSingular: 'Calendar event', + labelPlural: 'Calendar events', + description: 'Calendar events', + icon: 'IconCalendar', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '45bd7c28-f450-4487-a556-1fd85be68beb', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE4', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0c1f5af5-c2d5-4f38-9fd4-6ce854e693d3', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f06f5946-e54f-458d-9c77-47d6d8fbd995', + type: 'DATE_TIME', + name: 'endsAt', + label: 'End Date', + description: 'End Date', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bc8be6a6-4707-498a-9e79-8ffb86e92a43', + type: 'RELATION', + name: 'calendarEventParticipants', + label: 'Event Participants', + description: 'Event Participants', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '089a99c0-0893-4288-ad62-ac723007a426', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '75c685e2-f612-415f-a81c-6ca8eda30c8d', + nameSingular: 'calendarEvent', + namePlural: 'calendarEvents', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'bc8be6a6-4707-498a-9e79-8ffb86e92a43', + name: 'calendarEventParticipants', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + }, + targetFieldMetadata: { + __typename: 'field', + id: '597d153f-8724-4d61-8863-8bfae905721f', + name: 'calendarEvent', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6bfac067-9c6c-4b4d-bdaf-ecf7737b2599', + type: 'TEXT', + name: 'iCalUID', + label: 'iCal UID', + description: 'iCal UID', + icon: 'IconKey', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '45bd7c28-f450-4487-a556-1fd85be68beb', + type: 'TEXT', + name: 'title', + label: 'Title', + description: 'Title', + icon: 'IconH1', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '52d1ed74-b3d5-4339-b408-6f4c8dbc3969', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4078641f-c8b4-418c-9e7a-0bfdc411c4d9', + type: 'DATE_TIME', + name: 'externalUpdatedAt', + label: 'Update DateTime', + description: 'Update DateTime', + icon: 'IconCalendarCog', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ae4f8ff1-47f1-4b84-b61b-c519c939a409', + type: 'TEXT', + name: 'conferenceSolution', + label: 'Conference Solution', + description: 'Conference Solution', + icon: 'IconScreenShare', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a77794e2-adea-40cb-a0f9-a91a6d4494ed', + type: 'DATE_TIME', + name: 'startsAt', + label: 'Start Date', + description: 'Start Date', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '62d6a06b-0083-4702-be85-edd6ca882816', + type: 'TEXT', + name: 'location', + label: 'Location', + description: 'Location', + icon: 'IconMapPin', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '567c7852-6dc5-4c6e-826d-e4b253614e60', + type: 'TEXT', + name: 'recurringEventExternalId', + label: 'Recurring Event ID', + description: 'Recurring Event ID', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c0ed400f-b0cf-4fe1-a929-89698dc020a5', + type: 'DATE_TIME', + name: 'externalCreatedAt', + label: 'Creation DateTime', + description: 'Creation DateTime', + icon: 'IconCalendarPlus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'da0d1cc9-be28-4b41-9ddf-48041702024b', + type: 'TEXT', + name: 'description', + label: 'Description', + description: 'Description', + icon: 'IconFileDescription', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '52db308a-e428-4efd-95ed-2b0e19cbdc92', + type: 'RELATION', + name: 'calendarChannelEventAssociations', + label: 'Calendar Channel Event Associations', + description: 'Calendar Channel Event Associations', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '81106456-6209-4373-b7fd-e1ed6b6c26a5', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '75c685e2-f612-415f-a81c-6ca8eda30c8d', + nameSingular: 'calendarEvent', + namePlural: 'calendarEvents', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '52db308a-e428-4efd-95ed-2b0e19cbdc92', + name: 'calendarChannelEventAssociations', + }, + targetObjectMetadata: { + __typename: 'object', + id: '97548143-02cb-4372-8e0e-416793d65a38', + nameSingular: 'calendarChannelEventAssociation', + namePlural: 'calendarChannelEventAssociations', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c496110c-239a-4dd4-bdbd-022ca4fdc62c', + name: 'calendarEvent', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '63904769-6145-4230-b294-c4554c36a273', + type: 'BOOLEAN', + name: 'isCanceled', + label: 'Is canceled', + description: 'Is canceled', + icon: 'IconCalendarCancel', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: false, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '48fac512-a780-4c44-b1dc-f178bd8ab3f8', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1ba833a8-68ca-4396-b3ed-9a7411e1dc4f', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3050381d-7191-4d18-be27-9a92cbefb57a', + type: 'LINKS', + name: 'conferenceLink', + label: 'Meet Link', + description: 'Meet Link', + icon: 'IconLink', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b6cf9c5d-e923-4026-9316-c3a513ce7c12', + type: 'BOOLEAN', + name: 'isFullDay', + label: 'Is Full Day', + description: 'Is Full Day', + icon: 'Icon24Hours', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: false, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + labelSingular: 'Workspace Member', + labelPlural: 'Workspace Members', + description: 'A workspace member', + icon: 'IconUserCircle', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'a1ffe54a-6b76-47fa-bd25-df479a31eee2', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjI1', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ac76a0ff-f5c1-4127-b354-0b3ce2b3696b', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the workspace member', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '4549947d-17e5-497b-898e-cf42e1ad3d99', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'ac76a0ff-f5c1-4127-b354-0b3ce2b3696b', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '5b559e4c-eb75-4a1e-b904-a486d2328b24', + name: 'workspaceMember', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e32f7a81-d208-4c14-afb4-a4befc938670', + type: 'RELATION', + name: 'assignedActivities', + label: 'Assigned activities', + description: 'Activities assigned to the workspace member', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'bd41ada4-a132-4297-8f7f-e622a090f243', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'e32f7a81-d208-4c14-afb4-a4befc938670', + name: 'assignedActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'dd5354bb-dd0a-4426-ac75-87e9ab171dc4', + name: 'assignee', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '85df4525-aed1-4e46-b718-b5bc963da41d', + type: 'RELATION', + name: 'auditLogs', + label: 'Audit Logs', + description: 'Audit Logs linked to the workspace member', + icon: 'IconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '07071415-1159-4913-9dee-81b8f9b8cdb4', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '85df4525-aed1-4e46-b718-b5bc963da41d', + name: 'auditLogs', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'cd90b6c9-4f22-4c62-a107-dc396e5396ed', + nameSingular: 'auditLog', + namePlural: 'auditLogs', + }, + targetFieldMetadata: { + __typename: 'field', + id: '3d6dc314-877d-4aaa-88bd-364dc50f780b', + name: 'workspaceMember', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a1ffe54a-6b76-47fa-bd25-df479a31eee2', + type: 'FULL_NAME', + name: 'name', + label: 'Name', + description: 'Workspace member name', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + lastName: "''", + firstName: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7370da8c-294f-4671-91e5-7f87f4dccc1e', + type: 'RELATION', + name: 'calendarEventParticipants', + label: 'Calendar Event Participants', + description: 'Calendar Event Participants', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'd23fa3d8-e4ce-4cc9-a949-cafbd231d563', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '7370da8c-294f-4671-91e5-7f87f4dccc1e', + name: 'calendarEventParticipants', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + }, + targetFieldMetadata: { + __typename: 'field', + id: '30fd4e8a-2089-4443-ac06-5cd53d9a3fcf', + name: 'workspaceMember', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '13531c23-42ca-4b1e-a6e3-3fcfad74a3e9', + type: 'RELATION', + name: 'connectedAccounts', + label: 'Connected accounts', + description: 'Connected accounts', + icon: 'IconAt', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'ee186212-93d2-4f15-b74c-c703bedbd396', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '13531c23-42ca-4b1e-a6e3-3fcfad74a3e9', + name: 'connectedAccounts', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e90531b4-c0eb-454b-b246-b99c27e30d5d', + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + }, + targetFieldMetadata: { + __typename: 'field', + id: '236195db-49d1-4386-99b9-4518ab7586f2', + name: 'accountOwner', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a5fc2711-0e3d-40ac-938a-8beafeac1f57', + type: 'RELATION', + name: 'timelineActivities', + label: 'Events', + description: 'Events linked to the workspace member', + icon: 'IconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'db084a18-152f-4ea9-967e-69a45f2d24ab', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'a5fc2711-0e3d-40ac-938a-8beafeac1f57', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '137a88ef-9c08-414c-adcc-2d450624acf8', + name: 'workspaceMember', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bb548a08-0706-4021-833d-e527c23e2a48', + type: 'RELATION', + name: 'accountOwnerForCompanies', + label: 'Account Owner For Companies', + description: 'Account owner for companies', + icon: 'IconBriefcase', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '39f43faa-8471-4440-88d5-d6bc2c8e49fd', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'bb548a08-0706-4021-833d-e527c23e2a48', + name: 'accountOwnerForCompanies', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: '4882e808-7cd2-487f-911f-ab2d9353e60d', + name: 'accountOwner', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fc4f41c0-01ea-428d-9e0c-e2496acc765b', + type: 'TEXT', + name: 'avatarUrl', + label: 'Avatar Url', + description: 'Workspace member avatar', + icon: 'IconFileUpload', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f74a56bf-9230-4452-b6a0-099ba9f7de0d', + type: 'RELATION', + name: 'authoredComments', + label: 'Authored comments', + description: 'Authored comments', + icon: 'IconComment', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '00facee3-c07f-443c-8eca-4a8f4d8bec0d', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f74a56bf-9230-4452-b6a0-099ba9f7de0d', + name: 'authoredComments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '7610fd21-9f3e-44d2-bdf9-f30e442ead53', + nameSingular: 'comment', + namePlural: 'comments', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'b1ead0df-5b1c-4c00-b0c5-05a67ec37327', + name: 'author', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e2895a0d-0e4f-4673-a778-2b99cac1ab20', + type: 'UUID', + name: 'userId', + label: 'User Id', + description: 'Associated User Id', + icon: 'IconCircleUsers', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4cceec11-98cc-41c6-b08c-b04887a0ac22', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1dc4eef9-d576-4106-b19e-2fc91777470d', + type: 'TEXT', + name: 'timeZone', + label: 'Time zone', + description: 'User time zone', + icon: 'IconTimezone', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'system'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2f548d63-6cf6-4116-ae5a-03fcc35ffd1d', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6cc143e8-f88a-4d75-a52c-d5c7f7419d97', + type: 'SELECT', + name: 'timeFormat', + label: 'Time format', + description: "User's preferred time format", + icon: 'IconClock2', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'SYSTEM'", + options: [ + { + id: '1dd82256-aaf1-4ff7-b720-90d1fd15bcdd', + color: 'sky', + label: 'System', + value: 'SYSTEM', + position: 0, + }, + { + id: '3f2efae9-372a-4b46-9fba-4dae9ead2c7a', + color: 'red', + label: '24HRS', + value: 'HOUR_24', + position: 1, + }, + { + id: '77bb9aa5-2afe-4501-92c7-5527c457e59d', + color: 'purple', + label: '12HRS', + value: 'HOUR_12', + position: 2, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b9f4e812-721f-4c83-9f1e-42b79042d905', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '12e6ccfa-23ef-4b68-a043-6012bc7b9c67', + type: 'TEXT', + name: 'locale', + label: 'Language', + description: 'Preferred language', + icon: 'IconLanguage', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'en'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b75d64ca-eb86-439d-ad61-3f23efec07e4', + type: 'TEXT', + name: 'userEmail', + label: 'User Email', + description: 'Related user email address', + icon: 'IconMail', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dd63010d-24f1-4e62-9b49-b4728bb3bd81', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f173a8e9-af79-4377-9b21-5cb1ca27bc87', + type: 'TEXT', + name: 'colorScheme', + label: 'Color Scheme', + description: 'Preferred color scheme', + icon: 'IconColorSwatch', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'Light'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f76b3faa-0bc6-45ed-9654-0421171a1f1a', + type: 'RELATION', + name: 'authoredActivities', + label: 'Authored activities', + description: 'Activities created by the workspace member', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'dd13169a-0cc9-44c1-9e12-4d66e31dcfc0', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f76b3faa-0bc6-45ed-9654-0421171a1f1a', + name: 'authoredActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '3e63dfad-08ba-422f-88e5-0c1ebffd6496', + name: 'author', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c5df2d21-5db8-4e72-82bf-aeb3ec984ca9', + type: 'RELATION', + name: 'authoredAttachments', + label: 'Authored attachments', + description: 'Attachments created by the workspace member', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '58c1c703-990d-4296-a410-a5420209b106', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c5df2d21-5db8-4e72-82bf-aeb3ec984ca9', + name: 'authoredAttachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd9a80298-6f72-4b2f-a859-2bd355d36735', + name: 'author', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd82db237-ca6d-4bee-8d69-dfa0f753707b', + type: 'RELATION', + name: 'messageParticipants', + label: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'fa25f857-7b30-4cd7-87c6-7910bde2d050', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd82db237-ca6d-4bee-8d69-dfa0f753707b', + name: 'messageParticipants', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd205df4f-f9de-4f61-9a85-40f340a4de23', + name: 'workspaceMember', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e64fef03-fda1-4b5c-8894-d1bee725e7e2', + type: 'RELATION', + name: 'blocklist', + label: 'Blocklist', + description: 'Blocklisted handles', + icon: 'IconForbid2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'd0a8b3ba-9219-40d6-957c-3e8d5d656d3a', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'e64fef03-fda1-4b5c-8894-d1bee725e7e2', + name: 'blocklist', + }, + targetObjectMetadata: { + __typename: 'object', + id: '522136fb-741c-4b3b-b44a-b20b62352b47', + nameSingular: 'blocklist', + namePlural: 'blocklists', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f966b379-0438-4b9c-8696-3edf18c197f7', + name: 'workspaceMember', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3653df1b-5687-45c1-a2bf-afc261fe85a8', + type: 'RELATION', + name: 'assignedTasks', + label: 'Assigned tasks', + description: 'Tasks assigned to the workspace member', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'fe131172-06fc-4057-b1d0-c23dc5f030b9', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '3653df1b-5687-45c1-a2bf-afc261fe85a8', + name: 'assignedTasks', + }, + targetObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + targetFieldMetadata: { + __typename: 'field', + id: '7a062a59-07da-4d2d-a0e8-f79f87e2e5e3', + name: 'assignee', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '18a0276f-ce5e-4fc7-81fc-c32f6dd844f3', + type: 'SELECT', + name: 'dateFormat', + label: 'Date format', + description: "User's preferred date format", + icon: 'IconCalendarEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'SYSTEM'", + options: [ + { + id: 'bfb45c9c-2ac1-4504-9e92-7bd8e75fdd16', + color: 'turquoise', + label: 'System', + value: 'SYSTEM', + position: 0, + }, + { + id: 'df73e5f4-9269-4034-aeca-cfb69682a09d', + color: 'red', + label: 'Month First', + value: 'MONTH_FIRST', + position: 1, + }, + { + id: 'c3b8caaa-87e0-4836-b13e-ab0613dcc44f', + color: 'purple', + label: 'Day First', + value: 'DAY_FIRST', + position: 2, + }, + { + id: '2aabe048-b8c0-4b63-a733-a8bc293231aa', + color: 'sky', + label: 'Year First', + value: 'YEAR_FIRST', + position: 3, + }, + ], + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '6f69be9e-d899-4e40-bf15-0c8194e6a934', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'workflowEventListener', + namePlural: 'workflowEventListeners', + labelSingular: 'WorkflowEventListener', + labelPlural: 'WorkflowEventListeners', + description: 'A workflow event listener', + icon: null, + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'd26efc67-251a-4bdd-a585-177717e298a6', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjY=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f58f100f-8ee9-4a0c-8f35-8bdcb561d586', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a3740f53-215a-477d-82be-b57265731d83', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '67dbcf4d-f15b-4703-ba84-4bc2b9903579', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd26efc67-251a-4bdd-a585-177717e298a6', + type: 'TEXT', + name: 'eventName', + label: 'Name', + description: 'The workflow event listener name', + icon: 'IconPhoneCheck', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c8d7ed48-3d0e-47fa-a4af-5a62e578c128', + type: 'UUID', + name: 'workflowId', + label: 'Workflow id (foreign key)', + description: + 'WorkflowEventListener workflow id foreign key', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a424fba4-d3f4-41b1-bf9a-4b809ad628a9', + type: 'RELATION', + name: 'workflow', + label: 'Workflow', + description: 'WorkflowEventListener workflow', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '1353dcd5-92ce-4947-8156-c1de74eaf54b', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '6f69be9e-d899-4e40-bf15-0c8194e6a934', + nameSingular: 'workflowEventListener', + namePlural: 'workflowEventListeners', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'a424fba4-d3f4-41b1-bf9a-4b809ad628a9', + name: 'workflow', + }, + targetObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'b14865e9-26a6-4ae8-930d-d22c21c7696c', + name: 'eventListeners', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aabd6970-7bf9-488b-8411-5bc654574d58', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '69c8b455-e982-4fd2-965b-7bd5206cb860', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'viewField', + namePlural: 'viewFields', + labelSingular: 'View Field', + labelPlural: 'View Fields', + description: '(System) View Fields', + icon: 'IconTag', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '959d36dc-493b-4e08-ae3d-38680bab1d0d', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjk=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ee4d98d0-37a4-42cc-8794-653099d4df54', + type: 'BOOLEAN', + name: 'isVisible', + label: 'Visible', + description: 'View Field visibility', + icon: 'IconEye', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: true, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '643509ce-5666-4264-8b09-f095e23a1624', + type: 'NUMBER', + name: 'position', + label: 'Position', + description: 'View Field position', + icon: 'IconList', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 0, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c672e744-21f3-4d23-abd8-fcc03fad503a', + type: 'UUID', + name: 'viewId', + label: 'View id (foreign key)', + description: 'View Field related view id foreign key', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '49e8ada7-3a80-49c7-869a-3ebfdae35387', + type: 'NUMBER', + name: 'size', + label: 'Size', + description: 'View Field size', + icon: 'IconEye', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 0, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dd7510e1-4f22-4376-8436-19d7d631ea77', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f74ba2c1-22ab-4827-85ad-d2dbbe2a9b51', + type: 'RELATION', + name: 'view', + label: 'View', + description: 'View Field related view', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '76c82afe-f2bd-4a86-9c7f-4e7fa3918b1b', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '69c8b455-e982-4fd2-965b-7bd5206cb860', + nameSingular: 'viewField', + namePlural: 'viewFields', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f74ba2c1-22ab-4827-85ad-d2dbbe2a9b51', + name: 'view', + }, + targetObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + targetFieldMetadata: { + __typename: 'field', + id: '027418ee-6028-456f-a570-0b032d35b07f', + name: 'viewFields', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '959d36dc-493b-4e08-ae3d-38680bab1d0d', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '300b7bf6-e1fa-4cd2-a601-7a125b7bf1b8', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0f7acd2a-ccd1-437e-b80a-bf4555a7c034', + type: 'UUID', + name: 'fieldMetadataId', + label: 'Field Metadata Id', + description: 'View Field target field', + icon: 'IconTag', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '217be100-e82e-4aae-9566-b091823a5466', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '6987128d-cf7d-45eb-9bcc-19a406b774ec', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'viewSort', + namePlural: 'viewSorts', + labelSingular: 'View Sort', + labelPlural: 'View Sorts', + description: '(System) View Sorts', + icon: 'IconArrowsSort', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'e4f8f882-dec2-4d6b-a141-936e87d3fd27', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjc=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '330a6b96-c7eb-41ae-962e-eb528dc16aaf', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '45fe30a3-141f-4908-be8b-b826f84edb75', + type: 'UUID', + name: 'viewId', + label: 'View id (foreign key)', + description: 'View Sort related view id foreign key', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7924f4d6-c92b-436f-a86d-26b2dcc521aa', + type: 'TEXT', + name: 'direction', + label: 'Direction', + description: 'View Sort direction', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'asc'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fc34ddd1-7f8a-4f23-a2b6-9a6d3165cc0a', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e4f8f882-dec2-4d6b-a141-936e87d3fd27', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '25ae0938-795a-491a-b029-e4672412e85f', + type: 'RELATION', + name: 'view', + label: 'View', + description: 'View Sort related view', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '6156cfd2-ab7f-47d1-8b4a-5e093f08fb9e', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '6987128d-cf7d-45eb-9bcc-19a406b774ec', + nameSingular: 'viewSort', + namePlural: 'viewSorts', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '25ae0938-795a-491a-b029-e4672412e85f', + name: 'view', + }, + targetObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + targetFieldMetadata: { + __typename: 'field', + id: '23b99490-be92-4edc-a939-07e0f64f13eb', + name: 'viewSorts', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '540715e7-6531-4746-b567-b0a7fcda60ef', + type: 'UUID', + name: 'fieldMetadataId', + label: 'Field Metadata Id', + description: 'View Sort target field', + icon: 'IconTag', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '26889121-d2d9-49dc-86ac-51c64d123197', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'rocket', + namePlural: 'rockets', + labelSingular: 'Rocket', + labelPlural: 'Rockets', + description: 'A rocket', + icon: 'IconRocket', + isCustom: true, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + labelIdentifierFieldMetadataId: null, + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEy', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9aed4be2-3434-489f-a8a3-384311ee585e', + type: 'RELATION', + name: 'activityTargets', + label: 'Activities', + description: 'Activities tied to the Rocket', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.577Z', + updatedAt: '2024-09-25T13:45:42.577Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '624c8a51-ba95-409f-bd54-72c85bb1bb2d', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '9aed4be2-3434-489f-a8a3-384311ee585e', + name: 'activityTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '4a2da98e-6880-47be-8673-165e1d77a910', + name: 'rocket', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '13794481-6a3a-48cb-80c2-109b7558f7b3', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Attachments tied to the Rocket', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.595Z', + updatedAt: '2024-09-25T13:45:42.595Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '20cefbaf-15be-4235-a952-39dff94d00f2', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '13794481-6a3a-48cb-80c2-109b7558f7b3', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: '60f8c4fb-1ab9-44a7-a5bd-e89a0349feb7', + name: 'rocket', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '79da64bc-eea3-476e-801b-f08c86a8c337', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites tied to the Rocket', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.587Z', + updatedAt: '2024-09-25T13:45:42.587Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '2d9dcc60-3d44-4ea4-ac02-146fdbdeac22', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '79da64bc-eea3-476e-801b-f08c86a8c337', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '11e6c0a0-e1fa-4931-a705-8725a79afe24', + name: 'rocket', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0a688ec2-f55c-4485-a7a9-9438c19bcbe3', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '17cbb6ed-1acc-43e9-a802-96a2b373a067', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ba68ee30-5dc6-47db-bf6f-db25d829feb5', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'Name', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: "'Untitled'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ff73fd8a-9b60-4480-82d0-7b96c3c3aab6', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '83515891-eb29-472e-9cde-4a1d42b6855d', + type: 'RELATION', + name: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the Rocket', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.612Z', + updatedAt: '2024-09-25T13:45:42.612Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '140a67f3-988e-4d60-b24c-8a4fcb4ea6e9', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '83515891-eb29-472e-9cde-4a1d42b6855d', + name: 'taskTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'dadac630-f64e-4d3d-9923-78ca579373f3', + name: 'rocket', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '73428c65-a426-4c59-b50b-0dea5ffe9bf0', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6c65c781-9def-4c6c-98d4-25d3c0c085b8', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b2643f4a-319e-49d4-a7b7-cbfff4712bf7', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Deletion date', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.556Z', + updatedAt: '2024-09-25T13:45:42.556Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '75f64c23-e9a5-4ada-8dc6-3c2c2ea27280', + type: 'RELATION', + name: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the Rocket', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.605Z', + updatedAt: '2024-09-25T13:45:42.605Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '9cbf4ccc-cff9-4439-86c9-6f8c01970442', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '75f64c23-e9a5-4ada-8dc6-3c2c2ea27280', + name: 'noteTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '26c57af1-5c70-4a9d-974f-e54c6a77a2b4', + name: 'rocket', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aeefa434-6843-4b47-92f6-3ce6d8e93860', + type: 'RELATION', + name: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities tied to the Rocket', + icon: 'IconIconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.569Z', + updatedAt: '2024-09-25T13:45:42.569Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'f684f74f-b705-4253-aad5-caf1c5f7f19a', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'aeefa434-6843-4b47-92f6-3ce6d8e93860', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f2f27d9e-c959-4dee-aed4-f87c64229c3f', + name: 'rocket', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '522136fb-741c-4b3b-b44a-b20b62352b47', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'blocklist', + namePlural: 'blocklists', + labelSingular: 'Blocklist', + labelPlural: 'Blocklists', + description: 'Blocklist', + icon: 'IconForbid2', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '37f7671b-aa7c-4fed-b50c-9b7cc7f59aa8', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjY=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fa957d80-c61a-4298-aab9-54e8fba2110d', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f966b379-0438-4b9c-8696-3edf18c197f7', + type: 'RELATION', + name: 'workspaceMember', + label: 'WorkspaceMember', + description: 'WorkspaceMember', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'd0a8b3ba-9219-40d6-957c-3e8d5d656d3a', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '522136fb-741c-4b3b-b44a-b20b62352b47', + nameSingular: 'blocklist', + namePlural: 'blocklists', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f966b379-0438-4b9c-8696-3edf18c197f7', + name: 'workspaceMember', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'e64fef03-fda1-4b5c-8894-d1bee725e7e2', + name: 'blocklist', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '37f7671b-aa7c-4fed-b50c-9b7cc7f59aa8', + type: 'TEXT', + name: 'handle', + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '862261a3-5473-4e16-9220-16444ee99243', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1233f40e-cc97-4281-a8a8-c23de8961693', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a75f6045-cf57-4b05-960b-5719ce2037c9', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c30e3bff-ce4e-4e64-80e3-bf417ceefa25', + type: 'UUID', + name: 'workspaceMemberId', + label: 'WorkspaceMember id (foreign key)', + description: 'WorkspaceMember id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '51dd66f3-a025-4631-9d6a-594419bbda05', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'workflowRun', + namePlural: 'workflowRuns', + labelSingular: 'workflowRun', + labelPlural: 'WorkflowRuns', + description: 'A workflow run', + icon: null, + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'f40e2edc-c0dd-46d8-9a01-a0afd33a00db', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEx', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2d00a390-5ae4-40d9-8d6c-6abbcdc0bc75', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2aab6f08-2cab-4beb-8775-1ad8b89c3313', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f40e2edc-c0dd-46d8-9a01-a0afd33a00db', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '421de2e5-36a1-4fb2-ae00-4e2f62dd67e6', + type: 'UUID', + name: 'workflowVersionId', + label: 'Workflow version id (foreign key)', + description: + 'Workflow version linked to the run. id foreign key', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c9e837bb-4516-43ad-8756-7a9c2ad33ca9', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aec86cc0-1fb6-4ff0-b1df-85b74ee6a974', + type: 'UUID', + name: 'workflowId', + label: 'Workflow id (foreign key)', + description: 'Workflow linked to the run. id foreign key', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b38c3f7d-d455-4f1c-b674-66b86c0d56cc', + type: 'RELATION', + name: 'workflowVersion', + label: 'Workflow version', + description: 'Workflow version linked to the run.', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '2d71efdd-cd73-4056-8c3b-73ec03843110', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '51dd66f3-a025-4631-9d6a-594419bbda05', + nameSingular: 'workflowRun', + namePlural: 'workflowRuns', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'b38c3f7d-d455-4f1c-b674-66b86c0d56cc', + name: 'workflowVersion', + }, + targetObjectMetadata: { + __typename: 'object', + id: '081c04be-c9e7-455a-990b-ea6c92bb042f', + nameSingular: 'workflowVersion', + namePlural: 'workflowVersions', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'ef3d8797-2f17-4f31-9970-697fc230df7f', + name: 'runs', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '446d4c37-71ac-4a61-8b65-16d70250cbc5', + type: 'SELECT', + name: 'status', + label: 'Workflow run status', + description: 'Workflow run status', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'NOT_STARTED'", + options: [ + { + id: 'ac758ebd-217c-4402-806a-2989740a5674', + color: 'grey', + label: 'Not started', + value: 'NOT_STARTED', + position: 0, + }, + { + id: '2db304c4-717a-40c2-afe3-bc62f2114476', + color: 'yellow', + label: 'Running', + value: 'RUNNING', + position: 1, + }, + { + id: 'ae5d8a99-538f-4851-a186-1f3c56596b0c', + color: 'green', + label: 'Completed', + value: 'COMPLETED', + position: 2, + }, + { + id: 'ac331d7d-ab1b-4e77-9395-37334d102eb2', + color: 'red', + label: 'Failed', + value: 'FAILED', + position: 3, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0ed4a200-4d2e-4d4d-81b2-45240ae9e1b8', + type: 'DATE_TIME', + name: 'endedAt', + label: 'Workflow run ended at', + description: 'Workflow run ended at', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a5444b51-1ad5-46ae-b9d9-ef5f1def9232', + type: 'RELATION', + name: 'workflow', + label: 'Workflow', + description: 'Workflow linked to the run.', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'f4f3d2da-cded-4999-871d-2f70e96e99fc', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '51dd66f3-a025-4631-9d6a-594419bbda05', + nameSingular: 'workflowRun', + namePlural: 'workflowRuns', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'a5444b51-1ad5-46ae-b9d9-ef5f1def9232', + name: 'workflow', + }, + targetObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + targetFieldMetadata: { + __typename: 'field', + id: '4f32f14b-5009-4624-8b19-e65084368349', + name: 'runs', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b388b202-371a-4663-9299-afc6be461a8c', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2e84a165-18af-492f-8662-14fbd5852b0c', + type: 'DATE_TIME', + name: 'startedAt', + label: 'Workflow run started at', + description: 'Workflow run started at', + icon: 'IconHistory', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'task', + namePlural: 'tasks', + labelSingular: 'Task', + labelPlural: 'Tasks', + description: 'A task', + icon: 'IconCheckbox', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '0413dccd-00a6-4abd-967a-45233e8cf666', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE1', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6f41b722-fbc4-44d9-9315-51498900e157', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1d53ad9c-bdf4-4660-b4b6-e79162d13c39', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the task', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c349fbab-ecda-4dd6-bf3f-b60a4118db25', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '1d53ad9c-bdf4-4660-b4b6-e79162d13c39', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'dc005581-351b-4fa0-9b39-da5bbe2554b7', + name: 'task', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e7df66e0-50cc-4047-9b91-8f5ee1ff7246', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '34ec585e-b42e-4e63-8e4b-7f9bf6a4e79b', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '22b735aa-95d7-44fe-a4a6-965171e3f7b7', + type: 'DATE_TIME', + name: 'dueAt', + label: 'Due Date', + description: 'Task due date', + icon: 'IconCalendarEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fea3a2f3-73ca-4142-8d15-3b8877b68cee', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4f82dbad-cf61-4dd1-ad90-4cec71b288be', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Task attachments', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '5a06cc7e-b994-4a53-881f-d32decfe9f3e', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '4f82dbad-cf61-4dd1-ad90-4cec71b288be', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: '26668e62-39e7-4842-a198-a657f44206f8', + name: 'task', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b52cbdab-0c97-4601-b5ad-de766ec9f940', + type: 'SELECT', + name: 'status', + label: 'Status', + description: 'Task status', + icon: 'IconCheck', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'TODO'", + options: [ + { + id: 'daaeca90-3643-4127-b364-80cf3dea8f71', + color: 'sky', + label: 'To do', + value: 'TODO', + position: 0, + }, + { + id: '49f1408b-5f51-4659-a4e1-bb2bb74bb977', + color: 'purple', + label: 'In progress', + value: 'IN_PROGESS', + position: 1, + }, + { + id: '552511ed-d17e-4863-ae7e-862034214507', + color: 'green', + label: 'Done', + value: 'DONE', + position: 1, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1eea9af9-53a3-4085-9391-4a2fad697eb7', + type: 'RELATION', + name: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the task.', + icon: 'IconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '881b8fa7-814a-435a-84b7-da344fc0639a', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '1eea9af9-53a3-4085-9391-4a2fad697eb7', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '8626f50f-1d39-40e7-a05b-528c42fe4313', + name: 'task', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '78360243-9830-4f40-a515-59cd8faf88b1', + type: 'RICH_TEXT', + name: 'body', + label: 'Body', + description: 'Task body', + icon: 'IconFilePencil', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '33d7eb92-8231-417c-8efe-eb837c6ccadf', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5f9a8761-e5e6-492c-87ab-401c7b0e25cd', + type: 'UUID', + name: 'assigneeId', + label: 'Assignee id (foreign key)', + description: 'Task assignee id foreign key', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7a062a59-07da-4d2d-a0e8-f79f87e2e5e3', + type: 'RELATION', + name: 'assignee', + label: 'Assignee', + description: 'Task assignee', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'fe131172-06fc-4057-b1d0-c23dc5f030b9', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '7a062a59-07da-4d2d-a0e8-f79f87e2e5e3', + name: 'assignee', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: '3653df1b-5687-45c1-a2bf-afc261fe85a8', + name: 'assignedTasks', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '80932806-6350-4941-a291-4d1430275d65', + type: 'RELATION', + name: 'taskTargets', + label: 'Relations', + description: 'Task targets', + icon: 'IconArrowUpRight', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '81926481-abaa-4b04-900e-2170694cc034', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '80932806-6350-4941-a291-4d1430275d65', + name: 'taskTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'ec532542-a4dc-4722-99c3-fca6366db597', + name: 'task', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'daf389ba-49e6-4753-8a5a-a0330c5ab154', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Task record position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0413dccd-00a6-4abd-967a-45233e8cf666', + type: 'TEXT', + name: 'title', + label: 'Title', + description: 'Task title', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'workflow', + namePlural: 'workflows', + labelSingular: 'Workflow', + labelPlural: 'Workflows', + description: 'A workflow', + icon: 'IconSettingsAutomation', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'bab376b1-a7d9-48b8-88b7-f302bc6d483d', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEx', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '38f5127c-ab53-45bc-90b9-a3883d697eb9', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b2a7002e-19f2-4f16-8b5b-ea452aeb7104', + type: 'TEXT', + name: 'lastPublishedVersionId', + label: 'Last published Version Id', + description: 'The workflow last published version id', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd6fb9120-9aa5-4fdf-a84a-2805bb359855', + type: 'RELATION', + name: 'versions', + label: 'Versions', + description: 'Workflow versions linked to the workflow.', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8bcc3362-58ea-46ab-8639-e3def87eb454', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd6fb9120-9aa5-4fdf-a84a-2805bb359855', + name: 'versions', + }, + targetObjectMetadata: { + __typename: 'object', + id: '081c04be-c9e7-455a-990b-ea6c92bb042f', + nameSingular: 'workflowVersion', + namePlural: 'workflowVersions', + }, + targetFieldMetadata: { + __typename: 'field', + id: '54cde78b-4bd4-436b-b10b-e6de37494161', + name: 'workflow', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '99d7e7e6-ac6a-4b74-9129-d4a9759bc928', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '06a5a424-930c-4465-9943-2a9c486f2038', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '650b02ef-32b5-4b10-bdab-a49f4e3b7a9b', + type: 'MULTI_SELECT', + name: 'statuses', + label: 'Statuses', + description: + 'The current statuses of the workflow versions', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: [ + { + color: 'yellow', + label: 'Draft', + value: 'DRAFT', + position: 0, + }, + { + color: 'green', + label: 'Active', + value: 'ACTIVE', + position: 1, + }, + { + color: 'grey', + label: 'Deactivated', + value: 'DEACTIVATED', + position: 2, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b14865e9-26a6-4ae8-930d-d22c21c7696c', + type: 'RELATION', + name: 'eventListeners', + label: 'Event Listeners', + description: + 'Workflow event listeners linked to the workflow.', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '1353dcd5-92ce-4947-8156-c1de74eaf54b', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'b14865e9-26a6-4ae8-930d-d22c21c7696c', + name: 'eventListeners', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6f69be9e-d899-4e40-bf15-0c8194e6a934', + nameSingular: 'workflowEventListener', + namePlural: 'workflowEventListeners', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'a424fba4-d3f4-41b1-bf9a-4b809ad628a9', + name: 'workflow', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4f32f14b-5009-4624-8b19-e65084368349', + type: 'RELATION', + name: 'runs', + label: 'Runs', + description: 'Workflow runs linked to the workflow.', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'f4f3d2da-cded-4999-871d-2f70e96e99fc', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '4f32f14b-5009-4624-8b19-e65084368349', + name: 'runs', + }, + targetObjectMetadata: { + __typename: 'object', + id: '51dd66f3-a025-4631-9d6a-594419bbda05', + nameSingular: 'workflowRun', + namePlural: 'workflowRuns', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'a5444b51-1ad5-46ae-b9d9-ef5f1def9232', + name: 'workflow', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bab376b1-a7d9-48b8-88b7-f302bc6d483d', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'The workflow name', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '141281c7-5b28-41d4-99bd-31c1e4c88e9b', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the contact', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '892e8ce6-83f8-4dbd-8c0d-eb5bb7db71f6', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '141281c7-5b28-41d4-99bd-31c1e4c88e9b', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'eed525bd-edf3-4030-9f09-8ff68226a6a0', + name: 'workflow', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f21077b2-283f-4362-98fd-e5ea5f87d621', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Workflow record position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b063853c-a442-4b52-8f89-f750c44a2e04', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + labelSingular: 'Timeline Activity', + labelPlural: 'Timeline Activities', + description: + 'Aggregated / filtered event to be displayed on the timeline', + icon: 'IconIconTimelineEvent', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '6615546f-8744-4b36-83d5-59c1ef72e845', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjIz', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6615546f-8744-4b36-83d5-59c1ef72e845', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '299c9bdc-5137-4d2b-8225-ddb81a720bfe', + type: 'UUID', + name: 'rocketId', + label: 'Rocket ID (foreign key)', + description: 'Timeline Activity Rocket id foreign key', + icon: null, + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.564Z', + updatedAt: '2024-09-25T13:45:42.564Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8626f50f-1d39-40e7-a05b-528c42fe4313', + type: 'RELATION', + name: 'task', + label: 'Task', + description: 'Event task', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '881b8fa7-814a-435a-84b7-da344fc0639a', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '8626f50f-1d39-40e7-a05b-528c42fe4313', + name: 'task', + }, + targetObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + targetFieldMetadata: { + __typename: 'field', + id: '1eea9af9-53a3-4085-9391-4a2fad697eb7', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f2f27d9e-c959-4dee-aed4-f87c64229c3f', + type: 'RELATION', + name: 'rocket', + label: 'Rocket', + description: 'Timeline Activity Rocket', + icon: 'IconTimeline', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.569Z', + updatedAt: '2024-09-25T13:45:42.569Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'f684f74f-b705-4253-aad5-caf1c5f7f19a', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f2f27d9e-c959-4dee-aed4-f87c64229c3f', + name: 'rocket', + }, + targetObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'aeefa434-6843-4b47-92f6-3ce6d8e93860', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '62e278a5-d719-4b49-a820-fc5ed358311e', + type: 'DATE_TIME', + name: 'happensAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '145c8790-abd1-49fb-9857-650da78c6717', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'Event company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'b8909cf8-5b9d-4512-8fdf-d6fc4b450191', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '145c8790-abd1-49fb-9857-650da78c6717', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f8393bb6-05c2-44d7-bff8-4a7671b43f15', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '08dd3999-ca07-43cf-b872-a2bed317aa6a', + type: 'TEXT', + name: 'name', + label: 'Event name', + description: 'Event name', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bbdf103a-60cb-4c39-a982-1704e26f6735', + type: 'UUID', + name: 'noteId', + label: 'Note id (foreign key)', + description: 'Event note id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9e9d4989-fdf2-4e71-90af-aae2ef0b4923', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'Event person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'bc97fb28-bb40-41de-9535-4bae43cf653c', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '9e9d4989-fdf2-4e71-90af-aae2ef0b4923', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: '6e46c199-d4f9-4c60-b9bb-19da859991b4', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1b496b65-948d-4614-889f-2a9e0a6292f3', + type: 'UUID', + name: 'linkedObjectMetadataId', + label: 'Linked Object Metadata Id', + description: 'inked Object Metadata Id', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'cd22914c-60d6-4e45-9936-9ff345d3a5bb', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '77f9059d-33f5-4fa1-8641-4976d38eaeb7', + type: 'TEXT', + name: 'linkedRecordCachedName', + label: 'Linked Record cached name', + description: 'Cached record name', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '137a88ef-9c08-414c-adcc-2d450624acf8', + type: 'RELATION', + name: 'workspaceMember', + label: 'Workspace Member', + description: 'Event workspace member', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'db084a18-152f-4ea9-967e-69a45f2d24ab', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '137a88ef-9c08-414c-adcc-2d450624acf8', + name: 'workspaceMember', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'a5fc2711-0e3d-40ac-938a-8beafeac1f57', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b2df9370-1560-47f6-89b6-88293de46572', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'Event person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '9cb24716-07e8-4c54-a0c8-7005a619314e', + type: 'RAW_JSON', + name: 'properties', + label: 'Event details', + description: 'Json value for event details', + icon: 'IconListDetails', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bc5277df-a1ec-4ae2-affe-e42aed88f0b9', + type: 'UUID', + name: 'taskId', + label: 'Task id (foreign key)', + description: 'Event task id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'cda06c7c-9c62-4579-b3ba-2e8275c604b1', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '95fa7d72-fd85-4a32-a489-a5d03199debb', + type: 'UUID', + name: 'workspaceMemberId', + label: 'Workspace Member id (foreign key)', + description: 'Event workspace member id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1d16560a-4a8f-448c-8289-70e3e98ad3b4', + type: 'UUID', + name: 'linkedRecordId', + label: 'Linked Record id', + description: 'Linked Record id', + icon: 'IconAbc', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c646eaf5-2754-4924-a212-c5747b0d1d41', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'Event company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '88a829b3-6d66-4e53-b1ad-ed02e544e4d2', + type: 'RELATION', + name: 'opportunity', + label: 'Opportunity', + description: 'Event opportunity', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8d8d083e-b9a2-4de2-a368-2422a4df4a83', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '88a829b3-6d66-4e53-b1ad-ed02e544e4d2', + name: 'opportunity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '9019bf90-efbc-4499-a87b-0624bda5a559', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'db7ab4e8-9d93-4f45-bbbf-f68eb31776cb', + type: 'RELATION', + name: 'note', + label: 'Note', + description: 'Event note', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e122b1c1-7518-425d-854c-d0817d42988b', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'db7ab4e8-9d93-4f45-bbbf-f68eb31776cb', + name: 'note', + }, + targetObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + targetFieldMetadata: { + __typename: 'field', + id: '210b544b-46f7-422d-84e7-328ef270f081', + name: 'timelineActivities', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1ee1c4bc-7281-4eff-bc32-6afaff324477', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '225d1acc-2ccc-458d-acd5-06f7d8647a38', + type: 'UUID', + name: 'opportunityId', + label: 'Opportunity id (foreign key)', + description: 'Event opportunity id foreign key', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'person', + namePlural: 'people', + labelSingular: 'Person', + labelPlural: 'People', + description: 'A person', + icon: 'IconUser', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '5a063961-bffe-4d68-a0c8-e86b6b26f85e', + imageIdentifierFieldMetadataId: + '377efd0d-9798-4522-b9db-73c19bf55e26', + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjI4', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f926708e-cc19-4e5f-8684-d14a1a1bc7df', + type: 'RELATION', + name: 'pointOfContactForOpportunities', + label: 'Linked Opportunities', + description: + 'List of opportunities for which that person is the point of contact', + icon: 'IconTargetArrow', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c80603a0-f9b4-47c0-ba4d-7a1c5d0735e8', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f926708e-cc19-4e5f-8684-d14a1a1bc7df', + name: 'pointOfContactForOpportunities', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '7ad6853d-d1e9-46a8-a77a-38eeae27e1d6', + name: 'pointOfContact', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5a063961-bffe-4d68-a0c8-e86b6b26f85e', + type: 'FULL_NAME', + name: 'name', + label: 'Name', + description: 'Contact’s name', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + lastName: "''", + firstName: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd02d52c8-379b-476d-84d6-1222c2179db7', + type: 'LINKS', + name: 'linkedinLink', + label: 'Linkedin', + description: 'Contact’s Linkedin account', + icon: 'IconBrandLinkedin', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '504f7e23-1476-422b-ac1d-5d86d3d33022', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'Contact’s company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'd9add14d-13bd-4bb7-abab-06d4fdc78a3e', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '504f7e23-1476-422b-ac1d-5d86d3d33022', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: '37abc2ae-9f44-4bc0-8277-e3ddfd54738c', + name: 'people', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'daab9749-7d39-44cb-9557-23e0e257aaad', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the contact.', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e2ac522a-6bd8-4e24-9171-b9c00acf8ed1', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'daab9749-7d39-44cb-9557-23e0e257aaad', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: '610633e7-0221-4838-adaf-71943d18a5ca', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6e46c199-d4f9-4c60-b9bb-19da859991b4', + type: 'RELATION', + name: 'timelineActivities', + label: 'Events', + description: 'Events linked to the person', + icon: 'IconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'bc97fb28-bb40-41de-9535-4bae43cf653c', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '6e46c199-d4f9-4c60-b9bb-19da859991b4', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: '9e9d4989-fdf2-4e71-90af-aae2ef0b4923', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'aa5e7931-e042-45d5-af4a-e4c22979a3b7', + type: 'RELATION', + name: 'calendarEventParticipants', + label: 'Calendar Event Participants', + description: 'Calendar Event Participants', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7aced498-e104-4898-939c-187937ea7bca', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'aa5e7931-e042-45d5-af4a-e4c22979a3b7', + name: 'calendarEventParticipants', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'd2ea4c05-34cd-4c7c-9215-d044c9c92522', + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + }, + targetFieldMetadata: { + __typename: 'field', + id: '2f77bc8e-26dc-40b1-964a-f0748feb193a', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a8a3d68a-a1b1-4912-aa13-51f088c6a754', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e442f814-f8a6-44e9-b60c-d736afec87dd', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a91e4125-7885-4b3c-9672-0f6d2fc49c07', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4a9a6c3e-633d-47d6-99bc-b8e6e9b6aad9', + type: 'TEXT', + name: 'jobTitle', + label: 'Job Title', + description: 'Contact’s job title', + icon: 'IconBriefcase', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b801b0d2-2a24-42be-b878-ef439ef7ea78', + type: 'TEXT', + name: 'intro', + label: 'Intro', + description: "Contact's Intro", + icon: 'IconNote', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:42.038Z', + updatedAt: '2024-09-25T13:45:42.038Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c188f5b7-2259-4207-87d2-5232ec775029', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the contact', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '001dae2b-80e6-4e2d-b5fe-ee0349e940d7', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'c188f5b7-2259-4207-87d2-5232ec775029', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '8e506212-1b66-4981-95d6-f0ac83f5d869', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5cdf5de5-6c7f-4787-b47d-de5e3787e670', + type: 'MULTI_SELECT', + name: 'workPrefereance', + label: 'Work Preference', + description: "Person's Work Preference", + icon: 'IconHome', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.291Z', + updatedAt: '2024-09-25T13:45:42.291Z', + defaultValue: null, + options: [ + { + id: '4fa9fd50-9206-490f-92e3-f143915a6088', + color: 'green', + label: 'On-Site', + value: 'ON_SITE', + position: 0, + }, + { + id: 'abc69904-c7cb-4b4b-888d-0b5bd64f0edf', + color: 'turquoise', + label: 'Hybrid', + value: 'HYBRID', + position: 1, + }, + { + id: '1cc7265d-87ca-47fc-835e-5956108bb6d2', + color: 'sky', + label: 'Remote Work', + value: 'REMOTE_WORK', + position: 2, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1315ca79-3abd-4b7f-917e-8949db3e01f3', + type: 'RATING', + name: 'performanceRating', + label: 'Performance Rating', + description: "Person's Performance Rating", + icon: 'IconStars', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.424Z', + updatedAt: '2024-09-25T13:45:42.424Z', + defaultValue: null, + options: [ + { + id: 'fc406c33-e6dc-4e2c-b10c-d0c86fa17108', + label: '1', + value: 'RATING_1', + position: 0, + }, + { + id: '6657fe2f-4e4f-4725-b088-d4c01d16bfc7', + label: '2', + value: 'RATING_2', + position: 1, + }, + { + id: '21f68a36-568c-468f-8115-bc64b0473371', + label: '3', + value: 'RATING_3', + position: 2, + }, + { + id: 'fc09af32-0f32-422f-9def-c456a48e7e80', + label: '4', + value: 'RATING_4', + position: 3, + }, + { + id: '0c40c9f6-5d06-4692-8c8a-6dc14c3dc4be', + label: '5', + value: 'RATING_5', + position: 4, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '749e13b2-5430-4993-83db-635c6ff11d1a', + type: 'LINKS', + name: 'xLink', + label: 'X', + description: 'Contact’s X/Twitter account', + icon: 'IconBrandX', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryLinkUrl: "''", + secondaryLinks: null, + primaryLinkLabel: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '0f7b1621-5da6-439a-927f-948fd2dd6f29', + type: 'RELATION', + name: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the contact', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '4bde4058-4875-4a16-9cc3-4e387121a875', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '0f7b1621-5da6-439a-927f-948fd2dd6f29', + name: 'noteTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '77508442-f0de-4809-b690-3c998edfc0b5', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '759da4e9-e9c6-4827-9802-5b7b4021448f', + type: 'TEXT', + name: 'city', + label: 'City', + description: 'Contact’s city', + icon: 'IconMap', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '48f76fc3-3c82-463d-afa7-977011eed7c8', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'Contact’s company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '23c64ee1-4935-4a25-b401-afc08a0967fd', + type: 'RELATION', + name: 'activityTargets', + label: 'Activities', + description: 'Activities tied to the contact', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '22f8c2a7-9887-4642-821c-6fefaab56aed', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '23c64ee1-4935-4a25-b401-afc08a0967fd', + name: 'activityTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e241490a-b533-4c60-8fc8-a1cbda8d7e1d', + nameSingular: 'activityTarget', + namePlural: 'activityTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '867aff40-ddf5-4af8-a3f5-6359ab91eb2c', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd4a5fecc-285b-42d7-8eb4-96fc2a6838c4', + type: 'PHONES', + name: 'phones', + label: 'Phones', + description: 'Contact’s phone numbers', + icon: 'IconPhone', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + additionalPhones: null, + primaryPhoneNumber: "''", + primaryPhoneCountryCode: "''", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bb5900a5-29ff-46bb-8bbb-7dbedd844e29', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '54fbea0f-ce3f-4d28-8fa4-abcfe1ae3d54', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '718ee8a6-a294-4609-91d4-7ab0e83d996f', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Person record Position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '779bdf5a-a28d-48be-8d02-b6ca93851829', + type: 'RELATION', + name: 'messageParticipants', + label: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8c36bb62-2757-4c24-88da-160a6a9e56d6', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '779bdf5a-a28d-48be-8d02-b6ca93851829', + name: 'messageParticipants', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f3db188f-7329-40bc-9978-e30e5c07d962', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7f8249b8-5919-4fee-81cf-b4dfdb89cf4d', + type: 'EMAILS', + name: 'emails', + label: 'Emails', + description: 'Contact’s Emails', + icon: 'IconMail', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + primaryEmail: "''", + additionalEmails: null, + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'b328a712-5dc3-457a-aa56-8631f1b57248', + type: 'RELATION', + name: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the contact', + icon: 'IconCheckbox', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'c0c28147-9606-4d8f-9c27-688f19c00dc4', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'b328a712-5dc3-457a-aa56-8631f1b57248', + name: 'taskTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f823669a-4e86-415e-8758-be44b864de1c', + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '26cc6ba3-cff7-4b84-bf78-71823187a824', + name: 'person', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '377efd0d-9798-4522-b9db-73c19bf55e26', + type: 'TEXT', + name: 'avatarUrl', + label: 'Avatar', + description: 'Contact’s avatar', + icon: 'IconFileUpload', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3a34e81d-d5b1-417d-9831-a355040a6f44', + type: 'PHONES', + name: 'whatsapp', + label: 'Whatsapp', + description: "Contact's Whatsapp Number", + icon: 'IconBrandWhatsapp', + isCustom: true, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:42.159Z', + updatedAt: '2024-09-25T13:45:42.159Z', + defaultValue: { + additionalPhones: null, + primaryPhoneNumber: "''", + primaryPhoneCountryCode: "''", + }, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'note', + namePlural: 'notes', + labelSingular: 'Note', + labelPlural: 'Notes', + description: 'A note', + icon: 'IconNotes', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '7ffc4d21-aa5d-4f0f-bc91-61c72660f2ba', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEx', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f115229b-f5b3-4623-ac80-f8bf3df5e077', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the note', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'aeec4288-a886-4c86-8f42-1be726bd4fb4', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'f115229b-f5b3-4623-ac80-f8bf3df5e077', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '0ecb3679-5ff7-4b55-9ed3-9927bc9e184b', + name: 'note', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ed46299b-4006-45b4-aaa4-2dc7c0c25613', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '54952f24-63cc-475e-ab4c-b0f3ad6400bc', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'bef43ac8-834a-4a86-8bfb-5bed6cd94a57', + type: 'RELATION', + name: 'noteTargets', + label: 'Relations', + description: 'Note targets', + icon: 'IconArrowUpRight', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e512fc88-2b02-4ba4-a118-ead545db5a63', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'bef43ac8-834a-4a86-8bfb-5bed6cd94a57', + name: 'noteTargets', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'f274711e-b4cd-4a13-b74d-d48205f61332', + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '9d568132-6cbc-4e87-95e8-7c2509549391', + name: 'note', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '210b544b-46f7-422d-84e7-328ef270f081', + type: 'RELATION', + name: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the note.', + icon: 'IconTimelineEvent', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e122b1c1-7518-425d-854c-d0817d42988b', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '210b544b-46f7-422d-84e7-328ef270f081', + name: 'timelineActivities', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2ee34d7c-4efb-4ac2-abed-a53dff446b0b', + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'db7ab4e8-9d93-4f45-bbbf-f68eb31776cb', + name: 'note', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd80706c2-3c5d-491f-9759-b05b25004799', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'Note record position', + icon: 'IconHierarchy2', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2238e043-a33f-4e8d-99d6-386cd0d2ea3b', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c996b13e-a787-44f7-ad7a-2ba22afd46bc', + type: 'ACTOR', + name: 'createdBy', + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: { + name: "''", + source: "'MANUAL'", + }, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '61375724-caaa-46b1-8e50-4b2f23afac71', + type: 'RICH_TEXT', + name: 'body', + label: 'Body', + description: 'Note body', + icon: 'IconFilePencil', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7ffc4d21-aa5d-4f0f-bc91-61c72660f2ba', + type: 'TEXT', + name: 'title', + label: 'Title', + description: 'Note title', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '27b7400b-e754-4db9-b895-0a9252a015bf', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '80479763-1c19-4465-a62f-cd5e37c9165a', + type: 'RELATION', + name: 'attachments', + label: 'Attachments', + description: 'Note attachments', + icon: 'IconFileImport', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '9a0ad471-2e53-4943-8b28-30950550a9a7', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '80479763-1c19-4465-a62f-cd5e37c9165a', + name: 'attachments', + }, + targetObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + targetFieldMetadata: { + __typename: 'field', + id: '6a5833a9-0741-44f0-948d-424a60d3264e', + name: 'note', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '0c5ade71-e5e7-45a0-b93c-ecb3b84f6287', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'viewFilter', + namePlural: 'viewFilters', + labelSingular: 'View Filter', + labelPlural: 'View Filters', + description: '(System) View Filters', + icon: 'IconFilterBolt', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '362cb4b7-dda1-4136-9385-4f5402b4f700', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjk=', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4e4f0f26-89bd-41eb-bc00-a591e041ca7d', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '362cb4b7-dda1-4136-9385-4f5402b4f700', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd13848d4-b41e-43b0-87ca-ab40c00fd739', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '81685712-ecaa-4d04-a8d9-e6c93a6bfe7a', + type: 'TEXT', + name: 'displayValue', + label: 'Display Value', + description: 'View Filter Display Value', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f72701d1-8337-4640-84b7-4570cfbe96aa', + type: 'UUID', + name: 'viewId', + label: 'View id (foreign key)', + description: 'View Filter related view id foreign key', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e323bb1b-8018-4b6f-b065-37c979caf7fc', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '646c0bfc-071d-44f3-b8d4-428061106500', + type: 'UUID', + name: 'fieldMetadataId', + label: 'Field Metadata Id', + description: 'View Filter target field', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '016a2312-ac04-4d46-b7c7-2d6e24e363c8', + type: 'TEXT', + name: 'value', + label: 'Value', + description: 'View Filter value', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'e09cc7ab-2750-4cd9-86e1-c257dac8b390', + type: 'TEXT', + name: 'operand', + label: 'Operand', + description: 'View Filter operand', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'Contains'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd1829b60-e886-4dac-8cf3-0d3b84da093d', + type: 'RELATION', + name: 'view', + label: 'View', + description: 'View Filter related view', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7ffac7d4-2cfc-4932-9f3c-3ad4ab6eb4f7', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '0c5ade71-e5e7-45a0-b93c-ecb3b84f6287', + nameSingular: 'viewFilter', + namePlural: 'viewFilters', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd1829b60-e886-4dac-8cf3-0d3b84da093d', + name: 'view', + }, + targetObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + targetFieldMetadata: { + __typename: 'field', + id: '7974ab3b-7d05-4738-a05b-b76840f98328', + name: 'viewFilters', + }, + }, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '081c04be-c9e7-455a-990b-ea6c92bb042f', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'workflowVersion', + namePlural: 'workflowVersions', + labelSingular: 'WorkflowVersion', + labelPlural: 'WorkflowVersions', + description: 'A workflow version', + icon: 'IconVersions', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'ef2dd597-faaa-4b1d-96b7-5953cd8c8539', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEw', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dd208a4e-3e5e-4192-83a1-adbc5b9123a1', + type: 'RAW_JSON', + name: 'steps', + label: 'Version steps', + description: 'Json object to provide steps', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fe28de2e-8979-4cfd-9b66-03e67e93406b', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dcdf9413-04c8-44f7-ace7-a11950ce3019', + type: 'SELECT', + name: 'status', + label: 'Version status', + description: 'The workflow version status', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'DRAFT'", + options: [ + { + id: '8e499a03-e349-47ec-9d59-b32f2666cf2d', + color: 'yellow', + label: 'Draft', + value: 'DRAFT', + position: 0, + }, + { + id: 'c97e3271-1f41-424a-bd8f-5540f2b79a43', + color: 'green', + label: 'Active', + value: 'ACTIVE', + position: 1, + }, + { + id: '1e708b75-2826-4745-9014-b2427aad60a8', + color: 'red', + label: 'Deactivated', + value: 'DEACTIVATED', + position: 2, + }, + { + id: 'e458f973-723a-4fed-9146-cec11a7887bb', + color: 'grey', + label: 'Archived', + value: 'ARCHIVED', + position: 3, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ef3d8797-2f17-4f31-9970-697fc230df7f', + type: 'RELATION', + name: 'runs', + label: 'Runs', + description: 'Workflow runs linked to the version.', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '2d71efdd-cd73-4056-8c3b-73ec03843110', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '081c04be-c9e7-455a-990b-ea6c92bb042f', + nameSingular: 'workflowVersion', + namePlural: 'workflowVersions', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'ef3d8797-2f17-4f31-9970-697fc230df7f', + name: 'runs', + }, + targetObjectMetadata: { + __typename: 'object', + id: '51dd66f3-a025-4631-9d6a-594419bbda05', + nameSingular: 'workflowRun', + namePlural: 'workflowRuns', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'b38c3f7d-d455-4f1c-b674-66b86c0d56cc', + name: 'workflowVersion', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ebe58c33-17d2-418b-b33f-f5c3907e97d7', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1b223e47-9228-41c4-a420-ff6ed516393e', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '54cde78b-4bd4-436b-b10b-e6de37494161', + type: 'RELATION', + name: 'workflow', + label: 'Workflow', + description: 'WorkflowVersion workflow', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '8bcc3362-58ea-46ab-8639-e3def87eb454', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '081c04be-c9e7-455a-990b-ea6c92bb042f', + nameSingular: 'workflowVersion', + namePlural: 'workflowVersions', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '54cde78b-4bd4-436b-b10b-e6de37494161', + name: 'workflow', + }, + targetObjectMetadata: { + __typename: 'object', + id: '470b50d2-333a-4897-92cb-181d4883a0f3', + nameSingular: 'workflow', + namePlural: 'workflows', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd6fb9120-9aa5-4fdf-a84a-2805bb359855', + name: 'versions', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4ebb0eb9-9ad6-4e5b-b01b-837b0e2c0718', + type: 'RAW_JSON', + name: 'trigger', + label: 'Version trigger', + description: 'Json object to provide trigger', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ef2dd597-faaa-4b1d-96b7-5953cd8c8539', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'The workflow version name', + icon: 'IconVersions', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd9f1d5c8-ce95-48c3-a4f3-0909aea7e322', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '182c0466-9e03-4500-8cf7-22673e05b299', + type: 'UUID', + name: 'workflowId', + label: 'Workflow id (foreign key)', + description: 'WorkflowVersion workflow id foreign key', + icon: 'IconSettingsAutomation', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'attachment', + namePlural: 'attachments', + labelSingular: 'Attachment', + labelPlural: 'Attachments', + description: 'An attachment', + icon: 'IconFileImport', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'd76c9b48-5a3e-445f-be15-948de8ba2fc2', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjIy', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '426142c4-5a52-4105-a880-387b6dba6362', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4d459669-2ffd-4fd0-b28b-57d8a1eb9434', + type: 'UUID', + name: 'personId', + label: 'Person id (foreign key)', + description: 'Attachment person id foreign key', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1a6dd2bf-3da7-492d-80de-a8891c5307b7', + type: 'UUID', + name: 'opportunityId', + label: 'Opportunity id (foreign key)', + description: 'Attachment opportunity id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3669c8b2-ba73-4e9b-be61-10a2023955fd', + type: 'RELATION', + name: 'activity', + label: 'Activity', + description: 'Attachment activity', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e954bb33-50a5-4f94-85c3-be141fa17f70', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '3669c8b2-ba73-4e9b-be61-10a2023955fd', + name: 'activity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e1487ae7-cfcd-4c09-bb8b-80a9e1aea91f', + nameSingular: 'activity', + namePlural: 'activities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'bfa2ab3d-a55b-41ca-906b-9d497aee7ba8', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '023f376c-023a-4cae-89e8-961add0b3743', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '6a5833a9-0741-44f0-948d-424a60d3264e', + type: 'RELATION', + name: 'note', + label: 'Note', + description: 'Attachment note', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '9a0ad471-2e53-4943-8b28-30950550a9a7', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '6a5833a9-0741-44f0-948d-424a60d3264e', + name: 'note', + }, + targetObjectMetadata: { + __typename: 'object', + id: '1e1abbd5-5b66-4ddc-bbf8-d049802bb93e', + nameSingular: 'note', + namePlural: 'notes', + }, + targetFieldMetadata: { + __typename: 'field', + id: '80479763-1c19-4465-a62f-cd5e37c9165a', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1d3d2f23-c3e6-4ee0-b62e-7668e4f8147d', + type: 'TEXT', + name: 'fullPath', + label: 'Full path', + description: 'Attachment full path', + icon: 'IconLink', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd9a80298-6f72-4b2f-a859-2bd355d36735', + type: 'RELATION', + name: 'author', + label: 'Author', + description: 'Attachment author', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '58c1c703-990d-4296-a410-a5420209b106', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'd9a80298-6f72-4b2f-a859-2bd355d36735', + name: 'author', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6ffaa59f-d5f3-4e2f-b9d5-f69324638f75', + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'c5df2d21-5db8-4e72-82bf-aeb3ec984ca9', + name: 'authoredAttachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '42dbb8d7-320b-460d-a25e-943222ae2a9b', + type: 'TEXT', + name: 'type', + label: 'Type', + description: 'Attachment type', + icon: 'IconList', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a7971798-8b85-477e-8a1e-9b2f2fb5da6d', + type: 'UUID', + name: 'rocketId', + label: 'Rocket ID (foreign key)', + description: 'Attachment Rocket id foreign key', + icon: null, + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:42.593Z', + updatedAt: '2024-09-25T13:45:42.593Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '610633e7-0221-4838-adaf-71943d18a5ca', + type: 'RELATION', + name: 'person', + label: 'Person', + description: 'Attachment person', + icon: 'IconUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'e2ac522a-6bd8-4e24-9171-b9c00acf8ed1', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '610633e7-0221-4838-adaf-71943d18a5ca', + name: 'person', + }, + targetObjectMetadata: { + __typename: 'object', + id: '2c21d97b-9364-44a7-b916-8f24b8add9a4', + nameSingular: 'person', + namePlural: 'people', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'daab9749-7d39-44cb-9557-23e0e257aaad', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '26668e62-39e7-4842-a198-a657f44206f8', + type: 'RELATION', + name: 'task', + label: 'Task', + description: 'Attachment task', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '5a06cc7e-b994-4a53-881f-d32decfe9f3e', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '26668e62-39e7-4842-a198-a657f44206f8', + name: 'task', + }, + targetObjectMetadata: { + __typename: 'object', + id: '4e9be637-8364-454a-96f9-ecbc318ab884', + nameSingular: 'task', + namePlural: 'tasks', + }, + targetFieldMetadata: { + __typename: 'field', + id: '4f82dbad-cf61-4dd1-ad90-4cec71b288be', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1433d739-29ed-450c-8216-6afea26d21fb', + type: 'RELATION', + name: 'company', + label: 'Company', + description: 'Attachment company', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'ed757882-8668-407f-8fb8-314b68aa58f8', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '1433d739-29ed-450c-8216-6afea26d21fb', + name: 'company', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b4d6699a-eb22-49e3-ab15-eb292d72975b', + nameSingular: 'company', + namePlural: 'companies', + }, + targetFieldMetadata: { + __typename: 'field', + id: '2395970c-d0a2-43df-9f55-58299e930b34', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '1a8466d6-8be7-458a-a7ea-cdf11b4fe31d', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7dc968df-7127-4e05-b63e-f2e9809324ee', + type: 'UUID', + name: 'noteId', + label: 'Note id (foreign key)', + description: 'Attachment note id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7ffec116-99d2-402d-adea-68b731be4c74', + type: 'UUID', + name: 'taskId', + label: 'Task id (foreign key)', + description: 'Attachment task id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd76c9b48-5a3e-445f-be15-948de8ba2fc2', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'Attachment name', + icon: 'IconFileUpload', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'fa9d964c-3d30-4d8b-bc57-9b382053e9e3', + type: 'RELATION', + name: 'opportunity', + label: 'Opportunity', + description: 'Attachment opportunity', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'ca5b3017-82e4-4d9f-94c1-c73a37b56e0b', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: 'fa9d964c-3d30-4d8b-bc57-9b382053e9e3', + name: 'opportunity', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'e2456edb-3fd3-4f8c-9a49-1946108cc5b0', + nameSingular: 'opportunity', + namePlural: 'opportunities', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'aa651efa-1576-4edc-9599-070666a76dda', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '133dcd8e-aa07-4c9e-a337-92dabd5f7d03', + type: 'UUID', + name: 'activityId', + label: 'Activity id (foreign key)', + description: 'Attachment activity id foreign key', + icon: 'IconNotes', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'd10c5485-159b-4700-a709-37d3049a8778', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '60f8c4fb-1ab9-44a7-a5bd-e89a0349feb7', + type: 'RELATION', + name: 'rocket', + label: 'Rocket', + description: 'Attachment Rocket', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:42.595Z', + updatedAt: '2024-09-25T13:45:42.595Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '20cefbaf-15be-4235-a952-39dff94d00f2', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '03041aee-2468-4bec-820e-9ad1c15ac342', + nameSingular: 'attachment', + namePlural: 'attachments', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '60f8c4fb-1ab9-44a7-a5bd-e89a0349feb7', + name: 'rocket', + }, + targetObjectMetadata: { + __typename: 'object', + id: '545ae884-96b2-49d5-9db2-cad1c0cfca24', + nameSingular: 'rocket', + namePlural: 'rockets', + }, + targetFieldMetadata: { + __typename: 'field', + id: '13794481-6a3a-48cb-80c2-109b7558f7b3', + name: 'attachments', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'adaa359c-c834-44bb-8639-44ef1affce2f', + type: 'UUID', + name: 'authorId', + label: 'Author id (foreign key)', + description: 'Attachment author id foreign key', + icon: 'IconCircleUser', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '3486e0e2-053c-4e27-9d5d-c27b5dd739ea', + type: 'UUID', + name: 'companyId', + label: 'Company id (foreign key)', + description: 'Attachment company id foreign key', + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'message', + namePlural: 'messages', + labelSingular: 'Message', + labelPlural: 'Messages', + description: 'Message', + icon: 'IconMessage', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + '2697ab29-9991-4188-9569-8bc6fc079ec6', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjEx', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '827beccf-c3ca-4f24-a349-5d7c8690ac95', + type: 'TEXT', + name: 'headerMessageId', + label: 'Header message Id', + description: 'Message id from the message header', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f51b5646-06b0-45e4-960f-5f8eaeb18c83', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f32d4ef7-cadd-4ce5-84ce-a95fd76fde05', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'c36f257c-2318-4b61-9c63-666e1fc0810c', + type: 'DATE_TIME', + name: 'receivedAt', + label: 'Received At', + description: 'The date the message was received', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '86a6dca6-5ad5-4576-b8f4-4be343e573de', + type: 'RELATION', + name: 'messageChannelMessageAssociations', + label: 'Message Channel Association', + description: 'Messages from the channel.', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'f9f525c4-c303-48a0-aaeb-23dcb0ef41bb', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + nameSingular: 'message', + namePlural: 'messages', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '86a6dca6-5ad5-4576-b8f4-4be343e573de', + name: 'messageChannelMessageAssociations', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ee346c8e-6ca8-4142-852e-2d9180e80176', + nameSingular: 'messageChannelMessageAssociation', + namePlural: 'messageChannelMessageAssociations', + }, + targetFieldMetadata: { + __typename: 'field', + id: '1d9f0c85-c16f-41e9-9241-2acd90781cdd', + name: 'message', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '606cef74-d9c3-4abc-b6ae-bb778f518e49', + type: 'RELATION', + name: 'messageParticipants', + label: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7048eb73-25bf-4170-9ac0-41b7f8dec24b', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + nameSingular: 'message', + namePlural: 'messages', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '606cef74-d9c3-4abc-b6ae-bb778f518e49', + name: 'messageParticipants', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'ed425cdd-b5c8-4a35-8294-d3486a0c6149', + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'e2f2b624-93bf-4d16-8517-bf66e43cabc4', + name: 'message', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '21c34ce8-7505-4d6c-9fc8-218dd8532a25', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '48f20f05-700d-4609-965b-8a954bf07e8d', + type: 'UUID', + name: 'messageThreadId', + label: 'Message Thread Id id (foreign key)', + description: 'Message Thread Id id foreign key', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '11f38fa4-e7b8-4275-b0b2-59688cb2eed8', + type: 'RELATION', + name: 'messageThread', + label: 'Message Thread Id', + description: 'Message Thread Id', + icon: 'IconHash', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '30c65174-8905-4a32-9239-c5659a1acc9e', + direction: 'MANY_TO_ONE', + sourceObjectMetadata: { + __typename: 'object', + id: '027b772b-3cca-4634-931e-23b82dda16c7', + nameSingular: 'message', + namePlural: 'messages', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '11f38fa4-e7b8-4275-b0b2-59688cb2eed8', + name: 'messageThread', + }, + targetObjectMetadata: { + __typename: 'object', + id: 'b5cd74c7-a68f-4ccb-be66-24604d10a315', + nameSingular: 'messageThread', + namePlural: 'messageThreads', + }, + targetFieldMetadata: { + __typename: 'field', + id: '537e956c-58bb-4ed4-8127-beb0f2d04dd2', + name: 'messages', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2697ab29-9991-4188-9569-8bc6fc079ec6', + type: 'TEXT', + name: 'subject', + label: 'Subject', + description: 'Subject', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f6a75fcf-f8a3-41dd-b1d0-efce8358e2d2', + type: 'TEXT', + name: 'text', + label: 'Text', + description: 'Text', + icon: 'IconMessage', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '29f11f81-aab0-4b96-971f-24d84c81f1bf', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + { + __typename: 'objectEdge', + node: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + dataSourceId: '88ab50ee-cf39-4d7d-b004-b55f65b56041', + nameSingular: 'view', + namePlural: 'views', + labelSingular: 'View', + labelPlural: 'Views', + description: '(System) Views', + icon: 'IconLayoutCollage', + isCustom: false, + isRemote: false, + isActive: true, + isSystem: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + labelIdentifierFieldMetadataId: + 'a24df79d-a05a-45e7-8791-b71957dff236', + imageIdentifierFieldMetadataId: null, + fields: { + __typename: 'ObjectFieldsConnection', + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=', + endCursor: 'YXJyYXljb25uZWN0aW9uOjE1', + }, + edges: [ + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '61fe3c78-ab04-4a83-9a40-8560f7285abe', + type: 'RELATION', + name: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the view', + icon: 'IconHeart', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: 'a081c61b-9c8f-4e93-820e-a6c11cb51950', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '61fe3c78-ab04-4a83-9a40-8560f7285abe', + name: 'favorites', + }, + targetObjectMetadata: { + __typename: 'object', + id: '77c79754-bc77-4f77-bf4b-6b7b042500fa', + nameSingular: 'favorite', + namePlural: 'favorites', + }, + targetFieldMetadata: { + __typename: 'field', + id: '46ff8942-360f-4837-9a83-007739c8ba05', + name: 'view', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '027418ee-6028-456f-a570-0b032d35b07f', + type: 'RELATION', + name: 'viewFields', + label: 'View Fields', + description: 'View Fields', + icon: 'IconTag', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '76c82afe-f2bd-4a86-9c7f-4e7fa3918b1b', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '027418ee-6028-456f-a570-0b032d35b07f', + name: 'viewFields', + }, + targetObjectMetadata: { + __typename: 'object', + id: '69c8b455-e982-4fd2-965b-7bd5206cb860', + nameSingular: 'viewField', + namePlural: 'viewFields', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'f74ba2c1-22ab-4827-85ad-d2dbbe2a9b51', + name: 'view', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '4385a72b-bb9d-4ac6-9c08-d9853c468726', + type: 'UUID', + name: 'id', + label: 'Id', + description: 'Id', + icon: 'Icon123', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'uuid', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '421bf244-013a-4962-970a-37150cf38057', + type: 'TEXT', + name: 'type', + label: 'Type', + description: 'View type', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'table'", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '8ee5c1d6-718a-4e43-b468-91563270ae35', + type: 'TEXT', + name: 'icon', + label: 'Icon', + description: 'View icon', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '073a7e52-0c68-4853-a500-5470b026c914', + type: 'SELECT', + name: 'key', + label: 'Key', + description: 'View key', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "'INDEX'", + options: [ + { + id: 'e1a48d3b-78c6-479d-bca7-0816dcf2faec', + color: 'red', + label: 'Index', + value: 'INDEX', + position: 0, + }, + ], + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'ed944e8e-e84d-40ef-aa44-b423453c23f9', + type: 'BOOLEAN', + name: 'isCompact', + label: 'Compact View', + description: 'Describes if the view is in compact mode', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: false, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '5454b125-73c2-438b-991b-eb361bcd6295', + type: 'TEXT', + name: 'kanbanFieldMetadataId', + label: 'kanbanfieldMetadataId', + description: 'View Kanban column field', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '7974ab3b-7d05-4738-a05b-b76840f98328', + type: 'RELATION', + name: 'viewFilters', + label: 'View Filters', + description: 'View Filters', + icon: 'IconFilterBolt', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '7ffac7d4-2cfc-4932-9f3c-3ad4ab6eb4f7', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '7974ab3b-7d05-4738-a05b-b76840f98328', + name: 'viewFilters', + }, + targetObjectMetadata: { + __typename: 'object', + id: '0c5ade71-e5e7-45a0-b93c-ecb3b84f6287', + nameSingular: 'viewFilter', + namePlural: 'viewFilters', + }, + targetFieldMetadata: { + __typename: 'field', + id: 'd1829b60-e886-4dac-8cf3-0d3b84da093d', + name: 'view', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '23b99490-be92-4edc-a939-07e0f64f13eb', + type: 'RELATION', + name: 'viewSorts', + label: 'View Sorts', + description: 'View Sorts', + icon: 'IconArrowsSort', + isCustom: false, + isActive: true, + isSystem: true, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: { + __typename: 'RelationDefinition', + relationId: '6156cfd2-ab7f-47d1-8b4a-5e093f08fb9e', + direction: 'ONE_TO_MANY', + sourceObjectMetadata: { + __typename: 'object', + id: '020d393a-d6ba-431e-945c-174f5dceec6b', + nameSingular: 'view', + namePlural: 'views', + }, + sourceFieldMetadata: { + __typename: 'field', + id: '23b99490-be92-4edc-a939-07e0f64f13eb', + name: 'viewSorts', + }, + targetObjectMetadata: { + __typename: 'object', + id: '6987128d-cf7d-45eb-9bcc-19a406b774ec', + nameSingular: 'viewSort', + namePlural: 'viewSorts', + }, + targetFieldMetadata: { + __typename: 'field', + id: '25ae0938-795a-491a-b029-e4672412e85f', + name: 'view', + }, + }, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '36f1f251-121a-461c-aef5-aba2c9fa39a6', + type: 'UUID', + name: 'objectMetadataId', + label: 'Object Metadata Id', + description: 'View target object', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: '2fcf2221-da1f-4c19-acdc-adfb089ea219', + type: 'POSITION', + name: 'position', + label: 'Position', + description: 'View position', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a0e02b0d-6681-41da-a8a8-48c0bc5ba690', + type: 'DATE_TIME', + name: 'createdAt', + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'dbc64e7b-2b59-4e9e-9e1e-bcd9e9f5a57a', + type: 'DATE_TIME', + name: 'deletedAt', + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: true, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: null, + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'f5c9b9fc-87fd-4a74-af09-28a330a53bec', + type: 'DATE_TIME', + name: 'updatedAt', + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: 'now', + options: null, + relationDefinition: null, + }, + }, + { + __typename: 'fieldEdge', + node: { + __typename: 'field', + id: 'a24df79d-a05a-45e7-8791-b71957dff236', + type: 'TEXT', + name: 'name', + label: 'Name', + description: 'View name', + icon: null, + isCustom: false, + isActive: true, + isSystem: false, + isNullable: false, + createdAt: '2024-09-25T13:45:32.757Z', + updatedAt: '2024-09-25T13:45:32.757Z', + defaultValue: "''", + options: null, + relationDefinition: null, + }, + }, + ], + }, + }, + }, + ], + }, + } as ObjectMetadataItemsQuery; diff --git a/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts b/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts deleted file mode 100644 index d318a2e421a7..000000000000 --- a/packages/twenty-front/src/testing/mock-data/generated/standard-metadata-query-result.ts +++ /dev/null @@ -1,16015 +0,0 @@ -import { - ObjectMetadataItemsQuery -} from '~/generated-metadata/graphql'; - -// This file is not designed to be manually edited. -// It's an extract from the dev seeded environment metadata call -// TODO: automate the generation of this file -export const mockedStandardObjectMetadataQueryResult: ObjectMetadataItemsQuery = { - __typename: 'Query', - objects: { - "__typename": "ObjectConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjMx" - }, - "edges": [ - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "labelSingular": "Timeline Activity", - "labelPlural": "Timeline Activities", - "description": "Aggregated / filtered event to be displayed on the timeline", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "b2b89347-48a2-4f0c-a176-ad10ae33b7b1", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjIw" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0e545220-a625-4571-a8e7-f97b7aee90c1", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "Event note id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "987fd4f6-4c5f-48a4-82f3-fd769de80dc4", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "Event opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d8ae1b79-b532-412c-92cf-767a32e3cda2", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "987fd4f6-4c5f-48a4-82f3-fd769de80dc4", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4e24ba90-8fcd-4df5-9fe8-48679c75d374", - "name": "timelineActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "d8ae1b79-b532-412c-92cf-767a32e3cda2", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "4e24ba90-8fcd-4df5-9fe8-48679c75d374", - "fromObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ce28e696-4969-4e06-9056-6a176d9d7c90", - "type": "UUID", - "name": "linkedObjectMetadataId", - "label": "Linked Object Metadata Id", - "description": "inked Object Metadata Id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e48eeafe-43d8-4abc-95c8-6e7a6a56a7c9", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "Event task", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "87c0082f-5411-4202-97cd-fc1d9112fa7a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e48eeafe-43d8-4abc-95c8-6e7a6a56a7c9", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "975e6a19-d90c-45dc-9bb0-ffc57f4e1950", - "name": "timelineActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "87c0082f-5411-4202-97cd-fc1d9112fa7a", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "975e6a19-d90c-45dc-9bb0-ffc57f4e1950", - "fromObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b2b89347-48a2-4f0c-a176-ad10ae33b7b1", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0224c08b-2c2e-474f-8360-dafad378cf62", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Event company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1e93ed03-91a5-4ad4-bca7-c6a637551289", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0224c08b-2c2e-474f-8360-dafad378cf62", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f39f1db9-3d7f-46d3-aa0c-4cae44352407", - "name": "timelineActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "1e93ed03-91a5-4ad4-bca7-c6a637551289", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "f39f1db9-3d7f-46d3-aa0c-4cae44352407", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0669197c-bc4e-4a44-9cd9-db449bfa380e", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Event person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "680351ba-8759-405d-8fda-90799bf75741", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0669197c-bc4e-4a44-9cd9-db449bfa380e", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3700e772-3bf6-4150-b5ce-f7f00ded863a", - "name": "timelineActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "680351ba-8759-405d-8fda-90799bf75741", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "3700e772-3bf6-4150-b5ce-f7f00ded863a", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a3a51b55-8387-412f-8661-cbaf58bde346", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Event person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f064e57f-26ea-4aa5-9f95-eda25af30f0f", - "type": "DATE_TIME", - "name": "happensAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bc0e2a25-4e13-4751-a79a-2d264582ef9a", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "Event note", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "7ec36219-a377-4aea-98be-7954590f8a32", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "bc0e2a25-4e13-4751-a79a-2d264582ef9a", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b66379fc-ac94-4823-b759-aa940fde9c73", - "name": "timelineActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "7ec36219-a377-4aea-98be-7954590f8a32", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "b66379fc-ac94-4823-b759-aa940fde9c73", - "fromObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ae929592-4f74-419e-8b26-6d216859078f", - "type": "RAW_JSON", - "name": "properties", - "label": "Event details", - "description": "Json value for event details", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "64a86ebc-93d3-47f2-a013-0e6c8ef2af18", - "type": "TEXT", - "name": "name", - "label": "Event name", - "description": "Event name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7df779f8-89a1-4c41-9868-0d98f53b29aa", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Event company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cf56c3f4-dd93-465c-8ab3-edbd6cc5f246", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "27cf8bcc-101c-42e1-999f-32365e0abc80", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "Event opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9ddef7df-ec3c-42b6-b279-ffb60dbf5a8a", - "type": "UUID", - "name": "linkedRecordId", - "label": "Linked Record id", - "description": "Linked Record id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f465561a-ea75-46e7-8110-dd4ed4f25f72", - "type": "TEXT", - "name": "linkedRecordCachedName", - "label": "Linked Record cached name", - "description": "Cached record name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b7d464b1-d234-4295-9845-bed07dbc41e4", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "Event task id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "63ec5746-623a-41d5-8ed8-aca9577102eb", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9fc19fe9-2563-41ac-8c92-2062ff3a0c0c", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Event workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5b2015dd-3fac-4118-adf5-3cceede873eb", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "9fc19fe9-2563-41ac-8c92-2062ff3a0c0c", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ace8a324-075e-49a3-92fa-34e07590ec72", - "name": "timelineActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "5b2015dd-3fac-4118-adf5-3cceede873eb", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "ace8a324-075e-49a3-92fa-34e07590ec72", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d59ec465-34c7-471d-9c20-7be1f081d4cd", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Event workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "message", - "namePlural": "messages", - "labelSingular": "Message", - "labelPlural": "Messages", - "description": "Message", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "34c76e0d-23e5-476a-bd56-2f9b02eae3ea", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEx" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "74b4d296-dfde-40b4-b6aa-012a17ef6451", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "138ee2a7-7f7e-4901-b5d2-7ccc13a0bc38", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "906714b3-0268-49bb-85b4-705587e6f4c1", - "type": "SELECT", - "name": "direction", - "label": "Direction", - "description": "Message Direction", - "icon": "IconDirection", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'INCOMING'", - "options": [ - { - "id": "09fd3f5f-5903-4a3a-8f8b-335825349389", - "color": "green", - "label": "Incoming", - "value": "INCOMING", - "position": 0 - }, - { - "id": "0df4272e-dfef-450e-84b7-d1477e66ee7f", - "color": "blue", - "label": "Outgoing", - "value": "OUTGOING", - "position": 1 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "114f853e-2684-4e62-92c9-0213ace3c498", - "type": "RELATION", - "name": "messageThread", - "label": "Message Thread Id", - "description": "Message Thread Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c958fe88-7d66-4c1b-87c7-55ab724f42c5", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "nameSingular": "message", - "namePlural": "messages" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "114f853e-2684-4e62-92c9-0213ace3c498", - "name": "messageThread" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "9016096d-93c4-495f-93d5-b966e5bedc74", - "name": "messages" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "c958fe88-7d66-4c1b-87c7-55ab724f42c5", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "9016096d-93c4-495f-93d5-b966e5bedc74", - "fromObjectMetadata": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageThread", - "namePlural": "messageThreads", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0837697b-286c-43e2-9364-532d5e06cd76", - "type": "DATE_TIME", - "name": "receivedAt", - "label": "Received At", - "description": "The date the message was received", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f6a6d3f8-fef7-4d91-b187-7ea8d6291372", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "15658254-6562-4fad-9ef3-393f913e95c2", - "type": "RELATION", - "name": "messageParticipants", - "label": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2180d888-98dc-428e-a157-c30ce7bf8ce4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "nameSingular": "message", - "namePlural": "messages" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "15658254-6562-4fad-9ef3-393f913e95c2", - "name": "messageParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "660b4257-010e-4039-897a-e274f2559ed5", - "name": "message" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "2180d888-98dc-428e-a157-c30ce7bf8ce4", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "660b4257-010e-4039-897a-e274f2559ed5", - "toObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c4f2dcde-1110-419e-8590-dd1a26a0dfec", - "type": "UUID", - "name": "messageThreadId", - "label": "Message Thread Id id (foreign key)", - "description": "Message Thread Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "eb2e56c5-db83-4844-9179-3890e31edf15", - "type": "TEXT", - "name": "headerMessageId", - "label": "Header message Id", - "description": "Message id from the message header", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2ac789bf-ce05-4f0e-9f04-f848f93c2f21", - "type": "RELATION", - "name": "messageChannelMessageAssociations", - "label": "Message Channel Association", - "description": "Messages from the channel.", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "642b4d8c-f2f8-4590-abce-4b112d8689ba", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "nameSingular": "message", - "namePlural": "messages" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2ac789bf-ce05-4f0e-9f04-f848f93c2f21", - "name": "messageChannelMessageAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "785c0609-42b8-4b0e-b7c2-4d54b6ed651f", - "name": "message" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "642b4d8c-f2f8-4590-abce-4b112d8689ba", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "785c0609-42b8-4b0e-b7c2-4d54b6ed651f", - "toObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0b97d62c-af50-48e2-af87-eaedc63c17ee", - "type": "TEXT", - "name": "text", - "label": "Text", - "description": "Text", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "34c76e0d-23e5-476a-bd56-2f9b02eae3ea", - "type": "TEXT", - "name": "subject", - "label": "Subject", - "description": "Subject", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "labelSingular": "Note Target", - "labelPlural": "Note Targets", - "description": "A note target", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "e97affc0-248a-4f3b-b1c5-f46f3d1edd21", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEw" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5b2ec790-e8b8-4bd0-bf1b-db4ebc2b473a", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "NoteTarget opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c0946e53-4cdd-46b4-b30a-9fce040b9a7a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5b2ec790-e8b8-4bd0-bf1b-db4ebc2b473a", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e6fe20c1-091e-418f-9ff0-8ea7cfb864f8", - "name": "noteTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "c0946e53-4cdd-46b4-b30a-9fce040b9a7a", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "e6fe20c1-091e-418f-9ff0-8ea7cfb864f8", - "fromObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "be09126d-4c9e-42d1-b686-cd43c4aa32df", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "87334d50-0c5d-4327-a8c5-3db6bc28c1ea", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "NoteTarget note", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "663e9842-8b92-451a-bf73-12a886ff8b05", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "87334d50-0c5d-4327-a8c5-3db6bc28c1ea", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "04794a4e-35c3-46a9-8bf3-8ba1c0324f0b", - "name": "noteTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "663e9842-8b92-451a-bf73-12a886ff8b05", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "04794a4e-35c3-46a9-8bf3-8ba1c0324f0b", - "fromObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9025db40-92fb-4fd5-9df3-c5bbf2878e61", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "12ccd632-bfd4-47e7-80dc-4c3f913372f6", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "NoteTarget note id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f90c9e4d-c3d4-43d2-9697-9307e373669d", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "NoteTarget person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8ac4df39-f1a0-4221-a605-bd4c229fbc12", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "NoteTarget person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "700c5e52-3e7b-4471-9826-82270c03c37e", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "8ac4df39-f1a0-4221-a605-bd4c229fbc12", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "82d1a637-3df9-4d59-a412-1cbc1d92baf2", - "name": "noteTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "700c5e52-3e7b-4471-9826-82270c03c37e", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "82d1a637-3df9-4d59-a412-1cbc1d92baf2", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e97affc0-248a-4f3b-b1c5-f46f3d1edd21", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b92459f6-3ab6-4b8f-855e-a759b45118df", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "NoteTarget opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "662f602c-a292-489e-b784-476168f1efcb", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "NoteTarget company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5a0243d0-051b-4f30-b0d2-da66b3b8eefe", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "NoteTarget company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1670824b-e097-4afc-8401-feab7f9af0d4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5a0243d0-051b-4f30-b0d2-da66b3b8eefe", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "74bf3aba-450e-48f9-987a-60662929e768", - "name": "noteTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "1670824b-e097-4afc-8401-feab7f9af0d4", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "74bf3aba-450e-48f9-987a-60662929e768", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents", - "labelSingular": "Calendar event", - "labelPlural": "Calendar events", - "description": "Calendar events", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "a13f7bf6-02ab-4f9b-bd3a-c84a56e7ed49", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjE3" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "83cb4332-1363-4228-ab85-7a3d2c4922d1", - "type": "DATE_TIME", - "name": "externalUpdatedAt", - "label": "Update DateTime", - "description": "Update DateTime", - "icon": "IconCalendarCog", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "dde2d1d3-5a7d-4cf3-a982-4f7aff2dfb37", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c8013b48-cc15-4f19-8141-325a12e771e3", - "type": "BOOLEAN", - "name": "isFullDay", - "label": "Is Full Day", - "description": "Is Full Day", - "icon": "Icon24Hours", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": false, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "771aa870-f4e7-4fa6-b2e4-52c41cf3d5fc", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fe7dcb62-099f-4ad1-af7e-a74713f6159d", - "type": "RELATION", - "name": "calendarChannelEventAssociations", - "label": "Calendar Channel Event Associations", - "description": "Calendar Channel Event Associations", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0f9d244b-e9c6-44af-88f4-9ce798d50bf8", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fe7dcb62-099f-4ad1-af7e-a74713f6159d", - "name": "calendarChannelEventAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "18cea1c1-f521-4c41-b694-729756931795", - "name": "calendarEvent" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "0f9d244b-e9c6-44af-88f4-9ce798d50bf8", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "18cea1c1-f521-4c41-b694-729756931795", - "toObjectMetadata": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "74820be8-b911-440a-b7bd-622b3c0fb2f0", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d8ca199f-72ce-4a48-9e29-133a05520b0f", - "type": "TEXT", - "name": "location", - "label": "Location", - "description": "Location", - "icon": "IconMapPin", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a4688389-8263-4209-b72c-a6004d7f0804", - "type": "LINKS", - "name": "conferenceLink", - "label": "Meet Link", - "description": "Meet Link", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6d195419-c615-4b2f-be73-74481a270851", - "type": "DATE_TIME", - "name": "endsAt", - "label": "End Date", - "description": "End Date", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a13f7bf6-02ab-4f9b-bd3a-c84a56e7ed49", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Title", - "icon": "IconH1", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "eb3a27fb-9cb8-4017-b896-e52eaf801dc2", - "type": "RELATION", - "name": "calendarEventParticipants", - "label": "Event Participants", - "description": "Event Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e02ea7b1-1d5a-481b-ab71-3c94ab3f9bf0", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "eb3a27fb-9cb8-4017-b896-e52eaf801dc2", - "name": "calendarEventParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b04775e2-53a3-4f62-a2ab-858f2a456fa7", - "name": "calendarEvent" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "e02ea7b1-1d5a-481b-ab71-3c94ab3f9bf0", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "b04775e2-53a3-4f62-a2ab-858f2a456fa7", - "toObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "39d10ace-420f-4053-9d68-1111d3b8f39c", - "type": "TEXT", - "name": "description", - "label": "Description", - "description": "Description", - "icon": "IconFileDescription", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "39534ddd-1942-48ff-a2dc-c0365920bf73", - "type": "DATE_TIME", - "name": "startsAt", - "label": "Start Date", - "description": "Start Date", - "icon": "IconCalendarClock", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f3ed1238-8ccf-45e9-8feb-996c3052e57f", - "type": "BOOLEAN", - "name": "isCanceled", - "label": "Is canceled", - "description": "Is canceled", - "icon": "IconCalendarCancel", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": false, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f6723e97-b9a7-48d7-960c-291e105190fd", - "type": "DATE_TIME", - "name": "externalCreatedAt", - "label": "Creation DateTime", - "description": "Creation DateTime", - "icon": "IconCalendarPlus", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2f6c8e0f-dd7b-4f0b-8e5d-1205720b280b", - "type": "TEXT", - "name": "iCalUID", - "label": "iCal UID", - "description": "iCal UID", - "icon": "IconKey", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f7fddaf8-600c-4ff2-8538-19cc56582764", - "type": "TEXT", - "name": "conferenceSolution", - "label": "Conference Solution", - "description": "Conference Solution", - "icon": "IconScreenShare", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b6595570-eb50-47db-a823-832bf384ae25", - "type": "TEXT", - "name": "recurringEventExternalId", - "label": "Recurring Event ID", - "description": "Recurring Event ID", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "ccb2a7ce-f998-4363-b951-cdf7409b64dc", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "auditLog", - "namePlural": "auditLogs", - "labelSingular": "Audit Log", - "labelPlural": "Audit Logs", - "description": "An audit log of actions performed in the system", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "850587c2-97aa-42b0-a1f0-e87a1ad98f8c", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEw" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2ea84bb0-d37a-4b30-a562-5b1124f9090d", - "type": "UUID", - "name": "recordId", - "label": "Record id", - "description": "Record id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8cc90681-a560-4af8-8a68-695c21b981b1", - "type": "TEXT", - "name": "objectName", - "label": "Object name", - "description": "Object name", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7eda7a7a-c335-429e-b9ac-8009b94c43c1", - "type": "RAW_JSON", - "name": "properties", - "label": "Event details", - "description": "Json value for event details", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1f77c676-5b7e-4105-ad66-f1c3ae12ebbc", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0fedd2c5-1c9c-4e0a-8687-a8ce4dd88378", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Event workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d74023b4-87a8-44d0-84d8-9b2a85018e4b", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "ccb2a7ce-f998-4363-b951-cdf7409b64dc", - "nameSingular": "auditLog", - "namePlural": "auditLogs" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0fedd2c5-1c9c-4e0a-8687-a8ce4dd88378", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "82057d3c-fd1d-4479-a8e3-f18dd9207f3e", - "name": "auditLogs" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "d74023b4-87a8-44d0-84d8-9b2a85018e4b", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "82057d3c-fd1d-4479-a8e3-f18dd9207f3e", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bda06197-eea9-4fdd-a9b5-101fb473ba00", - "type": "RAW_JSON", - "name": "context", - "label": "Event context", - "description": "Json object to provide context (user, device, workspace, etc.)", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "850587c2-97aa-42b0-a1f0-e87a1ad98f8c", - "type": "TEXT", - "name": "name", - "label": "Event name", - "description": "Event name/type", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7ff2c10b-db27-44e5-bcaa-8ca3a68e7dae", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cb33c71d-a957-4c29-b9ea-b6eed8ae8eeb", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Event workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "737e4617-4310-4b6d-af50-bb4fb79a10b7", - "type": "TEXT", - "name": "objectMetadataId", - "label": "Object metadata id", - "description": "Object metadata id", - "icon": "IconAbc", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f9aadda1-e30c-4eea-908a-3cea6e5f41cc", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "c81903be-3be2-49af-82b3-d170cd35ac0f", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "viewField", - "namePlural": "viewFields", - "labelSingular": "View Field", - "labelPlural": "View Fields", - "description": "(System) View Fields", - "icon": "IconTag", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "98225cd7-c93e-4f1f-ab9a-36a8b56fbdc9", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjg=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ccf2d3bc-3859-4075-ab3f-4022294f2e30", - "type": "BOOLEAN", - "name": "isVisible", - "label": "Visible", - "description": "View Field visibility", - "icon": "IconEye", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "98225cd7-c93e-4f1f-ab9a-36a8b56fbdc9", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3c5e5a35-731d-4c06-934a-d52bb02bc715", - "type": "NUMBER", - "name": "size", - "label": "Size", - "description": "View Field size", - "icon": "IconEye", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": 0, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "337d9389-06a9-4cb1-9f2a-76dbb37a7576", - "type": "RELATION", - "name": "view", - "label": "View", - "description": "View Field related view", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ae731975-39ee-4387-a80c-de94dff0b760", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "c81903be-3be2-49af-82b3-d170cd35ac0f", - "nameSingular": "viewField", - "namePlural": "viewFields" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "337d9389-06a9-4cb1-9f2a-76dbb37a7576", - "name": "view" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "nameSingular": "view", - "namePlural": "views" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c086b30a-0267-4857-9fe0-29a2bbaa8dc8", - "name": "viewFields" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "ae731975-39ee-4387-a80c-de94dff0b760", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "c086b30a-0267-4857-9fe0-29a2bbaa8dc8", - "fromObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "view", - "namePlural": "views", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "aafd0a60-9abc-464c-a601-0f4b93643df0", - "type": "NUMBER", - "name": "position", - "label": "Position", - "description": "View Field position", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": 0, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "48b3cbca-7061-4431-b671-f517178a6fa6", - "type": "UUID", - "name": "viewId", - "label": "View id (foreign key)", - "description": "View Field related view id foreign key", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fd19a167-b702-4fe4-b59d-b0bf5b288ccf", - "type": "UUID", - "name": "fieldMetadataId", - "label": "Field Metadata Id", - "description": "View Field target field", - "icon": "IconTag", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "31ca8ba9-4d75-4b61-ba76-a879e0f230b6", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ba35303a-1451-47fe-8900-80262b90d4c6", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "comment", - "namePlural": "comments", - "labelSingular": "Comment", - "labelPlural": "Comments", - "description": "A comment", - "icon": "IconMessageCircle", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "468e8108-653e-4c9e-ba50-bff7937d89ad", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjc=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7c664574-0bcb-4833-aee1-5a95bad64fbb", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5e0574cf-4695-48f4-aa29-5b755b33102a", - "type": "TEXT", - "name": "body", - "label": "Body", - "description": "Comment body", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a7bc8581-749a-49cf-bf04-3b7bdc0b3f4e", - "type": "UUID", - "name": "authorId", - "label": "Author id (foreign key)", - "description": "Comment author id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2dd9dd34-4b7a-4082-b983-3e5faf37e60c", - "type": "UUID", - "name": "activityId", - "label": "Activity id (foreign key)", - "description": "Comment activity id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ace0311d-6b58-4c34-9e78-3c18ff147408", - "type": "RELATION", - "name": "activity", - "label": "Activity", - "description": "Comment activity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "eaf90876-fac7-448a-906c-7c2b6afcd346", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "nameSingular": "comment", - "namePlural": "comments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ace0311d-6b58-4c34-9e78-3c18ff147408", - "name": "activity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c2a21675-a29d-442a-9f02-84cd93df15ce", - "name": "comments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "eaf90876-fac7-448a-906c-7c2b6afcd346", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "c2a21675-a29d-442a-9f02-84cd93df15ce", - "fromObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "468e8108-653e-4c9e-ba50-bff7937d89ad", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fd9fcac5-c853-4fe7-ab1e-18081e4d4517", - "type": "RELATION", - "name": "author", - "label": "Author", - "description": "Comment author", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "017b3808-bc03-4817-8a67-b20770a6a126", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "nameSingular": "comment", - "namePlural": "comments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fd9fcac5-c853-4fe7-ab1e-18081e4d4517", - "name": "author" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c86049ea-6cac-4b7f-a58e-b68b917e4a2b", - "name": "authoredComments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "017b3808-bc03-4817-8a67-b20770a6a126", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "c86049ea-6cac-4b7f-a58e-b68b917e4a2b", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "52a840a8-0d1c-4fdb-bea8-b008c9d3986d", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "labelSingular": "Workspace Member", - "labelPlural": "Workspace Members", - "description": "A workspace member", - "icon": "IconUserCircle", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "b329059f-4b80-4d92-9a2a-4f6373cd8003", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjI0" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6062715e-08e8-4ff5-962d-eed4f992fc61", - "type": "RELATION", - "name": "calendarEventParticipants", - "label": "Calendar Event Participants", - "description": "Calendar Event Participants", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d5ffcbba-0ab9-4f4d-a5e6-15f1e668b04c", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6062715e-08e8-4ff5-962d-eed4f992fc61", - "name": "calendarEventParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fbc9d8eb-c04f-4c86-81ff-d4ca9957d0d4", - "name": "workspaceMember" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "d5ffcbba-0ab9-4f4d-a5e6-15f1e668b04c", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "fbc9d8eb-c04f-4c86-81ff-d4ca9957d0d4", - "toObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8d0cc1c9-ab4a-406c-b35b-1a1b40fd025c", - "type": "TEXT", - "name": "locale", - "label": "Language", - "description": "Preferred language", - "icon": "IconLanguage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'en'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ace8a324-075e-49a3-92fa-34e07590ec72", - "type": "RELATION", - "name": "timelineActivities", - "label": "Events", - "description": "Events linked to the workspace member", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5b2015dd-3fac-4118-adf5-3cceede873eb", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ace8a324-075e-49a3-92fa-34e07590ec72", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "9fc19fe9-2563-41ac-8c92-2062ff3a0c0c", - "name": "workspaceMember" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "5b2015dd-3fac-4118-adf5-3cceede873eb", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "9fc19fe9-2563-41ac-8c92-2062ff3a0c0c", - "toObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "57d6eb4f-c86b-4a50-98ce-fa04c849b1a2", - "type": "RELATION", - "name": "accountOwnerForCompanies", - "label": "Account Owner For Companies", - "description": "Account owner for companies", - "icon": "IconBriefcase", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "97b97e1e-aed0-4d59-997c-13ad9007e037", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "57d6eb4f-c86b-4a50-98ce-fa04c849b1a2", - "name": "accountOwnerForCompanies" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a56f365a-22c8-475d-816b-709f3a19c5fd", - "name": "accountOwner" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "97b97e1e-aed0-4d59-997c-13ad9007e037", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "a56f365a-22c8-475d-816b-709f3a19c5fd", - "toObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4e4050e5-e6fb-4466-b02b-6d12714373b7", - "type": "TEXT", - "name": "avatarUrl", - "label": "Avatar Url", - "description": "Workspace member avatar", - "icon": "IconFileUpload", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2e1b13a4-9ced-4b9d-b9f6-ca274410a933", - "type": "UUID", - "name": "userId", - "label": "User Id", - "description": "Associated User Id", - "icon": "IconCircleUsers", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b329059f-4b80-4d92-9a2a-4f6373cd8003", - "type": "FULL_NAME", - "name": "name", - "label": "Name", - "description": "Workspace member name", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "lastName": "''", - "firstName": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "867aef01-e708-4f56-96b2-11237093a8e6", - "type": "TEXT", - "name": "userEmail", - "label": "User Email", - "description": "Related user email address", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f9d4a27e-1728-44d8-b990-e648d838a35a", - "type": "RELATION", - "name": "authoredActivities", - "label": "Authored activities", - "description": "Activities created by the workspace member", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "fccbbaf8-c653-4e09-8d3e-5652b37d8209", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f9d4a27e-1728-44d8-b990-e648d838a35a", - "name": "authoredActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b31f4c53-a5ee-4939-9804-6964144540ca", - "name": "author" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "fccbbaf8-c653-4e09-8d3e-5652b37d8209", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "b31f4c53-a5ee-4939-9804-6964144540ca", - "toObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c6b1b4a1-bad8-4872-b408-aa0ceb668215", - "type": "RELATION", - "name": "blocklist", - "label": "Blocklist", - "description": "Blocklisted handles", - "icon": "IconForbid2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "19b7520c-bc6e-490c-bfab-a3b020315cc4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c6b1b4a1-bad8-4872-b408-aa0ceb668215", - "name": "blocklist" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "60637cd3-24f6-4d9a-9432-a590accbefb9", - "nameSingular": "blocklist", - "namePlural": "blocklists" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "96acdd2a-b7d1-452b-9e58-5c4265691444", - "name": "workspaceMember" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "19b7520c-bc6e-490c-bfab-a3b020315cc4", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "96acdd2a-b7d1-452b-9e58-5c4265691444", - "toObjectMetadata": { - "__typename": "object", - "id": "60637cd3-24f6-4d9a-9432-a590accbefb9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "blocklist", - "namePlural": "blocklists", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "328d9621-d8aa-4e2d-91c1-e03c621d79a1", - "type": "SELECT", - "name": "timeFormat", - "label": "Time format", - "description": "User's preferred time format", - "icon": "IconClock2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'SYSTEM'", - "options": [ - { - "id": "2ea77a47-9b23-4159-bda8-97bf23a52f61", - "color": "sky", - "label": "System", - "value": "SYSTEM", - "position": 0 - }, - { - "id": "3dc8e58f-c987-4078-b980-d5e2127968e8", - "color": "red", - "label": "24HRS", - "value": "HOUR_24", - "position": 1 - }, - { - "id": "7d24f928-a955-4419-9081-51117eb181e6", - "color": "purple", - "label": "12HRS", - "value": "HOUR_12", - "position": 2 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c00ccd93-ebc7-4744-8cb3-797a752b4627", - "type": "RELATION", - "name": "messageParticipants", - "label": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "7d3faf56-e4bb-45ec-9b75-612ca6e9ae5a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c00ccd93-ebc7-4744-8cb3-797a752b4627", - "name": "messageParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "bc788a8f-8eb2-47bf-a02c-42f7de197ca8", - "name": "workspaceMember" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "7d3faf56-e4bb-45ec-9b75-612ca6e9ae5a", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "bc788a8f-8eb2-47bf-a02c-42f7de197ca8", - "toObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2fa32c75-6169-449b-bfc2-e1576d5ce5fe", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e2234264-8612-4d1d-bfa8-929cc63bf6fd", - "type": "SELECT", - "name": "dateFormat", - "label": "Date format", - "description": "User's preferred date format", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'SYSTEM'", - "options": [ - { - "id": "c0053f9a-eaa7-44d2-9c0e-73d95715d007", - "color": "turquoise", - "label": "System", - "value": "SYSTEM", - "position": 0 - }, - { - "id": "aacbf232-6f01-48dd-9328-6da7ebea0986", - "color": "red", - "label": "Month First", - "value": "MONTH_FIRST", - "position": 1 - }, - { - "id": "a2b08c2c-7bf4-4730-a4f9-30d122dc5a4b", - "color": "purple", - "label": "Day First", - "value": "DAY_FIRST", - "position": 2 - }, - { - "id": "29de9f62-1eb7-4808-a63e-53d3dc764c9e", - "color": "sky", - "label": "Year First", - "value": "YEAR_FIRST", - "position": 3 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e4c25d9f-10cf-4c33-8c39-7aaac0a98f11", - "type": "RELATION", - "name": "assignedTasks", - "label": "Assigned tasks", - "description": "Tasks assigned to the workspace member", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "8cb075f2-e51c-4684-80f6-cf6af471e82a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e4c25d9f-10cf-4c33-8c39-7aaac0a98f11", - "name": "assignedTasks" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5bcc7e50-73ce-4146-b000-5a336f0e9c40", - "name": "assignee" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "8cb075f2-e51c-4684-80f6-cf6af471e82a", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "5bcc7e50-73ce-4146-b000-5a336f0e9c40", - "toObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2d52a31f-3ad8-4d57-90eb-61142bf58382", - "type": "RELATION", - "name": "assignedActivities", - "label": "Assigned activities", - "description": "Activities assigned to the workspace member", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d5315a70-980f-4c45-9a4f-74779a00fdd3", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2d52a31f-3ad8-4d57-90eb-61142bf58382", - "name": "assignedActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4ec37c9c-be4c-4f52-a441-03a1dfd951db", - "name": "assignee" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "d5315a70-980f-4c45-9a4f-74779a00fdd3", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "4ec37c9c-be4c-4f52-a441-03a1dfd951db", - "toObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e2cdfd71-1c3e-4793-a95d-91df4a3bbe8d", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "104209de-5259-4d74-b14a-f37badf49be9", - "type": "RELATION", - "name": "connectedAccounts", - "label": "Connected accounts", - "description": "Connected accounts", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1ecacc04-e834-421d-bf1b-c765e55a4318", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "104209de-5259-4d74-b14a-f37badf49be9", - "name": "connectedAccounts" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "95bd59b8-8083-4c76-b770-ec40a744138c", - "name": "accountOwner" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "1ecacc04-e834-421d-bf1b-c765e55a4318", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "95bd59b8-8083-4c76-b770-ec40a744138c", - "toObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "29055851-94dc-4fa9-84d8-295a3d161724", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the workspace member", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a72edc8d-e5e3-4eae-9fd6-4cb0792b18aa", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "29055851-94dc-4fa9-84d8-295a3d161724", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0aaf9f83-9b43-4f15-a187-9c11761b367a", - "name": "workspaceMember" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "a72edc8d-e5e3-4eae-9fd6-4cb0792b18aa", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0aaf9f83-9b43-4f15-a187-9c11761b367a", - "toObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c86049ea-6cac-4b7f-a58e-b68b917e4a2b", - "type": "RELATION", - "name": "authoredComments", - "label": "Authored comments", - "description": "Authored comments", - "icon": "IconComment", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "017b3808-bc03-4817-8a67-b20770a6a126", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c86049ea-6cac-4b7f-a58e-b68b917e4a2b", - "name": "authoredComments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "nameSingular": "comment", - "namePlural": "comments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fd9fcac5-c853-4fe7-ab1e-18081e4d4517", - "name": "author" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "017b3808-bc03-4817-8a67-b20770a6a126", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "fd9fcac5-c853-4fe7-ab1e-18081e4d4517", - "toObjectMetadata": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "comment", - "namePlural": "comments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fa2a9e43-03f2-4919-b67d-4b62f5c16758", - "type": "TEXT", - "name": "colorScheme", - "label": "Color Scheme", - "description": "Preferred color scheme", - "icon": "IconColorSwatch", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'Light'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "82057d3c-fd1d-4479-a8e3-f18dd9207f3e", - "type": "RELATION", - "name": "auditLogs", - "label": "Audit Logs", - "description": "Audit Logs linked to the workspace member", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d74023b4-87a8-44d0-84d8-9b2a85018e4b", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "82057d3c-fd1d-4479-a8e3-f18dd9207f3e", - "name": "auditLogs" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "ccb2a7ce-f998-4363-b951-cdf7409b64dc", - "nameSingular": "auditLog", - "namePlural": "auditLogs" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0fedd2c5-1c9c-4e0a-8687-a8ce4dd88378", - "name": "workspaceMember" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "d74023b4-87a8-44d0-84d8-9b2a85018e4b", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0fedd2c5-1c9c-4e0a-8687-a8ce4dd88378", - "toObjectMetadata": { - "__typename": "object", - "id": "ccb2a7ce-f998-4363-b951-cdf7409b64dc", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "auditLog", - "namePlural": "auditLogs", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c784bb11-cd83-4392-a14b-4b9028ac4280", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6e622089-670a-4831-964c-f27af03f39c0", - "type": "RELATION", - "name": "authoredAttachments", - "label": "Authored attachments", - "description": "Attachments created by the workspace member", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5b9f08b0-8960-40c4-b6bb-9d3552a24f8d", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6e622089-670a-4831-964c-f27af03f39c0", - "name": "authoredAttachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "85046974-8ab2-456d-a732-64da14715643", - "name": "author" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "5b9f08b0-8960-40c4-b6bb-9d3552a24f8d", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "85046974-8ab2-456d-a732-64da14715643", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "43ae7fcb-4e9c-4f67-a9cd-8fe5b2c3991b", - "type": "TEXT", - "name": "timeZone", - "label": "Time zone", - "description": "User time zone", - "icon": "IconTimezone", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'system'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "labelSingular": "Person", - "labelPlural": "People", - "description": "A person", - "icon": "IconUser", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "e1eb21dc-7a5e-41e5-99be-8889a3d5ca15", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjIz" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "130dedfb-f30c-4a70-b2ca-a70e2aa8c291", - "type": "TEXT", - "name": "jobTitle", - "label": "Job Title", - "description": "Contact’s job title", - "icon": "IconBriefcase", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "75210cae-eb24-4932-8f00-ccbce38a3d66", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "608e9b7c-8d7a-409c-88c8-455b72b1bbca", - "type": "TEXT", - "name": "avatarUrl", - "label": "Avatar", - "description": "Contact’s avatar", - "icon": "IconFileUpload", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2748b607-0fbb-42c8-b79f-695921bcb8ed", - "type": "LINKS", - "name": "xLink", - "label": "X", - "description": "Contact’s X/Twitter account", - "icon": "IconBrandX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ee5347ee-390c-42de-bde5-ebaffd2ad0e5", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5fbb29e4-4ee6-4122-b1c3-1a632e2501ef", - "type": "LINKS", - "name": "linkedinLink", - "label": "Linkedin", - "description": "Contact’s Linkedin account", - "icon": "IconBrandLinkedin", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "19f77ace-4b00-4fac-ba7d-8c7a3dde409b", - "type": "RELATION", - "name": "messageParticipants", - "label": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5bb99199-6a3c-4947-b16b-6a90c6097eac", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "19f77ace-4b00-4fac-ba7d-8c7a3dde409b", - "name": "messageParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "362195e4-4dfb-49e1-b25b-fe3ffe7b7f14", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "5bb99199-6a3c-4947-b16b-6a90c6097eac", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "362195e4-4dfb-49e1-b25b-fe3ffe7b7f14", - "toObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e1eb21dc-7a5e-41e5-99be-8889a3d5ca15", - "type": "FULL_NAME", - "name": "name", - "label": "Name", - "description": "Contact’s name", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "lastName": "''", - "firstName": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3700e772-3bf6-4150-b5ce-f7f00ded863a", - "type": "RELATION", - "name": "timelineActivities", - "label": "Events", - "description": "Events linked to the person", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "680351ba-8759-405d-8fda-90799bf75741", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3700e772-3bf6-4150-b5ce-f7f00ded863a", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0669197c-bc4e-4a44-9cd9-db449bfa380e", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "680351ba-8759-405d-8fda-90799bf75741", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0669197c-bc4e-4a44-9cd9-db449bfa380e", - "toObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d9594064-5e84-4981-a0f8-0d047322f1e9", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "05863c2c-bcf7-4d88-b0cd-f00335b6854d", - "type": "RELATION", - "name": "pointOfContactForOpportunities", - "label": "POC for Opportunities", - "description": "Point of Contact for Opportunities", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "58a081ed-e5e7-44f8-bae6-99be66b6ac2f", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "05863c2c-bcf7-4d88-b0cd-f00335b6854d", - "name": "pointOfContactForOpportunities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "18ea34ae-f9bc-4240-b65f-46f0d688135f", - "name": "pointOfContact" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "58a081ed-e5e7-44f8-bae6-99be66b6ac2f", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "18ea34ae-f9bc-4240-b65f-46f0d688135f", - "toObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cb89d529-55f2-4757-8248-6939aa038363", - "type": "EMAIL", - "name": "email", - "label": "Email", - "description": "Contact’s Email", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ee426b52-f4d3-4b96-a7fc-04d968b66331", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the contact", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "74f62324-bc36-4210-bb88-e0e6e0136c9f", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ee426b52-f4d3-4b96-a7fc-04d968b66331", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4a9e3e27-70b0-4ed7-9edf-9126c1675b22", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "74f62324-bc36-4210-bb88-e0e6e0136c9f", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "4a9e3e27-70b0-4ed7-9edf-9126c1675b22", - "toObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c87e6f64-f722-4487-9930-1c6fb67572c1", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the contact", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "450a3266-7706-4593-a458-5897c5f60fc5", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c87e6f64-f722-4487-9930-1c6fb67572c1", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f0748d0d-e6b4-44ea-b957-0c0d81af4627", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "450a3266-7706-4593-a458-5897c5f60fc5", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "f0748d0d-e6b4-44ea-b957-0c0d81af4627", - "toObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fe7c56ff-5531-4abc-a10a-048b01034596", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "538e49cd-f04a-4889-9994-35cacc0754b7", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Contact’s company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2f030298-14c7-48a4-b351-2ec185bb1814", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "538e49cd-f04a-4889-9994-35cacc0754b7", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0943b1b4-3aae-4ebe-8e8e-b1a8640d78d9", - "name": "people" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "2f030298-14c7-48a4-b351-2ec185bb1814", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "0943b1b4-3aae-4ebe-8e8e-b1a8640d78d9", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "aa9f1d0c-ef2c-4bec-849f-aaf3b83a6c3c", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Contact’s company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fd48c551-1309-473d-bb7e-921c577b731b", - "type": "RELATION", - "name": "calendarEventParticipants", - "label": "Calendar Event Participants", - "description": "Calendar Event Participants", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "178c5cfe-cc05-49ec-bedb-eff402da4e8f", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fd48c551-1309-473d-bb7e-921c577b731b", - "name": "calendarEventParticipants" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a2ecf99f-9725-4b20-90df-28ad410f173b", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "178c5cfe-cc05-49ec-bedb-eff402da4e8f", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "a2ecf99f-9725-4b20-90df-28ad410f173b", - "toObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d7df3544-94ed-439f-94de-86ad7828669a", - "type": "TEXT", - "name": "phone", - "label": "Phone", - "description": "Contact’s phone number", - "icon": "IconPhone", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "82d1a637-3df9-4d59-a412-1cbc1d92baf2", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the contact", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "700c5e52-3e7b-4471-9826-82270c03c37e", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "82d1a637-3df9-4d59-a412-1cbc1d92baf2", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "8ac4df39-f1a0-4221-a605-bd4c229fbc12", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "700c5e52-3e7b-4471-9826-82270c03c37e", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "8ac4df39-f1a0-4221-a605-bd4c229fbc12", - "toObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5030bb60-7366-4e7d-8ba4-35c6a6255547", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments linked to the contact.", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0c8f43c1-d325-4a58-99a7-926b1db4e8fc", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5030bb60-7366-4e7d-8ba4-35c6a6255547", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b192eb71-bcfb-46ab-ae88-83a73700ee34", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "0c8f43c1-d325-4a58-99a7-926b1db4e8fc", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "b192eb71-bcfb-46ab-ae88-83a73700ee34", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a53d5e8d-85d9-45de-9f45-d8b4f5b11c3a", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the contact", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e95da71a-7162-4282-8ff7-ea65fea36fe8", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a53d5e8d-85d9-45de-9f45-d8b4f5b11c3a", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "db61f1e6-17d5-4f1d-8c18-8cb5f1108831", - "name": "person" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "e95da71a-7162-4282-8ff7-ea65fea36fe8", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "db61f1e6-17d5-4f1d-8c18-8cb5f1108831", - "toObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "148421f0-84b0-4af0-bc54-17a116242b14", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Person record Position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "aeb6b83d-3545-4d48-8281-0d46258a3447", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "apiKey", - "namePlural": "apiKeys", - "labelSingular": "Api Key", - "labelPlural": "Api Keys", - "description": "An api key", - "icon": "IconRobot", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "d9c16cc2-6a42-4ea8-a6be-08f6d9571c14", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjU=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d9c16cc2-6a42-4ea8-a6be-08f6d9571c14", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "ApiKey name", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ac04da17-5ffc-4027-9124-4af02c307d23", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3b213998-ade1-4836-a42f-1dc9b476f8f3", - "type": "DATE_TIME", - "name": "expiresAt", - "label": "Expiration date", - "description": "ApiKey expiration date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a3a6cbc2-f8dd-4ed0-8648-065253f9183e", - "type": "DATE_TIME", - "name": "revokedAt", - "label": "Revocation date", - "description": "ApiKey revocation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "15091a7f-64c4-4011-91b0-a63ed1f298ec", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3003e27d-9fc7-417b-a388-062144884d76", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activity", - "namePlural": "activities", - "labelSingular": "Activity", - "labelPlural": "Activities", - "description": "An activity", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "c0608084-ab8e-4527-8a27-81f12f43550a", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjE1" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c0608084-ab8e-4527-8a27-81f12f43550a", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Activity title", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b478ec3c-46d5-46b1-9a55-0938c0a7213d", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5d7fa454-c89c-4fdd-ac48-6b119977c8bd", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Activity attachments", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "69539f96-cede-4f76-bd64-84b1182c3427", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5d7fa454-c89c-4fdd-ac48-6b119977c8bd", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a6299818-986d-4358-9a7b-04e6f5e0fd8b", - "name": "activity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "69539f96-cede-4f76-bd64-84b1182c3427", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "a6299818-986d-4358-9a7b-04e6f5e0fd8b", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "15c8c04b-1d3c-4d40-b405-bfce8d1c46ad", - "type": "UUID", - "name": "authorId", - "label": "Author id (foreign key)", - "description": "Activity author id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fdf929a7-5529-4be3-a7df-aa08d2a23b2c", - "type": "RELATION", - "name": "activityTargets", - "label": "Targets", - "description": "Activity targets", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "938c0b4f-e398-4db6-8893-ad6b609556a9", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fdf929a7-5529-4be3-a7df-aa08d2a23b2c", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "8bcf99e6-2368-4caa-9c5e-e70c46bc6ab7", - "name": "activity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "938c0b4f-e398-4db6-8893-ad6b609556a9", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "8bcf99e6-2368-4caa-9c5e-e70c46bc6ab7", - "toObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0cbf9212-7130-4a59-9752-c29b00b0e6fd", - "type": "TEXT", - "name": "type", - "label": "Type", - "description": "Activity type", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'Note'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c2a21675-a29d-442a-9f02-84cd93df15ce", - "type": "RELATION", - "name": "comments", - "label": "Comments", - "description": "Activity comments", - "icon": "IconComment", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "eaf90876-fac7-448a-906c-7c2b6afcd346", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c2a21675-a29d-442a-9f02-84cd93df15ce", - "name": "comments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "nameSingular": "comment", - "namePlural": "comments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ace0311d-6b58-4c34-9e78-3c18ff147408", - "name": "activity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "eaf90876-fac7-448a-906c-7c2b6afcd346", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "ace0311d-6b58-4c34-9e78-3c18ff147408", - "toObjectMetadata": { - "__typename": "object", - "id": "c6d8d5a8-08ab-4828-8b19-82a9a835685a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "comment", - "namePlural": "comments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b31f4c53-a5ee-4939-9804-6964144540ca", - "type": "RELATION", - "name": "author", - "label": "Author", - "description": "Activity author", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "fccbbaf8-c653-4e09-8d3e-5652b37d8209", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b31f4c53-a5ee-4939-9804-6964144540ca", - "name": "author" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f9d4a27e-1728-44d8-b990-e648d838a35a", - "name": "authoredActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "fccbbaf8-c653-4e09-8d3e-5652b37d8209", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "f9d4a27e-1728-44d8-b990-e648d838a35a", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4ec37c9c-be4c-4f52-a441-03a1dfd951db", - "type": "RELATION", - "name": "assignee", - "label": "Assignee", - "description": "Activity assignee", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d5315a70-980f-4c45-9a4f-74779a00fdd3", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4ec37c9c-be4c-4f52-a441-03a1dfd951db", - "name": "assignee" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2d52a31f-3ad8-4d57-90eb-61142bf58382", - "name": "assignedActivities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "d5315a70-980f-4c45-9a4f-74779a00fdd3", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "2d52a31f-3ad8-4d57-90eb-61142bf58382", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e3010b50-0dce-4ca7-8fc6-580601f03a6a", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bd9cb34e-4225-469b-8703-2948ff2a7503", - "type": "TEXT", - "name": "body", - "label": "Body", - "description": "Activity body", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ba97c4a5-7141-4a70-8963-f36e24c8ab09", - "type": "DATE_TIME", - "name": "completedAt", - "label": "Completion Date", - "description": "Activity completion date", - "icon": "IconCheck", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "eddc4e8e-0664-4e28-a46d-87d39efe8b82", - "type": "DATE_TIME", - "name": "reminderAt", - "label": "Reminder Date", - "description": "Activity reminder date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "845efc95-6c7c-4292-a4df-b9d1d159f6b9", - "type": "UUID", - "name": "assigneeId", - "label": "Assignee id (foreign key)", - "description": "Activity assignee id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e50e247e-3db5-468a-802d-04d02b7b0331", - "type": "DATE_TIME", - "name": "dueAt", - "label": "Due Date", - "description": "Activity due date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2a0b35ca-c76e-494f-a03a-c9e9844d2696", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "labelSingular": "Attachment", - "labelPlural": "Attachments", - "description": "An attachment", - "icon": "IconFileImport", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "9d4f5164-457e-4e78-bacd-8633e234153b", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjE5" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f4c14cf5-f007-4e2b-a7b5-f5a77c7c5492", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0913c9cc-c3d4-4fd4-9fc7-b758daa08ba4", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "Attachment task", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "cc228da1-14c7-4c49-a84d-231ba6166f38", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0913c9cc-c3d4-4fd4-9fc7-b758daa08ba4", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "7c3b7305-e7be-4dbf-9e94-ee354e011f63", - "name": "attachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "cc228da1-14c7-4c49-a84d-231ba6166f38", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "7c3b7305-e7be-4dbf-9e94-ee354e011f63", - "fromObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "36f7236a-bfd2-404c-adb6-66b294ca5435", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Attachment company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2be99c6b-02c8-4ca0-b155-dcf7539097b5", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "36f7236a-bfd2-404c-adb6-66b294ca5435", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "16706d44-4042-4998-b5c7-15437e052196", - "name": "attachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "2be99c6b-02c8-4ca0-b155-dcf7539097b5", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "16706d44-4042-4998-b5c7-15437e052196", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b192eb71-bcfb-46ab-ae88-83a73700ee34", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Attachment person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0c8f43c1-d325-4a58-99a7-926b1db4e8fc", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b192eb71-bcfb-46ab-ae88-83a73700ee34", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5030bb60-7366-4e7d-8ba4-35c6a6255547", - "name": "attachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "0c8f43c1-d325-4a58-99a7-926b1db4e8fc", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "5030bb60-7366-4e7d-8ba4-35c6a6255547", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a6299818-986d-4358-9a7b-04e6f5e0fd8b", - "type": "RELATION", - "name": "activity", - "label": "Activity", - "description": "Attachment activity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "69539f96-cede-4f76-bd64-84b1182c3427", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a6299818-986d-4358-9a7b-04e6f5e0fd8b", - "name": "activity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5d7fa454-c89c-4fdd-ac48-6b119977c8bd", - "name": "attachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "69539f96-cede-4f76-bd64-84b1182c3427", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "5d7fa454-c89c-4fdd-ac48-6b119977c8bd", - "fromObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1d2daa92-3e60-4d45-b3f5-2cdaea3171c8", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9d9f7585-6229-49ec-8657-a0f16608aa18", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Attachment person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bbde9d64-838e-4eea-b947-81fa6f44c76a", - "type": "UUID", - "name": "authorId", - "label": "Author id (foreign key)", - "description": "Attachment author id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f8a0a4ad-a6f5-4eb3-985d-a3134e5449ad", - "type": "RELATION", - "name": "note", - "label": "Note", - "description": "Attachment note", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bb4120f5-5135-4881-97a8-d50e6df2f97e", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f8a0a4ad-a6f5-4eb3-985d-a3134e5449ad", - "name": "note" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "nameSingular": "note", - "namePlural": "notes" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2a2fa9e4-242f-449e-a191-d1937ee4cedc", - "name": "attachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "bb4120f5-5135-4881-97a8-d50e6df2f97e", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "2a2fa9e4-242f-449e-a191-d1937ee4cedc", - "fromObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "note", - "namePlural": "notes", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9d4f5164-457e-4e78-bacd-8633e234153b", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "Attachment name", - "icon": "IconFileUpload", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9a3bd188-009f-4790-8f11-7978d420ebad", - "type": "UUID", - "name": "noteId", - "label": "Note id (foreign key)", - "description": "Attachment note id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "dd866825-21ca-4f0b-86e5-9bff38a9daa0", - "type": "TEXT", - "name": "type", - "label": "Type", - "description": "Attachment type", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "855ffc2d-08c3-42e1-bd5a-c8a11fced7dc", - "type": "TEXT", - "name": "fullPath", - "label": "Full path", - "description": "Attachment full path", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b16667c6-6f37-4010-871d-219f840a5b50", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Attachment company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f9a294b9-9def-4e4d-8f2b-8db82b65606c", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "Attachment opportunity id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b240e780-8bf4-4193-b4c4-1eaf8cac31f6", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6d99366d-b55c-4574-a533-709c8a902eef", - "type": "UUID", - "name": "activityId", - "label": "Activity id (foreign key)", - "description": "Attachment activity id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "85046974-8ab2-456d-a732-64da14715643", - "type": "RELATION", - "name": "author", - "label": "Author", - "description": "Attachment author", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5b9f08b0-8960-40c4-b6bb-9d3552a24f8d", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "85046974-8ab2-456d-a732-64da14715643", - "name": "author" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6e622089-670a-4831-964c-f27af03f39c0", - "name": "authoredAttachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "5b9f08b0-8960-40c4-b6bb-9d3552a24f8d", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "6e622089-670a-4831-964c-f27af03f39c0", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b4868b15-ff98-4f36-9f59-1dbf63052bb7", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "Attachment opportunity", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c20ecc99-e48a-4311-b850-8fbf1a7b68ea", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b4868b15-ff98-4f36-9f59-1dbf63052bb7", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "095b38a6-1881-40b8-9849-cb80d19aa295", - "name": "attachments" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "c20ecc99-e48a-4311-b850-8fbf1a7b68ea", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "095b38a6-1881-40b8-9849-cb80d19aa295", - "fromObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "04d74996-9228-47ee-9297-333439d4937e", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "Attachment task id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "labelSingular": "Activity Target", - "labelPlural": "Activity Targets", - "description": "An activity target", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "58b83d14-5f42-49c8-9048-485fe0259e7b", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEw" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "06fa978e-2d47-42ad-8652-00ad8e4f8c03", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "ActivityTarget company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8bcf99e6-2368-4caa-9c5e-e70c46bc6ab7", - "type": "RELATION", - "name": "activity", - "label": "Activity", - "description": "ActivityTarget activity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "938c0b4f-e398-4db6-8893-ad6b609556a9", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "8bcf99e6-2368-4caa-9c5e-e70c46bc6ab7", - "name": "activity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "nameSingular": "activity", - "namePlural": "activities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fdf929a7-5529-4be3-a7df-aa08d2a23b2c", - "name": "activityTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "938c0b4f-e398-4db6-8893-ad6b609556a9", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "fdf929a7-5529-4be3-a7df-aa08d2a23b2c", - "fromObjectMetadata": { - "__typename": "object", - "id": "96bf92fd-6b8f-40b4-afd6-f90fedc40a1a", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activity", - "namePlural": "activities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ddc84553-0678-4697-a8c2-06ddbc136cab", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "ActivityTarget opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2105fe76-e9fa-4610-992a-261d0f24722d", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ddc84553-0678-4697-a8c2-06ddbc136cab", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "1bab9225-7390-43d7-a2c5-1d14f918efc0", - "name": "activityTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "2105fe76-e9fa-4610-992a-261d0f24722d", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "1bab9225-7390-43d7-a2c5-1d14f918efc0", - "fromObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "242672b2-7f38-4864-8101-b8e2fb4605b0", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "ActivityTarget person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9a9a2055-3de4-46ef-a721-edf60be80cee", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "ActivityTarget opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f0748d0d-e6b4-44ea-b957-0c0d81af4627", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "ActivityTarget person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "450a3266-7706-4593-a458-5897c5f60fc5", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f0748d0d-e6b4-44ea-b957-0c0d81af4627", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c87e6f64-f722-4487-9930-1c6fb67572c1", - "name": "activityTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "450a3266-7706-4593-a458-5897c5f60fc5", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "c87e6f64-f722-4487-9930-1c6fb67572c1", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6cf6997c-82cd-41ae-9178-4e02467afe80", - "type": "UUID", - "name": "activityId", - "label": "Activity id (foreign key)", - "description": "ActivityTarget activity id foreign key", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "caeac93e-8092-4661-9b61-ba0c8b20d4e7", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "331d70b2-5cec-438f-b535-1ac0e59900bc", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6213d5af-e8cd-4e5d-9a60-bab631884ae5", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "ActivityTarget company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a0f5427c-2c97-4457-b87f-a4d145e06952", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "6213d5af-e8cd-4e5d-9a60-bab631884ae5", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "33454d9c-57f7-4639-9120-b024f365d52f", - "name": "activityTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "a0f5427c-2c97-4457-b87f-a4d145e06952", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "33454d9c-57f7-4639-9120-b024f365d52f", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "58b83d14-5f42-49c8-9048-485fe0259e7b", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "816a7154-5111-47fa-9d8d-87ca2dafc521", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "viewFilter", - "namePlural": "viewFilters", - "labelSingular": "View Filter", - "labelPlural": "View Filters", - "description": "(System) View Filters", - "icon": "IconFilterBolt", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "dc8df23b-c648-4781-a329-cc921f104396", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjg=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0fbd44d4-1342-45b9-a688-de8f8b3cfe97", - "type": "TEXT", - "name": "value", - "label": "Value", - "description": "View Filter value", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2ad7121a-e95e-4b14-9d36-387feebaf516", - "type": "UUID", - "name": "viewId", - "label": "View id (foreign key)", - "description": "View Filter related view id foreign key", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "07eed82c-b376-4cd6-a04a-042fde8d3058", - "type": "TEXT", - "name": "displayValue", - "label": "Display Value", - "description": "View Filter Display Value", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "89eaa2a3-6302-46d8-b06d-6640c336c489", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0f9c4eb8-501d-4861-827a-5ef45a01eba9", - "type": "RELATION", - "name": "view", - "label": "View", - "description": "View Filter related view", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "7c42db51-2fcc-44b6-9a80-787b1967e69e", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "816a7154-5111-47fa-9d8d-87ca2dafc521", - "nameSingular": "viewFilter", - "namePlural": "viewFilters" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0f9c4eb8-501d-4861-827a-5ef45a01eba9", - "name": "view" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "nameSingular": "view", - "namePlural": "views" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4f92f2f0-9204-4f23-afdc-894829664668", - "name": "viewFilters" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "7c42db51-2fcc-44b6-9a80-787b1967e69e", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "4f92f2f0-9204-4f23-afdc-894829664668", - "fromObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "view", - "namePlural": "views", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "dc8df23b-c648-4781-a329-cc921f104396", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4f9a929d-5701-4140-b509-8376c8853c2b", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "dfaccfbb-668f-42aa-9e9f-0dfefa4a7e94", - "type": "TEXT", - "name": "operand", - "label": "Operand", - "description": "View Filter operand", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'Contains'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "169eeb4d-f3e8-46f4-b0a3-7404bc1994cb", - "type": "UUID", - "name": "fieldMetadataId", - "label": "Field Metadata Id", - "description": "View Filter target field", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "718779fd-d87d-4b99-8f6c-3042a6bb03a3", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "viewSort", - "namePlural": "viewSorts", - "labelSingular": "View Sort", - "labelPlural": "View Sorts", - "description": "(System) View Sorts", - "icon": "IconArrowsSort", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "ef4449f6-3cb3-4538-9b93-4bed0060873e", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjY=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "da9e216d-b9ac-44de-a22f-ae579d76cd44", - "type": "TEXT", - "name": "direction", - "label": "Direction", - "description": "View Sort direction", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'asc'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7a4f3e54-7c7d-4fc6-8f12-a4c7f0d0d731", - "type": "UUID", - "name": "viewId", - "label": "View id (foreign key)", - "description": "View Sort related view id foreign key", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ef4449f6-3cb3-4538-9b93-4bed0060873e", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a021c847-07b3-4d3c-af30-b3330ce58e1b", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "11985659-99a1-4f03-9a95-c5d610acc8e9", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2c09d04d-007c-4652-9c90-c2cfa4696145", - "type": "RELATION", - "name": "view", - "label": "View", - "description": "View Sort related view", - "icon": "IconLayoutCollage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "fcf27acc-a651-4ac2-9f99-aba306756209", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "718779fd-d87d-4b99-8f6c-3042a6bb03a3", - "nameSingular": "viewSort", - "namePlural": "viewSorts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2c09d04d-007c-4652-9c90-c2cfa4696145", - "name": "view" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "nameSingular": "view", - "namePlural": "views" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5969cfdb-bf30-4a34-9b52-11b38945bbd0", - "name": "viewSorts" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "fcf27acc-a651-4ac2-9f99-aba306756209", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "5969cfdb-bf30-4a34-9b52-11b38945bbd0", - "fromObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "view", - "namePlural": "views", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "46007b88-46a1-4746-a25f-82151f01525e", - "type": "UUID", - "name": "fieldMetadataId", - "label": "Field Metadata Id", - "description": "View Sort target field", - "icon": "IconTag", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "labelSingular": "Company", - "labelPlural": "Companies", - "description": "A company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "9e123592-cd2b-471c-8143-3cc0b46089ef", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjIy" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a56f365a-22c8-475d-816b-709f3a19c5fd", - "type": "RELATION", - "name": "accountOwner", - "label": "Account Owner", - "description": "Your team member responsible for managing the company account", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "97b97e1e-aed0-4d59-997c-13ad9007e037", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a56f365a-22c8-475d-816b-709f3a19c5fd", - "name": "accountOwner" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "57d6eb4f-c86b-4a50-98ce-fa04c849b1a2", - "name": "accountOwnerForCompanies" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "97b97e1e-aed0-4d59-997c-13ad9007e037", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "57d6eb4f-c86b-4a50-98ce-fa04c849b1a2", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6c4a0327-d84f-416a-8491-269a74254437", - "type": "BOOLEAN", - "name": "idealCustomerProfile", - "label": "ICP", - "description": "Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you", - "icon": "IconTarget", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": false, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5dcef112-ce1b-46c1-a33a-4d1394628c34", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "277d8939-1ead-4cdb-a560-854644219779", - "type": "MULTI_SELECT", - "name": "testMultiSelect", - "label": "Test Multi Select", - "description": "Test Multi Select", - "icon": "IconSelect", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f207dd14-f05e-4f29-b222-8993d4680f31", - "type": "RAW_JSON", - "name": "testRawJson", - "label": "Test Raw Json", - "description": "Json value for event details", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "81db846a-a2f9-4b31-8931-81fac5cdd1b6", - "type": "RATING", - "name": "testRating", - "label": "Rating", - "description": "Rating value", - "icon": "IconListDetails", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b295267e-e066-4eb1-98ab-50a9d3004394", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the company", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ac6788b1-952c-4376-bafd-66ea5a031398", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b295267e-e066-4eb1-98ab-50a9d3004394", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d89d8a7f-6a14-4fc8-96ca-2966632a1ca4", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "ac6788b1-952c-4376-bafd-66ea5a031398", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "d89d8a7f-6a14-4fc8-96ca-2966632a1ca4", - "toObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "33454d9c-57f7-4639-9120-b024f365d52f", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the company", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a0f5427c-2c97-4457-b87f-a4d145e06952", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "33454d9c-57f7-4639-9120-b024f365d52f", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6213d5af-e8cd-4e5d-9a60-bab631884ae5", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "a0f5427c-2c97-4457-b87f-a4d145e06952", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "6213d5af-e8cd-4e5d-9a60-bab631884ae5", - "toObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "531f05f1-2c54-4f41-a569-eaac4d58a4ae", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Company record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b2304609-4b9c-40f9-b1d6-21c0974e636e", - "type": "LINKS", - "name": "xLink", - "label": "X", - "description": "The company Twitter/X account", - "icon": "IconBrandX", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "02a1dce3-e661-48d8-868b-83c6e6e79a35", - "type": "LINKS", - "name": "domainName", - "label": "Domain Name", - "description": "The company website URL. We use this url to fetch the company icon", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "81214e8d-e79d-420b-bb2d-8e1f0965b4a6", - "type": "UUID", - "name": "accountOwnerId", - "label": "Account Owner id (foreign key)", - "description": "Your team member responsible for managing the company account id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "92fa0702-e680-4042-aa65-ddf9721030b4", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a0df43b7-d926-44a2-ba12-252866607207", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the company", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "632aaba8-f213-4353-95a5-c090168c3ad7", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a0df43b7-d926-44a2-ba12-252866607207", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "4fa60a42-bd0d-462c-b05d-d85f96b00458", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "632aaba8-f213-4353-95a5-c090168c3ad7", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "4fa60a42-bd0d-462c-b05d-d85f96b00458", - "toObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f39f1db9-3d7f-46d3-aa0c-4cae44352407", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the company", - "icon": "IconIconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1e93ed03-91a5-4ad4-bca7-c6a637551289", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "f39f1db9-3d7f-46d3-aa0c-4cae44352407", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0224c08b-2c2e-474f-8360-dafad378cf62", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "1e93ed03-91a5-4ad4-bca7-c6a637551289", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0224c08b-2c2e-474f-8360-dafad378cf62", - "toObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1a843af7-219d-460b-9869-b2d89479e42a", - "type": "CURRENCY", - "name": "annualRecurringRevenue", - "label": "ARR", - "description": "Annual Recurring Revenue: The actual or estimated annual revenue of the company", - "icon": "IconMoneybag", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "amountMicros": null, - "currencyCode": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "16706d44-4042-4998-b5c7-15437e052196", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments linked to the company", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2be99c6b-02c8-4ca0-b155-dcf7539097b5", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "16706d44-4042-4998-b5c7-15437e052196", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "36f7236a-bfd2-404c-adb6-66b294ca5435", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "2be99c6b-02c8-4ca0-b155-dcf7539097b5", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "36f7236a-bfd2-404c-adb6-66b294ca5435", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9e123592-cd2b-471c-8143-3cc0b46089ef", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "The company name", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "76878ce1-1d00-4e86-8694-58b66bbb5df0", - "type": "LINKS", - "name": "linkedinLink", - "label": "Linkedin", - "description": "The company Linkedin account", - "icon": "IconBrandLinkedin", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "primaryLinkUrl": "''", - "secondaryLinks": null, - "primaryLinkLabel": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bcaf1d51-a492-48db-ab86-35b8ea496364", - "type": "ADDRESS", - "name": "address", - "label": "Address", - "description": "Address of the company", - "icon": "IconMap", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "addressLat": null, - "addressLng": null, - "addressCity": "''", - "addressState": "''", - "addressCountry": "''", - "addressStreet1": "''", - "addressStreet2": "''", - "addressPostcode": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "74bf3aba-450e-48f9-987a-60662929e768", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the company", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1670824b-e097-4afc-8401-feab7f9af0d4", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "74bf3aba-450e-48f9-987a-60662929e768", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5a0243d0-051b-4f30-b0d2-da66b3b8eefe", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "1670824b-e097-4afc-8401-feab7f9af0d4", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "5a0243d0-051b-4f30-b0d2-da66b3b8eefe", - "toObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "12a6505b-8d0b-4f02-ba94-742d7cc0ac8d", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7ecd1240-7300-4e9e-a9d2-02b489e160b9", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0943b1b4-3aae-4ebe-8e8e-b1a8640d78d9", - "type": "RELATION", - "name": "people", - "label": "People", - "description": "People linked to the company.", - "icon": "IconUsers", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2f030298-14c7-48a4-b351-2ec185bb1814", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0943b1b4-3aae-4ebe-8e8e-b1a8640d78d9", - "name": "people" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "538e49cd-f04a-4889-9994-35cacc0754b7", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "2f030298-14c7-48a4-b351-2ec185bb1814", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "538e49cd-f04a-4889-9994-35cacc0754b7", - "toObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0f4348ce-6621-4af6-b557-f03308a03101", - "type": "NUMBER", - "name": "employees", - "label": "Employees", - "description": "Number of employees in the company", - "icon": "IconUsers", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "34aec238-a534-46e7-be64-d0680a12c8ec", - "type": "RELATION", - "name": "opportunities", - "label": "Opportunities", - "description": "Opportunities linked to the company.", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1ebadb76-46e6-4c57-b24f-441acecbd2d9", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "34aec238-a534-46e7-be64-d0680a12c8ec", - "name": "opportunities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "727ec83b-93b7-4e6b-be22-6f00637ec3f5", - "name": "company" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "1ebadb76-46e6-4c57-b24f-441acecbd2d9", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "727ec83b-93b7-4e6b-be22-6f00637ec3f5", - "toObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "labelSingular": "Connected Account", - "labelPlural": "Connected Accounts", - "description": "A connected account", - "icon": "IconAt", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "d46591de-57c3-46ae-aca1-3d5cf2e39984", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEz" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d7c1698d-a73b-45f4-9bb1-b6b0a4f38fdb", - "type": "DATE_TIME", - "name": "authFailedAt", - "label": "Auth failed at", - "description": "Auth failed at", - "icon": "IconX", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3bf6ad9c-0441-4b8f-8dd0-12d93f83b67a", - "type": "RELATION", - "name": "messageChannels", - "label": "Message Channels", - "description": "Message Channels", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "21bbef75-8acf-48bf-80aa-1d26d50aea22", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "3bf6ad9c-0441-4b8f-8dd0-12d93f83b67a", - "name": "messageChannels" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d288fd3a-8fb0-493d-bec3-31a2c4a7d366", - "name": "connectedAccount" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "21bbef75-8acf-48bf-80aa-1d26d50aea22", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "d288fd3a-8fb0-493d-bec3-31a2c4a7d366", - "toObjectMetadata": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannel", - "namePlural": "messageChannels", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "98853a40-3d9b-42d4-942d-bc08c4d3a520", - "type": "TEXT", - "name": "provider", - "label": "provider", - "description": "The account provider", - "icon": "IconSettings", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d46591de-57c3-46ae-aca1-3d5cf2e39984", - "type": "TEXT", - "name": "handle", - "label": "handle", - "description": "The account handle (email, username, phone number, etc.)", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ac09a2a9-d4ec-4293-b595-e5d684fd776c", - "type": "TEXT", - "name": "lastSyncHistoryId", - "label": "Last sync history ID", - "description": "Last sync history ID", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bda628b5-29a7-41fc-8f50-4bc75902adc4", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c27f1d98-24b4-4776-a49e-ca104eea9aaf", - "type": "TEXT", - "name": "accessToken", - "label": "Access Token", - "description": "Messaging provider access token", - "icon": "IconKey", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e2ba34b6-e188-4b2b-bbf9-0625f33154e1", - "type": "TEXT", - "name": "refreshToken", - "label": "Refresh Token", - "description": "Messaging provider refresh token", - "icon": "IconKey", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bb10e69d-f049-4d97-84f4-09bce29cd401", - "type": "RELATION", - "name": "calendarChannels", - "label": "Calendar Channels", - "description": "Calendar Channels", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "b6b75323-8790-4b3e-8798-e0af646bb9aa", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "bb10e69d-f049-4d97-84f4-09bce29cd401", - "name": "calendarChannels" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ceaf8f8e-297a-418b-a652-01f3eeb5c562", - "name": "connectedAccount" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "b6b75323-8790-4b3e-8798-e0af646bb9aa", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "ceaf8f8e-297a-418b-a652-01f3eeb5c562", - "toObjectMetadata": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "48006d4c-0d9c-4099-9ab8-812d0e522faf", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ebc20c3a-157e-46a0-84c7-b0a4a93ead20", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "15512b35-a65c-4f87-8c98-0b0a1b6f92fe", - "type": "UUID", - "name": "accountOwnerId", - "label": "Account Owner id (foreign key)", - "description": "Account Owner id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "95bd59b8-8083-4c76-b770-ec40a744138c", - "type": "RELATION", - "name": "accountOwner", - "label": "Account Owner", - "description": "Account Owner", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1ecacc04-e834-421d-bf1b-c765e55a4318", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "95bd59b8-8083-4c76-b770-ec40a744138c", - "name": "accountOwner" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "104209de-5259-4d74-b14a-f37badf49be9", - "name": "connectedAccounts" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "1ecacc04-e834-421d-bf1b-c765e55a4318", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "104209de-5259-4d74-b14a-f37badf49be9", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "27048fa7-94eb-4ca0-8479-096a6b990e0f", - "type": "TEXT", - "name": "handleAliases", - "label": "Handle Aliases", - "description": "Handle Aliases", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "60637cd3-24f6-4d9a-9432-a590accbefb9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "blocklist", - "namePlural": "blocklists", - "labelSingular": "Blocklist", - "labelPlural": "Blocklists", - "description": "Blocklist", - "icon": "IconForbid2", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "67c4f9b6-f1b6-48d0-a502-71aef617fed2", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjU=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6d5237ae-e410-4701-ae0c-8d73bf83c49f", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "67c4f9b6-f1b6-48d0-a502-71aef617fed2", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "96acdd2a-b7d1-452b-9e58-5c4265691444", - "type": "RELATION", - "name": "workspaceMember", - "label": "WorkspaceMember", - "description": "WorkspaceMember", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "19b7520c-bc6e-490c-bfab-a3b020315cc4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "60637cd3-24f6-4d9a-9432-a590accbefb9", - "nameSingular": "blocklist", - "namePlural": "blocklists" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "96acdd2a-b7d1-452b-9e58-5c4265691444", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c6b1b4a1-bad8-4872-b408-aa0ceb668215", - "name": "blocklist" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "19b7520c-bc6e-490c-bfab-a3b020315cc4", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "c6b1b4a1-bad8-4872-b408-aa0ceb668215", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9b5ffcde-f21d-43c9-9d8c-ff718fe8c4cb", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "616690bd-fdca-483b-9b1d-e85642f770b4", - "type": "UUID", - "name": "workspaceMemberId", - "label": "WorkspaceMember id (foreign key)", - "description": "WorkspaceMember id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "697ba30c-5088-4af7-b7c4-39249c3df401", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "labelSingular": "Task Target", - "labelPlural": "Task Targets", - "description": "An task target", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "f9109154-65ca-42d5-b21c-1251790f60f8", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEw" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "807cfd9f-4081-4027-b646-cf66d81aa8c6", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "TaskTarget opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "457627a4-8e4f-4720-80b4-b8c47a49a1d7", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "807cfd9f-4081-4027-b646-cf66d81aa8c6", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "100f9c10-11c4-4fee-963a-f98a0e42d05d", - "name": "taskTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "457627a4-8e4f-4720-80b4-b8c47a49a1d7", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "100f9c10-11c4-4fee-963a-f98a0e42d05d", - "fromObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "db61f1e6-17d5-4f1d-8c18-8cb5f1108831", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "TaskTarget person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e95da71a-7162-4282-8ff7-ea65fea36fe8", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "db61f1e6-17d5-4f1d-8c18-8cb5f1108831", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a53d5e8d-85d9-45de-9f45-d8b4f5b11c3a", - "name": "taskTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "e95da71a-7162-4282-8ff7-ea65fea36fe8", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "a53d5e8d-85d9-45de-9f45-d8b4f5b11c3a", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f9109154-65ca-42d5-b21c-1251790f60f8", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e5958bbf-0743-46a4-9222-cefbaa0bd45f", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c84f3d16-2914-4861-8097-d4c58aa7e60e", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "03f631d8-6e86-49c0-9197-dab8df407176", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "TaskTarget person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0f37463a-4a08-44b6-87b6-8175ffa6bff0", - "type": "RELATION", - "name": "task", - "label": "Task", - "description": "TaskTarget task", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1cc7a6b5-66d2-40dc-aa08-4b1a252e3ae3", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0f37463a-4a08-44b6-87b6-8175ffa6bff0", - "name": "task" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "157bef1e-50c2-4c2a-bc48-a5bc790c0f08", - "name": "taskTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "1cc7a6b5-66d2-40dc-aa08-4b1a252e3ae3", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "157bef1e-50c2-4c2a-bc48-a5bc790c0f08", - "fromObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "task", - "namePlural": "tasks", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d89d8a7f-6a14-4fc8-96ca-2966632a1ca4", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "TaskTarget company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ac6788b1-952c-4376-bafd-66ea5a031398", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d89d8a7f-6a14-4fc8-96ca-2966632a1ca4", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b295267e-e066-4eb1-98ab-50a9d3004394", - "name": "taskTargets" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "ac6788b1-952c-4376-bafd-66ea5a031398", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "b295267e-e066-4eb1-98ab-50a9d3004394", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e5c3fbc8-1d4a-4474-a06b-001868038a82", - "type": "UUID", - "name": "taskId", - "label": "Task id (foreign key)", - "description": "TaskTarget task id foreign key", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e387828b-ddb0-4991-86bb-9f37149cf20c", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "TaskTarget opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1f6a22b6-d296-43ed-bdeb-1303d334aa8c", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "TaskTarget company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants", - "labelSingular": "Calendar event participant", - "labelPlural": "Calendar event participants", - "description": "Calendar event participants", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "a05d5847-6d10-4c04-9c9c-e1b6c239ed0f", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEy" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f50861f2-6921-4c3a-8218-930fa98dcb36", - "type": "UUID", - "name": "calendarEventId", - "label": "Event ID id (foreign key)", - "description": "Event ID id foreign key", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "13af93a8-ad97-477a-992d-be998d44f2f3", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Workspace Member id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3f1d464a-8f3a-42a3-98e3-f314f906d437", - "type": "SELECT", - "name": "responseStatus", - "label": "Response Status", - "description": "Response Status", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'NEEDS_ACTION'", - "options": [ - { - "id": "83748f1c-0fe1-4b92-929f-1adef17c1041", - "color": "orange", - "label": "Needs Action", - "value": "NEEDS_ACTION", - "position": 0 - }, - { - "id": "3b770f03-26a4-4b08-9eee-d2e7cf6fe3c9", - "color": "red", - "label": "Declined", - "value": "DECLINED", - "position": 1 - }, - { - "id": "86b4d0ed-a858-42df-bd9b-31ef0448ef68", - "color": "yellow", - "label": "Tentative", - "value": "TENTATIVE", - "position": 2 - }, - { - "id": "842f49df-916c-4119-86fe-f6332bf6aef2", - "color": "green", - "label": "Accepted", - "value": "ACCEPTED", - "position": 3 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ffaf23b6-1c4c-4073-9c66-2e213764dc86", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "78c18d2c-6316-45f4-983a-17505a4991f2", - "type": "BOOLEAN", - "name": "isOrganizer", - "label": "Is Organizer", - "description": "Is Organizer", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": false, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a2ecf99f-9725-4b20-90df-28ad410f173b", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "178c5cfe-cc05-49ec-bedb-eff402da4e8f", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "a2ecf99f-9725-4b20-90df-28ad410f173b", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fd48c551-1309-473d-bb7e-921c577b731b", - "name": "calendarEventParticipants" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "178c5cfe-cc05-49ec-bedb-eff402da4e8f", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "fd48c551-1309-473d-bb7e-921c577b731b", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4071dc84-8e86-4174-92c8-d201cbe00587", - "type": "TEXT", - "name": "displayName", - "label": "Display Name", - "description": "Display Name", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "07dcc4ef-0f27-4fd3-bfaf-0f931dfaba97", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b04775e2-53a3-4f62-a2ab-858f2a456fa7", - "type": "RELATION", - "name": "calendarEvent", - "label": "Event ID", - "description": "Event ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "e02ea7b1-1d5a-481b-ab71-3c94ab3f9bf0", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b04775e2-53a3-4f62-a2ab-858f2a456fa7", - "name": "calendarEvent" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "eb3a27fb-9cb8-4017-b896-e52eaf801dc2", - "name": "calendarEventParticipants" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "e02ea7b1-1d5a-481b-ab71-3c94ab3f9bf0", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "eb3a27fb-9cb8-4017-b896-e52eaf801dc2", - "fromObjectMetadata": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fbc9d8eb-c04f-4c86-81ff-d4ca9957d0d4", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Workspace Member", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d5ffcbba-0ab9-4f4d-a5e6-15f1e668b04c", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "53743ffb-932c-43ec-b624-f5119ec46808", - "nameSingular": "calendarEventParticipant", - "namePlural": "calendarEventParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fbc9d8eb-c04f-4c86-81ff-d4ca9957d0d4", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "6062715e-08e8-4ff5-962d-eed4f992fc61", - "name": "calendarEventParticipants" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "d5ffcbba-0ab9-4f4d-a5e6-15f1e668b04c", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "6062715e-08e8-4ff5-962d-eed4f992fc61", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cdb9b9ba-ac5c-4806-a017-8ca8b250fc50", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0178d7b0-59e1-48d2-bc62-4138e6d28b60", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a05d5847-6d10-4c04-9c9c-e1b6c239ed0f", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconMail", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations", - "labelSingular": "Calendar Channel Event Association", - "labelPlural": "Calendar Channel Event Associations", - "description": "Calendar Channel Event Associations", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "277a098a-129a-4c86-b467-6738edc923e6", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjc=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3ff32421-dddd-49d6-bce2-51517a50e621", - "type": "TEXT", - "name": "eventExternalId", - "label": "Event external ID", - "description": "Event external ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cae3d473-1e5b-4963-a88d-8fd2ef8090dc", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "18cea1c1-f521-4c41-b694-729756931795", - "type": "RELATION", - "name": "calendarEvent", - "label": "Event ID", - "description": "Event ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "0f9d244b-e9c6-44af-88f4-9ce798d50bf8", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "18cea1c1-f521-4c41-b694-729756931795", - "name": "calendarEvent" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fe7dcb62-099f-4ad1-af7e-a74713f6159d", - "name": "calendarChannelEventAssociations" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "0f9d244b-e9c6-44af-88f4-9ce798d50bf8", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "fe7dcb62-099f-4ad1-af7e-a74713f6159d", - "fromObjectMetadata": { - "__typename": "object", - "id": "d2834e90-eecc-4528-bab3-ad005effd6f2", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarEvent", - "namePlural": "calendarEvents", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4ddb8993-4601-4743-b042-8dab9784a405", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "277a098a-129a-4c86-b467-6738edc923e6", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "567e7a03-352b-4ba6-9fd8-c173a72d8465", - "type": "UUID", - "name": "calendarChannelId", - "label": "Channel ID id (foreign key)", - "description": "Channel ID id foreign key", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d3039865-07b4-4114-bd78-18aa0be2a93b", - "type": "RELATION", - "name": "calendarChannel", - "label": "Channel ID", - "description": "Channel ID", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bf0f695a-08cd-4767-9a83-4fd09f617793", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d3039865-07b4-4114-bd78-18aa0be2a93b", - "name": "calendarChannel" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "9867ad34-df58-4ad0-a459-cc283990b5e5", - "name": "calendarChannelEventAssociations" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "bf0f695a-08cd-4767-9a83-4fd09f617793", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "9867ad34-df58-4ad0-a459-cc283990b5e5", - "fromObjectMetadata": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "461f9bbb-92b0-4070-a7d2-7f029bae5cff", - "type": "UUID", - "name": "calendarEventId", - "label": "Event ID id (foreign key)", - "description": "Event ID id foreign key", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "note", - "namePlural": "notes", - "labelSingular": "Note", - "labelPlural": "Notes", - "description": "A note", - "icon": "IconNotes", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "e031b434-6370-484a-a88e-c9c526abde5d", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjk=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2b3caa88-203b-460c-be49-88db3b45e18d", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Note record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b66379fc-ac94-4823-b759-aa940fde9c73", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the note.", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "7ec36219-a377-4aea-98be-7954590f8a32", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "b66379fc-ac94-4823-b759-aa940fde9c73", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "bc0e2a25-4e13-4751-a79a-2d264582ef9a", - "name": "note" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "7ec36219-a377-4aea-98be-7954590f8a32", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "bc0e2a25-4e13-4751-a79a-2d264582ef9a", - "toObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "04794a4e-35c3-46a9-8bf3-8ba1c0324f0b", - "type": "RELATION", - "name": "noteTargets", - "label": "Targets", - "description": "Note targets", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "663e9842-8b92-451a-bf73-12a886ff8b05", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "04794a4e-35c3-46a9-8bf3-8ba1c0324f0b", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "87334d50-0c5d-4327-a8c5-3db6bc28c1ea", - "name": "note" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "663e9842-8b92-451a-bf73-12a886ff8b05", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "87334d50-0c5d-4327-a8c5-3db6bc28c1ea", - "toObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2a2fa9e4-242f-449e-a191-d1937ee4cedc", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Note attachments", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bb4120f5-5135-4881-97a8-d50e6df2f97e", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4cd6194a-093e-4c5d-9ff2-218970b01e3c", - "nameSingular": "note", - "namePlural": "notes" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2a2fa9e4-242f-449e-a191-d1937ee4cedc", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "f8a0a4ad-a6f5-4eb3-985d-a3134e5449ad", - "name": "note" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "bb4120f5-5135-4881-97a8-d50e6df2f97e", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "f8a0a4ad-a6f5-4eb3-985d-a3134e5449ad", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e031b434-6370-484a-a88e-c9c526abde5d", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Note title", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0c70e522-0571-4fca-8e4e-11c856819aeb", - "type": "RICH_TEXT", - "name": "body", - "label": "Body", - "description": "Note body", - "icon": "IconFilePencil", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "71958224-6de5-4998-82fc-8e85a3b247d6", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0121cd64-663f-4856-b9fc-97973a7e5ee5", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6de21035-5574-471c-80d9-4fb72375ff30", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0d8481f5-5c58-4604-9283-7a5780eab671", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "task", - "namePlural": "tasks", - "labelSingular": "Task", - "labelPlural": "Tasks", - "description": "A task", - "icon": "IconCheckbox", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "d55d2259-62d5-4738-ab6c-07a7293ccb1d", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEz" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "54f90efb-a0f4-4adb-9752-58593520ba14", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "671afe20-9fe1-41f7-9ea1-37a41b3f14ea", - "type": "SELECT", - "name": "status", - "label": "Status", - "description": "Task status", - "icon": "IconCheck", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'TODO'", - "options": [ - { - "id": "dedd046f-fc42-4f12-b791-0eb51ca8fa87", - "color": "sky", - "label": "To do", - "value": "TODO", - "position": 0 - }, - { - "id": "849a02b8-c8d4-4249-9b18-4f44a226b8a1", - "color": "purple", - "label": "In progress", - "value": "IN_PROGESS", - "position": 1 - }, - { - "id": "ff6527b5-06af-4e84-808f-bd8148525341", - "color": "green", - "label": "Done", - "value": "DONE", - "position": 1 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "975e6a19-d90c-45dc-9bb0-ffc57f4e1950", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the task.", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "87c0082f-5411-4202-97cd-fc1d9112fa7a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "975e6a19-d90c-45dc-9bb0-ffc57f4e1950", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e48eeafe-43d8-4abc-95c8-6e7a6a56a7c9", - "name": "task" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "87c0082f-5411-4202-97cd-fc1d9112fa7a", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "e48eeafe-43d8-4abc-95c8-6e7a6a56a7c9", - "toObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "91359011-baa5-43a5-9fc2-d46c55c01a50", - "type": "UUID", - "name": "assigneeId", - "label": "Assignee id (foreign key)", - "description": "Task assignee id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "200825f9-f61c-486d-bafc-c89df63bf661", - "type": "DATE_TIME", - "name": "dueAt", - "label": "Due Date", - "description": "Task due date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "811501e4-0b89-41bb-8571-95bcc3875491", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "61f19623-4e85-4710-867c-a5cc500fb3bc", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d34f8907-4850-452f-ae0f-2f4e678b74cc", - "type": "RICH_TEXT", - "name": "body", - "label": "Body", - "description": "Task body", - "icon": "IconFilePencil", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7c3b7305-e7be-4dbf-9e94-ee354e011f63", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Task attachments", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "cc228da1-14c7-4c49-a84d-231ba6166f38", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "7c3b7305-e7be-4dbf-9e94-ee354e011f63", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0913c9cc-c3d4-4fd4-9fc7-b758daa08ba4", - "name": "task" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "cc228da1-14c7-4c49-a84d-231ba6166f38", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0913c9cc-c3d4-4fd4-9fc7-b758daa08ba4", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ca0bf40d-2ddf-494f-bf1b-754f7c3f9c33", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4628c7ec-ba15-4567-b386-10d32e338eb7", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Task record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "157bef1e-50c2-4c2a-bc48-a5bc790c0f08", - "type": "RELATION", - "name": "taskTargets", - "label": "Targets", - "description": "Task targets", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1cc7a6b5-66d2-40dc-aa08-4b1a252e3ae3", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "157bef1e-50c2-4c2a-bc48-a5bc790c0f08", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0f37463a-4a08-44b6-87b6-8175ffa6bff0", - "name": "task" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "1cc7a6b5-66d2-40dc-aa08-4b1a252e3ae3", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0f37463a-4a08-44b6-87b6-8175ffa6bff0", - "toObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5bcc7e50-73ce-4146-b000-5a336f0e9c40", - "type": "RELATION", - "name": "assignee", - "label": "Assignee", - "description": "Task assignee", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "8cb075f2-e51c-4684-80f6-cf6af471e82a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4601f72c-580d-4e64-8004-4864f5e60da7", - "nameSingular": "task", - "namePlural": "tasks" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5bcc7e50-73ce-4146-b000-5a336f0e9c40", - "name": "assignee" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "e4c25d9f-10cf-4c33-8c39-7aaac0a98f11", - "name": "assignedTasks" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "8cb075f2-e51c-4684-80f6-cf6af471e82a", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "e4c25d9f-10cf-4c33-8c39-7aaac0a98f11", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d55d2259-62d5-4738-ab6c-07a7293ccb1d", - "type": "TEXT", - "name": "title", - "label": "Title", - "description": "Task title", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "favorite", - "namePlural": "favorites", - "labelSingular": "Favorite", - "labelPlural": "Favorites", - "description": "A favorite", - "icon": "IconHeart", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "283bbd7b-1828-47c0-ac12-59b840904057", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEx" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8028b960-41fe-45a5-bd88-ed41e3ec9f55", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Favorite workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4a9e3e27-70b0-4ed7-9edf-9126c1675b22", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Favorite person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "74f62324-bc36-4210-bb88-e0e6e0136c9f", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4a9e3e27-70b0-4ed7-9edf-9126c1675b22", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ee426b52-f4d3-4b96-a7fc-04d968b66331", - "name": "favorites" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "74f62324-bc36-4210-bb88-e0e6e0136c9f", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "ee426b52-f4d3-4b96-a7fc-04d968b66331", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2a725662-fe1a-44e8-af06-2ae21c9ae0c2", - "type": "RELATION", - "name": "opportunity", - "label": "Opportunity", - "description": "Favorite opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2f07395e-a114-465c-a3a2-9c6b990d3dca", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2a725662-fe1a-44e8-af06-2ae21c9ae0c2", - "name": "opportunity" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2e93a9a9-774b-43fd-8338-d54c29b8704c", - "name": "favorites" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "2f07395e-a114-465c-a3a2-9c6b990d3dca", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "2e93a9a9-774b-43fd-8338-d54c29b8704c", - "fromObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bdc61888-3791-42db-8276-1e91d7f81054", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "283bbd7b-1828-47c0-ac12-59b840904057", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0aaf9f83-9b43-4f15-a187-9c11761b367a", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Favorite workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "a72edc8d-e5e3-4eae-9fd6-4cb0792b18aa", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "0aaf9f83-9b43-4f15-a187-9c11761b367a", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "29055851-94dc-4fa9-84d8-295a3d161724", - "name": "favorites" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "a72edc8d-e5e3-4eae-9fd6-4cb0792b18aa", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "29055851-94dc-4fa9-84d8-295a3d161724", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4fa60a42-bd0d-462c-b05d-d85f96b00458", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Favorite company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "632aaba8-f213-4353-95a5-c090168c3ad7", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4fa60a42-bd0d-462c-b05d-d85f96b00458", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "a0df43b7-d926-44a2-ba12-252866607207", - "name": "favorites" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "632aaba8-f213-4353-95a5-c090168c3ad7", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "a0df43b7-d926-44a2-ba12-252866607207", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "539da33b-6863-41b5-9640-555cd190abf6", - "type": "NUMBER", - "name": "position", - "label": "Position", - "description": "Favorite position", - "icon": "IconList", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": 0, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0d36e64d-b3aa-43a2-a8d5-26639e695a3c", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Favorite person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f3f3b22c-cd38-4f87-bbf1-333b2661382f", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9cdaf83f-8f2b-4745-9f5e-ed7e295261ab", - "type": "UUID", - "name": "opportunityId", - "label": "Opportunity id (foreign key)", - "description": "Favorite opportunity id foreign key", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2a2e1910-5dd3-4f52-b164-b05117b51e43", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Favorite company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "3babbb57-d5c5-40e3-8c90-4623c39861f4", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "webhook", - "namePlural": "webhooks", - "labelSingular": "Webhook", - "labelPlural": "Webhooks", - "description": "A webhook", - "icon": "IconRobot", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "46a319ab-9265-4f31-914a-b361849a7c93", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjU=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4f333e42-291b-49c0-8e34-a5011899ad64", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "46a319ab-9265-4f31-914a-b361849a7c93", - "type": "TEXT", - "name": "targetUrl", - "label": "Target Url", - "description": "Webhook target url", - "icon": "IconLink", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d5763abd-3ab0-460a-8ce5-f7c69286bdce", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bf449824-9fba-40d3-85b5-b05101952339", - "type": "TEXT", - "name": "description", - "label": "Description", - "description": null, - "icon": "IconInfo", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "03d0aab2-d561-4177-9894-9368c5e7fcaf", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "dfa8f17b-8277-47b8-9be0-ccf18d40fa7e", - "type": "TEXT", - "name": "operation", - "label": "Operation", - "description": "Webhook operation", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannel", - "namePlural": "messageChannels", - "labelSingular": "Message Channel", - "labelPlural": "Message Channels", - "description": "Message Channels", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "fd617e16-7acc-445c-8e47-bae3df663831", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjE5" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "562e521e-c5d5-4ff8-a9c9-1970032b7d31", - "type": "DATE_TIME", - "name": "syncStageStartedAt", - "label": "Sync stage started at", - "description": "Sync stage started at", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fd617e16-7acc-445c-8e47-bae3df663831", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "25a76025-cde8-4ced-91c9-83c053d14384", - "type": "SELECT", - "name": "visibility", - "label": "Visibility", - "description": "Visibility", - "icon": "IconEyeglass", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'SHARE_EVERYTHING'", - "options": [ - { - "id": "29cb9455-90fd-4eff-9dcf-f335b86ad0e2", - "color": "green", - "label": "Metadata", - "value": "METADATA", - "position": 0 - }, - { - "id": "696eef0c-758e-4db3-a897-e8724f3bbb91", - "color": "blue", - "label": "Subject", - "value": "SUBJECT", - "position": 1 - }, - { - "id": "8a2a24ed-dfb4-4dca-b92f-398b9239ec81", - "color": "orange", - "label": "Share Everything", - "value": "SHARE_EVERYTHING", - "position": 2 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3650c95e-adc9-4e10-af9b-f271e3011175", - "type": "TEXT", - "name": "syncCursor", - "label": "Last sync cursor", - "description": "Last sync cursor", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4028ab71-03ae-4743-81fa-53e0fc802839", - "type": "SELECT", - "name": "contactAutoCreationPolicy", - "label": "Contact auto creation policy", - "description": "Automatically create People records when receiving or sending emails", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'SENT'", - "options": [ - { - "id": "db68b799-8701-4d82-8496-0dc007f0f352", - "color": "green", - "label": "Sent and Received", - "value": "SENT_AND_RECEIVED", - "position": 0 - }, - { - "id": "4e01422b-7a3e-4dc5-a3f7-8ffe8a0ce561", - "color": "blue", - "label": "Sent", - "value": "SENT", - "position": 1 - }, - { - "id": "41656b1a-4c84-44b1-8b23-44740840b68e", - "color": "red", - "label": "None", - "value": "NONE", - "position": 2 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0f338b41-0db1-45ae-bd58-7db0f1623d73", - "type": "SELECT", - "name": "syncStage", - "label": "Sync stage", - "description": "Sync stage", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'FULL_MESSAGE_LIST_FETCH_PENDING'", - "options": [ - { - "id": "5d0c8e59-584c-47d4-818b-6b28d6aa6c63", - "color": "blue", - "label": "Full messages list fetch pending", - "value": "FULL_MESSAGE_LIST_FETCH_PENDING", - "position": 0 - }, - { - "id": "460f32ef-f8fd-4744-bb0d-e78991e3ad43", - "color": "blue", - "label": "Partial messages list fetch pending", - "value": "PARTIAL_MESSAGE_LIST_FETCH_PENDING", - "position": 1 - }, - { - "id": "daecc0da-ec0b-45ab-ad2d-2240945a3401", - "color": "orange", - "label": "Messages list fetch ongoing", - "value": "MESSAGE_LIST_FETCH_ONGOING", - "position": 2 - }, - { - "id": "4d2db113-0d55-4b08-aa62-d046cba0355e", - "color": "blue", - "label": "Messages import pending", - "value": "MESSAGES_IMPORT_PENDING", - "position": 3 - }, - { - "id": "36352f84-d97b-4762-b1a1-f10c2174831e", - "color": "orange", - "label": "Messages import ongoing", - "value": "MESSAGES_IMPORT_ONGOING", - "position": 4 - }, - { - "id": "8f3c45c2-8539-48bb-83a0-4af18f9f7852", - "color": "red", - "label": "Failed", - "value": "FAILED", - "position": 5 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3b94c079-895b-4334-ae18-08d6892a5b7c", - "type": "BOOLEAN", - "name": "isContactAutoCreationEnabled", - "label": "Is Contact Auto Creation Enabled", - "description": "Is Contact Auto Creation Enabled", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cc44284e-0f2a-4d29-89b0-12416ed5db94", - "type": "NUMBER", - "name": "throttleFailureCount", - "label": "Throttle Failure Count", - "description": "Throttle Failure Count", - "icon": "IconX", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": 0, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "415b8ccc-aa22-4fdc-933c-bbaf477ff84b", - "type": "SELECT", - "name": "syncStatus", - "label": "Sync status", - "description": "Sync status", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": [ - { - "id": "38d30f8d-c137-46a6-b4a8-6e3cf681fe1f", - "color": "yellow", - "label": "Ongoing", - "value": "ONGOING", - "position": 1 - }, - { - "id": "e10615dc-208c-4e59-85bb-a109111c3888", - "color": "blue", - "label": "Not Synced", - "value": "NOT_SYNCED", - "position": 2 - }, - { - "id": "f600af02-8be4-4dcd-9880-ed8e00576f20", - "color": "green", - "label": "Active", - "value": "ACTIVE", - "position": 3 - }, - { - "id": "18ff3cfe-7680-4065-8400-6b2a31553de4", - "color": "red", - "label": "Failed Insufficient Permissions", - "value": "FAILED_INSUFFICIENT_PERMISSIONS", - "position": 4 - }, - { - "id": "f0bdbb33-e57d-4f14-8696-077c0edcc3d6", - "color": "red", - "label": "Failed Unknown", - "value": "FAILED_UNKNOWN", - "position": 5 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "90feafa8-c1c8-4c02-97cc-4b2779f64991", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bdd7ff46-118c-44e7-9b2e-cd522a248a8a", - "type": "RELATION", - "name": "messageChannelMessageAssociations", - "label": "Message Channel Association", - "description": "Messages from the channel.", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "40e51c6c-0268-47ca-bab9-4a899391e74b", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "bdd7ff46-118c-44e7-9b2e-cd522a248a8a", - "name": "messageChannelMessageAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "34479a8f-e7a4-4069-9f05-08d09113c8dc", - "name": "messageChannel" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "40e51c6c-0268-47ca-bab9-4a899391e74b", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "34479a8f-e7a4-4069-9f05-08d09113c8dc", - "toObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1beb00c7-4641-439c-bd91-2d497de10f63", - "type": "BOOLEAN", - "name": "excludeGroupEmails", - "label": "Exclude group emails", - "description": "Exclude group emails", - "icon": "IconUsersGroup", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f4e6c74c-01ba-4afc-83d2-0e5149a35233", - "type": "DATE_TIME", - "name": "syncedAt", - "label": "Last sync date", - "description": "Last sync date", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "36d2fee2-936b-4b7d-82fc-eecb49f8d142", - "type": "SELECT", - "name": "type", - "label": "Type", - "description": "Channel Type", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'email'", - "options": [ - { - "id": "734f44a0-597e-403a-aaab-00ba91d6e832", - "color": "green", - "label": "Email", - "value": "email", - "position": 0 - }, - { - "id": "2827a65a-b2c7-4515-80d8-7d9c12ad5f8a", - "color": "blue", - "label": "SMS", - "value": "sms", - "position": 1 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "cefb6cd7-554d-4e70-8f45-fbb8dbd0fe92", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "d288fd3a-8fb0-493d-bec3-31a2c4a7d366", - "type": "RELATION", - "name": "connectedAccount", - "label": "Connected Account", - "description": "Connected Account", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "21bbef75-8acf-48bf-80aa-1d26d50aea22", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "d288fd3a-8fb0-493d-bec3-31a2c4a7d366", - "name": "connectedAccount" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "3bf6ad9c-0441-4b8f-8dd0-12d93f83b67a", - "name": "messageChannels" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "21bbef75-8acf-48bf-80aa-1d26d50aea22", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "3bf6ad9c-0441-4b8f-8dd0-12d93f83b67a", - "fromObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e2f86b34-c7ea-41aa-b0cb-dfa171a9380a", - "type": "UUID", - "name": "connectedAccountId", - "label": "Connected Account id (foreign key)", - "description": "Connected Account id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a36aa9b7-abbb-4143-949d-42c9f711679f", - "type": "BOOLEAN", - "name": "isSyncEnabled", - "label": "Is Sync Enabled", - "description": "Is Sync Enabled", - "icon": "IconRefresh", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5fc28ad8-3623-4fb8-a872-efe52af486c1", - "type": "BOOLEAN", - "name": "excludeNonProfessionalEmails", - "label": "Exclude non professional emails", - "description": "Exclude non professional emails", - "icon": "IconBriefcase", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "0397d2f1-3e81-4521-9abf-1b39c584d8eb", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "opportunity", - "namePlural": "opportunities", - "labelSingular": "Opportunity", - "labelPlural": "Opportunities", - "description": "An opportunity", - "icon": "IconTargetArrow", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "3d6fa6cd-b06a-4465-8033-dc0ed8abda9d", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjE4" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "18ea34ae-f9bc-4240-b65f-46f0d688135f", - "type": "RELATION", - "name": "pointOfContact", - "label": "Point of Contact", - "description": "Opportunity point of contact", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "58a081ed-e5e7-44f8-bae6-99be66b6ac2f", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "18ea34ae-f9bc-4240-b65f-46f0d688135f", - "name": "pointOfContact" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "05863c2c-bcf7-4d88-b0cd-f00335b6854d", - "name": "pointOfContactForOpportunities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "58a081ed-e5e7-44f8-bae6-99be66b6ac2f", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "05863c2c-bcf7-4d88-b0cd-f00335b6854d", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2e93a9a9-774b-43fd-8338-d54c29b8704c", - "type": "RELATION", - "name": "favorites", - "label": "Favorites", - "description": "Favorites linked to the opportunity", - "icon": "IconHeart", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2f07395e-a114-465c-a3a2-9c6b990d3dca", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "2e93a9a9-774b-43fd-8338-d54c29b8704c", - "name": "favorites" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "nameSingular": "favorite", - "namePlural": "favorites" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2a725662-fe1a-44e8-af06-2ae21c9ae0c2", - "name": "opportunity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "2f07395e-a114-465c-a3a2-9c6b990d3dca", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "2a725662-fe1a-44e8-af06-2ae21c9ae0c2", - "toObjectMetadata": { - "__typename": "object", - "id": "4566e731-1922-4610-8e85-0beab7fc57be", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "favorite", - "namePlural": "favorites", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4e24ba90-8fcd-4df5-9fe8-48679c75d374", - "type": "RELATION", - "name": "timelineActivities", - "label": "Timeline Activities", - "description": "Timeline Activities linked to the opportunity.", - "icon": "IconTimelineEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "d8ae1b79-b532-412c-92cf-767a32e3cda2", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4e24ba90-8fcd-4df5-9fe8-48679c75d374", - "name": "timelineActivities" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "987fd4f6-4c5f-48a4-82f3-fd769de80dc4", - "name": "opportunity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "d8ae1b79-b532-412c-92cf-767a32e3cda2", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "987fd4f6-4c5f-48a4-82f3-fd769de80dc4", - "toObjectMetadata": { - "__typename": "object", - "id": "e095e196-08d4-493c-8a02-01c4a3decb5c", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "timelineActivity", - "namePlural": "timelineActivities", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3d6fa6cd-b06a-4465-8033-dc0ed8abda9d", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "The opportunity name", - "icon": "IconTargetArrow", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7e6746ac-3625-4b14-86bc-11adc29e347c", - "type": "UUID", - "name": "companyId", - "label": "Company id (foreign key)", - "description": "Opportunity company id foreign key", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1bab9225-7390-43d7-a2c5-1d14f918efc0", - "type": "RELATION", - "name": "activityTargets", - "label": "Activities", - "description": "Activities tied to the opportunity", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2105fe76-e9fa-4610-992a-261d0f24722d", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "1bab9225-7390-43d7-a2c5-1d14f918efc0", - "name": "activityTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "nameSingular": "activityTarget", - "namePlural": "activityTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "ddc84553-0678-4697-a8c2-06ddbc136cab", - "name": "opportunity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "2105fe76-e9fa-4610-992a-261d0f24722d", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "ddc84553-0678-4697-a8c2-06ddbc136cab", - "toObjectMetadata": { - "__typename": "object", - "id": "948a52f8-eba6-4bb2-a3a7-b1aa61c0daf7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "activityTarget", - "namePlural": "activityTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "809ebb3f-8c63-4009-a8b9-3e184d6f140c", - "type": "CURRENCY", - "name": "amount", - "label": "Amount", - "description": "Opportunity amount", - "icon": "IconCurrencyDollar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "amountMicros": null, - "currencyCode": "''" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "100f9c10-11c4-4fee-963a-f98a0e42d05d", - "type": "RELATION", - "name": "taskTargets", - "label": "Tasks", - "description": "Tasks tied to the opportunity", - "icon": "IconCheckbox", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "457627a4-8e4f-4720-80b4-b8c47a49a1d7", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "100f9c10-11c4-4fee-963a-f98a0e42d05d", - "name": "taskTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "nameSingular": "taskTarget", - "namePlural": "taskTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "807cfd9f-4081-4027-b646-cf66d81aa8c6", - "name": "opportunity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "457627a4-8e4f-4720-80b4-b8c47a49a1d7", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "807cfd9f-4081-4027-b646-cf66d81aa8c6", - "toObjectMetadata": { - "__typename": "object", - "id": "5e92b318-bc10-4fe3-b997-de41b7e45c36", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "taskTarget", - "namePlural": "taskTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "21626287-1f6d-4604-869f-59b77b98e529", - "type": "DATE_TIME", - "name": "closeDate", - "label": "Close date", - "description": "Opportunity close date", - "icon": "IconCalendarEvent", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a9d9912d-6f0d-4ddb-85ce-48acbba6ae00", - "type": "SELECT", - "name": "stage", - "label": "Stage", - "description": "Opportunity stage", - "icon": "IconProgressCheck", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'NEW'", - "options": [ - { - "id": "c8c92b5e-af59-4c21-a68c-c2dbdd513b2c", - "color": "red", - "label": "New", - "value": "NEW", - "position": 0 - }, - { - "id": "b33eff93-1fec-4275-97f0-03beb704a709", - "color": "purple", - "label": "Screening", - "value": "SCREENING", - "position": 1 - }, - { - "id": "d4fff9a7-53ea-4e10-a16e-b721133f9cda", - "color": "sky", - "label": "Meeting", - "value": "MEETING", - "position": 2 - }, - { - "id": "e0b16f06-4e59-4f8c-ac30-a6e3fc37eac8", - "color": "turquoise", - "label": "Proposal", - "value": "PROPOSAL", - "position": 3 - }, - { - "id": "a0ad0f8d-fed5-49c0-8dfd-00be4521db24", - "color": "yellow", - "label": "Customer", - "value": "CUSTOMER", - "position": 4 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1433c5e0-2dfc-404b-b04e-17126fd75e0a", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "727ec83b-93b7-4e6b-be22-6f00637ec3f5", - "type": "RELATION", - "name": "company", - "label": "Company", - "description": "Opportunity company", - "icon": "IconBuildingSkyscraper", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1ebadb76-46e6-4c57-b24f-441acecbd2d9", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "727ec83b-93b7-4e6b-be22-6f00637ec3f5", - "name": "company" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "nameSingular": "company", - "namePlural": "companies" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "34aec238-a534-46e7-be64-d0680a12c8ec", - "name": "opportunities" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "1ebadb76-46e6-4c57-b24f-441acecbd2d9", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "34aec238-a534-46e7-be64-d0680a12c8ec", - "fromObjectMetadata": { - "__typename": "object", - "id": "701aecf9-eb1c-4d84-9d94-b954b231b64b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "company", - "namePlural": "companies", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "89f08f6a-f94a-4f1c-823b-8e5513362c0b", - "type": "ACTOR", - "name": "createdBy", - "label": "Created by", - "description": "The creator of the record", - "icon": "IconCreativeCommonsSa", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": { - "name": "''", - "source": "'MANUAL'" - }, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8ac2f70d-3c5d-40a2-835c-849ae6c1ab81", - "type": "UUID", - "name": "pointOfContactId", - "label": "Point of Contact id (foreign key)", - "description": "Opportunity point of contact id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "095b38a6-1881-40b8-9849-cb80d19aa295", - "type": "RELATION", - "name": "attachments", - "label": "Attachments", - "description": "Attachments linked to the opportunity", - "icon": "IconFileImport", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c20ecc99-e48a-4311-b850-8fbf1a7b68ea", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "095b38a6-1881-40b8-9849-cb80d19aa295", - "name": "attachments" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "nameSingular": "attachment", - "namePlural": "attachments" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "b4868b15-ff98-4f36-9f59-1dbf63052bb7", - "name": "opportunity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "c20ecc99-e48a-4311-b850-8fbf1a7b68ea", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "b4868b15-ff98-4f36-9f59-1dbf63052bb7", - "toObjectMetadata": { - "__typename": "object", - "id": "963747ea-45e2-4deb-b36d-73b014e17c42", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "attachment", - "namePlural": "attachments", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f74b36a5-caf7-4318-994b-251eb2be2668", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e6fe20c1-091e-418f-9ff0-8ea7cfb864f8", - "type": "RELATION", - "name": "noteTargets", - "label": "Notes", - "description": "Notes tied to the opportunity", - "icon": "IconNotes", - "isCustom": false, - "isActive": true, - "isSystem": false, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c0946e53-4cdd-46b4-b30a-9fce040b9a7a", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2dbf5d59-f03c-4578-8ff3-750f4bcdf8d0", - "nameSingular": "opportunity", - "namePlural": "opportunities" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "e6fe20c1-091e-418f-9ff0-8ea7cfb864f8", - "name": "noteTargets" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "nameSingular": "noteTarget", - "namePlural": "noteTargets" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "5b2ec790-e8b8-4bd0-bf1b-db4ebc2b473a", - "name": "opportunity" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "c0946e53-4cdd-46b4-b30a-9fce040b9a7a", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "5b2ec790-e8b8-4bd0-bf1b-db4ebc2b473a", - "toObjectMetadata": { - "__typename": "object", - "id": "dcb774a3-71e8-44cc-bf53-7f195e0bfdb6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "noteTarget", - "namePlural": "noteTargets", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "206e678d-dc5d-4e69-b3e0-a16f9ec59676", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7717144e-ac08-4f29-8614-f12ad830ce5a", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "Opportunity record position", - "icon": "IconHierarchy2", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "view", - "namePlural": "views", - "labelSingular": "View", - "labelPlural": "Views", - "description": "(System) Views", - "icon": "IconLayoutCollage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "edfa9baf-6165-4be4-9f0f-0831c167cc43", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEz" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "92815f89-9c9d-4fc7-b0b0-dd9c0ca24fe7", - "type": "TEXT", - "name": "type", - "label": "Type", - "description": "View type", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'table'", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "15896bc9-fb20-4c1f-bc0d-f3abe768d388", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7a703490-9619-44e3-a1d7-95b37f128d7c", - "type": "SELECT", - "name": "key", - "label": "Key", - "description": "View key", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'INDEX'", - "options": [ - { - "id": "590b78a5-1851-436a-b696-acc719fa4be8", - "color": "red", - "label": "Index", - "value": "INDEX", - "position": 0 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "78afce65-d674-42b7-90dd-f61238fdbcf1", - "type": "TEXT", - "name": "icon", - "label": "Icon", - "description": "View icon", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c086b30a-0267-4857-9fe0-29a2bbaa8dc8", - "type": "RELATION", - "name": "viewFields", - "label": "View Fields", - "description": "View Fields", - "icon": "IconTag", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "ae731975-39ee-4387-a80c-de94dff0b760", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "nameSingular": "view", - "namePlural": "views" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "c086b30a-0267-4857-9fe0-29a2bbaa8dc8", - "name": "viewFields" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "c81903be-3be2-49af-82b3-d170cd35ac0f", - "nameSingular": "viewField", - "namePlural": "viewFields" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "337d9389-06a9-4cb1-9f2a-76dbb37a7576", - "name": "view" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "ae731975-39ee-4387-a80c-de94dff0b760", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "337d9389-06a9-4cb1-9f2a-76dbb37a7576", - "toObjectMetadata": { - "__typename": "object", - "id": "c81903be-3be2-49af-82b3-d170cd35ac0f", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "viewField", - "namePlural": "viewFields", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "edfa9baf-6165-4be4-9f0f-0831c167cc43", - "type": "TEXT", - "name": "name", - "label": "Name", - "description": "View name", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5969cfdb-bf30-4a34-9b52-11b38945bbd0", - "type": "RELATION", - "name": "viewSorts", - "label": "View Sorts", - "description": "View Sorts", - "icon": "IconArrowsSort", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "fcf27acc-a651-4ac2-9f99-aba306756209", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "nameSingular": "view", - "namePlural": "views" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "5969cfdb-bf30-4a34-9b52-11b38945bbd0", - "name": "viewSorts" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "718779fd-d87d-4b99-8f6c-3042a6bb03a3", - "nameSingular": "viewSort", - "namePlural": "viewSorts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2c09d04d-007c-4652-9c90-c2cfa4696145", - "name": "view" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "fcf27acc-a651-4ac2-9f99-aba306756209", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "2c09d04d-007c-4652-9c90-c2cfa4696145", - "toObjectMetadata": { - "__typename": "object", - "id": "718779fd-d87d-4b99-8f6c-3042a6bb03a3", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "viewSort", - "namePlural": "viewSorts", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "563534f3-90f6-42f8-9dbc-0f067ca5424c", - "type": "POSITION", - "name": "position", - "label": "Position", - "description": "View position", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "8fd9225d-5f08-4e21-a0cf-d596d4ec1eaf", - "type": "UUID", - "name": "objectMetadataId", - "label": "Object Metadata Id", - "description": "View target object", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4f92f2f0-9204-4f23-afdc-894829664668", - "type": "RELATION", - "name": "viewFilters", - "label": "View Filters", - "description": "View Filters", - "icon": "IconFilterBolt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "7c42db51-2fcc-44b6-9a80-787b1967e69e", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "2c6e4a32-28cd-4a72-8ca6-915fd819ed32", - "nameSingular": "view", - "namePlural": "views" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "4f92f2f0-9204-4f23-afdc-894829664668", - "name": "viewFilters" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "816a7154-5111-47fa-9d8d-87ca2dafc521", - "nameSingular": "viewFilter", - "namePlural": "viewFilters" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "0f9c4eb8-501d-4861-827a-5ef45a01eba9", - "name": "view" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "7c42db51-2fcc-44b6-9a80-787b1967e69e", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "0f9c4eb8-501d-4861-827a-5ef45a01eba9", - "toObjectMetadata": { - "__typename": "object", - "id": "816a7154-5111-47fa-9d8d-87ca2dafc521", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "viewFilter", - "namePlural": "viewFilters", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5c342176-2358-4269-9293-f7666691b1ff", - "type": "TEXT", - "name": "kanbanFieldMetadataId", - "label": "kanbanfieldMetadataId", - "description": "View Kanban column field", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "193fbb6a-6c71-4871-92dc-d4b71b856b83", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "87c37d2e-9457-47f3-bdf4-41879bb81b90", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "80e2dcf2-ffff-45db-adbc-174d739f1fb6", - "type": "BOOLEAN", - "name": "isCompact", - "label": "Compact View", - "description": "Describes if the view is in compact mode", - "icon": null, - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": false, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageThread", - "namePlural": "messageThreads", - "labelSingular": "Message Thread", - "labelPlural": "Message Threads", - "description": "Message Thread", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "408fe748-df73-4975-b473-8260e9da2e4b", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjQ=" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9016096d-93c4-495f-93d5-b966e5bedc74", - "type": "RELATION", - "name": "messages", - "label": "Messages", - "description": "Messages from the thread.", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "c958fe88-7d66-4c1b-87c7-55ab724f42c5", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "9016096d-93c4-495f-93d5-b966e5bedc74", - "name": "messages" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "nameSingular": "message", - "namePlural": "messages" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "114f853e-2684-4e62-92c9-0213ace3c498", - "name": "messageThread" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "c958fe88-7d66-4c1b-87c7-55ab724f42c5", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "114f853e-2684-4e62-92c9-0213ace3c498", - "toObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "message", - "namePlural": "messages", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6fe89951-20b6-4ef3-81d8-08498b09954b", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "25bbf51f-17fa-4a2c-9636-3f3fdba41e08", - "type": "RELATION", - "name": "messageChannelMessageAssociations", - "label": "Message Channel Association", - "description": "Messages from the channel", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1d8cbabc-edf5-40c9-8bd5-d1e47a93d246", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "25bbf51f-17fa-4a2c-9636-3f3fdba41e08", - "name": "messageChannelMessageAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "fcbef4a3-f1d9-4714-b7ea-f44816821d6e", - "name": "messageThread" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "1d8cbabc-edf5-40c9-8bd5-d1e47a93d246", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "fcbef4a3-f1d9-4714-b7ea-f44816821d6e", - "toObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "aef283f1-b060-4de8-a5b9-f1ef4e4c0bb4", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "408fe748-df73-4975-b473-8260e9da2e4b", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels", - "labelSingular": "Calendar Channel", - "labelPlural": "Calendar Channels", - "description": "Calendar Channels", - "icon": "IconCalendar", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "2cfd31ac-4391-4922-a640-38ac515564fc", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjE1" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "31ed435c-f012-4dfb-8825-35c522129243", - "type": "BOOLEAN", - "name": "isSyncEnabled", - "label": "Is Sync Enabled", - "description": "Is Sync Enabled", - "icon": "IconRefresh", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "4faab073-db9b-4644-8a16-57eb573c428d", - "type": "SELECT", - "name": "syncStage", - "label": "Sync stage", - "description": "Sync stage", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING'", - "options": [ - { - "id": "74fb48bf-87b9-4094-8c46-4f74128e78d8", - "color": "blue", - "label": "Full calendar event list fetch pending", - "value": "FULL_CALENDAR_EVENT_LIST_FETCH_PENDING", - "position": 0 - }, - { - "id": "f0b2944c-b9e4-4889-b405-99e023b69a65", - "color": "blue", - "label": "Partial calendar event list fetch pending", - "value": "PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING", - "position": 1 - }, - { - "id": "ec321870-1e95-4a7e-bc9d-ea58d0020d43", - "color": "orange", - "label": "Calendar event list fetch ongoing", - "value": "CALENDAR_EVENT_LIST_FETCH_ONGOING", - "position": 2 - }, - { - "id": "bf48f26c-8ce9-43cf-a89a-53e7fbb1afc6", - "color": "blue", - "label": "Calendar events import pending", - "value": "CALENDAR_EVENTS_IMPORT_PENDING", - "position": 3 - }, - { - "id": "d3d349ad-b3bf-4762-8aad-92796cd86e08", - "color": "orange", - "label": "Calendar events import ongoing", - "value": "CALENDAR_EVENTS_IMPORT_ONGOING", - "position": 4 - }, - { - "id": "7a882ecb-67ae-42c4-bac7-216c6b8522c4", - "color": "red", - "label": "Failed", - "value": "FAILED", - "position": 5 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "b1d2c87b-9e88-44b7-9b2d-138d359c28df", - "type": "SELECT", - "name": "syncStatus", - "label": "Sync status", - "description": "Sync status", - "icon": "IconStatusChange", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": [ - { - "id": "ab4ddbc1-8af6-4f9e-a3e9-f87a18e47951", - "color": "yellow", - "label": "Ongoing", - "value": "ONGOING", - "position": 1 - }, - { - "id": "bee7589a-9d59-4b01-9d9b-ef45dd4c17ca", - "color": "blue", - "label": "Not Synced", - "value": "NOT_SYNCED", - "position": 2 - }, - { - "id": "11fad735-37f3-4297-9da4-0251355ff461", - "color": "green", - "label": "Active", - "value": "ACTIVE", - "position": 3 - }, - { - "id": "e7da6feb-df29-49f4-b5ba-a82534490e5c", - "color": "red", - "label": "Failed Insufficient Permissions", - "value": "FAILED_INSUFFICIENT_PERMISSIONS", - "position": 4 - }, - { - "id": "61ae12e3-22e5-4971-9044-3ed274567b29", - "color": "red", - "label": "Failed Unknown", - "value": "FAILED_UNKNOWN", - "position": 5 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3e26b011-c7eb-44ff-9599-15b85ef5576d", - "type": "SELECT", - "name": "visibility", - "label": "Visibility", - "description": "Visibility", - "icon": "IconEyeglass", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'SHARE_EVERYTHING'", - "options": [ - { - "id": "d27d8a0e-d892-4581-b982-500f33b53803", - "color": "green", - "label": "Metadata", - "value": "METADATA", - "position": 0 - }, - { - "id": "fa61ab2d-1e83-4a01-8526-81c8460cc7dc", - "color": "orange", - "label": "Share Everything", - "value": "SHARE_EVERYTHING", - "position": 1 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ceaf8f8e-297a-418b-a652-01f3eeb5c562", - "type": "RELATION", - "name": "connectedAccount", - "label": "Connected Account", - "description": "Connected Account", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "b6b75323-8790-4b3e-8798-e0af646bb9aa", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "ceaf8f8e-297a-418b-a652-01f3eeb5c562", - "name": "connectedAccount" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "bb10e69d-f049-4d97-84f4-09bce29cd401", - "name": "calendarChannels" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "b6b75323-8790-4b3e-8798-e0af646bb9aa", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "bb10e69d-f049-4d97-84f4-09bce29cd401", - "fromObjectMetadata": { - "__typename": "object", - "id": "66cd3a29-e2d8-4efa-8852-d17d7b538efa", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "connectedAccount", - "namePlural": "connectedAccounts", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "284f9e52-0885-4860-98ea-2083911aa453", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3127b8eb-f998-4987-a797-01a8943e677a", - "type": "UUID", - "name": "connectedAccountId", - "label": "Connected Account id (foreign key)", - "description": "Connected Account id foreign key", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fd92e8cd-5f05-49e7-aa15-ae8c3a8905d6", - "type": "DATE_TIME", - "name": "syncStageStartedAt", - "label": "Sync stage started at", - "description": "Sync stage started at", - "icon": "IconHistory", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9867ad34-df58-4ad0-a459-cc283990b5e5", - "type": "RELATION", - "name": "calendarChannelEventAssociations", - "label": "Calendar Channel Event Associations", - "description": "Calendar Channel Event Associations", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "bf0f695a-08cd-4767-9a83-4fd09f617793", - "direction": "ONE_TO_MANY", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0e285964-d858-48bc-98ab-b8c6b1bd5d0b", - "nameSingular": "calendarChannel", - "namePlural": "calendarChannels" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "9867ad34-df58-4ad0-a459-cc283990b5e5", - "name": "calendarChannelEventAssociations" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "d3039865-07b4-4114-bd78-18aa0be2a93b", - "name": "calendarChannel" - } - }, - "toRelationMetadata": null, - "fromRelationMetadata": { - "__typename": "relation", - "id": "bf0f695a-08cd-4767-9a83-4fd09f617793", - "relationType": "ONE_TO_MANY", - "toFieldMetadataId": "d3039865-07b4-4114-bd78-18aa0be2a93b", - "toObjectMetadata": { - "__typename": "object", - "id": "4fed9657-e68b-4856-8e6d-a1c860d16242", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "calendarChannelEventAssociation", - "namePlural": "calendarChannelEventAssociations", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "1da10e0f-ddc1-441e-8d88-c2453ea397f7", - "type": "BOOLEAN", - "name": "isContactAutoCreationEnabled", - "label": "Is Contact Auto Creation Enabled", - "description": "Is Contact Auto Creation Enabled", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": true, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "2cfd31ac-4391-4922-a640-38ac515564fc", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c62bba75-6421-4fd0-966c-6749870b0b5b", - "type": "NUMBER", - "name": "throttleFailureCount", - "label": "Throttle Failure Count", - "description": "Throttle Failure Count", - "icon": "IconX", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": 0, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ae2fc211-7736-43b8-a7e2-b08476446ea5", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "e4ede7f5-3c11-4e77-9327-fe433429105b", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "ee994c99-3f91-4d2a-9956-449ab18af0e7", - "type": "SELECT", - "name": "contactAutoCreationPolicy", - "label": "Contact auto creation policy", - "description": "Automatically create records for people you participated with in an event.", - "icon": "IconUserCircle", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'AS_PARTICIPANT_AND_ORGANIZER'", - "options": [ - { - "id": "add1e0ce-43a9-457a-b7ba-8ddd71acff41", - "color": "green", - "label": "As Participant and Organizer", - "value": "AS_PARTICIPANT_AND_ORGANIZER", - "position": 0 - }, - { - "id": "93ef8799-ed7b-42f8-a4a4-b878c9599108", - "color": "orange", - "label": "As Participant", - "value": "AS_PARTICIPANT", - "position": 1 - }, - { - "id": "a94610a1-429d-449e-ae0b-67eaba058ef8", - "color": "blue", - "label": "As Organizer", - "value": "AS_ORGANIZER", - "position": 2 - }, - { - "id": "ca729343-a09c-486b-a240-5d80e7e076eb", - "color": "red", - "label": "None", - "value": "NONE", - "position": 3 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "c31280e5-0ed4-49e3-8f52-0d301698db1d", - "type": "TEXT", - "name": "syncCursor", - "label": "Sync Cursor", - "description": "Sync Cursor. Used for syncing events from the calendar provider", - "icon": "IconReload", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants", - "labelSingular": "Message Participant", - "labelPlural": "Message Participants", - "description": "Message Participants", - "icon": "IconUserCircle", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "3a3ffcd3-9a78-4eed-ae5b-6838156857fe", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEx" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "90e73039-1ac8-4d7c-9d65-301373ade28b", - "type": "TEXT", - "name": "displayName", - "label": "Display Name", - "description": "Display Name", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5b46d192-34b1-4122-801c-7b6f74b49743", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "5353cebc-8357-49bd-bcf2-292409d637ba", - "type": "UUID", - "name": "workspaceMemberId", - "label": "Workspace Member id (foreign key)", - "description": "Workspace member id foreign key", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "bc788a8f-8eb2-47bf-a02c-42f7de197ca8", - "type": "RELATION", - "name": "workspaceMember", - "label": "Workspace Member", - "description": "Workspace member", - "icon": "IconCircleUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "7d3faf56-e4bb-45ec-9b75-612ca6e9ae5a", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "bc788a8f-8eb2-47bf-a02c-42f7de197ca8", - "name": "workspaceMember" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "c00ccd93-ebc7-4744-8cb3-797a752b4627", - "name": "messageParticipants" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "7d3faf56-e4bb-45ec-9b75-612ca6e9ae5a", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "c00ccd93-ebc7-4744-8cb3-797a752b4627", - "fromObjectMetadata": { - "__typename": "object", - "id": "b87720c6-bead-46a9-8c1e-c8596bdb702e", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "workspaceMember", - "namePlural": "workspaceMembers", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f897f356-ea94-4bd4-869a-4c138e57704e", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3a3ffcd3-9a78-4eed-ae5b-6838156857fe", - "type": "TEXT", - "name": "handle", - "label": "Handle", - "description": "Handle", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "728a4a3f-1145-48cb-804e-b790fdf1c0f4", - "type": "UUID", - "name": "personId", - "label": "Person id (foreign key)", - "description": "Person id foreign key", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "52b01517-9ac7-48d9-a292-b969197a33f5", - "type": "UUID", - "name": "messageId", - "label": "Message id (foreign key)", - "description": "Message id foreign key", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "660b4257-010e-4039-897a-e274f2559ed5", - "type": "RELATION", - "name": "message", - "label": "Message", - "description": "Message", - "icon": "IconMessage", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "2180d888-98dc-428e-a157-c30ce7bf8ce4", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "660b4257-010e-4039-897a-e274f2559ed5", - "name": "message" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "nameSingular": "message", - "namePlural": "messages" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "15658254-6562-4fad-9ef3-393f913e95c2", - "name": "messageParticipants" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "2180d888-98dc-428e-a157-c30ce7bf8ce4", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "15658254-6562-4fad-9ef3-393f913e95c2", - "fromObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "message", - "namePlural": "messages", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "362195e4-4dfb-49e1-b25b-fe3ffe7b7f14", - "type": "RELATION", - "name": "person", - "label": "Person", - "description": "Person", - "icon": "IconUser", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "5bb99199-6a3c-4947-b16b-6a90c6097eac", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0c0a3db9-f3ba-485a-8dff-488c477f3fa6", - "nameSingular": "messageParticipant", - "namePlural": "messageParticipants" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "362195e4-4dfb-49e1-b25b-fe3ffe7b7f14", - "name": "person" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "nameSingular": "person", - "namePlural": "people" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "19f77ace-4b00-4fac-ba7d-8c7a3dde409b", - "name": "messageParticipants" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "5bb99199-6a3c-4947-b16b-6a90c6097eac", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "19f77ace-4b00-4fac-ba7d-8c7a3dde409b", - "fromObjectMetadata": { - "__typename": "object", - "id": "aeffaa4e-cae1-4dd8-b76e-5658eb73d0a9", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "person", - "namePlural": "people", - "isSystem": false, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6dec8f79-0674-48e8-9b01-74585880e8a2", - "type": "SELECT", - "name": "role", - "label": "Role", - "description": "Role", - "icon": "IconAt", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "'from'", - "options": [ - { - "id": "f105c9e6-9a17-4cb0-bede-fd7dc67cdeb7", - "color": "green", - "label": "From", - "value": "from", - "position": 0 - }, - { - "id": "a8fa2086-b0bd-48cf-914d-247be3fef5fd", - "color": "blue", - "label": "To", - "value": "to", - "position": 1 - }, - { - "id": "2b763815-9fc7-4b47-a364-f6cb639ef609", - "color": "orange", - "label": "Cc", - "value": "cc", - "position": 2 - }, - { - "id": "23b26d79-b074-44d1-a910-25ecb3ff808a", - "color": "red", - "label": "Bcc", - "value": "bcc", - "position": 3 - } - ], - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "66a43663-68e0-404d-9e36-63be0bd5e406", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - }, - { - "__typename": "objectEdge", - "node": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations", - "labelSingular": "Message Channel Message Association", - "labelPlural": "Message Channel Message Associations", - "description": "Message Synced with a Message Channel", - "icon": "IconMessage", - "isCustom": false, - "isRemote": false, - "isActive": true, - "isSystem": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "labelIdentifierFieldMetadataId": "6cb4b092-b140-4f6c-97d6-0f7f7d3ae6f7", - "imageIdentifierFieldMetadataId": null, - "fields": { - "__typename": "ObjectFieldsConnection", - "pageInfo": { - "__typename": "PageInfo", - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "YXJyYXljb25uZWN0aW9uOjA=", - "endCursor": "YXJyYXljb25uZWN0aW9uOjEw" - }, - "edges": [ - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7f9297fa-ca06-4da9-9a6c-83028f25ba88", - "type": "UUID", - "name": "messageId", - "label": "Message Id id (foreign key)", - "description": "Message Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "9810950a-952a-412b-a590-be91bbb7efcd", - "type": "TEXT", - "name": "messageExternalId", - "label": "Message External Id", - "description": "Message id from the messaging provider", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6d269e30-23a1-4963-8c78-4bdf7108875c", - "type": "UUID", - "name": "messageChannelId", - "label": "Message Channel Id id (foreign key)", - "description": "Message Channel Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "f2b8af0c-5143-4715-b0ef-0ecf06874fa7", - "type": "TEXT", - "name": "messageThreadExternalId", - "label": "Thread External Id", - "description": "Thread id from the messaging provider", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "''", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "3f3c11b1-b1b5-4831-9a4e-963317c8c9a5", - "type": "DATE_TIME", - "name": "createdAt", - "label": "Creation date", - "description": "Creation date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "785c0609-42b8-4b0e-b7c2-4d54b6ed651f", - "type": "RELATION", - "name": "message", - "label": "Message Id", - "description": "Message Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "642b4d8c-f2f8-4590-abce-4b112d8689ba", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "785c0609-42b8-4b0e-b7c2-4d54b6ed651f", - "name": "message" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "nameSingular": "message", - "namePlural": "messages" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "2ac789bf-ce05-4f0e-9f04-f848f93c2f21", - "name": "messageChannelMessageAssociations" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "642b4d8c-f2f8-4590-abce-4b112d8689ba", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "2ac789bf-ce05-4f0e-9f04-f848f93c2f21", - "fromObjectMetadata": { - "__typename": "object", - "id": "dfdcf91e-f4b4-4460-8c89-919ef501fd79", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "message", - "namePlural": "messages", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "34479a8f-e7a4-4069-9f05-08d09113c8dc", - "type": "RELATION", - "name": "messageChannel", - "label": "Message Channel Id", - "description": "Message Channel Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "40e51c6c-0268-47ca-bab9-4a899391e74b", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "34479a8f-e7a4-4069-9f05-08d09113c8dc", - "name": "messageChannel" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "nameSingular": "messageChannel", - "namePlural": "messageChannels" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "bdd7ff46-118c-44e7-9b2e-cd522a248a8a", - "name": "messageChannelMessageAssociations" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "40e51c6c-0268-47ca-bab9-4a899391e74b", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "bdd7ff46-118c-44e7-9b2e-cd522a248a8a", - "fromObjectMetadata": { - "__typename": "object", - "id": "311ea123-5b30-4637-ae39-3e639e780c83", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageChannel", - "namePlural": "messageChannels", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "6cb4b092-b140-4f6c-97d6-0f7f7d3ae6f7", - "type": "UUID", - "name": "id", - "label": "Id", - "description": "Id", - "icon": "Icon123", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "uuid", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "7d037a16-39b4-45ef-b06e-a8b99151d223", - "type": "UUID", - "name": "messageThreadId", - "label": "Message Thread Id id (foreign key)", - "description": "Message Thread Id id foreign key", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "fcbef4a3-f1d9-4714-b7ea-f44816821d6e", - "type": "RELATION", - "name": "messageThread", - "label": "Message Thread Id", - "description": "Message Thread Id", - "icon": "IconHash", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": true, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": null, - "options": null, - "fromRelationMetadata": null, - "relationDefinition": { - "__typename": "RelationDefinition", - "relationId": "1d8cbabc-edf5-40c9-8bd5-d1e47a93d246", - "direction": "MANY_TO_ONE", - "sourceObjectMetadata": { - "__typename": "object", - "id": "0985d46f-722d-468f-9fa6-efa219405aa7", - "nameSingular": "messageChannelMessageAssociation", - "namePlural": "messageChannelMessageAssociations" - }, - "sourceFieldMetadata": { - "__typename": "field", - "id": "fcbef4a3-f1d9-4714-b7ea-f44816821d6e", - "name": "messageThread" - }, - "targetObjectMetadata": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "nameSingular": "messageThread", - "namePlural": "messageThreads" - }, - "targetFieldMetadata": { - "__typename": "field", - "id": "25bbf51f-17fa-4a2c-9636-3f3fdba41e08", - "name": "messageChannelMessageAssociations" - } - }, - "toRelationMetadata": { - "__typename": "relation", - "id": "1d8cbabc-edf5-40c9-8bd5-d1e47a93d246", - "relationType": "ONE_TO_MANY", - "fromFieldMetadataId": "25bbf51f-17fa-4a2c-9636-3f3fdba41e08", - "fromObjectMetadata": { - "__typename": "object", - "id": "1f73c3c3-a356-4a70-8a91-948e70120fdf", - "dataSourceId": "8b919f4b-aef5-40ba-aeeb-3f29b90e765f", - "nameSingular": "messageThread", - "namePlural": "messageThreads", - "isSystem": true, - "isRemote": false - } - } - } - }, - { - "__typename": "fieldEdge", - "node": { - "__typename": "field", - "id": "a00f2265-a78a-4b12-9367-e034da304ac6", - "type": "DATE_TIME", - "name": "updatedAt", - "label": "Update date", - "description": "Update date", - "icon": "IconCalendar", - "isCustom": false, - "isActive": true, - "isSystem": true, - "isNullable": false, - "createdAt": "2024-08-02T16:00:05.938Z", - "updatedAt": "2024-08-02T16:00:05.938Z", - "defaultValue": "now", - "options": null, - "relationDefinition": null, - "fromRelationMetadata": null, - "toRelationMetadata": null - } - } - ] - } - } - } - ] -} - -} as ObjectMetadataItemsQuery; - diff --git a/packages/twenty-front/src/testing/mock-data/metadata.ts b/packages/twenty-front/src/testing/mock-data/metadata.ts index c86d17d47afb..f739afd46647 100644 --- a/packages/twenty-front/src/testing/mock-data/metadata.ts +++ b/packages/twenty-front/src/testing/mock-data/metadata.ts @@ -5,7 +5,7 @@ import { ObjectEdge, ObjectMetadataItemsQuery, } from '~/generated-metadata/graphql'; -import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/standard-metadata-query-result'; +import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/mock-metadata-query-result'; // TODO: replace with new mock const customObjectMetadataItemEdge: ObjectEdge = { @@ -83,22 +83,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { name: 'myCustom', }, }, - toRelationMetadata: null, - fromRelationMetadata: { - __typename: 'relation', - id: 'c5cdbacd-2489-4409-be9e-bb4cb38f6ddd', - relationType: 'ONE_TO_MANY', - toFieldMetadataId: 'c9607ed7-168d-4743-a56a-689ffcfffe98', - toObjectMetadata: { - __typename: 'object', - id: 'dba899da-7d88-41ac-b70e-5ea612ab4b2e', - dataSourceId: 'd36e6a2d-28bc-459d-afd5-fe18e4405729', - nameSingular: 'viewField', - namePlural: 'viewFields', - isSystem: true, - isRemote: false, - }, - }, }, }, { @@ -120,8 +104,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: null, relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, { @@ -143,8 +125,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: null, relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, { @@ -166,8 +146,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: "''", relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, { @@ -189,8 +167,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: 'now', relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, { @@ -212,8 +188,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: 'now', relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, { @@ -235,8 +209,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: 'uuid', relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, { @@ -277,8 +249,6 @@ const customObjectMetadataItemEdge: ObjectEdge = { updatedAt: '2024-04-08T12:48:49.538Z', defaultValue: null, relationDefinition: null, - fromRelationMetadata: null, - toRelationMetadata: null, }, }, ], diff --git a/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts b/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts index a728493428ca..63631396de02 100644 --- a/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts +++ b/packages/twenty-front/src/testing/mock-data/objectMetadataItems.ts @@ -1,5 +1,5 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; -import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/standard-metadata-query-result'; +import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/mock-metadata-query-result'; export const generatedMockObjectMetadataItems: ObjectMetadataItem[] = mockedStandardObjectMetadataQueryResult.objects.edges.map((edge) => ({ diff --git a/packages/twenty-front/src/testing/mock-data/people.ts b/packages/twenty-front/src/testing/mock-data/people.ts index 98dfa085d0a7..9139aa194367 100644 --- a/packages/twenty-front/src/testing/mock-data/people.ts +++ b/packages/twenty-front/src/testing/mock-data/people.ts @@ -12,6 +12,7 @@ export const mockedEmptyPersonData = { lastName: '', phone: null, email: null, + city: null, createdBy: null, displayName: null, avatarUrl: null, @@ -43,7 +44,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:52:46.814Z', - phone: '', + city: 'ASd', + phones: { + primaryPhoneNumber: '781234562', + primaryPhoneCountryCode: '+33', + }, id: 'da3c2c4b-da01-4b81-9734-226069eb4cd0', jobTitle: '', position: 0, @@ -169,7 +174,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-01T09:50:00.000Z', - phone: '+33789012345', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781234562', + primaryPhoneCountryCode: '+33', + }, id: '20202020-1c0e-494c-a1b6-85b1c6fefaa5', jobTitle: '', position: 1, @@ -295,7 +304,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33780123456', + city: 'Los Angeles', + phones: { + primaryPhoneNumber: '781234576', + primaryPhoneCountryCode: '+33', + }, id: '20202020-ac73-4797-824e-87a1f5aea9e0', jobTitle: '', position: 2, @@ -390,7 +403,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33789012345', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781234545', + primaryPhoneCountryCode: '+33', + }, id: '20202020-f517-42fd-80ae-14173b3b70ae', jobTitle: '', position: 3, @@ -485,7 +502,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33780123456', + city: 'Los Angeles', + phones: { + primaryPhoneNumber: '781234587', + primaryPhoneCountryCode: '+33', + }, id: '20202020-eee1-4690-ad2c-8619e5b56a2e', jobTitle: '', position: 4, @@ -580,7 +601,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33781234567', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781234599', + primaryPhoneCountryCode: '+33', + }, id: '20202020-6784-4449-afdf-dc62cb8702f2', jobTitle: '', position: 5, @@ -675,7 +700,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33782345678', + city: 'New York', + phones: { + primaryPhoneNumber: '781234572', + primaryPhoneCountryCode: '+33', + }, id: '20202020-490f-4466-8391-733cfd66a0c8', jobTitle: '', position: 6, @@ -770,7 +799,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33783456789', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781234582', + primaryPhoneCountryCode: '+33', + }, id: '20202020-80f1-4dff-b570-a74942528de3', jobTitle: '', position: 7, @@ -865,7 +898,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33784567890', + city: 'New York', + phones: { + primaryPhoneNumber: '781234569', + primaryPhoneCountryCode: '+33', + }, id: '20202020-338b-46df-8811-fa08c7d19d35', jobTitle: '', position: 8, @@ -960,7 +997,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33785678901', + city: 'San Francisco', + phones: { + primaryPhoneNumber: '781234962', + primaryPhoneCountryCode: '+33', + }, id: '20202020-64ad-4b0e-bbfd-e9fd795b7016', jobTitle: '', position: 9, @@ -1055,7 +1096,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33786789012', + city: 'New York', + phones: { + primaryPhoneNumber: '781234502', + primaryPhoneCountryCode: '+33', + }, id: '20202020-5d54-41b7-ba36-f0d20e1417ae', jobTitle: '', position: 10, @@ -1150,7 +1195,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33787890123', + city: 'Los Angeles', + phones: { + primaryPhoneNumber: '781234563', + primaryPhoneCountryCode: '+33', + }, id: '20202020-623d-41fe-92e7-dd45b7c568e1', jobTitle: '', position: 11, @@ -1245,7 +1294,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33788901234', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781234542', + primaryPhoneCountryCode: '+33', + }, id: '20202020-2d40-4e49-8df4-9c6a049190ef', jobTitle: '', position: 12, @@ -1340,7 +1393,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33788901234', + city: 'Seattle', + phones: { + primaryPhoneNumber: '782234562', + primaryPhoneCountryCode: '+33', + }, id: '20202020-2d40-4e49-8df4-9c6a049190df', jobTitle: '', position: 13, @@ -1435,7 +1492,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33788901234', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781274562', + primaryPhoneCountryCode: '+33', + }, id: '20202020-2d40-4e49-8df4-9c6a049191de', jobTitle: '', position: 14, @@ -1530,7 +1591,11 @@ export const peopleQueryResult: { people: RecordGqlConnection } = { node: { __typename: 'Person', createdAt: '2024-08-02T09:48:36.193Z', - phone: '+33788901235', + city: 'Seattle', + phones: { + primaryPhoneNumber: '781239562', + primaryPhoneCountryCode: '+33', + }, id: '20202020-2d40-4e49-8df4-9c6a049191df', jobTitle: '', position: 15, diff --git a/packages/twenty-front/src/testing/mock-data/timeline-activities.ts b/packages/twenty-front/src/testing/mock-data/timeline-activities.ts index 5051ea8076c8..971ab159737c 100644 --- a/packages/twenty-front/src/testing/mock-data/timeline-activities.ts +++ b/packages/twenty-front/src/testing/mock-data/timeline-activities.ts @@ -58,7 +58,7 @@ export const mockedTimelineActivities: Array<TimelineActivity> = [ linkedObjectMetadataId: '1ad72a42-6ab4-4474-a62a-a57cae3c0298', linkedRecordCachedName: 'New Task', linkedRecordId: 'ce40eca0-8f4b-4bba-ba91-5cbd870c64d2', - name: 'task.created', + name: 'linked-task.created', createdAt: '2023-04-26T10:12:42.33625+00:00', workspaceMember: { __typename: 'WorkspaceMember', diff --git a/packages/twenty-front/src/testing/mock-data/view-fields.ts b/packages/twenty-front/src/testing/mock-data/view-fields.ts index f8af8db65787..b68cfb706a27 100644 --- a/packages/twenty-front/src/testing/mock-data/view-fields.ts +++ b/packages/twenty-front/src/testing/mock-data/view-fields.ts @@ -4,7 +4,7 @@ export const mockedViewFieldsData = [ // Companies { id: '79035310-e955-4986-a4a4-73f9d9949c6a', - fieldMetadataId: 'name', + fieldMetadataId: '9e123592-cd2b-471c-8143-3cc0b46089ef', viewId: mockedViewsData[0].id, position: 0, isVisible: true, diff --git a/packages/twenty-front/src/testing/mock-data/views.ts b/packages/twenty-front/src/testing/mock-data/views.ts index f924a9fccd7b..d13c0dc3fdfb 100644 --- a/packages/twenty-front/src/testing/mock-data/views.ts +++ b/packages/twenty-front/src/testing/mock-data/views.ts @@ -807,7 +807,7 @@ export const mockedViewsData = [ { id: '37a8a866-eb17-4e76-9382-03143a2f6a80', name: 'All companies', - objectMetadataId: 'f9fd99a8-108f-4066-9675-cde753cf5de9', + objectMetadataId: '701aecf9-eb1c-4d84-9d94-b954b231b64b', type: 'table', icon: 'IconSkyline', key: 'INDEX', @@ -850,7 +850,7 @@ export const mockedViewsData = [ { id: '5c307222-1dd5-4ff3-ab06-8d990e9b3c74', name: 'All companies (v2)', - objectMetadataId: 'f9fd99a8-108f-4066-9675-cde753cf5de9', + objectMetadataId: '701aecf9-eb1c-4d84-9d94-b954b231b64b', type: 'table', icon: 'IconSkyline', key: 'INDEX', diff --git a/packages/twenty-front/src/utils/createRootPropsContext.ts b/packages/twenty-front/src/utils/createRootPropsContext.ts new file mode 100644 index 000000000000..9ace2a67ede2 --- /dev/null +++ b/packages/twenty-front/src/utils/createRootPropsContext.ts @@ -0,0 +1,11 @@ +import { Context, createContext } from 'react'; + +type RootProps = Record<string, any>; + +export type RootPropsContext<T extends RootProps> = T extends RootProps + ? T + : never; + +export const createRootPropsContext = <T extends RootProps>(): Context< + RootPropsContext<T> +> => createContext<RootPropsContext<T>>({} as RootPropsContext<T>); diff --git a/packages/twenty-front/src/utils/format/spiltFullName.ts b/packages/twenty-front/src/utils/format/spiltFullName.ts new file mode 100644 index 000000000000..6ec1ac2d8ca8 --- /dev/null +++ b/packages/twenty-front/src/utils/format/spiltFullName.ts @@ -0,0 +1,13 @@ +export const splitFullName = (name: string) => { + const splittedName = name.trim().split(/\s+/); + + if (splittedName.length === 2) { + return splittedName; + } + + if (splittedName.length > 2) { + return [splittedName[0].trim(), splittedName[1].trim()]; + } + + return [name.trim(), '']; +}; diff --git a/packages/twenty-front/src/utils/getDisplayValueByUrlType.ts b/packages/twenty-front/src/utils/getDisplayValueByUrlType.ts index 75cf16fa197d..5e5087d5c0ba 100644 --- a/packages/twenty-front/src/utils/getDisplayValueByUrlType.ts +++ b/packages/twenty-front/src/utils/getDisplayValueByUrlType.ts @@ -16,7 +16,7 @@ export const getDisplayValueByUrlType = ({ /(?:https?:\/\/)?(?:www.)?linkedin.com\/(?:in|company|school)\/(.*)/, ); if (isDefined(matches?.[1])) { - return matches?.[1]; + return decodeURIComponent(matches?.[1]); } else { return 'LinkedIn'; } diff --git a/packages/twenty-front/src/utils/string/turnIntoEmptyStringIfWhitespacesOnly.ts b/packages/twenty-front/src/utils/string/turnIntoEmptyStringIfWhitespacesOnly.ts new file mode 100644 index 000000000000..ba480c345baf --- /dev/null +++ b/packages/twenty-front/src/utils/string/turnIntoEmptyStringIfWhitespacesOnly.ts @@ -0,0 +1,3 @@ +export const turnIntoEmptyStringIfWhitespacesOnly = (value: string): string => { + return value.trim().length > 0 ? value : ''; +}; diff --git a/packages/twenty-front/src/utils/string/turnIntoUndefinedIfWhitespacesOnly.ts b/packages/twenty-front/src/utils/string/turnIntoUndefinedIfWhitespacesOnly.ts new file mode 100644 index 000000000000..1f2d257a5917 --- /dev/null +++ b/packages/twenty-front/src/utils/string/turnIntoUndefinedIfWhitespacesOnly.ts @@ -0,0 +1,5 @@ +export const turnIntoUndefinedIfWhitespacesOnly = ( + value: string, +): string | undefined => { + return value.trim() === '' ? undefined : value.trim(); +}; diff --git a/packages/twenty-front/src/utils/url/__tests__/isValidUrl.test.ts b/packages/twenty-front/src/utils/url/__tests__/isValidUrl.test.ts new file mode 100644 index 000000000000..6279a9bba746 --- /dev/null +++ b/packages/twenty-front/src/utils/url/__tests__/isValidUrl.test.ts @@ -0,0 +1,25 @@ +import { isValidUrl } from '../isValidUrl'; + +describe('isValidUrl', () => { + it('test cases', () => { + // Truthy + expect(isValidUrl('https://www.example.com')).toBe(true); + expect(isValidUrl('http://192.168.2.0:3000')).toBe(true); + expect(isValidUrl('http://localhost')).toBe(true); + expect(isValidUrl('http://localhost:3000')).toBe(true); + expect(isValidUrl('http://subdomain.example.com')).toBe(true); + expect(isValidUrl('https://www.example.com/path')).toBe(true); + expect(isValidUrl('https://www.example.com/path/path2?query=123')).toBe( + true, + ); + expect(isValidUrl('http://localhost:3000')).toBe(true); + expect(isValidUrl('example.com')).toBe(true); + expect(isValidUrl('www.subdomain.example.com')).toBe(true); + + // Falsy + expect(isValidUrl('?o')).toBe(false); + expect(isValidUrl('')).toBe(false); + expect(isValidUrl('\\')).toBe(false); + expect(isValidUrl('wwwexamplecom')).toBe(false); + }); +}); diff --git a/packages/twenty-front/src/utils/url/isValidUrl.ts b/packages/twenty-front/src/utils/url/isValidUrl.ts new file mode 100644 index 000000000000..195e445aa10d --- /dev/null +++ b/packages/twenty-front/src/utils/url/isValidUrl.ts @@ -0,0 +1,8 @@ +export const isValidUrl = (url: string) => { + const urlRegex = + /^(https?:\/\/)?((([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(localhost))(:\d+)?(\/[^\s]*)?(\?[^\s]*)?$/; + + const urlPattern = new RegExp(urlRegex, 'i'); + + return !!urlPattern.test(url); +}; diff --git a/packages/twenty-front/tsconfig.json b/packages/twenty-front/tsconfig.json index ec14700eb407..48b5bf3817a8 100644 --- a/packages/twenty-front/tsconfig.json +++ b/packages/twenty-front/tsconfig.json @@ -28,7 +28,6 @@ } }, "files": [], - "exclude": ["**/object-metadata/utils/getObjectMetadataItemsMock.ts"], "include": [], "references": [ { diff --git a/packages/twenty-front/vite.config.ts b/packages/twenty-front/vite.config.ts index 4daf48a283e3..282f9d6dd202 100644 --- a/packages/twenty-front/vite.config.ts +++ b/packages/twenty-front/vite.config.ts @@ -30,19 +30,16 @@ export default defineConfig(({ command, mode }) => { }; if (VITE_DISABLE_TYPESCRIPT_CHECKER === 'true') { - // eslint-disable-next-line no-console console.log( `VITE_DISABLE_TYPESCRIPT_CHECKER: ${VITE_DISABLE_TYPESCRIPT_CHECKER}`, ); } if (VITE_DISABLE_ESLINT_CHECKER === 'true') { - // eslint-disable-next-line no-console console.log(`VITE_DISABLE_ESLINT_CHECKER: ${VITE_DISABLE_ESLINT_CHECKER}`); } if (VITE_BUILD_SOURCEMAP === 'true') { - // eslint-disable-next-line no-console console.log(`VITE_BUILD_SOURCEMAP: ${VITE_BUILD_SOURCEMAP}`); } @@ -130,5 +127,10 @@ export default defineConfig(({ command, mode }) => { localsConvention: 'camelCaseOnly', }, }, + resolve: { + alias: { + path: 'rollup-plugin-node-polyfills/polyfills/path', + }, + }, }; }); diff --git a/packages/twenty-postgres/linux/provision-postgres-linux.sh b/packages/twenty-postgres/linux/provision-postgres-linux.sh index 620d3e887fee..0652e3bda34e 100755 --- a/packages/twenty-postgres/linux/provision-postgres-linux.sh +++ b/packages/twenty-postgres/linux/provision-postgres-linux.sh @@ -20,6 +20,12 @@ handle_error () { exit 1 } +read -p "This script uses sudo to install postgresql, curl and change different settings, do you want to run this script? [y/N]" AGREEMENT + +if ! echo "$AGREEMENT" | grep -iq "^y"; then + exit 1 +fi + cat << "EOF" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@#*+=================@@@@@%*+=========++*%@@@@@@@ @@ -56,7 +62,7 @@ echo_header $GREEN "Step [1/4]: Installing PostgreSQL..." sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/trusted.gpg.d/pgdg.asc &>/dev/null sudo apt update -y || handle_error "Failed to update package list." -sudo apt install -y postgresql-$PG_MAIN_VERSION postgresql-contrib-$PG_MAIN_VERSION || handle_error "Failed to install PostgreSQL."su +sudo apt install -y postgresql-$PG_MAIN_VERSION postgresql-contrib-$PG_MAIN_VERSION || handle_error "Failed to install PostgreSQL." sudo apt install -y curl || handle_error "Failed to install curl." # Install pg_graphql extensions diff --git a/packages/twenty-server/.env.example b/packages/twenty-server/.env.example index 2724fb7c4c71..6f8167d6b869 100644 --- a/packages/twenty-server/.env.example +++ b/packages/twenty-server/.env.example @@ -52,6 +52,8 @@ SIGN_IN_PREFILLED=true # MESSAGE_QUEUE_TYPE=pg-boss # REDIS_HOST=127.0.0.1 # REDIS_PORT=6379 +# REDIS_USERNAME= +# REDIS_PASSWORD= # DEMO_WORKSPACE_IDS=REPLACE_ME_WITH_A_RANDOM_UUID # SERVER_URL=http://localhost:3000 # WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION=30 diff --git a/packages/twenty-server/.env.test b/packages/twenty-server/.env.test index fc51ab9e1e22..ed0c63d78337 100644 --- a/packages/twenty-server/.env.test +++ b/packages/twenty-server/.env.test @@ -1,26 +1,26 @@ -DEBUG_MODE=true -PG_DATABASE_URL=postgres://twenty:twenty@localhost:5432/test?connection_limit=1 -# Use this for docker setup -# PG_DATABASE_URL=postgres://twenty:twenty@postgres:5432/default?connection_limit=1 +PG_DATABASE_URL=postgres://twenty:twenty@localhost:5432/test -# the URL of the front-end app +DEBUG_MODE=true +DEBUG_PORT=9000 FRONT_BASE_URL=http://localhost:3001 -# random keys used to generate JWT tokens -ACCESS_TOKEN_SECRET=secret_jwt -LOGIN_TOKEN_SECRET=secret_login_tokens -REFRESH_TOKEN_SECRET=secret_refresh_token -FILE_TOKEN_SECRET=secret_file_token +ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access +LOGIN_TOKEN_SECRET=replace_me_with_a_random_string_login +REFRESH_TOKEN_SECRET=replace_me_with_a_random_string_refresh +SIGN_IN_PREFILLED=true +EXCEPTION_HANDLER_DRIVER=console +SENTRY_DSN=https://ba869cb8fd72d5faeb6643560939cee0@o4505516959793152.ingest.sentry.io/4506660900306944 +DEMO_WORKSPACE_IDS=63db4589-590f-42b3-bdf1-85268b3da02f,8de58f3f-7e86-4a0b-998d-b2cbe314ee3a,4d957b72-0b37-4bad-9468-8dc828ee082d,daa0b739-269e-49b6-9be5-5f0215941489,59c15f6a-909a-4495-9cf4-3ce1b0abbb6a,7202cc9d-92da-4b52-a323-d29d38cd3b4e,5f071b0d-646b-411a-94f1-5d9ba9d5c6ac,7bc10973-897b-4767-ab2f-35cdac3b2aec,4b3ba0be-2d29-4b1e-be66-8ac7eb65d000,edfb500d-cc4e-4f22-8e2b-f139a9758a68,eee459c9-9057-4459-ae0d-d51d14c01635,3dd2f505-0075-4217-ba33-fc4244aeaaa9,3d1a9165-3f3f-494e-a99d-f858eae95144,84db6ded-cfce-4aee-9160-6553b05c8143,96fb1540-269b-4d13-af21-2a8268eff8ca,b2463e69-d121-4ea5-80c9-bba82403e93e,5af30c15-867d-49ed-b939-d4856bed8514,b5677aa1-68fa-4818-aaaa-434a07ae2ed4,1ec7fa9a-d6bf-4fa2-a753-9a235d75ee3f,753a6fa2-df27-4c87-8c90-4da78fcb30dd,2138f2f2-bbe9-41df-b483-687a9075f94e,a885cfef-4636-4c3a-9788-1ff6e6b92df5,5458f7fb-9431-47a2-b7a0-32f31d115e23,6c09929f-11c3-4f92-9508-aa0e6b934d1e,57ae0a2c-7a4e-4c7d-8f43-68548e7f1206,cc7f0b85-6868-4c2d-85c5-3ce9977ea346,21871a7f-f067-45ea-989e-44339bb5ad07,c3efedab-84f5-4656-8297-55964b3d26cb,647dcdd1-4540-4003-9f58-fd84d4d759b7,fc5e6857-8d67-47b8-98f2-edeb0671e326,1ad8d72c-1826-40ed-8b44-d15a1d2aab70,eac6c90a-d25d-4c8c-a053-cfbc7cde0afb,023a70de-a85e-43fc-bbc6-757fbf6562f0,f3f0a7fb-1409-443b-8e39-4e58e628796e,62828804-97d4-40ec-82fa-2992a6ce4a81,af5441fe-b16f-4996-87f4-1a433ec53dd6,e8857860-f7b1-4478-9741-1eb9e7c11f2c,6bca9c44-c8c0-49f8-b0b5-1bb2ca7842b8,d50da092-09df-448f-84ea-3ebddfe1d9f6,9efd5d6d-db64-47d4-9ad3-5e4d8b65ff7f,6f089094-2dd2-4b0e-b5b7-8bb52b93ea8e,299b0822-68e9-4bfa-af35-da799012e80e,a3dd579c-93be-45a0-ad35-f518d8ed45dd,023b1b3e-4891-4061-aae0-f34368644f40,50174445-33c5-4482-bb8c-3ef6c511c8cd,9933c048-07a7-4735-9af2-940c2f9b6683,beadc568-3962-46bd-ad4d-06e23b37615b,0cdafc9f-d4c1-4576-837e-d7f6ec28643d,50bb24ce-1709-4928-a87b-d9d9e147a2ab,7690ed72-910d-4357-8e0e-17aa702b0b94,1ad0d69f-60fa-414f-bf79-4f94c2abba43,946d84a4-db4d-48cb-a5d3-03081b5c7e8e,1a080055-d2bf-4b14-8957-88a7d08769b8,ed343e38-e405-4fae-9486-27b09c98bdad,c8bdef75-a98c-4646-a372-3251340d2dea,87a8c6fa-f93e-4950-aff2-5f956ca1a6ba,604781ba-23c2-4220-a717-b5615431fcd9,31af6841-ad9f-4f28-a637-b5c5e6589447,cf067451-7b88-4ff2-a96d-3fc9c5d6fea0,26a8ad5e-29d9-4e7d-aa1f-e6221e8ea32a,fd14db29-e4df-44a7-9b3f-d00384458122,73b477a8-fcf4-4860-a685-65a0a79b8653,82e0f305-4c6c-4160-be1d-b0de834124e6,e38567ab-a6e2-4a94-99c5-a7db31c0aae8,faf3d6dc-66ff-4c1b-9658-f65a9cd9fcf1,6df6bb90-200e-4290-b73d-9bb374554229,2ff10cf4-a871-404a-9e7b-5ca7a232567e,06c614e2-0f36-4b72-8c82-59631680add2,5e508c81-3453-4185-ae8c-4c9b841f8c15,21b5c371-6010-4b1b-be67-7538eb877efb,54e61442-e291-4eea-8d49-7f11b5f85bd2,b6b7260a-4eea-40b0-9f7f-1dfd4c3cc7a8,e163fe76-30fb-44fb-b51a-50cc78745a21,4da672f2-29b4-4a98-b27c-b39a4aecc858,2fdb0601-c882-4aaf-ad49-ae17e530d47a,49525e1b-1b47-4545-a98c-0ba58778179f,f958ab32-b152-4004-9228-18148f7380f1,0ff5025a-62cd-4a10-a722-79f7cf360f01,642df445-e314-409a-a97d-64fc2aa2a15e,38b0dab5-d4fb-44f9-8cf9-bb35cf82e91d,62054133-f35a-4f64-a2ee-a31e48952835,536dbe8c-af33-4eab-a0a8-8d039a00db40,a04998ba-52c9-4538-b6d9-6d04408dbaf2,89016c7a-3d36-4619-a5c6-4f31795eebf7,7708b9a9-776c-46fc-94a4-dc28e7880958,5c92bc69-b328-4c66-a791-a05dbaf7a6f8,ad580a50-80b4-44be-9bc4-f2b57cd23207,36c0241c-891e-4b74-bd10-5e99df96bbc8,a96842ff-18be-4536-a23d-20d973d91621,0ea549b0-9558-4bdf-9944-5abc707c7660,0186c353-5ed2-4c94-b71a-fc0b48c90288,1508a165-2217-4911-b31c-1ea42a08f097,1731e392-dfdf-4fc4-863b-27ae62b0e374,0b245cea-96a6-4a3a-af6a-ef43496c239c,a844e208-7078-43a2-8bd0-86f31498cd3f,53d112b5-87f2-490b-a788-df1f4624f9ad,0d5794d4-3a52-482b-9a6a-f8185018bad1,df877aa6-231c-47fb-9be0-906e61677356,c56c6d1a-3418-49d2-82ce-bd9370668043,6e0b6f34-3cd0-4aa0-ae1f-25f5545dca68 +MUTATION_MAXIMUM_RECORD_AFFECTED=100 +MESSAGE_QUEUE_TYPE=pg-boss +CACHE_STORAGE_TYPE=redis +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 +REDIS_USERNAME=default +REDIS_PASSWORD= -# ———————— Optional ———————— -# DEBUG_MODE=false -# SIGN_IN_PREFILLED=false -# ACCESS_TOKEN_EXPIRES_IN=30m -# LOGIN_TOKEN_EXPIRES_IN=15m -# REFRESH_TOKEN_EXPIRES_IN=90d -# FILE_TOKEN_EXPIRES_IN=1d -# FRONT_AUTH_CALLBACK_URL=http://localhost:3001/verify -# AUTH_GOOGLE_ENABLED=false -# MESSAGING_PROVIDER_GMAIL_ENABLED=false -# STORAGE_TYPE=local -# STORAGE_LOCAL_PATH=.local-storage -# MUTATION_MAXIMUM_AFFECTED_RECORDS=100 +AUTH_GOOGLE_ENABLED=false +MESSAGING_PROVIDER_GMAIL_ENABLED=false +CALENDAR_PROVIDER_GOOGLE_ENABLED=false +AUTH_GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/redirect +AUTH_GOOGLE_APIS_CALLBACK_URL=http://localhost:3000/auth/google-apis/get-access-token +MESSAGING_PROVIDER_GMAIL_CALLBACK_URL=http://localhost:3000/auth/google-gmail/get-access-token diff --git a/packages/twenty-server/.eslintrc.cjs b/packages/twenty-server/.eslintrc.cjs index 3486687757ce..6510f3e04e1a 100644 --- a/packages/twenty-server/.eslintrc.cjs +++ b/packages/twenty-server/.eslintrc.cjs @@ -93,5 +93,11 @@ module.exports = { '@nx/workspace-inject-workspace-repository': 'warn', }, }, + { + files: ['scripts/**/*.ts'], + parserOptions: { + project: ['packages/twenty-server/tsconfig.scripts.json'], + }, + }, ], }; diff --git a/packages/twenty-server/.gitignore b/packages/twenty-server/.gitignore index 63ed409f3d41..4095299626e1 100644 --- a/packages/twenty-server/.gitignore +++ b/packages/twenty-server/.gitignore @@ -1,3 +1,4 @@ dist/* .local-storage logs/**/* +*.log diff --git a/packages/twenty-server/.idea/.gitignore b/packages/twenty-server/.idea/.gitignore new file mode 100644 index 000000000000..b58b603fea78 --- /dev/null +++ b/packages/twenty-server/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/packages/twenty-server/.idea/codeStyles/Project.xml b/packages/twenty-server/.idea/codeStyles/Project.xml new file mode 100644 index 000000000000..287878a40a64 --- /dev/null +++ b/packages/twenty-server/.idea/codeStyles/Project.xml @@ -0,0 +1,119 @@ +<component name="ProjectCodeStyleConfiguration"> + <code_scheme name="Project" version="173"> + <HTMLCodeStyleSettings> + <option name="HTML_UNIFORM_INDENT" value="true" /> + <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" /> + </HTMLCodeStyleSettings> + <JSCodeStyleSettings version="0"> + <option name="FORCE_SEMICOLON_STYLE" value="true" /> + <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> + <option name="USE_DOUBLE_QUOTES" value="false" /> + <option name="FORCE_QUOTE_STYlE" value="true" /> + <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" /> + <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" /> + <option name="SPACES_WITHIN_IMPORTS" value="true" /> + </JSCodeStyleSettings> + <JetCodeStyleSettings> + <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + </JetCodeStyleSettings> + <Objective-C> + <option name="INDENT_NAMESPACE_MEMBERS" value="0" /> + <option name="INDENT_C_STRUCT_MEMBERS" value="2" /> + <option name="INDENT_CLASS_MEMBERS" value="2" /> + <option name="INDENT_VISIBILITY_KEYWORDS" value="1" /> + <option name="INDENT_INSIDE_CODE_BLOCK" value="2" /> + <option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true" /> + <option name="KEEP_CASE_EXPRESSIONS_IN_ONE_LINE" value="true" /> + <option name="FUNCTION_NON_TOP_AFTER_RETURN_TYPE_WRAP" value="0" /> + <option name="FUNCTION_TOP_AFTER_RETURN_TYPE_WRAP" value="0" /> + <option name="FUNCTION_PARAMETERS_WRAP" value="5" /> + <option name="FUNCTION_CALL_ARGUMENTS_WRAP" value="5" /> + <option name="TEMPLATE_CALL_ARGUMENTS_WRAP" value="5" /> + <option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE" value="true" /> + <option name="CLASS_CONSTRUCTOR_INIT_LIST_WRAP" value="5" /> + <option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false" /> + <option name="SPACE_BEFORE_PROTOCOLS_BRACKETS" value="false" /> + <option name="SPACE_BEFORE_COLON_IN_FOREACH" value="true" /> + <option name="KEEP_BLANK_LINES_BEFORE_END" value="1" /> + <option name="HEADER_GUARD_STYLE_PATTERN" value="${PROJECT_NAME}_${PROJECT_REL_PATH}_${FILE_NAME}_${EXT}_" /> + </Objective-C> + <Objective-C-extensions> + <rules> + <rule entity="MACRO" visibility="ANY" specifier="ANY" prefix="" style="SCREAMING_SNAKE_CASE" suffix="" /> + <rule entity="NAMESPACE" visibility="ANY" specifier="ANY" prefix="" style="SNAKE_CASE" suffix="" /> + <rule entity="CLASS,ENUM,UNION,TYPEDEF" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" /> + <rule entity="CLASS_MEMBER_FIELD" visibility="ANY" specifier="ANY" prefix="" style="SNAKE_CASE" suffix="_" /> + <rule entity="STRUCT_MEMBER_FIELD" visibility="ANY" specifier="ANY" prefix="" style="SNAKE_CASE" suffix="" /> + <rule entity="ENUMERATOR" visibility="ANY" specifier="ANY" prefix="" style="SCREAMING_SNAKE_CASE" suffix="" /> + <rule entity="GLOBAL_FUNCTION,CLASS_MEMBER_FUNCTION,STRUCT_MEMBER_FUNCTION" visibility="ANY" specifier="ANY" prefix="" style="PASCAL_CASE" suffix="" /> + <rule entity="PARAMETER,LOCAL_VARIABLE" visibility="ANY" specifier="ANY" prefix="" style="SNAKE_CASE" suffix="" /> + <rule entity="GLOBAL_VARIABLE,LOCAL_VARIABLE" visibility="ANY" specifier="CONST" prefix="k" style="PASCAL_CASE" suffix="" /> + </rules> + </Objective-C-extensions> + <TypeScriptCodeStyleSettings version="0"> + <option name="FORCE_SEMICOLON_STYLE" value="true" /> + <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> + <option name="USE_DOUBLE_QUOTES" value="false" /> + <option name="FORCE_QUOTE_STYlE" value="true" /> + <option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" /> + <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" /> + <option name="SPACES_WITHIN_IMPORTS" value="true" /> + </TypeScriptCodeStyleSettings> + <VueCodeStyleSettings> + <option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" /> + <option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" /> + </VueCodeStyleSettings> + <codeStyleSettings language="HTML"> + <option name="SOFT_MARGINS" value="80" /> + <indentOptions> + <option name="INDENT_SIZE" value="2" /> + <option name="CONTINUATION_INDENT_SIZE" value="2" /> + <option name="TAB_SIZE" value="2" /> + <option name="KEEP_INDENTS_ON_EMPTY_LINES" value="true" /> + </indentOptions> + </codeStyleSettings> + <codeStyleSettings language="JavaScript"> + <option name="SOFT_MARGINS" value="80" /> + <indentOptions> + <option name="INDENT_SIZE" value="2" /> + <option name="CONTINUATION_INDENT_SIZE" value="2" /> + <option name="TAB_SIZE" value="2" /> + </indentOptions> + </codeStyleSettings> + <codeStyleSettings language="ObjectiveC"> + <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" /> + <option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> + <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" /> + <option name="BLANK_LINES_BEFORE_IMPORTS" value="0" /> + <option name="BLANK_LINES_AFTER_IMPORTS" value="0" /> + <option name="BLANK_LINES_AROUND_CLASS" value="0" /> + <option name="BLANK_LINES_AROUND_METHOD" value="0" /> + <option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" /> + <option name="ALIGN_MULTILINE_BINARY_OPERATION" value="false" /> + <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" /> + <option name="FOR_STATEMENT_WRAP" value="1" /> + <option name="ASSIGNMENT_WRAP" value="1" /> + <indentOptions> + <option name="INDENT_SIZE" value="2" /> + <option name="CONTINUATION_INDENT_SIZE" value="4" /> + </indentOptions> + </codeStyleSettings> + <codeStyleSettings language="TypeScript"> + <option name="SOFT_MARGINS" value="80" /> + <indentOptions> + <option name="INDENT_SIZE" value="2" /> + <option name="CONTINUATION_INDENT_SIZE" value="2" /> + <option name="TAB_SIZE" value="2" /> + </indentOptions> + </codeStyleSettings> + <codeStyleSettings language="Vue"> + <option name="SOFT_MARGINS" value="80" /> + <indentOptions> + <option name="CONTINUATION_INDENT_SIZE" value="2" /> + </indentOptions> + </codeStyleSettings> + <codeStyleSettings language="kotlin"> + <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + </codeStyleSettings> + </code_scheme> +</component> \ No newline at end of file diff --git a/packages/twenty-server/.idea/codeStyles/codeStyleConfig.xml b/packages/twenty-server/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000000..79ee123c2b23 --- /dev/null +++ b/packages/twenty-server/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ +<component name="ProjectCodeStyleConfiguration"> + <state> + <option name="USE_PER_PROJECT_SETTINGS" value="true" /> + </state> +</component> \ No newline at end of file diff --git a/packages/twenty-server/.idea/inspectionProfiles/Project_Default.xml b/packages/twenty-server/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000000..03d9549ea8e4 --- /dev/null +++ b/packages/twenty-server/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" /> + </profile> +</component> \ No newline at end of file diff --git a/packages/twenty-server/.idea/modules.xml b/packages/twenty-server/.idea/modules.xml new file mode 100644 index 000000000000..fd0aa3d57217 --- /dev/null +++ b/packages/twenty-server/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/twenty-server.iml" filepath="$PROJECT_DIR$/.idea/twenty-server.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/packages/twenty-server/.idea/twenty-server.iml b/packages/twenty-server/.idea/twenty-server.iml new file mode 100644 index 000000000000..24643cc37449 --- /dev/null +++ b/packages/twenty-server/.idea/twenty-server.iml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="WEB_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$"> + <excludeFolder url="file://$MODULE_DIR$/.tmp" /> + <excludeFolder url="file://$MODULE_DIR$/temp" /> + <excludeFolder url="file://$MODULE_DIR$/tmp" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file diff --git a/packages/twenty-server/.idea/vcs.xml b/packages/twenty-server/.idea/vcs.xml new file mode 100644 index 000000000000..b2bdec2d71b6 --- /dev/null +++ b/packages/twenty-server/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$/../.." vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/packages/twenty-server/@types/jest.d.ts b/packages/twenty-server/@types/jest.d.ts new file mode 100644 index 000000000000..225e29ff2e55 --- /dev/null +++ b/packages/twenty-server/@types/jest.d.ts @@ -0,0 +1,17 @@ +import 'jest'; + +declare module '@jest/types' { + namespace Config { + interface ConfigGlobals { + APP_PORT: number; + ACCESS_TOKEN: string; + } + } +} + +declare global { + const APP_PORT: number; + const ACCESS_TOKEN: string; +} + +export {}; diff --git a/packages/twenty-server/jest-integration.config.ts b/packages/twenty-server/jest-integration.config.ts new file mode 100644 index 000000000000..10b5cc9e2099 --- /dev/null +++ b/packages/twenty-server/jest-integration.config.ts @@ -0,0 +1,34 @@ +import { JestConfigWithTsJest, pathsToModuleNameMapper } from 'ts-jest'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const tsConfig = require('./tsconfig.json'); + +const jestConfig: JestConfigWithTsJest = { + silent: false, + verbose: true, + moduleFileExtensions: ['js', 'json', 'ts'], + rootDir: '.', + testEnvironment: 'node', + testRegex: '.integration-spec.ts$', + modulePathIgnorePatterns: ['<rootDir>/dist'], + globalSetup: '<rootDir>/test/utils/setup-test.ts', + globalTeardown: '<rootDir>/test/utils/teardown-test.ts', + testTimeout: 15000, + moduleNameMapper: { + ...pathsToModuleNameMapper(tsConfig.compilerOptions.paths), + 'twenty-emails': '<rootDir>/../twenty-emails/dist/index.js', + }, + fakeTimers: { + enableGlobally: true, + }, + transform: { + '^.+\\.(t|j)s$': 'ts-jest', + }, + globals: { + APP_PORT: 4000, + ACCESS_TOKEN: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwiaWF0IjoxNzI2NDkyNTAyLCJleHAiOjEzMjQ1MDE2NTAyfQ.zM6TbfeOqYVH5Sgryc2zf02hd9uqUOSL1-iJlMgwzsI', + }, +}; + +export default jestConfig; diff --git a/packages/twenty-server/jest.config.ts b/packages/twenty-server/jest.config.ts index 56bfdd647ee7..00c1b6f06fdb 100644 --- a/packages/twenty-server/jest.config.ts +++ b/packages/twenty-server/jest.config.ts @@ -1,22 +1,27 @@ -module.exports = { +import { JestConfigWithTsJest } from 'ts-jest'; + +const jestConfig: JestConfigWithTsJest = { // to enable logs, comment out the following line silent: true, clearMocks: true, - preset: 'ts-jest', - testEnvironment: 'node', - modulePathIgnorePatterns: ['<rootDir>/dist'], - moduleFileExtensions: ['js', 'json', 'ts'], - moduleNameMapper: { - '^src/(.*)': '<rootDir>/src/$1', - }, + displayName: 'twenty-server', rootDir: './', + testEnvironment: 'node', + transformIgnorePatterns: ['../../node_modules/'], testRegex: '.*\\.spec\\.ts$', transform: { '^.+\\.(t|j)s$': 'ts-jest', }, + moduleNameMapper: { + '^src/(.*)': '<rootDir>/src/$1', + }, + moduleFileExtensions: ['js', 'json', 'ts'], + modulePathIgnorePatterns: ['<rootDir>/dist'], fakeTimers: { enableGlobally: true, }, collectCoverageFrom: ['**/*.(t|j)s'], coverageDirectory: '../coverage', }; + +export default jestConfig; diff --git a/packages/twenty-server/nest-cli.json b/packages/twenty-server/nest-cli.json index c8c53e937434..ce6375096831 100644 --- a/packages/twenty-server/nest-cli.json +++ b/packages/twenty-server/nest-cli.json @@ -4,6 +4,21 @@ "sourceRoot": "src", "compilerOptions": { "builder": "swc", - "typeCheck": true + "typeCheck": true, + "assets": [ + { + "include": "**/serverless/drivers/layers/*/package.json", + "outDir": "dist/src" + }, + { + "include": "**/serverless/drivers/layers/*/yarn.lock", + "outDir": "dist/src" + }, + { + "include": "**/serverless/drivers/layers/engine/**", + "outDir": "dist/src" + } + ], + "watchAssets": true } } diff --git a/packages/twenty-server/package.json b/packages/twenty-server/package.json index 477a5fc2022e..d77b2faf4d78 100644 --- a/packages/twenty-server/package.json +++ b/packages/twenty-server/package.json @@ -1,6 +1,6 @@ { "name": "twenty-server", - "version": "0.24.0", + "version": "0.30.0", "description": "", "author": "", "private": true, @@ -15,7 +15,8 @@ "typeorm": "../../node_modules/typeorm/.bin/typeorm" }, "dependencies": { - "@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch", "@langchain/mistralai": "^0.0.24", "@langchain/openai": "^0.1.3", "@monaco-editor/react": "^4.6.0", @@ -24,10 +25,12 @@ "@nestjs/graphql": "patch:@nestjs/graphql@12.1.1#./patches/@nestjs+graphql+12.1.1.patch", "@ptc-org/nestjs-query-graphql": "patch:@ptc-org/nestjs-query-graphql@4.2.0#./patches/@ptc-org+nestjs-query-graphql+4.2.0.patch", "@revertdotdev/revert-react": "^0.0.21", + "@sentry/nestjs": "^8.30.0", "cache-manager": "^5.4.0", "cache-manager-redis-yet": "^4.1.2", "class-validator": "patch:class-validator@0.14.0#./patches/class-validator+0.14.0.patch", "graphql-middleware": "^6.1.35", + "handlebars": "^4.7.8", "jsdom": "~22.1.0", "jwt-decode": "^4.0.0", "langchain": "^0.2.6", @@ -37,11 +40,13 @@ "lodash.omitby": "^4.6.0", "lodash.uniq": "^4.5.0", "lodash.uniqby": "^4.7.0", - "monaco-editor": "^0.50.0", + "monaco-editor": "^0.51.0", + "monaco-editor-auto-typings": "^0.4.5", "passport": "^0.7.0", "psl": "^1.9.0", "tsconfig-paths": "^4.2.0", "typeorm": "patch:typeorm@0.3.20#./patches/typeorm+0.3.20.patch", + "unzipper": "^0.12.3", "zod-to-json-schema": "^3.23.1" }, "devDependencies": { @@ -59,6 +64,7 @@ "@types/lodash.uniqby": "^4.7.9", "@types/lodash.upperfirst": "^4.3.7", "@types/react": "^18.2.39", + "@types/unzipper": "^0", "rimraf": "^5.0.5", "typescript": "5.3.3" }, diff --git a/packages/twenty-server/patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch b/packages/twenty-server/patches/@graphql-yoga+nestjs+2.1.0.patch similarity index 92% rename from packages/twenty-server/patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch rename to packages/twenty-server/patches/@graphql-yoga+nestjs+2.1.0.patch index b15363c16b86..07d271f6e509 100644 --- a/packages/twenty-server/patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch +++ b/packages/twenty-server/patches/@graphql-yoga+nestjs+2.1.0.patch @@ -1,5 +1,5 @@ diff --git a/dist/cjs/index.js b/dist/cjs/index.js -index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd38790b508 100644 +index 1684394..32602b3 100644 --- a/dist/cjs/index.js +++ b/dist/cjs/index.js @@ -3,10 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); @@ -26,7 +26,7 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3 const app = this.httpAdapterHost.httpAdapter.getInstance(); preStartHook?.(app); // nest's logger doesnt have the info method -@@ -42,6 +46,40 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver { +@@ -42,6 +46,46 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver { } const yoga = (0, graphql_yoga_1.createYoga)({ ...options, @@ -60,6 +60,12 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3 + schemas, + }); + ++ for (const key of this.schemaCache.keys()) { ++ if (key.startsWith(`${workspaceId}-`)) { ++ this.schemaCache.delete(key); ++ } ++ } ++ + this.schemaCache.set(cacheKey, mergedSchemas) + + return mergedSchemas; @@ -67,7 +73,7 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3 graphqlEndpoint: options.path, // disable logging by default // however, if `true` use nest logger -@@ -54,11 +91,45 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver { +@@ -54,11 +98,51 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver { this.yoga = yoga; app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res })); } @@ -107,6 +113,12 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3 + schemas, + }); + ++ for (const key of this.schemaCache.keys()) { ++ if (key.startsWith(`${workspaceId}-`)) { ++ this.schemaCache.delete(key); ++ } ++ } ++ + this.schemaCache.set(cacheKey, mergedSchemas) + + return mergedSchemas; @@ -115,15 +127,19 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3 // disable logging by default // however, if `true` use fastify logger diff --git a/dist/esm/index.js b/dist/esm/index.js -index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b39f580570 100644 +index 7068c51..b8cbf9e 100644 --- a/dist/esm/index.js +++ b/dist/esm/index.js -@@ -2,8 +2,12 @@ import { __decorate } from "tslib"; - import { printSchema } from 'graphql'; - import { createYoga, filter, pipe } from 'graphql-yoga'; - import { Injectable, Logger } from '@nestjs/common'; +@@ -1,9 +1,13 @@ +-import { __decorate } from "tslib"; +-import { printSchema } from 'graphql'; +-import { createYoga, filter, pipe } from 'graphql-yoga'; +import { mergeSchemas } from '@graphql-tools/schema'; + import { Injectable, Logger } from '@nestjs/common'; import { AbstractGraphQLDriver, GqlSubscriptionService, } from '@nestjs/graphql'; ++import { printSchema } from 'graphql'; ++import { createYoga, filter, pipe } from 'graphql-yoga'; ++import { __decorate } from "tslib"; export class AbstractYogaDriver extends AbstractGraphQLDriver { + + schemaCache = new Map(); @@ -140,7 +156,7 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3 const app = this.httpAdapterHost.httpAdapter.getInstance(); preStartHook?.(app); // nest's logger doesnt have the info method -@@ -39,6 +43,40 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver { +@@ -39,6 +43,46 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver { } const yoga = createYoga({ ...options, @@ -171,9 +187,15 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3 + } + + const mergedSchemas = mergeSchemas({ -+ schemas, ++ schemas, + }); + ++ for (const key of this.schemaCache.keys()) { ++ if (key.startsWith(`${workspaceId}-`)) { ++ this.schemaCache.delete(key); ++ } ++ } ++ + this.schemaCache.set(cacheKey, mergedSchemas) + + return mergedSchemas; @@ -181,7 +203,7 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3 graphqlEndpoint: options.path, // disable logging by default // however, if `true` use nest logger -@@ -51,11 +88,45 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver { +@@ -51,11 +95,51 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver { this.yoga = yoga; app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res })); } @@ -221,6 +243,12 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3 + schemas, + }); + ++ for (const key of this.schemaCache.keys()) { ++ if (key.startsWith(`${workspaceId}-`)) { ++ this.schemaCache.delete(key); ++ } ++ } ++ + this.schemaCache.set(cacheKey, mergedSchemas) + + return mergedSchemas; @@ -229,7 +257,7 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3 // disable logging by default // however, if `true` use fastify logger diff --git a/dist/typings/index.d.cts b/dist/typings/index.d.cts -index 2c6a9656193392680121487c7147db459d6b69ab..2f2b59f0e311f0526a7cfdad97372229301aabd7 100644 +index 2c6a965..2f2b59f 100644 --- a/dist/typings/index.d.cts +++ b/dist/typings/index.d.cts @@ -1,7 +1,8 @@ @@ -268,7 +296,7 @@ index 2c6a9656193392680121487c7147db459d6b69ab..2f2b59f0e311f0526a7cfdad97372229 }): void; subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>; diff --git a/dist/typings/index.d.ts b/dist/typings/index.d.ts -index 2c6a9656193392680121487c7147db459d6b69ab..fd86daccf3e5a93ff44b568c9793c16d761f4f53 100644 +index 2c6a965..fd86dac 100644 --- a/dist/typings/index.d.ts +++ b/dist/typings/index.d.ts @@ -1,7 +1,8 @@ @@ -306,7 +334,7 @@ index 2c6a9656193392680121487c7147db459d6b69ab..fd86daccf3e5a93ff44b568c9793c16d }): void; subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>; diff --git a/src/index.ts b/src/index.ts -index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac941edabb 100644 +index ce142f6..10e17d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,10 @@ @@ -422,7 +450,7 @@ index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac graphqlEndpoint: options.path, // disable logging by default // however, if `true` use nest logger -@@ -105,8 +149,8 @@ export abstract class AbstractYogaDriver< +@@ -105,8 +150,8 @@ export abstract class AbstractYogaDriver< options.logging == null ? false : options.logging @@ -433,7 +461,7 @@ index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac }); this.yoga = yoga as YogaDriverServerInstance<Platform>; -@@ -115,7 +159,7 @@ export abstract class AbstractYogaDriver< +@@ -115,7 +160,7 @@ export abstract class AbstractYogaDriver< } protected registerFastify( @@ -442,7 +470,7 @@ index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac { preStartHook }: { preStartHook?: (app: FastifyInstance) => void } = {}, ) { const app: FastifyInstance = this.httpAdapterHost.httpAdapter.getInstance(); -@@ -124,6 +168,40 @@ export abstract class AbstractYogaDriver< +@@ -124,6 +169,40 @@ export abstract class AbstractYogaDriver< const yoga = createYoga<YogaDriverServerContext<'fastify'>>({ ...options, @@ -483,7 +511,7 @@ index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac graphqlEndpoint: options.path, // disable logging by default // however, if `true` use fastify logger -@@ -191,8 +268,8 @@ export class YogaDriver< +@@ -191,8 +270,8 @@ export class YogaDriver< const config: SubscriptionConfig = options.subscriptions === true ? { diff --git a/packages/twenty-server/project.json b/packages/twenty-server/project.json index a92e19caae28..a31ff4fb101f 100644 --- a/packages/twenty-server/project.json +++ b/packages/twenty-server/project.json @@ -11,6 +11,16 @@ "commands": ["rimraf dist", "nest build --path ./tsconfig.build.json"] } }, + "test:integration": { + "executor": "nx:run-commands", + "options": { + "cwd": "packages/twenty-server", + "commands": [ + "NODE_ENV=test nx database:reset > reset-logs.log && NODE_ENV=test nx jest --config ./jest-integration.config.ts" + ] + }, + "parallel": false + }, "build:packageJson": { "executor": "@nx/js:tsc", "options": { @@ -108,12 +118,11 @@ "command": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register ../../node_modules/.bin/jest --runInBand" } }, - "test:e2e": { + "jest": { "executor": "nx:run-commands", - "dependsOn": ["build"], "options": { "cwd": "packages/twenty-server", - "command": "./scripts/run-integration.sh" + "command": "jest" } }, "database:migrate": { @@ -140,6 +149,16 @@ "parallel": false } }, + "generate:integration-test": { + "executor": "nx:run-commands", + "options": { + "cwd": "packages/twenty-server", + "commands": [ + "nx ts-node-no-deps -- ./scripts/generate-integration-tests/index.ts" + ], + "parallel": false + } + }, "database:reset": { "executor": "nx:run-commands", "dependsOn": ["build"], @@ -149,6 +168,7 @@ "nx ts-node-no-deps -- ./scripts/truncate-db.ts", "nx ts-node-no-deps -- ./scripts/setup-db.ts", "nx database:migrate", + "nx command-no-deps -- cache:flush", "nx command-no-deps -- workspace:seed:dev" ], "parallel": false diff --git a/packages/twenty-server/scripts/generate-integration-tests/index.ts b/packages/twenty-server/scripts/generate-integration-tests/index.ts new file mode 100644 index 000000000000..5b635d3bccd7 --- /dev/null +++ b/packages/twenty-server/scripts/generate-integration-tests/index.ts @@ -0,0 +1,213 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as process from 'process'; + +import { INTROSPECTION_QUERY } from './introspection-query'; +import { + Field, + InputValue, + IntrospectionResponse, + TypeRef, +} from './introspection.interface'; + +const GRAPHQL_URL = 'http://localhost:3000/graphql'; +const BEARER_TOKEN = + 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwiaWF0IjoxNzI2NDkyNTAyLCJleHAiOjEzMjQ1MDE2NTAyfQ.zM6TbfeOqYVH5Sgryc2zf02hd9uqUOSL1-iJlMgwzsI'; +const TEST_OUTPUT_DIR = './test'; + +const fetchGraphQLSchema = async (): Promise<IntrospectionResponse> => { + const headers = { + Authorization: BEARER_TOKEN, + 'Content-Type': 'application/json', + }; + const response = await fetch(GRAPHQL_URL, { + method: 'POST', + headers, + body: JSON.stringify({ query: INTROSPECTION_QUERY }), + }); + + if (!response.ok) { + throw new Error(`Failed to fetch schema: ${response.statusText}`); + } + + return response.json(); +}; + +const toKebabCase = (name: string): string => { + return name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); +}; + +const unwrapType = (typeInfo: TypeRef): any => { + while (typeInfo.ofType) { + typeInfo = typeInfo.ofType; + } + + return typeInfo; +}; + +const hasRequiredArgs = (args: InputValue[]): boolean => { + return args.some((arg) => unwrapType(arg.type).kind === 'NON_NULL'); +}; + +const generateTestContent = ( + queryName: string, + fields: Field[], +): string | null => { + const fieldNames = fields + .filter((f) => ['SCALAR', 'ENUM'].includes(unwrapType(f.type).kind)) + .map((f) => f.name); + + if (fieldNames.length === 0) { + console.log(`Skipping ${queryName}: No usable fields found.`); + + return null; + } + + const fieldSelection = fieldNames.join('\n '); + const expectSelection = fieldNames + .map((f) => `expect(${queryName}).toHaveProperty('${f}');`) + .join('\n '); + + return `import request from 'supertest'; + +const client = request(\`http://localhost:\${APP_PORT}\`); + +describe('${queryName}Resolver (e2e)', () => { + it('should find many ${queryName}', () => { + const queryData = { + query: \` + query ${queryName} { + ${queryName} { + edges { + node { + ${fieldSelection} + } + } + } + } + \`, + }; + + return client + .post('/graphql') + .set('Authorization', \`Bearer \${ACCESS_TOKEN}\`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.${queryName}; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const ${queryName} = edges[0].node; + + ${expectSelection} + } + }); + }); +}); +`; +}; + +const writeTestFile = ( + queryName: string, + content: string | null, + force = false, +): string => { + if (!content) return 'skipped'; + + const fileName = `${toKebabCase(queryName)}.integration-spec.ts`; + const filePath = path.join(TEST_OUTPUT_DIR, fileName); + + if (fs.existsSync(filePath) && !force) { + return 'skipped'; + } + + fs.writeFileSync(filePath, content); + + return force ? 'updated' : 'created'; +}; + +const generateTests = async (force = false) => { + fs.mkdirSync(TEST_OUTPUT_DIR, { recursive: true }); + const schemaData = await fetchGraphQLSchema(); + const types = schemaData.data.__schema.types; + + const queryTypeName = schemaData.data.__schema.queryType.name; + const queryType = types.find((t: any) => t.name === queryTypeName); + + let createdCount = 0; + let updatedCount = 0; + let totalCount = 0; + + if (!queryType?.fields) { + console.log('No query fields found.'); + + return; + } + + for (const query of queryType.fields) { + const queryName = query.name; + + if (hasRequiredArgs(query.args)) continue; + if (queryName.includes('Duplicates')) continue; + + const queryReturnType = unwrapType(query.type); + + if ( + queryReturnType.kind === 'OBJECT' && + queryReturnType.name.includes('Connection') + ) { + totalCount++; + const connectionTypeInfo = types.find( + (f: any) => f.name === queryReturnType.name, + ); + const edgeTypeInfo = connectionTypeInfo?.fields?.find( + (f: any) => f.name === 'edges', + ); + + if (edgeTypeInfo) { + const returnType = unwrapType(edgeTypeInfo.type); + const returnTypeInfo = types.find( + (t: any) => t.name === returnType.name, + ); + const returnNodeTypeInfo = returnTypeInfo?.fields?.find( + (f: any) => f.name === 'node', + ); + + if (returnNodeTypeInfo) { + const nodeType = unwrapType(returnNodeTypeInfo.type); + const nodeTypeInfo = types.find((t: any) => t.name === nodeType.name); + + if (!nodeTypeInfo?.fields) { + continue; + } + + const content = generateTestContent(queryName, nodeTypeInfo?.fields); + const result = writeTestFile(queryName, content, force); + + if (result === 'created') createdCount++; + if (result === 'updated') updatedCount++; + } + } + } + } + + console.log(`Number of tests created: ${createdCount}/${totalCount}`); + if (force) { + console.log(`Number of tests updated: ${updatedCount}/${totalCount}`); + } +}; + +// Basic command-line argument parsing +const forceArg = process.argv.includes('--force'); + +// Call the function with the parsed argument +generateTests(forceArg); diff --git a/packages/twenty-server/scripts/generate-integration-tests/introspection-query.ts b/packages/twenty-server/scripts/generate-integration-tests/introspection-query.ts new file mode 100644 index 000000000000..c93c469ae5ee --- /dev/null +++ b/packages/twenty-server/scripts/generate-integration-tests/introspection-query.ts @@ -0,0 +1,89 @@ +export const INTROSPECTION_QUERY = ` +query IntrospectionQuery { + __schema { + queryType { name } + mutationType { name } + subscriptionType { name } + types { + ...FullType + } + directives { + name + description + locations + args { + ...InputValue + } + } + } +} + +fragment FullType on __Type { + kind + name + description + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } +} + +fragment InputValue on __InputValue { + name + description + type { ...TypeRef } + defaultValue +} + +fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } +} +`; diff --git a/packages/twenty-server/scripts/generate-integration-tests/introspection.interface.ts b/packages/twenty-server/scripts/generate-integration-tests/introspection.interface.ts new file mode 100644 index 000000000000..cec8fd9f5c13 --- /dev/null +++ b/packages/twenty-server/scripts/generate-integration-tests/introspection.interface.ts @@ -0,0 +1,60 @@ +export interface IntrospectionResponse { + data: { + __schema: Schema; + }; +} + +export interface Schema { + queryType: { name: string }; + mutationType: { name: string | null }; + subscriptionType: { name: string | null }; + types: GraphQLType[]; + directives: Directive[]; +} + +export interface Directive { + name: string; + description: string | null; + locations: string[]; + args: InputValue[]; +} + +export interface GraphQLType { + kind: string; + name: string; + description: string | null; + fields?: Field[]; + inputFields?: InputValue[]; + interfaces?: TypeRef[]; + enumValues?: EnumValue[]; + possibleTypes?: TypeRef[]; +} + +export interface Field { + name: string; + description: string | null; + args: InputValue[]; + type: TypeRef; + isDeprecated: boolean; + deprecationReason: string | null; +} + +export interface InputValue { + name: string; + description: string | null; + type: TypeRef; + defaultValue: string | null; +} + +export interface TypeRef { + kind: string; + name: string | null; + ofType: TypeRef | null; +} + +export interface EnumValue { + name: string; + description: string | null; + isDeprecated: boolean; + deprecationReason: string | null; +} diff --git a/packages/twenty-server/scripts/run-integration.sh b/packages/twenty-server/scripts/run-integration.sh deleted file mode 100755 index 0da23f2dee6f..000000000000 --- a/packages/twenty-server/scripts/run-integration.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# scripts/run-integration.sh - -DIR="$(cd "$(dirname "$0")" && pwd)" -source $DIR/set-env-test.sh - -npx nx database:reset -npx nx jest --config ./test/jest-e2e.json diff --git a/packages/twenty-server/scripts/set-env-test.sh b/packages/twenty-server/scripts/set-env-test.sh deleted file mode 100755 index 98e7ac7c9cb3..000000000000 --- a/packages/twenty-server/scripts/set-env-test.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# scripts/set-env-test.sh - -# Get script's directory -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -# Construct the absolute path of .env file in the project root directory -ENV_PATH="${SCRIPT_DIR}/../.env.test" - -# Check if the file exists -if [ -f "${ENV_PATH}" ]; then - echo "🔵 - Loading environment variables from "${ENV_PATH}"..." - # Export env vars - while IFS= read -r line || [ -n "$line" ]; do - if echo "$line" | grep -F = &>/dev/null - then - varname=$(echo "$line" | cut -d '=' -f 1) - varvalue=$(echo "$line" | cut -d '=' -f 2- | cut -d '#' -f 1) - export "$varname"="$varvalue" - fi - done < <(grep -v '^#' "${ENV_PATH}") -else - echo "Error: ${ENV_PATH} does not exist." - exit 1 -fi diff --git a/packages/twenty-server/src/app.module.ts b/packages/twenty-server/src/app.module.ts index 4641f3a04bde..491582085677 100644 --- a/packages/twenty-server/src/app.module.ts +++ b/packages/twenty-server/src/app.module.ts @@ -12,49 +12,41 @@ import { existsSync } from 'fs'; import { join } from 'path'; import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs'; +import { SentryModule } from '@sentry/nestjs/setup'; import { CoreGraphQLApiModule } from 'src/engine/api/graphql/core-graphql-api.module'; import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module'; import { GraphQLConfigService } from 'src/engine/api/graphql/graphql-config/graphql-config.service'; import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module'; import { RestApiModule } from 'src/engine/api/rest/rest-api.module'; -import { MessageQueueDriverType } from 'src/engine/integrations/message-queue/interfaces'; -import { MessageQueueModule } from 'src/engine/integrations/message-queue/message-queue.module'; -import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { MessageQueueDriverType } from 'src/engine/core-modules/message-queue/interfaces'; +import { MessageQueueModule } from 'src/engine/core-modules/message-queue/message-queue.module'; import { GraphQLHydrateRequestFromTokenMiddleware } from 'src/engine/middlewares/graphql-hydrate-request-from-token.middleware'; import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module'; +import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; import { ModulesModule } from 'src/modules/modules.module'; import { CoreEngineModule } from './engine/core-modules/core-engine.module'; -import { IntegrationsModule } from './engine/integrations/integrations.module'; @Module({ imports: [ - // Nest.js devtools, use devtools.nestjs.com to debug - // DevtoolsModule.registerAsync({ - // useFactory: (environmentService: EnvironmentService) => ({ - // http: environmentService.get('DEBUG_MODE'), - // port: environmentService.get('DEBUG_PORT'), - // }), - // inject: [EnvironmentService], - // }), + SentryModule.forRoot(), ConfigModule.forRoot({ isGlobal: true, + envFilePath: process.env.NODE_ENV === 'test' ? '.env.test' : '.env', }), GraphQLModule.forRootAsync<YogaDriverConfig>({ driver: YogaDriver, - imports: [CoreEngineModule, GraphQLConfigModule], + imports: [GraphQLConfigModule], useClass: GraphQLConfigService, }), TwentyORMModule, - // Integrations module, contains all the integrations with other services - IntegrationsModule, // Core engine module, contains all the core modules CoreEngineModule, // Modules module, contains all business logic modules ModulesModule, // Needed for the user workspace middleware - WorkspaceMetadataVersionModule, + WorkspaceCacheStorageModule, // Api modules CoreGraphQLApiModule, MetadataGraphQLApiModule, diff --git a/packages/twenty-server/src/command/command.ts b/packages/twenty-server/src/command/command.ts index 7fbd410349df..5e45fde2ad74 100644 --- a/packages/twenty-server/src/command/command.ts +++ b/packages/twenty-server/src/command/command.ts @@ -1,7 +1,7 @@ import { CommandFactory } from 'nest-commander'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { LoggerService } from 'src/engine/integrations/logger/logger.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; import { shouldFilterException } from 'src/engine/utils/global-exception-handler.util'; import { CommandModule } from './command.module'; diff --git a/packages/twenty-server/src/database/commands/active-workspaces.command.ts b/packages/twenty-server/src/database/commands/active-workspaces.command.ts new file mode 100644 index 000000000000..d741144cb8ea --- /dev/null +++ b/packages/twenty-server/src/database/commands/active-workspaces.command.ts @@ -0,0 +1,92 @@ +import { Logger } from '@nestjs/common'; + +import chalk from 'chalk'; +import { Option } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { + BaseCommandOptions, + BaseCommandRunner, +} from 'src/database/commands/base.command'; +import { + Workspace, + WorkspaceActivationStatus, +} from 'src/engine/core-modules/workspace/workspace.entity'; + +export type ActiveWorkspacesCommandOptions = BaseCommandOptions & { + workspaceId?: string; +}; + +export abstract class ActiveWorkspacesCommandRunner extends BaseCommandRunner { + private workspaceIds: string[] = []; + + protected readonly logger: Logger; + + constructor(protected readonly workspaceRepository: Repository<Workspace>) { + super(); + this.logger = new Logger(this.constructor.name); + } + + @Option({ + flags: '-w, --workspace-id [workspace_id]', + description: + 'workspace id. Command runs on all active workspaces if not provided', + required: false, + }) + parseWorkspaceId(val: string): string[] { + this.workspaceIds.push(val); + + return this.workspaceIds; + } + + protected async fetchActiveWorkspaceIds(): Promise<string[]> { + const activeWorkspaces = await this.workspaceRepository.find({ + select: ['id'], + where: { + activationStatus: WorkspaceActivationStatus.ACTIVE, + }, + }); + + return activeWorkspaces.map((workspace) => workspace.id); + } + + protected logWorkspaceCount(activeWorkspaceIds: string[]): void { + if (!activeWorkspaceIds.length) { + this.logger.log(chalk.yellow('No workspace found')); + } else { + this.logger.log( + chalk.green( + `Running command on ${activeWorkspaceIds.length} workspaces`, + ), + ); + } + } + + override async executeBaseCommand( + passedParams: string[], + options: BaseCommandOptions, + ): Promise<void> { + const activeWorkspaceIds = + this.workspaceIds.length > 0 + ? this.workspaceIds + : await this.fetchActiveWorkspaceIds(); + + this.logWorkspaceCount(activeWorkspaceIds); + + if (options.dryRun) { + this.logger.log(chalk.yellow('Dry run mode: No changes will be applied')); + } + + await this.executeActiveWorkspacesCommand( + passedParams, + options, + activeWorkspaceIds, + ); + } + + protected abstract executeActiveWorkspacesCommand( + passedParams: string[], + options: BaseCommandOptions, + activeWorkspaceIds: string[], + ): Promise<void>; +} diff --git a/packages/twenty-server/src/database/commands/base.command.ts b/packages/twenty-server/src/database/commands/base.command.ts new file mode 100644 index 000000000000..6715b5c293bd --- /dev/null +++ b/packages/twenty-server/src/database/commands/base.command.ts @@ -0,0 +1,46 @@ +import { Logger } from '@nestjs/common'; + +import chalk from 'chalk'; +import { CommandRunner, Option } from 'nest-commander'; + +export type BaseCommandOptions = { + workspaceId?: string; + dryRun?: boolean; +}; + +export abstract class BaseCommandRunner extends CommandRunner { + protected readonly logger: Logger; + + constructor() { + super(); + this.logger = new Logger(this.constructor.name); + } + + @Option({ + flags: '-d, --dry-run', + description: 'Simulate the command without making actual changes', + required: false, + }) + parseDryRun(): boolean { + return true; + } + + override async run( + passedParams: string[], + options: BaseCommandOptions, + ): Promise<void> { + try { + await this.executeBaseCommand(passedParams, options); + } catch (error) { + this.logger.error(chalk.red(`Command failed`)); + throw error; + } finally { + this.logger.log(chalk.blue('Command completed!')); + } + } + + protected abstract executeBaseCommand( + passedParams: string[], + options: BaseCommandOptions, + ): Promise<void>; +} diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/start-data-seed-demo-workspace.cron.command.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/start-data-seed-demo-workspace.cron.command.ts index bdf120095b23..bc2c1c395d57 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/start-data-seed-demo-workspace.cron.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/start-data-seed-demo-workspace.cron.command.ts @@ -2,9 +2,9 @@ import { Command, CommandRunner } from 'nest-commander'; import { dataSeedDemoWorkspaceCronPattern } from 'src/database/commands/data-seed-demo-workspace/crons/data-seed-demo-workspace-cron-pattern'; import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; @Command({ name: 'workspace-seed-demo:cron:start', diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/stop-data-seed-demo-workspace.cron.command.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/stop-data-seed-demo-workspace.cron.command.ts index 99dd1558bf7f..a5fbf20ddf65 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/stop-data-seed-demo-workspace.cron.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/crons/stop-data-seed-demo-workspace.cron.command.ts @@ -2,9 +2,9 @@ import { Command, CommandRunner } from 'nest-commander'; import { dataSeedDemoWorkspaceCronPattern } from 'src/database/commands/data-seed-demo-workspace/crons/data-seed-demo-workspace-cron-pattern'; import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; @Command({ name: 'workspace-seed-demo:cron:stop', diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts index 10d644c03f44..d3ce4a65fa40 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts @@ -1,11 +1,17 @@ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; -import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; import { DataSeedDemoWorkspaceService } from 'src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; @Module({ - imports: [WorkspaceManagerModule, EnvironmentModule], + imports: [ + WorkspaceManagerModule, + EnvironmentModule, + TypeOrmModule.forFeature([Workspace], 'core'), + ], providers: [DataSeedDemoWorkspaceService], exports: [DataSeedDemoWorkspaceService], }) diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job.ts index 14655209c009..af89585182d5 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job.ts @@ -1,7 +1,7 @@ import { DataSeedDemoWorkspaceService } from 'src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; @Processor(MessageQueue.cronQueue) export class DataSeedDemoWorkspaceJob { diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts index 9be19725af5c..a7457d6a76ea 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts @@ -1,18 +1,29 @@ import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; import { deleteCoreSchema, seedCoreSchema, } from 'src/database/typeorm-seeds/core/demo'; import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; @Injectable() export class DataSeedDemoWorkspaceService { constructor( private readonly environmentService: EnvironmentService, private readonly workspaceManagerService: WorkspaceManagerService, + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) + private readonly workspaceSchemaCache: CacheStorageService, ) {} async seedDemo(): Promise<void> { @@ -26,9 +37,18 @@ export class DataSeedDemoWorkspaceService { 'Could not get DEMO_WORKSPACE_IDS. Please specify in .env', ); } + + await this.workspaceSchemaCache.flush(); + for (const workspaceId of demoWorkspaceIds) { - await deleteCoreSchema(rawDataSource, workspaceId); - await this.workspaceManagerService.delete(workspaceId); + const existingWorkspaces = await this.workspaceRepository.findBy({ + id: workspaceId, + }); + + if (existingWorkspaces.length > 0) { + await this.workspaceManagerService.delete(workspaceId); + await deleteCoreSchema(rawDataSource, workspaceId); + } await seedCoreSchema(rawDataSource, workspaceId); await this.workspaceManagerService.initDemo(workspaceId); diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index 6e5fef348b0a..50113a1c95b4 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -12,12 +12,14 @@ import { getDevSeedCompanyCustomFields, getDevSeedPeopleCustomFields, } from 'src/database/typeorm-seeds/metadata/fieldsMetadata'; +import { getDevSeedCustomObjects } from 'src/database/typeorm-seeds/metadata/objectsMetadata'; import { seedCalendarChannels } from 'src/database/typeorm-seeds/workspace/calendar-channel'; import { seedCalendarChannelEventAssociations } from 'src/database/typeorm-seeds/workspace/calendar-channel-event-association'; import { seedCalendarEventParticipants } from 'src/database/typeorm-seeds/workspace/calendar-event-participants'; import { seedCalendarEvents } from 'src/database/typeorm-seeds/workspace/calendar-events'; import { seedCompanies } from 'src/database/typeorm-seeds/workspace/companies'; import { seedConnectedAccount } from 'src/database/typeorm-seeds/workspace/connected-account'; +import { seedWorkspaceFavorites } from 'src/database/typeorm-seeds/workspace/favorites'; import { seedMessageChannelMessageAssociation } from 'src/database/typeorm-seeds/workspace/message-channel-message-associations'; import { seedMessageChannel } from 'src/database/typeorm-seeds/workspace/message-channels'; import { seedMessageParticipant } from 'src/database/typeorm-seeds/workspace/message-participants'; @@ -29,11 +31,11 @@ import { seedPeople } from 'src/database/typeorm-seeds/workspace/people'; import { seedWorkspaceMember } from 'src/database/typeorm-seeds/workspace/workspace-members'; import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; @@ -62,6 +64,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { private readonly objectMetadataService: ObjectMetadataService, @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) private readonly workspaceSchemaCache: CacheStorageService, + private readonly featureFlagService: FeatureFlagService, ) { super(); } @@ -128,10 +131,17 @@ export class DataSeedWorkspaceCommand extends CommandRunner { return acc; }, {}); - const featureFlagRepository = - workspaceDataSource.getRepository<FeatureFlagEntity>('featureFlag'); + const isMessageThreadSubscriberEnabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IsMessageThreadSubscriberEnabled, + workspaceId, + ); - const featureFlags = await featureFlagRepository.find({}); + const isWorkflowEnabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IsWorkflowEnabled, + workspaceId, + ); await this.seedCompanyCustomFields( objectMetadataMap[STANDARD_OBJECT_IDS.company], @@ -141,6 +151,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { objectMetadataMap[STANDARD_OBJECT_IDS.person], workspaceId, ); + await this.seedCustomObjects(workspaceId, dataSourceMetadata.id); await workspaceDataSource.transaction( async (entityManager: EntityManager) => { @@ -160,13 +171,6 @@ export class DataSeedWorkspaceCommand extends CommandRunner { dataSourceMetadata.schema, ); - const isMessageThreadSubscriberEnabled = featureFlags.some( - (featureFlag) => - featureFlag.key === - FeatureFlagKey.IsMessageThreadSubscriberEnabled && - featureFlag.value === true, - ); - if (isMessageThreadSubscriberEnabled) { await seedMessageThreadSubscribers( entityManager, @@ -206,11 +210,19 @@ export class DataSeedWorkspaceCommand extends CommandRunner { ); } - await viewPrefillData( + const viewDefinitionsWithId = await viewPrefillData( entityManager, dataSourceMetadata.schema, objectMetadataMap, - featureFlags, + isWorkflowEnabled, + ); + + await seedWorkspaceFavorites( + viewDefinitionsWithId + .filter((view) => view.key === 'INDEX') + .map((view) => view.id), + entityManager, + dataSourceMetadata.schema, ); }, ); @@ -272,4 +284,15 @@ export class DataSeedWorkspaceCommand extends CommandRunner { }); } } + + async seedCustomObjects(workspaceId: string, dataSourceId: string) { + const devSeedCustomObjects = getDevSeedCustomObjects( + workspaceId, + dataSourceId, + ); + + for (const customObject of devSeedCustomObjects) { + await this.objectMetadataService.createOne(customObject); + } + } } diff --git a/packages/twenty-server/src/database/commands/database-command.module.ts b/packages/twenty-server/src/database/commands/database-command.module.ts index d240657f5f0f..9d98d33abd75 100644 --- a/packages/twenty-server/src/database/commands/database-command.module.ts +++ b/packages/twenty-server/src/database/commands/database-command.module.ts @@ -7,10 +7,12 @@ import { DataSeedDemoWorkspaceCommand } from 'src/database/commands/data-seed-de import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module'; import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command'; import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question'; -import { UpgradeTo0_24CommandModule } from 'src/database/commands/upgrade-version/0-24/0-24-upgrade-version.module'; +import { UpgradeTo0_30CommandModule } from 'src/database/commands/upgrade-version/0-30/0-30-upgrade-version.module'; +import { UpgradeTo0_31CommandModule } from 'src/database/commands/upgrade-version/0-31/0-31-upgrade-version.module'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; @@ -19,9 +21,9 @@ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; -import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module'; import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module'; @Module({ @@ -40,12 +42,14 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp WorkspaceModule, WorkspaceDataSourceModule, WorkspaceSyncMetadataModule, - WorkspaceStatusModule, ObjectMetadataModule, FieldMetadataModule, DataSeedDemoWorkspaceModule, + WorkspaceCacheStorageModule, WorkspaceMetadataVersionModule, - UpgradeTo0_24CommandModule, + UpgradeTo0_30CommandModule, + UpgradeTo0_31CommandModule, + FeatureFlagModule, ], providers: [ DataSeedWorkspaceCommand, diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command.ts deleted file mode 100644 index b8689ecfaad5..000000000000 --- a/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import chalk from 'chalk'; -import { Command, CommandRunner, Option } from 'nest-commander'; -import { Any, Repository } from 'typeorm'; - -import { - Workspace, - WorkspaceActivationStatus, -} from 'src/engine/core-modules/workspace/workspace.entity'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; -import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; -import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; - -interface SetMessageDirectionCommandOptions { - workspaceId?: string; -} - -const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE = 10; - -@Command({ - name: 'upgrade-0.24:set-message-direction', - description: 'Set message direction', -}) -export class SetMessageDirectionCommand extends CommandRunner { - private readonly logger = new Logger(SetMessageDirectionCommand.name); - constructor( - private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, - private readonly twentyORMGlobalManager: TwentyORMGlobalManager, - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository<Workspace>, - ) { - super(); - } - - @Option({ - flags: '-w, --workspace-id [workspace_id]', - description: 'workspace id. Command runs on all workspaces if not provided', - required: false, - }) - parseWorkspaceId(value: string): string { - return value; - } - - async run( - _passedParam: string[], - options: SetMessageDirectionCommandOptions, - ): Promise<void> { - let activeWorkspaceIds: string[] = []; - - if (options.workspaceId) { - activeWorkspaceIds = [options.workspaceId]; - } else { - const activeWorkspaces = await this.workspaceRepository.find({ - where: { - activationStatus: WorkspaceActivationStatus.ACTIVE, - ...(options.workspaceId && { id: options.workspaceId }), - }, - }); - - activeWorkspaceIds = activeWorkspaces.map((workspace) => workspace.id); - } - - if (!activeWorkspaceIds.length) { - this.logger.log(chalk.yellow('No workspace found')); - - return; - } else { - this.logger.log( - chalk.green( - `Running command on ${activeWorkspaceIds.length} workspaces`, - ), - ); - } - - for (const workspaceId of activeWorkspaceIds) { - try { - const messageChannelMessageAssociationRepository = - await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelMessageAssociationWorkspaceEntity>( - workspaceId, - 'messageChannelMessageAssociation', - ); - - const workspaceDataSource = - await this.twentyORMGlobalManager.getDataSourceForWorkspace( - workspaceId, - ); - - await workspaceDataSource.transaction(async (transactionManager) => { - try { - const messageChannelMessageAssociationCount = - await messageChannelMessageAssociationRepository.count( - {}, - transactionManager, - ); - - for ( - let i = 0; - i < messageChannelMessageAssociationCount; - i += MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE - ) { - const messageChannelMessageAssociationsPage = - await messageChannelMessageAssociationRepository.find( - { - where: { - message: { - messageParticipants: { - role: 'from', - }, - }, - }, - relations: { - message: { - messageParticipants: true, - }, - messageChannel: { - connectedAccount: true, - }, - }, - take: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE, - skip: i, - }, - transactionManager, - ); - - const { incoming, outgoing } = - messageChannelMessageAssociationsPage.reduce( - ( - acc: { - incoming: string[]; - outgoing: string[]; - }, - messageChannelMessageAssociation, - ) => { - const connectedAccountHandle = - messageChannelMessageAssociation?.messageChannel - ?.connectedAccount?.handle; - const connectedAccountHandleAliases = - messageChannelMessageAssociation?.messageChannel - ?.connectedAccount?.handleAliases; - const fromHandle = - messageChannelMessageAssociation?.message - ?.messageParticipants?.[0]?.handle ?? ''; - - if ( - connectedAccountHandle === fromHandle || - connectedAccountHandleAliases?.includes(fromHandle) - ) { - acc.outgoing.push(messageChannelMessageAssociation.id); - } else { - acc.incoming.push(messageChannelMessageAssociation.id); - } - - return acc; - }, - { incoming: [], outgoing: [] }, - ); - - await messageChannelMessageAssociationRepository.update( - { - id: Any(incoming), - }, - { - direction: MessageDirection.INCOMING, - }, - transactionManager, - ); - - await messageChannelMessageAssociationRepository.update( - { - id: Any(outgoing), - }, - { - direction: MessageDirection.OUTGOING, - }, - transactionManager, - ); - - const numberOfProcessedAssociations = - i + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE; - - if ( - numberOfProcessedAssociations % - (MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE * 10) === - 0 || - numberOfProcessedAssociations >= - messageChannelMessageAssociationCount - ) { - this.logger.log( - chalk.green( - `Processed ${Math.min(numberOfProcessedAssociations, messageChannelMessageAssociationCount)} of ${messageChannelMessageAssociationCount} message channel message associations`, - ), - ); - } - } - } catch (error) { - this.logger.log( - chalk.red(`Running command on workspace ${workspaceId} failed`), - ); - throw error; - } - }); - - await this.workspaceMetadataVersionService.incrementMetadataVersion( - workspaceId, - ); - - this.logger.log( - chalk.green(`Running command on workspace ${workspaceId} done`), - ); - } catch (error) { - this.logger.error( - `Migration failed for workspace ${workspaceId}: ${error.message}`, - ); - } - } - - this.logger.log(chalk.green(`Command completed!`)); - } -} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.command.ts deleted file mode 100644 index 08b32b05e235..000000000000 --- a/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.command.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Command, CommandRunner, Option } from 'nest-commander'; - -import { SetMessageDirectionCommand } from 'src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command'; -import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; - -interface UpdateTo0_24CommandOptions { - workspaceId?: string; -} - -@Command({ - name: 'upgrade-0.24', - description: 'Upgrade to 0.24', -}) -export class UpgradeTo0_24Command extends CommandRunner { - constructor( - private readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, - private readonly setMessagesDirectionCommand: SetMessageDirectionCommand, - ) { - super(); - } - - @Option({ - flags: '-w, --workspace-id [workspace_id]', - description: - 'workspace id. Command runs on all active workspaces if not provided', - required: false, - }) - parseWorkspaceId(value: string): string { - return value; - } - - async run( - _passedParam: string[], - options: UpdateTo0_24CommandOptions, - ): Promise<void> { - await this.syncWorkspaceMetadataCommand.run(_passedParam, { - ...options, - force: true, - }); - await this.setMessagesDirectionCommand.run(_passedParam, options); - } -} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.module.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.module.ts deleted file mode 100644 index b718b9ed249c..000000000000 --- a/packages/twenty-server/src/database/commands/upgrade-version/0-24/0-24-upgrade-version.module.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { SetMessageDirectionCommand } from 'src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command'; -import { UpgradeTo0_24Command } from 'src/database/commands/upgrade-version/0-24/0-24-upgrade-version.command'; -import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; -import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity'; -import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { FileStorageModule } from 'src/engine/integrations/file-storage/file-storage.module'; -import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; -import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module'; -import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([Workspace, KeyValuePair], 'core'), - WorkspaceSyncMetadataCommandsModule, - FileStorageModule, - OnboardingModule, - TypeORMModule, - DataSourceModule, - WorkspaceMetadataVersionModule, - FieldMetadataModule, - WorkspaceStatusModule, - TypeOrmModule.forFeature( - [FieldMetadataEntity, ObjectMetadataEntity], - 'metadata', - ), - TypeORMModule, - ], - providers: [UpgradeTo0_24Command, SetMessageDirectionCommand], -}) -export class UpgradeTo0_24CommandModule {} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command.ts new file mode 100644 index 000000000000..9356d7d920c1 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command.ts @@ -0,0 +1,161 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { isDefined } from 'class-validator'; +import { Command } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; +import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { ViewService } from 'src/modules/view/services/view.service'; +@Command({ + name: 'upgrade-0.30:fix-email-field-migration', + description: + 'Fix migration - delete deprecated email fields and add emails to person views', +}) +export class FixEmailFieldsToEmailsCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, + private readonly fieldMetadataService: FieldMetadataService, + private readonly typeORMService: TypeORMService, + private readonly dataSourceService: DataSourceService, + private readonly viewService: ViewService, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log('Running command to fix migration'); + + for (const workspaceId of workspaceIds) { + let dataSourceMetadata; + + this.logger.log(`Running command for workspace ${workspaceId}`); + try { + dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( + workspaceId, + ); + + if (!dataSourceMetadata) { + throw new Error( + `Could not find dataSourceMetadata for workspace ${workspaceId}`, + ); + } + + const workspaceDataSource = + await this.typeORMService.connectToDataSource(dataSourceMetadata); + + if (!workspaceDataSource) { + throw new Error( + `Could not connect to dataSource for workspace ${workspaceId}`, + ); + } + } catch (error) { + this.logger.log( + chalk.red( + `Could not connect to workspace data source for workspace ${workspaceId}`, + ), + ); + continue; + } + + try { + const deprecatedPersonEmailFieldsMetadata = + await this.fieldMetadataRepository.findBy({ + standardId: PERSON_STANDARD_FIELD_IDS.email, + workspaceId: workspaceId, + }); + + const migratedEmailFieldMetadata = await this.fieldMetadataRepository + .findBy({ + standardId: PERSON_STANDARD_FIELD_IDS.emails, + workspaceId: workspaceId, + }) + .then((fields) => fields[0]); + + const personEmailFieldWasMigratedButHasDuplicate = + deprecatedPersonEmailFieldsMetadata.length > 0 && + isDefined(migratedEmailFieldMetadata); + + if (!personEmailFieldWasMigratedButHasDuplicate) { + this.logger.log( + chalk.yellow('No fields to migrate for workspace ' + workspaceId), + ); + continue; + } + + for (const deprecatedEmailFieldMetadata of deprecatedPersonEmailFieldsMetadata) { + await this.fieldMetadataService.deleteOneField( + { id: deprecatedEmailFieldMetadata.id }, + workspaceId, + ); + this.logger.log( + chalk.green(`Deleted email field for workspace ${workspaceId}.`), + ); + } + + const personObjectMetadaIdForWorkspace = + migratedEmailFieldMetadata.objectMetadataId; + + if (!isDefined(personObjectMetadaIdForWorkspace)) { + this.logger.log( + chalk.red( + `Could not find person object for workspace ${workspaceId}. Could not add emails to person view`, + ), + ); + continue; + } + + const personViewsIds = + await this.viewService.getViewsIdsForObjectMetadataId({ + workspaceId, + objectMetadataId: personObjectMetadaIdForWorkspace as string, + }); + + await this.viewService.addFieldToViews({ + workspaceId: workspaceId, + fieldId: migratedEmailFieldMetadata.id, + viewsIds: personViewsIds, + positions: personViewsIds.reduce((acc, personView) => { + if (!personView.id) { + return acc; + } + acc[personView.id] = 4; + + return acc; + }, []), + }); + this.logger.log(chalk.green(`Added emails to view ${workspaceId}.`)); + } catch (error) { + this.logger.log( + chalk.red( + `Running command on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } finally { + this.logger.log( + chalk.green(`Finished running command for workspace ${workspaceId}.`), + ); + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-view-filter-operand-for-date-time.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-view-filter-operand-for-date-time.command.ts new file mode 100644 index 000000000000..f2e98d6600a7 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-fix-view-filter-operand-for-date-time.command.ts @@ -0,0 +1,110 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { Any, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { + FieldMetadataEntity, + FieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/view-filter.workspace-entity'; + +@Command({ + name: 'upgrade-0.30:fix-view-filter-operand-for-date-time', + description: 'Fix the view filter operand for date time fields', +}) +export class FixViewFilterOperandForDateTimeCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, + private readonly dataSourceService: DataSourceService, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + for (const workspaceId of workspaceIds) { + try { + const dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( + workspaceId, + ); + + if (!dataSourceMetadata) { + throw new Error( + `Could not find dataSourceMetadata for workspace ${workspaceId}`, + ); + } + + const viewFilterRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewFilterWorkspaceEntity>( + workspaceId, + 'viewFilter', + ); + + const dateTimeFieldMetadata = await this.fieldMetadataRepository.find({ + where: { + workspaceId, + type: FieldMetadataType.DATE_TIME, + }, + }); + + const dateTimeFieldMetadataIds = dateTimeFieldMetadata.map( + (fieldMetadata) => fieldMetadata.id, + ); + + const lessThanUpdatedResult = await viewFilterRepository.update( + { + operand: 'lessThan', + fieldMetadataId: Any(dateTimeFieldMetadataIds), + }, + { + operand: 'isBefore', + }, + ); + + const greaterThanUpdatedResult = await viewFilterRepository.update( + { + operand: 'greaterThan', + fieldMetadataId: Any(dateTimeFieldMetadataIds), + }, + { + operand: 'isAfter', + }, + ); + + this.logger.log( + `Updated ${(lessThanUpdatedResult.affected ?? 0) + (greaterThanUpdatedResult.affected ?? 0)} view filters for workspace ${workspaceId}`, + ); + } catch (error) { + this.logger.log( + chalk.red( + `Error running command for workspace ${workspaceId}: ${error}`, + ), + ); + continue; + } finally { + this.logger.log( + chalk.green(`Finished running command for workspace ${workspaceId}.`), + ); + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command.ts new file mode 100644 index 000000000000..2e4969297a6b --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command.ts @@ -0,0 +1,360 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { QueryRunner, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { + FieldMetadataEntity, + FieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { computeTableName } from 'src/engine/utils/compute-table-name.util'; +import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { ViewService } from 'src/modules/view/services/view.service'; +import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; +@Command({ + name: 'upgrade-0.30:migrate-email-fields-to-emails', + description: 'Migrating fields of deprecated type EMAIL to type EMAILS', +}) +export class MigrateEmailFieldsToEmailsCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + private readonly fieldMetadataService: FieldMetadataService, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + private readonly typeORMService: TypeORMService, + private readonly dataSourceService: DataSourceService, + private readonly viewService: ViewService, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log( + 'Running command to migrate email type fields to emails type', + ); + + for (const workspaceId of workspaceIds) { + let dataSourceMetadata; + let workspaceQueryRunner; + + this.logger.log(`Running command for workspace ${workspaceId}`); + try { + dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( + workspaceId, + ); + + if (!dataSourceMetadata) { + throw new Error( + `Could not find dataSourceMetadata for workspace ${workspaceId}`, + ); + } + + const workspaceDataSource = + await this.typeORMService.connectToDataSource(dataSourceMetadata); + + if (!workspaceDataSource) { + throw new Error( + `Could not connect to dataSource for workspace ${workspaceId}`, + ); + } + + workspaceQueryRunner = workspaceDataSource.createQueryRunner(); + + await workspaceQueryRunner.connect(); + } catch (error) { + this.logger.log( + chalk.red( + `Could not connect to workspace data source for workspace ${workspaceId}`, + ), + ); + continue; + } + + try { + await this.migratePersonEmailFieldToEmailsField( + workspaceId, + workspaceQueryRunner, + dataSourceMetadata, + ); + + const customFieldsWithEmailType = + await this.fieldMetadataRepository.find({ + where: { + workspaceId, + type: FieldMetadataType.EMAIL, + isCustom: true, + }, + }); + + for (const customFieldWithEmailType of customFieldsWithEmailType) { + const objectMetadata = await this.objectMetadataRepository.findOne({ + where: { id: customFieldWithEmailType.objectMetadataId }, + }); + + if (!objectMetadata) { + throw new Error( + `Could not find objectMetadata for field ${customFieldWithEmailType.name}`, + ); + } + + this.logger.log( + `Attempting to migrate custom field ${customFieldWithEmailType.name} on ${objectMetadata.nameSingular}.`, + ); + + const fieldName = customFieldWithEmailType.name; + const { id: _id, ...fieldWithEmailTypeWithoutId } = + customFieldWithEmailType; + + const emailDefaultValue = fieldWithEmailTypeWithoutId.defaultValue; + + const defaultValueForEmailsField = { + primaryEmail: emailDefaultValue, + additionalEmails: null, + }; + + try { + const tmpNewEmailsField = await this.fieldMetadataService.createOne( + { + ...fieldWithEmailTypeWithoutId, + type: FieldMetadataType.EMAILS, + defaultValue: defaultValueForEmailsField, + name: `${fieldName}Tmp`, + } satisfies CreateFieldInput, + ); + + const tableName = computeTableName( + objectMetadata.nameSingular, + objectMetadata.isCustom, + ); + + // Migrate data from email to emails.primaryEmail + await this.migrateDataWithinTable({ + sourceColumnName: `${customFieldWithEmailType.name}`, + targetColumnName: `${tmpNewEmailsField.name}PrimaryEmail`, + tableName, + workspaceQueryRunner, + dataSourceMetadata, + }); + + // Duplicate email field's views behaviour for new emails field + await this.viewService.removeFieldFromViews({ + workspaceId: workspaceId, + fieldId: tmpNewEmailsField.id, + }); + + const viewFieldRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewFieldWorkspaceEntity>( + workspaceId, + 'viewField', + ); + const viewFieldsWithDeprecatedField = + await viewFieldRepository.find({ + where: { + fieldMetadataId: customFieldWithEmailType.id, + isVisible: true, + }, + }); + + await this.viewService.addFieldToViews({ + workspaceId: workspaceId, + fieldId: tmpNewEmailsField.id, + viewsIds: viewFieldsWithDeprecatedField + .filter((viewField) => viewField.viewId !== null) + .map((viewField) => viewField.viewId as string), + positions: viewFieldsWithDeprecatedField.reduce( + (acc, viewField) => { + if (!viewField.viewId) { + return acc; + } + acc[viewField.viewId] = viewField.position; + + return acc; + }, + [], + ), + }); + + // Delete email field + await this.fieldMetadataService.deleteOneField( + { id: customFieldWithEmailType.id }, + workspaceId, + ); + + // Rename temporary emails field + await this.fieldMetadataService.updateOne(tmpNewEmailsField.id, { + id: tmpNewEmailsField.id, + workspaceId: tmpNewEmailsField.workspaceId, + name: `${fieldName}`, + isCustom: false, + }); + + this.logger.log( + `Migration of ${customFieldWithEmailType.name} on ${objectMetadata.nameSingular} done!`, + ); + } catch (error) { + this.logger.log( + `Failed to migrate field ${customFieldWithEmailType.name} on ${objectMetadata.nameSingular}, rolling back.`, + ); + + // Re-create initial field if it was deleted + const initialField = + await this.fieldMetadataService.findOneWithinWorkspace( + workspaceId, + { + where: { + name: `${customFieldWithEmailType.name}`, + objectMetadataId: customFieldWithEmailType.objectMetadataId, + }, + }, + ); + + const tmpNewEmailsField = + await this.fieldMetadataService.findOneWithinWorkspace( + workspaceId, + { + where: { + name: `${customFieldWithEmailType.name}Tmp`, + objectMetadataId: customFieldWithEmailType.objectMetadataId, + }, + }, + ); + + if (!initialField) { + this.logger.log( + `Re-creating initial Email field ${customFieldWithEmailType.name} but of type emails`, // Cannot create email fields anymore + ); + const restoredField = await this.fieldMetadataService.createOne({ + ...customFieldWithEmailType, + defaultValue: defaultValueForEmailsField, + type: FieldMetadataType.EMAILS, + }); + const tableName = computeTableName( + objectMetadata.nameSingular, + objectMetadata.isCustom, + ); + + if (tmpNewEmailsField) { + this.logger.log( + `Restoring data in field ${customFieldWithEmailType.name}`, + ); + await this.migrateDataWithinTable({ + sourceColumnName: `${tmpNewEmailsField.name}PrimaryEmail`, + targetColumnName: `${restoredField.name}PrimaryEmail`, + tableName, + workspaceQueryRunner, + dataSourceMetadata, + }); + } else { + this.logger.log( + `Failed to restore data in link field ${customFieldWithEmailType.name}`, + ); + } + } + + if (tmpNewEmailsField) { + await this.fieldMetadataService.deleteOneField( + { id: tmpNewEmailsField.id }, + workspaceId, + ); + } + } + } + } catch (error) { + await workspaceQueryRunner.release(); + + this.logger.log( + chalk.red( + `Running command on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } finally { + await workspaceQueryRunner.release(); + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } + + private async migratePersonEmailFieldToEmailsField( + workspaceId: string, + workspaceQueryRunner: any, + dataSourceMetadata: any, + ) { + this.logger.log(`Migrating person email field of type EMAIL to EMAILS`); + + const personEmailFieldMetadata = await this.fieldMetadataRepository.findOne( + { + where: { + workspaceId, + standardId: PERSON_STANDARD_FIELD_IDS.email, + }, + }, + ); + + if (!personEmailFieldMetadata) { + this.logger.log( + `Could not find person email field with standardId ${PERSON_STANDARD_FIELD_IDS.email}, skipping migration`, + ); + + return; + } + + await this.migrateDataWithinTable({ + sourceColumnName: 'email', + targetColumnName: 'emailsPrimaryEmail', + tableName: 'person', + workspaceQueryRunner, + dataSourceMetadata, + }); + + if (personEmailFieldMetadata) { + await this.fieldMetadataService.deleteOneField( + { + id: personEmailFieldMetadata.id, + }, + workspaceId, + ); + } + } + + private async migrateDataWithinTable({ + sourceColumnName, + targetColumnName, + tableName, + workspaceQueryRunner, + dataSourceMetadata, + }: { + sourceColumnName: string; + targetColumnName: string; + tableName: string; + workspaceQueryRunner: QueryRunner; + dataSourceMetadata: DataSourceEntity; + }) { + await workspaceQueryRunner.query( + `UPDATE "${dataSourceMetadata.schema}"."${tableName}" SET "${targetColumnName}" = "${sourceColumnName}"`, + ); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-phone-fields-to-phones.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-phone-fields-to-phones.command.ts new file mode 100644 index 000000000000..6560bb9625dc --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-migrate-phone-fields-to-phones.command.ts @@ -0,0 +1,366 @@ +import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { isDefined, isEmpty } from 'class-validator'; +import { parsePhoneNumber } from 'libphonenumber-js'; +import { Command } from 'nest-commander'; +import { DataSource, QueryRunner, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { + FieldMetadataEntity, + FieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; +import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { computeTableName } from 'src/engine/utils/compute-table-name.util'; +import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { ViewService } from 'src/modules/view/services/view.service'; +import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; + +type MigratePhoneFieldsToPhonesCommandOptions = ActiveWorkspacesCommandOptions; +@Command({ + name: 'upgrade-0.30:migrate-phone-fields-to-phones', + description: 'Migrating fields of deprecated type PHONE to type PHONES', +}) +export class MigratePhoneFieldsToPhonesCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + @InjectDataSource('metadata') + private readonly metadataDataSource: DataSource, + private readonly fieldMetadataService: FieldMetadataService, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + private readonly typeORMService: TypeORMService, + private readonly dataSourceService: DataSourceService, + private readonly viewService: ViewService, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: MigratePhoneFieldsToPhonesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log( + 'Running command to migrate phone type fields to phones type', + ); + for (const workspaceId of workspaceIds) { + this.logger.log(`Running command for workspace ${workspaceId}`); + try { + const dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( + workspaceId, + ); + + if (!dataSourceMetadata) { + throw new Error( + `Could not find dataSourceMetadata for workspace ${workspaceId}`, + ); + } + const workspaceDataSource = + await this.typeORMService.connectToDataSource(dataSourceMetadata); + + if (!workspaceDataSource) { + throw new Error( + `Could not connect to dataSource for workspace ${workspaceId}`, + ); + } + const standardPersonPhoneFieldWithTextType = + await this.fieldMetadataRepository.findOneBy({ + workspaceId, + standardId: PERSON_STANDARD_FIELD_IDS.phone, + }); + + if (!standardPersonPhoneFieldWithTextType) { + throw new Error( + `Could not find standard phone field on person for workspace ${workspaceId}`, + ); + } + + await this.migrateStandardPersonPhoneField({ + standardPersonPhoneField: standardPersonPhoneFieldWithTextType, + workspaceDataSource, + workspaceSchemaName: dataSourceMetadata.schema, + }); + + const fieldsWithPhoneType = await this.fieldMetadataRepository.find({ + where: { + workspaceId, + type: FieldMetadataType.PHONE, + }, + }); + + for (const deprecatedPhoneField of fieldsWithPhoneType) { + await this.migrateCustomPhoneField({ + phoneField: deprecatedPhoneField, + workspaceDataSource, + workspaceSchemaName: dataSourceMetadata.schema, + }); + } + } catch (error) { + this.logger.log( + chalk.red( + `Field migration on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } + this.logger.log(chalk.green(`Command completed!`)); + } + } + + private async migrateStandardPersonPhoneField({ + standardPersonPhoneField, + workspaceDataSource, + workspaceSchemaName, + }: { + standardPersonPhoneField: FieldMetadataEntity; + workspaceDataSource: DataSource; + workspaceSchemaName: string; + }) { + const personObjectMetadata = await this.objectMetadataRepository.findOne({ + where: { id: standardPersonPhoneField.objectMetadataId }, + }); + + if (!personObjectMetadata) { + throw new Error( + `Could not find Person objectMetadata (id ${standardPersonPhoneField.objectMetadataId})`, + ); + } + + this.logger.log(`Attempting to migrate standard person phone field.`); + const workspaceQueryRunner = workspaceDataSource.createQueryRunner(); + + await workspaceQueryRunner.connect(); + const { id: _id, ...deprecatedPhoneFieldWithoutId } = + standardPersonPhoneField; + + const workspaceId = standardPersonPhoneField.workspaceId; + + try { + let standardPersonPhonesField = + await this.fieldMetadataRepository.findOneBy({ + workspaceId, + standardId: PERSON_STANDARD_FIELD_IDS.phones, + }); + + if (!standardPersonPhonesField) { + standardPersonPhonesField = await this.fieldMetadataService.createOne({ + ...deprecatedPhoneFieldWithoutId, + label: 'Phones', + type: FieldMetadataType.PHONES, + defaultValue: null, + name: 'phones', + } satisfies CreateFieldInput); + + // StandardId and isCustom are not exposed in CreateFieldInput + await this.metadataDataSource.query( + `UPDATE "metadata"."fieldMetadata" SET "standardId" = $1, "isCustom" = $2 where "id"=$3`, + [ + PERSON_STANDARD_FIELD_IDS.phones, + 'false', + standardPersonPhonesField.id, + ], + ); + + await this.viewService.removeFieldFromViews({ + workspaceId: workspaceId, + fieldId: standardPersonPhonesField.id, + }); + } + + // Copy phone data from Text type to Phones type + await this.copyAndParseDeprecatedPhoneFieldDataIntoNewPhonesField({ + workspaceQueryRunner, + workspaceSchemaName, + }); + + // Add (deprecated) to Phone field label + await this.metadataDataSource.query( + `UPDATE "metadata"."fieldMetadata" SET "label" = $1 where "id"=$2`, + ['Phone (deprecated)', standardPersonPhoneField.id], + ); + + // Add new phones field to views and hide deprecated phone field + const viewFieldRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewFieldWorkspaceEntity>( + workspaceId, + 'viewField', + ); + const viewFieldsWithDeprecatedPhoneField = await viewFieldRepository.find( + { + where: { + fieldMetadataId: standardPersonPhoneField.id, + isVisible: true, + }, + }, + ); + + await this.viewService.addFieldToViews({ + workspaceId: workspaceId, + fieldId: standardPersonPhonesField.id, + viewsIds: viewFieldsWithDeprecatedPhoneField + .filter((viewField) => viewField.viewId !== null) + .map((viewField) => viewField.viewId as string), + positions: viewFieldsWithDeprecatedPhoneField.reduce( + (acc, viewField) => { + if (!viewField.viewId) { + return acc; + } + acc[viewField.viewId] = viewField.position; + + return acc; + }, + [], + ), + size: 150, + }); + + await this.viewService.removeFieldFromViews({ + workspaceId: workspaceId, + fieldId: standardPersonPhoneField.id, + }); + + this.logger.log( + `Migration of standard person phone field to phones is done!`, + ); + } catch (error) { + this.logger.log( + chalk.red( + `Failed to migrate field standard person phone field to phones, rolling back. (Error: ${error})`, + ), + ); + + // Delete new phones field if it was created + const newPhonesField = + await this.fieldMetadataService.findOneWithinWorkspace(workspaceId, { + where: { + name: 'phones', + objectMetadataId: standardPersonPhoneField.objectMetadataId, + }, + }); + + if (newPhonesField) { + this.logger.log( + `Deleting phones field of type Phone as part of rolling back.`, + ); + await this.fieldMetadataService.deleteOneField( + { id: newPhonesField.id }, + workspaceId, + ); + } + + // Revert Phone field label (remove (deprecated)) + await this.metadataDataSource.query( + `UPDATE "metadata"."fieldMetadata" SET "label" = $1 where "id"=$2`, + ['Phone', standardPersonPhoneField.id], + ); + } finally { + await workspaceQueryRunner.release(); + } + } + + private async migrateCustomPhoneField({ + phoneField, + workspaceDataSource, + workspaceSchemaName, + }: { + phoneField: FieldMetadataEntity; + workspaceDataSource: DataSource; + workspaceSchemaName: string; + }) { + if (!phoneField) return; + const objectMetadata = await this.objectMetadataRepository.findOne({ + where: { id: phoneField.objectMetadataId }, + }); + + if (!objectMetadata) { + throw new Error( + `Could not find objectMetadata for field ${phoneField.name}`, + ); + } + this.logger.log( + `Attempting to migrate field ${phoneField.name} on ${objectMetadata.nameSingular} from Phone to Text.`, + ); + const workspaceQueryRunner = workspaceDataSource.createQueryRunner(); + + await workspaceQueryRunner.connect(); + + try { + await this.metadataDataSource.query( + `UPDATE "metadata"."fieldMetadata" SET "type" = $1 where "id"=$2`, + [FieldMetadataType.TEXT, phoneField.id], + ); + + await workspaceQueryRunner.query( + `ALTER TABLE "${workspaceSchemaName}"."${computeTableName(objectMetadata.nameSingular, objectMetadata.isCustom)}" ALTER COLUMN "${computeColumnName(phoneField.name)}" TYPE TEXT`, + ); + } catch (error) { + this.logger.log( + chalk.red( + `Failed to migrate field ${phoneField.name} on ${objectMetadata.nameSingular} from Phone to Text.`, + ), + ); + } finally { + await workspaceQueryRunner.release(); + } + } + + private async copyAndParseDeprecatedPhoneFieldDataIntoNewPhonesField({ + workspaceQueryRunner, + workspaceSchemaName, + }: { + workspaceQueryRunner: QueryRunner; + workspaceSchemaName: string; + }) { + const deprecatedPhoneFieldRows = await workspaceQueryRunner.query( + `SELECT id, phone FROM "${workspaceSchemaName}"."person" WHERE + phone IS NOT null`, + ); + + for (const row of deprecatedPhoneFieldRows) { + const phoneColumnValue = row['phone']; + + if (isDefined(phoneColumnValue) && !isEmpty(phoneColumnValue)) { + const query = `UPDATE "${workspaceSchemaName}"."person" SET "phonesPrimaryPhoneCountryCode" = $1,"phonesPrimaryPhoneNumber" = $2 where "id"=$3 AND ("phonesPrimaryPhoneCountryCode" IS NULL OR "phonesPrimaryPhoneCountryCode" = '');`; + + try { + const parsedPhoneColumnValue = parsePhoneNumber(phoneColumnValue); + + await workspaceQueryRunner.query(query, [ + `+${parsedPhoneColumnValue.countryCallingCode}`, + parsedPhoneColumnValue.nationalNumber, + row.id, + ]); + } catch (error) { + this.logger.log( + chalk.red( + `Could not save phone number ${phoneColumnValue}, will try again storing value as is without parsing, with default country code.`, + ), + ); + // Store the invalid string for invalid phone numbers + await workspaceQueryRunner.query(query, [ + '', + phoneColumnValue, + row.id, + ]); + } + } + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending.ts new file mode 100644 index 000000000000..3d1744910f48 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending.ts @@ -0,0 +1,90 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { IsNull, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { + MessageChannelSyncStage, + MessageChannelWorkspaceEntity, +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +@Command({ + name: 'upgrade-0.30:set-stale-message-sync-back-to-pending', + description: 'Set stale message sync back to pending', +}) +export class SetStaleMessageSyncBackToPendingCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log( + 'Running command to set stale message sync back to pending', + ); + + for (const workspaceId of workspaceIds) { + this.logger.log(`Running command for workspace ${workspaceId}`); + + try { + const dataSource = + await this.twentyORMGlobalManager.getDataSourceForWorkspace( + workspaceId, + ); + + const messageChannelRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>( + workspaceId, + 'messageChannel', + ); + + dataSource.transaction(async (entityManager) => { + await messageChannelRepository.update( + { + syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING, + syncStageStartedAt: IsNull(), + }, + { + syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_PENDING, + }, + entityManager, + ); + + await messageChannelRepository.update( + { + syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING, + syncStageStartedAt: IsNull(), + }, + { + syncStage: + MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING, + }, + entityManager, + ); + }); + } catch (error) { + this.logger.log( + chalk.red( + `Running command on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.command.ts new file mode 100644 index 000000000000..25ff077ca5e1 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.command.ts @@ -0,0 +1,76 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command'; +import { FixEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command'; +import { FixViewFilterOperandForDateTimeCommand } from 'src/database/commands/upgrade-version/0-30/0-30-fix-view-filter-operand-for-date-time.command'; +import { MigrateEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command'; +import { MigratePhoneFieldsToPhonesCommand } from 'src/database/commands/upgrade-version/0-30/0-30-migrate-phone-fields-to-phones.command'; +import { SetStaleMessageSyncBackToPendingCommand } from 'src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; + +interface UpdateTo0_30CommandOptions { + workspaceId?: string; +} + +@Command({ + name: 'upgrade-0.30', + description: 'Upgrade to 0.30', +}) +export class UpgradeTo0_30Command extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + private readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, + private readonly migrateEmailFieldsToEmails: MigrateEmailFieldsToEmailsCommand, + private readonly setStaleMessageSyncBackToPendingCommand: SetStaleMessageSyncBackToPendingCommand, + private readonly fixEmailFieldsToEmailsCommand: FixEmailFieldsToEmailsCommand, + private readonly migratePhoneFieldsToPhones: MigratePhoneFieldsToPhonesCommand, + private readonly fixViewFilterOperandForDateTimeCommand: FixViewFilterOperandForDateTimeCommand, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + passedParam: string[], + options: UpdateTo0_30CommandOptions, + workspaceIds: string[], + ): Promise<void> { + await this.syncWorkspaceMetadataCommand.executeActiveWorkspacesCommand( + passedParam, + { + ...options, + force: true, + }, + workspaceIds, + ); + await this.migrateEmailFieldsToEmails.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + await this.setStaleMessageSyncBackToPendingCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + await this.fixEmailFieldsToEmailsCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + await this.migratePhoneFieldsToPhones.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + await this.fixViewFilterOperandForDateTimeCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.module.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.module.ts new file mode 100644 index 000000000000..191bad9352cb --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-30/0-30-upgrade-version.module.ts @@ -0,0 +1,43 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { FixEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-fix-email-field-migration.command'; +import { FixViewFilterOperandForDateTimeCommand } from 'src/database/commands/upgrade-version/0-30/0-30-fix-view-filter-operand-for-date-time.command'; +import { MigrateEmailFieldsToEmailsCommand } from 'src/database/commands/upgrade-version/0-30/0-30-migrate-email-fields-to-emails.command'; +import { MigratePhoneFieldsToPhonesCommand } from 'src/database/commands/upgrade-version/0-30/0-30-migrate-phone-fields-to-phones.command'; +import { SetStaleMessageSyncBackToPendingCommand } from 'src/database/commands/upgrade-version/0-30/0-30-set-stale-message-sync-back-to-pending'; +import { UpgradeTo0_30Command } from 'src/database/commands/upgrade-version/0-30/0-30-upgrade-version.command'; +import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module'; +import { ViewModule } from 'src/modules/view/view.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Workspace], 'core'), + WorkspaceSyncMetadataCommandsModule, + DataSourceModule, + WorkspaceMetadataVersionModule, + FieldMetadataModule, + TypeOrmModule.forFeature( + [FieldMetadataEntity, ObjectMetadataEntity], + 'metadata', + ), + TypeORMModule, + ViewModule, + ], + providers: [ + UpgradeTo0_30Command, + MigrateEmailFieldsToEmailsCommand, + SetStaleMessageSyncBackToPendingCommand, + FixEmailFieldsToEmailsCommand, + MigratePhoneFieldsToPhonesCommand, + FixViewFilterOperandForDateTimeCommand, + ], +}) +export class UpgradeTo0_30CommandModule {} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-add-index-key-to-tasks-and-notes-views.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-add-index-key-to-tasks-and-notes-views.command.ts new file mode 100644 index 000000000000..35f9a55b0744 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-add-index-key-to-tasks-and-notes-views.command.ts @@ -0,0 +1,128 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { In, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; + +@Command({ + name: 'upgrade-0.31:add-index-key-to-tasks-and-notes-views', + description: 'Add index key to tasks and notes views', +}) +export class AddIndexKeyToTasksAndNotesViewsCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log('Running command to fix migration'); + + for (const workspaceId of workspaceIds) { + this.logger.log(`Running command for workspace ${workspaceId}`); + + try { + this.logger.log(chalk.green(`Cleaning views of ${workspaceId}.`)); + + await this.addIndexKeyToTasksAndNotesViews( + workspaceId, + _options.dryRun ?? false, + ); + + await this.twentyORMGlobalManager.destroyDataSourceForWorkspace( + workspaceId, + ); + } catch (error) { + this.logger.log( + chalk.red( + `Running command on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } finally { + this.logger.log( + chalk.green(`Finished running command for workspace ${workspaceId}.`), + ); + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } + + private async addIndexKeyToTasksAndNotesViews( + workspaceId: string, + dryRun: boolean, + ): Promise<void> { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewWorkspaceEntity>( + workspaceId, + 'view', + false, + ); + + const allViews = await viewRepository.find(); + + const viewObjectMetadataIds = allViews.map((view) => view.objectMetadataId); + + const objectMetadataEntities = await this.objectMetadataRepository.find({ + where: { + id: In(viewObjectMetadataIds), + }, + }); + + const tasksAndNotesObjectMetadataIds = objectMetadataEntities.filter( + (entity) => + entity.standardId === STANDARD_OBJECT_IDS.task || + entity.standardId === STANDARD_OBJECT_IDS.note, + ); + + const viewsToUpdate = allViews.filter( + (view) => + tasksAndNotesObjectMetadataIds.some( + (entity) => entity.id === view.objectMetadataId, + ) && + ['All Tasks', 'All Notes'].includes(view.name) && + view.key === null, + ); + + if (dryRun) { + this.logger.log( + chalk.green( + `Found ${viewsToUpdate.length} views to update in workspace ${workspaceId}.`, + ), + ); + } + + if (viewsToUpdate.length > 0 && !dryRun) { + await viewRepository.update( + viewsToUpdate.map((view) => view.id), + { + key: 'INDEX', + }, + ); + this.logger.log(chalk.green(`Updating ${viewsToUpdate.length} views.`)); + } + + if (viewsToUpdate.length === 0 && !dryRun) { + this.logger.log(chalk.green(`No views to update.`)); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-backfill-workspace-favorites.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-backfill-workspace-favorites.command.ts new file mode 100644 index 000000000000..90c415123a38 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-backfill-workspace-favorites.command.ts @@ -0,0 +1,162 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { In, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; + +@Command({ + name: 'upgrade-0.31:backfill-workspace-favorites-migration', + description: 'Create a workspace favorite for all workspace views', +}) +export class BackfillWorkspaceFavoritesCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log('Running command to fix migration'); + + for (const workspaceId of workspaceIds) { + this.logger.log(`Running command for workspace ${workspaceId}`); + + try { + const allWorkspaceIndexViews = await this.getIndexViews(workspaceId); + + const activeWorkspaceIndexViews = + await this.filterViewsWithoutObjectMetadata( + workspaceId, + allWorkspaceIndexViews, + ); + + await this.createViewWorkspaceFavorites( + workspaceId, + activeWorkspaceIndexViews.map((view) => view.id), + _options.dryRun ?? false, + ); + + this.logger.log( + chalk.green(`Backfilled workspace favorites to ${workspaceId}.`), + ); + + await this.twentyORMGlobalManager.destroyDataSourceForWorkspace( + workspaceId, + ); + } catch (error) { + this.logger.log( + chalk.red( + `Running command on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } finally { + this.logger.log( + chalk.green(`Finished running command for workspace ${workspaceId}.`), + ); + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } + + private async getIndexViews( + workspaceId: string, + ): Promise<ViewWorkspaceEntity[]> { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewWorkspaceEntity>( + workspaceId, + 'view', + false, + ); + + return viewRepository.find({ + where: { + key: 'INDEX', + }, + }); + } + + private async filterViewsWithoutObjectMetadata( + workspaceId: string, + views: ViewWorkspaceEntity[], + ): Promise<ViewWorkspaceEntity[]> { + const viewObjectMetadataIds = views.map((view) => view.objectMetadataId); + + const objectMetadataEntities = await this.objectMetadataRepository.find({ + where: { + workspaceId, + id: In(viewObjectMetadataIds), + }, + }); + + const objectMetadataIds = new Set( + objectMetadataEntities.map((entity) => entity.id), + ); + + return views.filter((view) => objectMetadataIds.has(view.objectMetadataId)); + } + + private async createViewWorkspaceFavorites( + workspaceId: string, + viewIds: string[], + dryRun: boolean, + ) { + const favoriteRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<FavoriteWorkspaceEntity>( + workspaceId, + 'favorite', + ); + + let nextFavoritePosition = await favoriteRepository.count(); + let createdFavorites = 0; + + for (const viewId of viewIds) { + const existingFavorites = await favoriteRepository.find({ + where: { + viewId, + }, + }); + + if (existingFavorites.length) { + continue; + } + + if (!dryRun) { + await favoriteRepository.insert( + favoriteRepository.create({ + viewId, + position: nextFavoritePosition, + }), + ); + } + + createdFavorites++; + nextFavoritePosition++; + } + + this.logger.log( + chalk.green( + `Found ${createdFavorites} favorites to backfill in workspace ${workspaceId}.`, + ), + ); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-clean-views-associated-with-outdated-objects.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-clean-views-associated-with-outdated-objects.command.ts new file mode 100644 index 000000000000..6643f68427e2 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-clean-views-associated-with-outdated-objects.command.ts @@ -0,0 +1,119 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { In, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; + +@Command({ + name: 'upgrade-0.31:clean-views-associated-with-outdated-objects', + description: + 'Clean views associated with deleted object metadata or activities', +}) +export class CleanViewsAssociatedWithOutdatedObjectsCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + _options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise<void> { + this.logger.log('Running command to fix migration'); + + for (const workspaceId of workspaceIds) { + this.logger.log(`Running command for workspace ${workspaceId}`); + + try { + this.logger.log(chalk.green(`Cleaning views of ${workspaceId}.`)); + + await this.cleanViewsWithDeletedObjectMetadata( + workspaceId, + _options.dryRun ?? false, + ); + + await this.twentyORMGlobalManager.destroyDataSourceForWorkspace( + workspaceId, + ); + } catch (error) { + this.logger.log( + chalk.red( + `Running command on workspace ${workspaceId} failed with error: ${error}`, + ), + ); + continue; + } finally { + this.logger.log( + chalk.green(`Finished running command for workspace ${workspaceId}.`), + ); + } + + this.logger.log(chalk.green(`Command completed!`)); + } + } + + private async cleanViewsWithDeletedObjectMetadata( + workspaceId: string, + dryRun: boolean, + ): Promise<void> { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewWorkspaceEntity>( + workspaceId, + 'view', + false, + ); + + const allViews = await viewRepository.find(); + + const viewObjectMetadataIds = allViews.map((view) => view.objectMetadataId); + + const objectMetadataEntities = await this.objectMetadataRepository.find({ + where: { + id: In(viewObjectMetadataIds), + }, + }); + + const validObjectMetadataIds = new Set( + objectMetadataEntities + .filter((entity) => entity.standardId !== STANDARD_OBJECT_IDS.activity) + .map((entity) => entity.id), + ); + + const viewIdsToDelete = allViews + .filter((view) => !validObjectMetadataIds.has(view.objectMetadataId)) + .map((view) => view.id); + + if (dryRun) { + this.logger.log( + chalk.green( + `Found ${viewIdsToDelete.length} views to clean in workspace ${workspaceId}.`, + ), + ); + } + + if (viewIdsToDelete.length > 0 && !dryRun) { + await viewRepository.delete(viewIdsToDelete); + this.logger.log(chalk.green(`Cleaning ${viewIdsToDelete.length} views.`)); + } + + if (viewIdsToDelete.length === 0) { + this.logger.log(chalk.green(`No views to clean.`)); + } + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.command.ts new file mode 100644 index 000000000000..1ab48a059db3 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.command.ts @@ -0,0 +1,62 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command'; +import { AddIndexKeyToTasksAndNotesViewsCommand } from 'src/database/commands/upgrade-version/0-31/0-31-add-index-key-to-tasks-and-notes-views.command'; +import { BackfillWorkspaceFavoritesCommand } from 'src/database/commands/upgrade-version/0-31/0-31-backfill-workspace-favorites.command'; +import { CleanViewsAssociatedWithOutdatedObjectsCommand } from 'src/database/commands/upgrade-version/0-31/0-31-clean-views-associated-with-outdated-objects.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; + +interface UpdateTo0_31CommandOptions { + workspaceId?: string; +} + +@Command({ + name: 'upgrade-0.31', + description: 'Upgrade to 0.31', +}) +export class UpgradeTo0_31Command extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, + private readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, + private readonly backfillWorkspaceFavoritesCommand: BackfillWorkspaceFavoritesCommand, + private readonly cleanViewsAssociatedWithOutdatedObjectsCommand: CleanViewsAssociatedWithOutdatedObjectsCommand, + private readonly addIndexKeyToTasksAndNotesViewsCommand: AddIndexKeyToTasksAndNotesViewsCommand, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + passedParam: string[], + options: UpdateTo0_31CommandOptions, + workspaceIds: string[], + ): Promise<void> { + await this.syncWorkspaceMetadataCommand.executeActiveWorkspacesCommand( + passedParam, + { + ...options, + force: true, + }, + workspaceIds, + ); + await this.cleanViewsAssociatedWithOutdatedObjectsCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + await this.addIndexKeyToTasksAndNotesViewsCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + await this.backfillWorkspaceFavoritesCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.module.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.module.ts new file mode 100644 index 000000000000..d53dc237e96a --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-31/0-31-upgrade-version.module.ts @@ -0,0 +1,25 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { AddIndexKeyToTasksAndNotesViewsCommand } from 'src/database/commands/upgrade-version/0-31/0-31-add-index-key-to-tasks-and-notes-views.command'; +import { BackfillWorkspaceFavoritesCommand } from 'src/database/commands/upgrade-version/0-31/0-31-backfill-workspace-favorites.command'; +import { CleanViewsAssociatedWithOutdatedObjectsCommand } from 'src/database/commands/upgrade-version/0-31/0-31-clean-views-associated-with-outdated-objects.command'; +import { UpgradeTo0_31Command } from 'src/database/commands/upgrade-version/0-31/0-31-upgrade-version.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Workspace], 'core'), + TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), + WorkspaceSyncMetadataCommandsModule, + ], + providers: [ + UpgradeTo0_31Command, + BackfillWorkspaceFavoritesCommand, + CleanViewsAssociatedWithOutdatedObjectsCommand, + AddIndexKeyToTasksAndNotesViewsCommand, + ], +}) +export class UpgradeTo0_31CommandModule {} diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/demo/user-workspaces.ts b/packages/twenty-server/src/database/typeorm-seeds/core/demo/user-workspaces.ts index 92ec82344db7..5e49424cb848 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/demo/user-workspaces.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/demo/user-workspaces.ts @@ -24,7 +24,7 @@ export const seedUserWorkspaces = async ( workspaceId: workspaceId, }, { - userId: DEMO_SEED_USER_IDS.JULIA, + userId: DEMO_SEED_USER_IDS.TIM, workspaceId: workspaceId, }, ]) diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/demo/users.ts b/packages/twenty-server/src/database/typeorm-seeds/core/demo/users.ts index 5b8760f07528..b82c73c07b39 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/demo/users.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/demo/users.ts @@ -7,7 +7,7 @@ const tableName = 'user'; export const DEMO_SEED_USER_IDS = { NOAH: '20202020-9e3b-46d4-a556-88b9ddc2b035', HUGO: '20202020-3957-4908-9c36-2929a23f8358', - JULIA: '20202020-7169-42cf-bc47-1cfef15264b9', + TIM: '20202020-7169-42cf-bc47-1cfef15264b9', }; export const seedUsers = async ( @@ -47,10 +47,10 @@ export const seedUsers = async ( defaultWorkspaceId: workspaceId, }, { - id: DEMO_SEED_USER_IDS.JULIA, - firstName: 'Julia', - lastName: 'S', - email: 'julia.s@demo.dev', + id: DEMO_SEED_USER_IDS.TIM, + firstName: 'Tim', + lastName: 'Apple', + email: 'tim@apple.dev', passwordHash: '$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025 defaultWorkspaceId: workspaceId, diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts index dd0be3fa81b7..8d3036235454 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts @@ -15,11 +15,6 @@ export const seedFeatureFlags = async ( .into(`${schemaName}.${tableName}`, ['key', 'workspaceId', 'value']) .orIgnore() .values([ - { - key: FeatureFlagKey.IsBlocklistEnabled, - workspaceId: workspaceId, - value: true, - }, { key: FeatureFlagKey.IsAirtableIntegrationEnabled, workspaceId: workspaceId, @@ -41,29 +36,29 @@ export const seedFeatureFlags = async ( value: true, }, { - key: FeatureFlagKey.IsMessagingAliasFetchingEnabled, + key: FeatureFlagKey.IsFunctionSettingsEnabled, workspaceId: workspaceId, value: true, }, { - key: FeatureFlagKey.IsGoogleCalendarSyncV2Enabled, + key: FeatureFlagKey.IsWorkflowEnabled, workspaceId: workspaceId, - value: true, + value: false, }, { - key: FeatureFlagKey.IsFunctionSettingsEnabled, + key: FeatureFlagKey.IsMessageThreadSubscriberEnabled, workspaceId: workspaceId, - value: true, + value: false, }, { - key: FeatureFlagKey.IsWorkflowEnabled, + key: FeatureFlagKey.IsWorkspaceFavoriteEnabled, workspaceId: workspaceId, value: false, }, { - key: FeatureFlagKey.IsMessageThreadSubscriberEnabled, + key: FeatureFlagKey.IsQueryRunnerTwentyORMEnabled, workspaceId: workspaceId, - value: false, + value: true, }, ]) .execute(); diff --git a/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts b/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts index ec81351541be..330975f00d02 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts @@ -92,7 +92,7 @@ export const getDevSeedPeopleCustomFields = ( }, { workspaceId, - type: FieldMetadataType.PHONE, + type: FieldMetadataType.PHONES, name: 'whatsapp', label: 'Whatsapp', description: "Contact's Whatsapp Number", diff --git a/packages/twenty-server/src/database/typeorm-seeds/metadata/objectsMetadata.ts b/packages/twenty-server/src/database/typeorm-seeds/metadata/objectsMetadata.ts new file mode 100644 index 000000000000..640b0b4c1d37 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm-seeds/metadata/objectsMetadata.ts @@ -0,0 +1,20 @@ +import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input'; + +export const getDevSeedCustomObjects = ( + workspaceId: string, + dataSourceId: string, +): CreateObjectInput[] => { + return [ + { + workspaceId, + dataSourceId, + labelPlural: 'Rockets', + labelSingular: 'Rocket', + namePlural: 'rockets', + nameSingular: 'rocket', + description: 'A rocket', + icon: 'IconRocket', + isRemote: false, + }, + ]; +}; diff --git a/packages/twenty-server/src/database/typeorm-seeds/workspace/favorites.ts b/packages/twenty-server/src/database/typeorm-seeds/workspace/favorites.ts new file mode 100644 index 000000000000..53d9b50d8d40 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm-seeds/workspace/favorites.ts @@ -0,0 +1,23 @@ +import { EntityManager } from 'typeorm'; +import { v4 } from 'uuid'; + +const tableName = 'favorite'; + +export const seedWorkspaceFavorites = async ( + viewIds: string[], + entityManager: EntityManager, + schemaName: string, +) => { + await entityManager + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, ['id', 'viewId', 'position']) + .values( + viewIds.map((viewId, index) => ({ + id: v4(), + viewId, + position: index, + })), + ) + .execute(); +}; diff --git a/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts b/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts index 03fa76409a1e..22adfe0142e9 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts @@ -34,11 +34,14 @@ export const seedPeople = async ( 'id', 'nameFirstName', 'nameLastName', - 'phone', + 'phonesPrimaryPhoneCountryCode', + 'phonesPrimaryPhoneNumber', + 'city', 'companyId', - 'email', + 'emailsPrimaryEmail', 'position', - 'whatsapp', + 'whatsappPrimaryPhoneCountryCode', + 'whatsappPrimaryPhoneNumber', 'createdBySource', 'createdByWorkspaceMemberId', 'createdByName', @@ -49,11 +52,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.CHRISTOPH, nameFirstName: 'Christoph', nameLastName: 'Callisto', - phone: '+33789012345', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '789012345', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.LINKEDIN, - email: 'christoph.calisto@linkedin.com', + emailsPrimaryEmail: 'christoph.calisto@linkedin.com', position: 1, - whatsapp: '+33789012345', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '789012345', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -62,11 +68,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.SYLVIE, nameFirstName: 'Sylvie', nameLastName: 'Palmer', - phone: '+33780123456', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '780123456', + city: 'Los Angeles', companyId: DEV_SEED_COMPANY_IDS.LINKEDIN, - email: 'sylvie.palmer@linkedin.com', + emailsPrimaryEmail: 'sylvie.palmer@linkedin.com', position: 2, - whatsapp: '+33780123456', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '780123456', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -75,11 +84,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.CHRISTOPHER_G, nameFirstName: 'Christopher', nameLastName: 'Gonzalez', - phone: '+33789012345', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '789012345', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.QONTO, - email: 'christopher.gonzalez@qonto.com', + emailsPrimaryEmail: 'christopher.gonzalez@qonto.com', position: 3, - whatsapp: '+33789012345', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '789012345', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -88,11 +100,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.ASHLEY, nameFirstName: 'Ashley', nameLastName: 'Parker', - phone: '+33780123456', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '780123456', + city: 'Los Angeles', companyId: DEV_SEED_COMPANY_IDS.QONTO, - email: 'ashley.parker@qonto.com', + emailsPrimaryEmail: 'ashley.parker@qonto.com', position: 4, - whatsapp: '+33780123456', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '780123456', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -101,11 +116,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.NICHOLAS, nameFirstName: 'Nicholas', nameLastName: 'Wright', - phone: '+33781234567', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '781234567', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.MICROSOFT, - email: 'nicholas.wright@microsoft.com', + emailsPrimaryEmail: 'nicholas.wright@microsoft.com', position: 5, - whatsapp: '+33781234567', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '781234567', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -114,11 +132,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.ISABELLA, nameFirstName: 'Isabella', nameLastName: 'Scott', - phone: '+33782345678', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '782345678', + city: 'New York', companyId: DEV_SEED_COMPANY_IDS.MICROSOFT, - email: 'isabella.scott@microsoft.com', + emailsPrimaryEmail: 'isabella.scott@microsoft.com', position: 6, - whatsapp: '+33782345678', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '782345678', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -127,11 +148,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.MATTHEW, nameFirstName: 'Matthew', nameLastName: 'Green', - phone: '+33783456789', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '783456789', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.MICROSOFT, - email: 'matthew.green@microsoft.com', + emailsPrimaryEmail: 'matthew.green@microsoft.com', position: 7, - whatsapp: '+33783456789', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '783456789', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -140,11 +164,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.ELIZABETH, nameFirstName: 'Elizabeth', nameLastName: 'Baker', - phone: '+33784567890', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '784567890', + city: 'New York', companyId: DEV_SEED_COMPANY_IDS.AIRBNB, - email: 'elizabeth.baker@airbnb.com', + emailsPrimaryEmail: 'elizabeth.baker@airbnb.com', position: 8, - whatsapp: '+33784567890', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '784567890', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -153,11 +180,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.CHRISTOPHER_N, nameFirstName: 'Christopher', nameLastName: 'Nelson', - phone: '+33785678901', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '785678901', + city: 'San Francisco', companyId: DEV_SEED_COMPANY_IDS.AIRBNB, - email: 'christopher.nelson@airbnb.com', + emailsPrimaryEmail: 'christopher.nelson@airbnb.com', position: 9, - whatsapp: '+33785678901', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '785678901', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -166,11 +196,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.AVERY, nameFirstName: 'Avery', nameLastName: 'Carter', - phone: '+33786789012', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '786789012', + city: 'New York', companyId: DEV_SEED_COMPANY_IDS.AIRBNB, - email: 'avery.carter@airbnb.com', + emailsPrimaryEmail: 'avery.carter@airbnb.com', position: 10, - whatsapp: '+33786789012', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '786789012', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -179,11 +212,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.ETHAN, nameFirstName: 'Ethan', nameLastName: 'Mitchell', - phone: '+33787890123', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '787890123', + city: 'Los Angeles', companyId: DEV_SEED_COMPANY_IDS.GOOGLE, - email: 'ethan.mitchell@google.com', + emailsPrimaryEmail: 'ethan.mitchell@google.com', position: 11, - whatsapp: '+33787890123', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '787890123', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -192,11 +228,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.MADISON, nameFirstName: 'Madison', nameLastName: 'Perez', - phone: '+33788901234', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '788901234', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.GOOGLE, - email: 'madison.perez@google.com', + emailsPrimaryEmail: 'madison.perez@google.com', position: 12, - whatsapp: '+33788901234', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '788901234', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -205,11 +244,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.BERTRAND, nameFirstName: 'Bertrand', nameLastName: 'Voulzy', - phone: '+33788901234', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '788901234', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.GOOGLE, - email: 'bertrand.voulzy@google.com', + emailsPrimaryEmail: 'bertrand.voulzy@google.com', position: 13, - whatsapp: '+33788901234', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '788901234', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -218,11 +260,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.LOUIS, nameFirstName: 'Louis', nameLastName: 'Duss', - phone: '+33788901234', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '789012345', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.GOOGLE, - email: 'louis.duss@google.com', + emailsPrimaryEmail: 'louis.duss@google.com', position: 14, - whatsapp: '+33788901234', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '789012345', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -231,11 +276,14 @@ export const seedPeople = async ( id: DEV_SEED_PERSON_IDS.LORIE, nameFirstName: 'Lorie', nameLastName: 'Vladim', - phone: '+33788901235', + phonePrimaryPhoneCountryCode: '+33', + phonePrimaryPhoneNumber: '788901235', + city: 'Seattle', companyId: DEV_SEED_COMPANY_IDS.GOOGLE, - email: 'lorie.vladim@google.com', + emailsPrimaryEmail: 'lorie.vladim@google.com', position: 15, - whatsapp: '+33788901235', + whatsappPrimaryPhoneCountryCode: '+33', + whatsappPrimaryPhoneNumber: '788901235', createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: '', diff --git a/packages/twenty-server/src/database/typeorm/core/core.datasource.ts b/packages/twenty-server/src/database/typeorm/core/core.datasource.ts index 1260f9bcf01d..0395f8cf2ae1 100644 --- a/packages/twenty-server/src/database/typeorm/core/core.datasource.ts +++ b/packages/twenty-server/src/database/typeorm/core/core.datasource.ts @@ -2,18 +2,24 @@ import { TypeOrmModuleOptions } from '@nestjs/typeorm'; import { config } from 'dotenv'; import { DataSource, DataSourceOptions } from 'typeorm'; -config(); +config({ path: process.env.NODE_ENV === 'test' ? '.env.test' : '.env' }); + +const isJest = process.argv.some((arg) => arg.includes('jest')); export const typeORMCoreModuleOptions: TypeOrmModuleOptions = { url: process.env.PG_DATABASE_URL, type: 'postgres', logging: ['error'], schema: 'core', - entities: ['dist/src/engine/core-modules/**/*.entity{.ts,.js}'], + entities: [ + `${isJest ? '' : 'dist/'}src/engine/core-modules/**/*.entity{.ts,.js}`, + ], synchronize: false, migrationsRun: false, migrationsTableName: '_typeorm_migrations', - migrations: ['dist/src/database/typeorm/core/migrations/*{.ts,.js}'], + migrations: [ + `${isJest ? '' : 'dist/'}src/database/typeorm/core/migrations/*{.ts,.js}`, + ], ssl: process.env.PG_SSL_ALLOW_SELF_SIGNED === 'true' ? { diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/1724056827317-addInvitation.ts b/packages/twenty-server/src/database/typeorm/core/migrations/1724056827317-addInvitation.ts new file mode 100644 index 000000000000..877b99999850 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/1724056827317-addInvitation.ts @@ -0,0 +1,51 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddInvitation1724056827317 implements MigrationInterface { + name = 'AddInvitation1724056827317'; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + 'ALTER TABLE core."appToken" ALTER COLUMN "userId" DROP NOT NULL', + ); + + await queryRunner.query( + `ALTER TABLE core."appToken" ADD CONSTRAINT "userIdIsNullWhenTypeIsInvitation" CHECK ("appToken".type != 'INVITATION_TOKEN' OR "appToken"."userId" IS NULL)`, + ); + + await queryRunner.query( + `ALTER TABLE core."appToken" ADD CONSTRAINT "userIdNotNullWhenTypeIsNotInvitation" CHECK ("appToken".type = 'INVITATION_TOKEN' OR "appToken"."userId" NOTNULL)`, + ); + + await queryRunner.query('ALTER TABLE core."appToken" ADD "context" jsonb'); + + await queryRunner.query( + 'CREATE UNIQUE INDEX apptoken_unique_invitation_by_user_workspace ON core."appToken" ("workspaceId", ("context" ->> \'email\')) WHERE type = \'INVITATION_TOKEN\';', + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `DROP INDEX core.apptoken_unique_invitation_by_user_workspace;`, + ); + + await queryRunner.query( + 'DELETE FROM "core"."appToken" WHERE "userId" IS NULL', + ); + + await queryRunner.query( + 'ALTER TABLE core."appToken" DROP CONSTRAINT "userIdIsNullWhenTypeIsInvitation"', + ); + + await queryRunner.query( + 'ALTER TABLE core."appToken" DROP CONSTRAINT "userIdNotNullWhenTypeIsNotInvitation"', + ); + + await queryRunner.query( + 'ALTER TABLE core."appToken" DROP COLUMN "context"', + ); + + await queryRunner.query( + 'ALTER TABLE core."appToken" ALTER COLUMN "userId" SET NOT NULL', + ); + } +} diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/1726849473832-addUniqueConstraintOnUsers.ts b/packages/twenty-server/src/database/typeorm/core/migrations/1726849473832-addUniqueConstraintOnUsers.ts new file mode 100644 index 000000000000..f7f58cb7f88b --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/1726849473832-addUniqueConstraintOnUsers.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddUniqueConstraintOnUsers1726849473832 + implements MigrationInterface +{ + name = 'AddUniqueConstraintOnUsers1726849473832'; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE "core"."user" ADD CONSTRAINT "UQ_USER_EMAIL" UNIQUE ("email", "deletedAt")`, + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE "core"."user" DROP CONSTRAINT "UQ_USER_EMAIL"`, + ); + } +} diff --git a/packages/twenty-server/src/database/typeorm/metadata/metadata.datasource.ts b/packages/twenty-server/src/database/typeorm/metadata/metadata.datasource.ts index 7aa3ed1ab77d..cdc833973be8 100644 --- a/packages/twenty-server/src/database/typeorm/metadata/metadata.datasource.ts +++ b/packages/twenty-server/src/database/typeorm/metadata/metadata.datasource.ts @@ -1,19 +1,25 @@ import { TypeOrmModuleOptions } from '@nestjs/typeorm'; -import { DataSource, DataSourceOptions } from 'typeorm'; import { config } from 'dotenv'; -config(); +import { DataSource, DataSourceOptions } from 'typeorm'; +config({ path: process.env.NODE_ENV === 'test' ? '.env.test' : '.env' }); + +const isJest = process.argv.some((arg) => arg.includes('jest')); export const typeORMMetadataModuleOptions: TypeOrmModuleOptions = { url: process.env.PG_DATABASE_URL, type: 'postgres', logging: ['error'], schema: 'metadata', - entities: ['dist/src/engine/metadata-modules/**/*.entity{.ts,.js}'], + entities: [ + `${isJest ? '' : 'dist/'}src/engine/metadata-modules/**/*.entity{.ts,.js}`, + ], synchronize: false, migrationsRun: false, migrationsTableName: '_typeorm_migrations', - migrations: ['dist/src/database/typeorm/metadata/migrations/*{.ts,.js}'], + migrations: [ + `${isJest ? '' : 'dist/'}src/database/typeorm/metadata/migrations/*{.ts,.js}`, + ], ssl: process.env.PG_SSL_ALLOW_SELF_SIGNED === 'true' ? { @@ -24,6 +30,7 @@ export const typeORMMetadataModuleOptions: TypeOrmModuleOptions = { query_timeout: 10000, }, }; + export const connectionSource = new DataSource( typeORMMetadataModuleOptions as DataSourceOptions, ); diff --git a/packages/twenty-server/src/database/typeorm/metadata/migrations/1724946099627-addServerlessFunctionLayerVersionColumn.ts b/packages/twenty-server/src/database/typeorm/metadata/migrations/1724946099627-addServerlessFunctionLayerVersionColumn.ts new file mode 100644 index 000000000000..ac6b5e4f7e62 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/metadata/migrations/1724946099627-addServerlessFunctionLayerVersionColumn.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddServerlessFunctionLayerVersionColumn1724946099627 + implements MigrationInterface +{ + name = 'AddServerlessFunctionLayerVersionColumn1724946099627'; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE "metadata"."serverlessFunction" ADD "layerVersion" integer`, + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE "metadata"."serverlessFunction" DROP COLUMN "layerVersion"`, + ); + } +} diff --git a/packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts b/packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts new file mode 100644 index 000000000000..a0837d901ba1 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/metadata/migrations/1726486735275-removeObjectMetadataIsSoftDeletable.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveObjectMetadataIsSoftDeletable1726486735275 + implements MigrationInterface +{ + name = 'RemoveObjectMetadataIsSoftDeletable1726486735275'; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE "metadata"."objectMetadata" DROP COLUMN "isSoftDeletable"`, + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE "metadata"."objectMetadata" ADD "isSoftDeletable" boolean`, + ); + } +} diff --git a/packages/twenty-server/src/database/typeorm/raw/raw.datasource.ts b/packages/twenty-server/src/database/typeorm/raw/raw.datasource.ts index a50567c43238..d39907593c55 100644 --- a/packages/twenty-server/src/database/typeorm/raw/raw.datasource.ts +++ b/packages/twenty-server/src/database/typeorm/raw/raw.datasource.ts @@ -1,6 +1,6 @@ import { config } from 'dotenv'; import { DataSource, DataSourceOptions } from 'typeorm'; -config(); +config({ path: process.env.NODE_ENV === 'test' ? '.env.test' : '.env' }); const typeORMRawModuleOptions: DataSourceOptions = { url: process.env.PG_DATABASE_URL, diff --git a/packages/twenty-server/src/database/typeorm/typeorm.module.ts b/packages/twenty-server/src/database/typeorm/typeorm.module.ts index b24fe05bad94..15733f0c632d 100644 --- a/packages/twenty-server/src/database/typeorm/typeorm.module.ts +++ b/packages/twenty-server/src/database/typeorm/typeorm.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { typeORMCoreModuleOptions } from 'src/database/typeorm/core/core.datasource'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { TypeORMService } from './typeorm.service'; diff --git a/packages/twenty-server/src/database/typeorm/typeorm.service.ts b/packages/twenty-server/src/database/typeorm/typeorm.service.ts index ca1f9c44cf64..0e8b97094b58 100644 --- a/packages/twenty-server/src/database/typeorm/typeorm.service.ts +++ b/packages/twenty-server/src/database/typeorm/typeorm.service.ts @@ -2,17 +2,17 @@ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; -import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; +import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity'; import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity'; +import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class TypeORMService implements OnModuleInit, OnModuleDestroy { diff --git a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts index ab348dd176f8..337cdda3e2ae 100644 --- a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts +++ b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts @@ -7,6 +7,7 @@ export const FIELD_CURRENCY_MOCK_NAME = 'fieldCurrency'; export const FIELD_ADDRESS_MOCK_NAME = 'fieldAddress'; export const FIELD_ACTOR_MOCK_NAME = 'fieldActor'; export const FIELD_FULL_NAME_MOCK_NAME = 'fieldFullName'; +export const FIELD_PHONES_MOCK_NAME = 'fieldPhones'; export const fieldNumberMock = { name: 'fieldNumber', @@ -156,7 +157,23 @@ const fieldRatingMock = { name: 'fieldRating', type: FieldMetadataType.RATING, isNullable: true, - defaultValue: null, + defaultValue: 'RATING_1', + options: [ + { + id: '9a519a86-422b-4598-88ae-78751353f683', + color: 'red', + label: 'Opt 1', + value: 'RATING_1', + position: 0, + }, + { + id: '33f28d51-bc82-4e1d-ae4b-d9e4c0ed0ab4', + color: 'purple', + label: 'Opt 2', + value: 'RATING_2', + position: 1, + }, + ], }; const fieldPositionMock = { @@ -205,6 +222,7 @@ const fieldActorMock = { name: '', }, }; + const fieldEmailsMock = { name: 'fieldEmails', type: FieldMetadataType.EMAILS, @@ -212,10 +230,31 @@ const fieldEmailsMock = { defaultValue: [{ primaryEmail: '', additionalEmails: {} }], }; +const fieldArrayMock = { + name: 'fieldArray', + type: FieldMetadataType.ARRAY, + isNullable: true, + defaultValue: null, +}; + +const fieldPhonesMock = { + name: FIELD_PHONES_MOCK_NAME, + type: FieldMetadataType.PHONES, + isNullable: false, + defaultValue: [ + { + primaryPhoneNumber: '', + primaryPhoneCountryCode: '', + additionalPhones: {}, + }, + ], +}; + export const fields = [ fieldUuidMock, fieldTextMock, fieldPhoneMock, + fieldPhonesMock, fieldEmailMock, fieldEmailsMock, fieldDateTimeMock, @@ -235,6 +274,7 @@ export const fields = [ fieldRawJsonMock, fieldRichTextMock, fieldActorMock, + fieldArrayMock, ]; export const objectMetadataItemMock = { diff --git a/packages/twenty-server/src/engine/api/graphql/__tests__/workspace.factory.spec.ts b/packages/twenty-server/src/engine/api/graphql/__tests__/workspace.factory.spec.ts index 57d051363e3f..05d0cbaa9efe 100644 --- a/packages/twenty-server/src/engine/api/graphql/__tests__/workspace.factory.spec.ts +++ b/packages/twenty-server/src/engine/api/graphql/__tests__/workspace.factory.spec.ts @@ -6,7 +6,7 @@ import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace- import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; describe('WorkspaceSchemaFactory', () => { @@ -41,7 +41,7 @@ describe('WorkspaceSchemaFactory', () => { useValue: {}, }, { - provide: WorkspaceMetadataVersionService, + provide: WorkspaceMetadataCacheService, useValue: {}, }, ], diff --git a/packages/twenty-server/src/engine/api/graphql/core-graphql-api.module.ts b/packages/twenty-server/src/engine/api/graphql/core-graphql-api.module.ts index c9b0aa852312..1b0603186fc8 100644 --- a/packages/twenty-server/src/engine/api/graphql/core-graphql-api.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/core-graphql-api.module.ts @@ -4,25 +4,18 @@ import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars- import { WorkspaceResolverBuilderModule } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module'; import { WorkspaceSchemaBuilderModule } from 'src/engine/api/graphql/workspace-schema-builder/workspace-schema-builder.module'; import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module'; -import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module'; import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; import { WorkspaceSchemaFactory } from './workspace-schema.factory'; @Module({ imports: [ - // TODO: Seems like it's breaking /metadata query and mutation arguments - // we should investigate this issue - // GraphQLModule.forRootAsync<YogaDriverConfig>({ - // driver: YogaDriver, - // imports: [CoreEngineModule, GraphQLConfigModule], - // useClass: GraphQLConfigService, - // }), MetadataEngineModule, WorkspaceSchemaBuilderModule, WorkspaceResolverBuilderModule, WorkspaceCacheStorageModule, - WorkspaceMetadataVersionModule, + WorkspaceMetadataCacheModule, ], providers: [WorkspaceSchemaFactory, ScalarsExplorerService], exports: [WorkspaceSchemaFactory], diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.module.ts b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.module.ts index dbfb77932d4c..8b4af6579c07 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.module.ts @@ -5,6 +5,6 @@ import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module'; @Module({ imports: [CoreEngineModule], providers: [], - exports: [], + exports: [CoreEngineModule], }) export class GraphQLConfigModule {} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts index 8c0521173fee..572531308178 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts @@ -14,15 +14,15 @@ import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken'; import { useThrottler } from 'src/engine/api/graphql/graphql-config/hooks/use-throttler'; import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { useSentryTracing } from 'src/engine/core-modules/exception-handler/hooks/use-sentry-tracing'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { useSentryTracing } from 'src/engine/integrations/exception-handler/hooks/use-sentry-tracing'; import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util'; import { renderApolloPlayground } from 'src/engine/utils/render-apollo-playground.util'; @@ -69,13 +69,18 @@ export class GraphQLConfigService let workspace: Workspace | undefined; try { - if (!this.tokenService.isTokenPresent(context.req)) { + const { user, workspace, apiKey, workspaceMemberId } = context.req; + + if (!workspace) { return new GraphQLSchema({}); } - const data = await this.tokenService.validateToken(context.req); - - return await this.createSchema(context, data); + return await this.createSchema(context, { + user, + workspace, + apiKey, + workspaceMemberId, + }); } catch (error) { if (error instanceof UnauthorizedException) { throw new GraphQLError('Unauthenticated', { diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts index d7ea0e979232..55c70c5af215 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception.ts @@ -8,6 +8,7 @@ export class GraphqlQueryRunnerException extends CustomException { } export enum GraphqlQueryRunnerExceptionCode { + INVALID_QUERY_INPUT = 'INVALID_QUERY_INPUT', MAX_DEPTH_REACHED = 'MAX_DEPTH_REACHED', INVALID_CURSOR = 'INVALID_CURSOR', INVALID_DIRECTION = 'INVALID_DIRECTION', @@ -15,4 +16,8 @@ export enum GraphqlQueryRunnerExceptionCode { ARGS_CONFLICT = 'ARGS_CONFLICT', FIELD_NOT_FOUND = 'FIELD_NOT_FOUND', OBJECT_METADATA_NOT_FOUND = 'OBJECT_METADATA_NOT_FOUND', + RECORD_NOT_FOUND = 'RECORD_NOT_FOUND', + INVALID_ARGS_FIRST = 'INVALID_ARGS_FIRST', + INVALID_ARGS_LAST = 'INVALID_ARGS_LAST', + METADATA_CACHE_VERSION_NOT_FOUND = 'METADATA_CACHE_VERSION_NOT_FOUND', } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser.ts index 82421ed74e82..093364db8479 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser.ts @@ -1,107 +1,150 @@ -import { FindOptionsWhere, ObjectLiteral } from 'typeorm'; +import { + Brackets, + NotBrackets, + SelectQueryBuilder, + WhereExpressionBuilder, +} from 'typeorm'; import { RecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; -import { FieldMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; +import { FieldMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { GraphqlQueryFilterFieldParser } from './graphql-query-filter-field.parser'; export class GraphqlQueryFilterConditionParser { private fieldMetadataMap: FieldMetadataMap; - private fieldConditionParser: GraphqlQueryFilterFieldParser; + private queryFilterFieldParser: GraphqlQueryFilterFieldParser; constructor(fieldMetadataMap: FieldMetadataMap) { this.fieldMetadataMap = fieldMetadataMap; - this.fieldConditionParser = new GraphqlQueryFilterFieldParser( + this.queryFilterFieldParser = new GraphqlQueryFilterFieldParser( this.fieldMetadataMap, ); } public parse( - conditions: RecordFilter, - isNegated = false, - ): FindOptionsWhere<ObjectLiteral> | FindOptionsWhere<ObjectLiteral>[] { - if (Array.isArray(conditions)) { - return this.parseAndCondition(conditions, isNegated); + queryBuilder: SelectQueryBuilder<any>, + objectNameSingular: string, + filter: RecordFilter, + ): SelectQueryBuilder<any> { + if (!filter || Object.keys(filter).length === 0) { + return queryBuilder; } - const result: FindOptionsWhere<ObjectLiteral> = {}; - - for (const [key, value] of Object.entries(conditions)) { - switch (key) { - case 'and': - return this.parseAndCondition(value, isNegated); - case 'or': - return this.parseOrCondition(value, isNegated); - case 'not': - return this.parse(value, !isNegated); - default: - Object.assign( - result, - this.fieldConditionParser.parse(key, value, isNegated), - ); - } - } - - return result; - } - - private parseAndCondition( - conditions: RecordFilter[], - isNegated: boolean, - ): FindOptionsWhere<ObjectLiteral>[] { - const parsedConditions = conditions.map((condition) => - this.parse(condition, isNegated), + return queryBuilder.where( + new Brackets((qb) => { + Object.entries(filter).forEach(([key, value], index) => { + this.parseKeyFilter(qb, objectNameSingular, key, value, index === 0); + }); + }), ); - - return this.combineConditions(parsedConditions, isNegated ? 'or' : 'and'); } - private parseOrCondition( - conditions: RecordFilter[], - isNegated: boolean, - ): FindOptionsWhere<ObjectLiteral>[] { - const parsedConditions = conditions.map((condition) => - this.parse(condition, isNegated), - ); + private parseKeyFilter( + queryBuilder: WhereExpressionBuilder, + objectNameSingular: string, + key: string, + value: any, + isFirst = false, + ): void { + switch (key) { + case 'and': { + const andWhereCondition = new Brackets((qb) => { + value.forEach((filter: RecordFilter, index: number) => { + const whereCondition = new Brackets((qb2) => { + Object.entries(filter).forEach( + ([subFilterkey, subFilterValue], index) => { + this.parseKeyFilter( + qb2, + objectNameSingular, + subFilterkey, + subFilterValue, + index === 0, + ); + }, + ); + }); + + if (index === 0) { + qb.where(whereCondition); + } else { + qb.andWhere(whereCondition); + } + }); + }); - return this.combineConditions(parsedConditions, isNegated ? 'and' : 'or'); - } + if (isFirst) { + queryBuilder.where(andWhereCondition); + } else { + queryBuilder.andWhere(andWhereCondition); + } + break; + } + case 'or': { + const orWhereCondition = new Brackets((qb) => { + value.forEach((filter: RecordFilter, index: number) => { + const whereCondition = new Brackets((qb2) => { + Object.entries(filter).forEach( + ([subFilterkey, subFilterValue], index) => { + this.parseKeyFilter( + qb2, + objectNameSingular, + subFilterkey, + subFilterValue, + index === 0, + ); + }, + ); + }); + + if (index === 0) { + qb.where(whereCondition); + } else { + qb.orWhere(whereCondition); + } + }); + }); - private combineConditions( - conditions: ( - | FindOptionsWhere<ObjectLiteral> - | FindOptionsWhere<ObjectLiteral>[] - )[], - combineType: 'and' | 'or', - ): FindOptionsWhere<ObjectLiteral>[] { - if (combineType === 'and') { - let result: FindOptionsWhere<ObjectLiteral>[] = [{}]; + if (isFirst) { + queryBuilder.where(orWhereCondition); + } else { + queryBuilder.andWhere(orWhereCondition); + } - for (const condition of conditions) { - if (Array.isArray(condition)) { - const newResult: FindOptionsWhere<ObjectLiteral>[] = []; + break; + } + case 'not': { + const notWhereCondition = new NotBrackets((qb) => { + Object.entries(value).forEach( + ([subFilterkey, subFilterValue], index) => { + this.parseKeyFilter( + qb, + objectNameSingular, + subFilterkey, + subFilterValue, + index === 0, + ); + }, + ); + }); - for (const existingCondition of result) { - for (const orCondition of condition) { - newResult.push({ - ...existingCondition, - ...orCondition, - }); - } - } - result = newResult; + if (isFirst) { + queryBuilder.where(notWhereCondition); } else { - result = result.map((existingCondition) => ({ - ...existingCondition, - ...condition, - })); + queryBuilder.andWhere(notWhereCondition); } - } - return result; + break; + } + default: + this.queryFilterFieldParser.parse( + queryBuilder, + objectNameSingular, + key, + value, + isFirst, + ); + break; } - - return conditions.flat(); } } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser.ts index a855ec6e96bb..fe37c4d445da 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser.ts @@ -1,64 +1,162 @@ -import { FindOptionsWhere, Not, ObjectLiteral } from 'typeorm'; +import { ObjectLiteral, WhereExpressionBuilder } from 'typeorm'; -import { RecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; -import { FieldMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; +import { FieldMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { CompositeFieldMetadataType } from 'src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory'; import { capitalize } from 'src/utils/capitalize'; -import { isPlainObject } from 'src/utils/is-plain-object'; -import { GraphqlQueryFilterConditionParser } from './graphql-query-filter-condition.parser'; -import { GraphqlQueryFilterOperatorParser } from './graphql-query-filter-operator.parser'; +type WhereConditionParts = { + sql: string; + params: ObjectLiteral; +}; export class GraphqlQueryFilterFieldParser { private fieldMetadataMap: FieldMetadataMap; - private operatorParser: GraphqlQueryFilterOperatorParser; constructor(fieldMetadataMap: FieldMetadataMap) { this.fieldMetadataMap = fieldMetadataMap; - this.operatorParser = new GraphqlQueryFilterOperatorParser(); } public parse( + queryBuilder: WhereExpressionBuilder, + objectNameSingular: string, key: string, - value: any, - isNegated: boolean, - ): FindOptionsWhere<ObjectLiteral> { - const fieldMetadata = this.fieldMetadataMap[key]; + filterValue: any, + isFirst = false, + ): void { + const fieldMetadata = this.fieldMetadataMap[`${key}`]; if (!fieldMetadata) { - return { - [key]: (value: RecordFilter, isNegated: boolean) => { - const conditionParser = new GraphqlQueryFilterConditionParser( - this.fieldMetadataMap, - ); - - return conditionParser.parse(value, isNegated); - }, - }; + throw new Error(`Field metadata not found for field: ${key}`); } if (isCompositeFieldMetadataType(fieldMetadata.type)) { - return this.parseCompositeFieldForFilter(fieldMetadata, value, isNegated); + return this.parseCompositeFieldForFilter( + queryBuilder, + fieldMetadata, + objectNameSingular, + filterValue, + isFirst, + ); + } + const [[operator, value]] = Object.entries(filterValue); + + if (operator === 'in') { + if (!Array.isArray(value) || value.length === 0) { + throw new GraphqlQueryRunnerException( + `Invalid filter value for field ${key}. Expected non-empty array`, + GraphqlQueryRunnerExceptionCode.INVALID_QUERY_INPUT, + ); + } } - if (isPlainObject(value)) { - const parsedValue = this.operatorParser.parseOperator(value, isNegated); + const { sql, params } = this.computeWhereConditionParts( + fieldMetadata, + operator, + objectNameSingular, + key, + value, + ); - return { [key]: parsedValue }; + if (isFirst) { + queryBuilder.where(sql, params); + } else { + queryBuilder.andWhere(sql, params); } + } - return { [key]: isNegated ? Not(value) : value }; + private computeWhereConditionParts( + fieldMetadata: FieldMetadataInterface, + operator: string, + objectNameSingular: string, + key: string, + value: any, + ): WhereConditionParts { + const uuid = Math.random().toString(36).slice(2, 7); + + switch (operator) { + case 'eq': + return { + sql: `${objectNameSingular}.${key} = :${key}${uuid}`, + params: { [`${key}${uuid}`]: value }, + }; + case 'neq': + return { + sql: `${objectNameSingular}.${key} != :${key}${uuid}`, + params: { [`${key}${uuid}`]: value }, + }; + case 'gt': + return { + sql: `${objectNameSingular}.${key} > :${key}${uuid}`, + params: { [`${key}${uuid}`]: value }, + }; + case 'gte': + return { + sql: `${objectNameSingular}.${key} >= :${key}${uuid}`, + params: { [`${key}${uuid}`]: value }, + }; + case 'lt': + return { + sql: `${objectNameSingular}.${key} < :${key}${uuid}`, + params: { [`${key}${uuid}`]: value }, + }; + case 'lte': + return { + sql: `${objectNameSingular}.${key} <= :${key}${uuid}`, + params: { [`${key}${uuid}`]: value }, + }; + case 'in': + return { + sql: `${objectNameSingular}.${key} IN (:...${key}${uuid})`, + params: { [`${key}${uuid}`]: value }, + }; + case 'is': + return { + sql: `${objectNameSingular}.${key} IS ${value === 'NULL' ? 'NULL' : 'NOT NULL'}`, + params: {}, + }; + case 'like': + return { + sql: `${objectNameSingular}.${key} LIKE :${key}${uuid}`, + params: { [`${key}${uuid}`]: `${value}` }, + }; + case 'ilike': + return { + sql: `${objectNameSingular}.${key} ILIKE :${key}${uuid}`, + params: { [`${key}${uuid}`]: `${value}` }, + }; + case 'startsWith': + return { + sql: `${objectNameSingular}.${key} LIKE :${key}${uuid}`, + params: { [`${key}${uuid}`]: `${value}` }, + }; + case 'endsWith': + return { + sql: `${objectNameSingular}.${key} LIKE :${key}${uuid}`, + params: { [`${key}${uuid}`]: `${value}` }, + }; + default: + throw new GraphqlQueryRunnerException( + `Operator "${operator}" is not supported`, + GraphqlQueryRunnerExceptionCode.UNSUPPORTED_OPERATOR, + ); + } } private parseCompositeFieldForFilter( + queryBuilder: WhereExpressionBuilder, fieldMetadata: FieldMetadataInterface, + objectNameSingular: string, fieldValue: any, - isNegated: boolean, - ): FindOptionsWhere<ObjectLiteral> { + isFirst = false, + ): void { const compositeType = compositeTypeDefinitions.get( fieldMetadata.type as CompositeFieldMetadataType, ); @@ -69,34 +167,36 @@ export class GraphqlQueryFilterFieldParser { ); } - return Object.entries(fieldValue).reduce( - (result, [subFieldKey, subFieldValue]) => { - const subFieldMetadata = compositeType.properties.find( - (property) => property.name === subFieldKey, + Object.entries(fieldValue).map(([subFieldKey, subFieldFilter], index) => { + const subFieldMetadata = compositeType.properties.find( + (property) => property.name === subFieldKey, + ); + + if (!subFieldMetadata) { + throw new Error( + `Sub field metadata not found for composite type: ${fieldMetadata.type}`, ); + } - if (!subFieldMetadata) { - throw new Error( - `Sub field metadata not found for composite type: ${fieldMetadata.type}`, - ); - } - - const fullFieldName = `${fieldMetadata.name}${capitalize(subFieldKey)}`; - - if (isPlainObject(subFieldValue)) { - result[fullFieldName] = this.operatorParser.parseOperator( - subFieldValue, - isNegated, - ); - } else { - result[fullFieldName] = isNegated - ? Not(subFieldValue) - : subFieldValue; - } - - return result; - }, - {} as FindOptionsWhere<ObjectLiteral>, - ); + const fullFieldName = `${fieldMetadata.name}${capitalize(subFieldKey)}`; + + const [[operator, value]] = Object.entries( + subFieldFilter as Record<string, any>, + ); + + const { sql, params } = this.computeWhereConditionParts( + fieldMetadata, + operator, + objectNameSingular, + fullFieldName, + value, + ); + + if (isFirst && index === 0) { + queryBuilder.where(sql, params); + } + + queryBuilder.andWhere(sql, params); + }); } } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser.ts index d64a4b3e8962..aaa242d804aa 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser.ts @@ -1,5 +1,3 @@ -import { FindOptionsOrderValue } from 'typeorm'; - import { OrderByDirection, RecordOrderBy, @@ -10,12 +8,11 @@ import { GraphqlQueryRunnerException, GraphqlQueryRunnerExceptionCode, } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; -import { FieldMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; +import { FieldMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { CompositeFieldMetadataType } from 'src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory'; import { capitalize } from 'src/utils/capitalize'; - export class GraphqlQueryOrderFieldParser { private fieldMetadataMap: FieldMetadataMap; @@ -23,7 +20,11 @@ export class GraphqlQueryOrderFieldParser { this.fieldMetadataMap = fieldMetadataMap; } - parse(orderBy: RecordOrderBy): Record<string, FindOptionsOrderValue> { + parse( + orderBy: RecordOrderBy, + objectNameSingular: string, + isForwardPagination = true, + ): Record<string, string> { return orderBy.reduce( (acc, item) => { Object.entries(item).forEach(([key, value]) => { @@ -40,24 +41,29 @@ export class GraphqlQueryOrderFieldParser { const compositeOrder = this.parseCompositeFieldForOrder( fieldMetadata, value, + objectNameSingular, + isForwardPagination, ); Object.assign(acc, compositeOrder); } else { - acc[key] = this.convertOrderByToFindOptionsOrder(value); + acc[`"${objectNameSingular}"."${key}"`] = + this.convertOrderByToFindOptionsOrder(value, isForwardPagination); } }); return acc; }, - {} as Record<string, FindOptionsOrderValue>, + {} as Record<string, string>, ); } private parseCompositeFieldForOrder( fieldMetadata: FieldMetadataInterface, value: any, - ): Record<string, FindOptionsOrderValue> { + objectNameSingular: string, + isForwardPagination = true, + ): Record<string, string> { const compositeType = compositeTypeDefinitions.get( fieldMetadata.type as CompositeFieldMetadataType, ); @@ -80,34 +86,37 @@ export class GraphqlQueryOrderFieldParser { ); } - const fullFieldName = `${fieldMetadata.name}${capitalize(subFieldKey)}`; + const fullFieldName = `"${objectNameSingular}"."${fieldMetadata.name}${capitalize(subFieldKey)}"`; if (!this.isOrderByDirection(subFieldValue)) { throw new Error( `Sub field order by value must be of type OrderByDirection, but got: ${subFieldValue}`, ); } - acc[fullFieldName] = - this.convertOrderByToFindOptionsOrder(subFieldValue); + acc[fullFieldName] = this.convertOrderByToFindOptionsOrder( + subFieldValue, + isForwardPagination, + ); return acc; }, - {} as Record<string, FindOptionsOrderValue>, + {} as Record<string, string>, ); } private convertOrderByToFindOptionsOrder( direction: OrderByDirection, - ): FindOptionsOrderValue { + isForwardPagination = true, + ): string { switch (direction) { case OrderByDirection.AscNullsFirst: - return { direction: 'ASC', nulls: 'FIRST' }; + return `${isForwardPagination ? 'ASC' : 'DESC'} NULLS FIRST`; case OrderByDirection.AscNullsLast: - return { direction: 'ASC', nulls: 'LAST' }; + return `${isForwardPagination ? 'ASC' : 'DESC'} NULLS LAST`; case OrderByDirection.DescNullsFirst: - return { direction: 'DESC', nulls: 'FIRST' }; + return `${isForwardPagination ? 'DESC' : 'ASC'} NULLS FIRST`; case OrderByDirection.DescNullsLast: - return { direction: 'DESC', nulls: 'LAST' }; + return `${isForwardPagination ? 'DESC' : 'ASC'} NULLS LAST`; default: throw new GraphqlQueryRunnerException( `Invalid direction: ${direction}`, diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-relation.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-relation.parser.ts index 4d22099219ac..19308a44989c 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-relation.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-relation.parser.ts @@ -1,8 +1,8 @@ import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { GraphqlQuerySelectedFieldsParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser'; -import { ObjectMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; import { getRelationObjectMetadata } from 'src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; export class GraphqlQuerySelectedFieldsRelationParser { private objectMetadataMap: ObjectMetadataMap; @@ -17,12 +17,12 @@ export class GraphqlQuerySelectedFieldsRelationParser { fieldValue: any, result: { select: Record<string, any>; relations: Record<string, any> }, ): void { - result.relations[fieldKey] = true; - if (!fieldValue || typeof fieldValue !== 'object') { return; } + result.relations[fieldKey] = true; + const referencedObjectMetadata = getRelationObjectMetadata( fieldMetadata, this.objectMetadataMap, diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser.ts index 8abcafd6de0b..d1b69345fee2 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser.ts @@ -5,9 +5,9 @@ import { GraphqlQueryRunnerExceptionCode, } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { GraphqlQuerySelectedFieldsRelationParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields-relation.parser'; -import { ObjectMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { CompositeFieldMetadataType } from 'src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory'; import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; import { capitalize } from 'src/utils/capitalize'; diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts index ed52b4ef4c47..d83667211bd0 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser.ts @@ -1,7 +1,8 @@ import { - FindOptionsOrderValue, FindOptionsWhere, ObjectLiteral, + OrderByCondition, + SelectQueryBuilder, } from 'typeorm'; import { @@ -10,17 +11,19 @@ import { } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { GraphqlQueryFilterConditionParser as GraphqlQueryFilterParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser'; -import { GraphqlQueryOrderFieldParser as GraphqlQueryOrderParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser'; +import { GraphqlQueryFilterConditionParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-condition.parser'; +import { GraphqlQueryOrderFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-order/graphql-query-order.parser'; import { GraphqlQuerySelectedFieldsParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-selected-fields/graphql-selected-fields.parser'; import { FieldMetadataMap, ObjectMetadataMap, -} from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; +} from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; export class GraphqlQueryParser { private fieldMetadataMap: FieldMetadataMap; private objectMetadataMap: ObjectMetadataMap; + private filterConditionParser: GraphqlQueryFilterConditionParser; + private orderFieldParser: GraphqlQueryOrderFieldParser; constructor( fieldMetadataMap: FieldMetadataMap, @@ -28,24 +31,76 @@ export class GraphqlQueryParser { ) { this.objectMetadataMap = objectMetadataMap; this.fieldMetadataMap = fieldMetadataMap; + this.filterConditionParser = new GraphqlQueryFilterConditionParser( + this.fieldMetadataMap, + ); + this.orderFieldParser = new GraphqlQueryOrderFieldParser( + this.fieldMetadataMap, + ); } - parseFilter( + applyFilterToBuilder( + queryBuilder: SelectQueryBuilder<any>, + objectNameSingular: string, recordFilter: RecordFilter, - ): FindOptionsWhere<ObjectLiteral> | FindOptionsWhere<ObjectLiteral>[] { - const graphqlQueryFilterParser = new GraphqlQueryFilterParser( - this.fieldMetadataMap, + ): SelectQueryBuilder<any> { + return this.filterConditionParser.parse( + queryBuilder, + objectNameSingular, + recordFilter, ); + } + + applyDeletedAtToBuilder( + queryBuilder: SelectQueryBuilder<any>, + recordFilter: RecordFilter, + ): SelectQueryBuilder<any> { + if (this.checkForDeletedAtFilter(recordFilter)) { + queryBuilder.withDeleted(); + } - return graphqlQueryFilterParser.parse(recordFilter); + return queryBuilder; } - parseOrder(orderBy: RecordOrderBy): Record<string, FindOptionsOrderValue> { - const graphqlQueryOrderParser = new GraphqlQueryOrderParser( - this.fieldMetadataMap, + private checkForDeletedAtFilter = ( + filter: FindOptionsWhere<ObjectLiteral> | FindOptionsWhere<ObjectLiteral>[], + ): boolean => { + if (Array.isArray(filter)) { + return filter.some((subFilter) => + this.checkForDeletedAtFilter(subFilter), + ); + } + + for (const [key, value] of Object.entries(filter)) { + if (key === 'deletedAt') { + return true; + } + + if (typeof value === 'object' && value !== null) { + if ( + this.checkForDeletedAtFilter(value as FindOptionsWhere<ObjectLiteral>) + ) { + return true; + } + } + } + + return false; + }; + + applyOrderToBuilder( + queryBuilder: SelectQueryBuilder<any>, + orderBy: RecordOrderBy, + objectNameSingular: string, + isForwardPagination = true, + ): SelectQueryBuilder<any> { + const parsedOrderBys = this.orderFieldParser.parse( + orderBy, + objectNameSingular, + isForwardPagination, ); - return graphqlQueryOrderParser.parse(orderBy); + return queryBuilder.orderBy(parsedOrderBys as OrderByCondition); } parseSelectedFields( diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.module.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.module.ts index 87d6c025522d..96f15862e392 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.module.ts @@ -1,8 +1,11 @@ import { Module } from '@nestjs/common'; import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; +import { WorkspaceQueryHookModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module'; +import { WorkspaceQueryRunnerModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module'; @Module({ + imports: [WorkspaceQueryHookModule, WorkspaceQueryRunnerModule], providers: [GraphqlQueryRunnerService], exports: [GraphqlQueryRunnerService], }) diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service.ts index 152d44e8ef6d..8eb4a614add5 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service.ts @@ -1,8 +1,5 @@ import { Injectable } from '@nestjs/common'; -import graphqlFields from 'graphql-fields'; -import { FindManyOptions, ObjectLiteral } from 'typeorm'; - import { Record as IRecord, RecordFilter, @@ -10,29 +7,93 @@ import { } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { IConnection } from 'src/engine/api/graphql/workspace-query-runner/interfaces/connection.interface'; import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-query-runner/interfaces/query-runner-option.interface'; -import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { + CreateManyResolverArgs, + CreateOneResolverArgs, + DestroyOneResolverArgs, + FindManyResolverArgs, + FindOneResolverArgs, + ResolverArgsType, +} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; +import { GraphqlQueryCreateManyResolverService } from 'src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-create-many-resolver.service'; +import { GraphqlQueryDestroyOneResolverService } from 'src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-destroy-one-resolver.service'; +import { GraphqlQueryFindManyResolverService } from 'src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service'; +import { GraphqlQueryFindOneResolverService } from 'src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service'; +import { QueryRunnerArgsFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-runner-args.factory'; +import { + CallWebhookJobsJob, + CallWebhookJobsJobData, + CallWebhookJobsJobOperation, +} from 'src/engine/api/graphql/workspace-query-runner/jobs/call-webhook-jobs.job'; +import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; +import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service'; import { - GraphqlQueryRunnerException, - GraphqlQueryRunnerExceptionCode, -} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; -import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; -import { ObjectRecordsToGraphqlConnectionMapper } from 'src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper'; -import { applyRangeFilter } from 'src/engine/api/graphql/graphql-query-runner/utils/apply-range-filter.util'; -import { convertObjectMetadataToMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; -import { decodeCursor } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util'; + WorkspaceQueryRunnerException, + WorkspaceQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { LogExecutionTime } from 'src/engine/decorators/observability/log-execution-time.decorator'; +import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @Injectable() export class GraphqlQueryRunnerService { constructor( private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + private readonly workspaceQueryHookService: WorkspaceQueryHookService, + private readonly queryRunnerArgsFactory: QueryRunnerArgsFactory, + private readonly workspaceEventEmitter: WorkspaceEventEmitter, + @InjectMessageQueue(MessageQueue.webhookQueue) + private readonly messageQueueService: MessageQueueService, ) {} @LogExecutionTime() - async findManyWithTwentyOrm< + async findOne< + ObjectRecord extends IRecord = IRecord, + Filter extends RecordFilter = RecordFilter, + >( + args: FindOneResolverArgs<Filter>, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord | undefined> { + const graphqlQueryFindOneResolverService = + new GraphqlQueryFindOneResolverService(this.twentyORMGlobalManager); + + const { authContext, objectMetadataItem } = options; + + if (!args.filter || Object.keys(args.filter).length === 0) { + throw new WorkspaceQueryRunnerException( + 'Missing filter argument', + WorkspaceQueryRunnerExceptionCode.INVALID_QUERY_INPUT, + ); + } + + const hookedArgs = + await this.workspaceQueryHookService.executePreQueryHooks( + authContext, + objectMetadataItem.nameSingular, + 'findOne', + args, + ); + + const computedArgs = (await this.queryRunnerArgsFactory.create( + hookedArgs, + options, + ResolverArgsType.FindOne, + )) as FindOneResolverArgs<Filter>; + + return graphqlQueryFindOneResolverService.findOne(computedArgs, options); + } + + @LogExecutionTime() + async findMany< ObjectRecord extends IRecord = IRecord, Filter extends RecordFilter = RecordFilter, OrderBy extends RecordOrderBy = RecordOrderBy, @@ -40,93 +101,278 @@ export class GraphqlQueryRunnerService { args: FindManyResolverArgs<Filter, OrderBy>, options: WorkspaceQueryRunnerOptions, ): Promise<IConnection<ObjectRecord>> { - const { authContext, objectMetadataItem, info, objectMetadataCollection } = - options; + const graphqlQueryFindManyResolverService = + new GraphqlQueryFindManyResolverService(this.twentyORMGlobalManager); - const repository = - await this.twentyORMGlobalManager.getRepositoryForWorkspace( - authContext.workspace.id, + const { authContext, objectMetadataItem } = options; + + const hookedArgs = + await this.workspaceQueryHookService.executePreQueryHooks( + authContext, objectMetadataItem.nameSingular, + 'findMany', + args, ); - const selectedFields = graphqlFields(info); + const computedArgs = (await this.queryRunnerArgsFactory.create( + hookedArgs, + options, + ResolverArgsType.FindMany, + )) as FindManyResolverArgs<Filter, OrderBy>; - const objectMetadataMap = convertObjectMetadataToMap( - objectMetadataCollection, - ); + return graphqlQueryFindManyResolverService.findMany(computedArgs, options); + } - const objectMetadata = objectMetadataMap[objectMetadataItem.nameSingular]; + @LogExecutionTime() + async createOne<ObjectRecord extends IRecord = IRecord>( + args: CreateOneResolverArgs<Partial<ObjectRecord>>, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord | undefined> { + const graphqlQueryCreateManyResolverService = + new GraphqlQueryCreateManyResolverService(this.twentyORMGlobalManager); - if (!objectMetadata) { - throw new Error( - `Object metadata for ${objectMetadataItem.nameSingular} not found`, - ); + const { authContext, objectMetadataItem } = options; + + assertMutationNotOnRemoteObject(objectMetadataItem); + + if (args.data.id) { + assertIsValidUuid(args.data.id); } - const fieldMetadataMap = objectMetadata.fields; + const createManyArgs = { + data: [args.data], + upsert: args.upsert, + } as CreateManyResolverArgs<ObjectRecord>; + + const hookedArgs = + await this.workspaceQueryHookService.executePreQueryHooks( + authContext, + objectMetadataItem.nameSingular, + 'createMany', + createManyArgs, + ); + + const computedArgs = (await this.queryRunnerArgsFactory.create( + hookedArgs, + options, + ResolverArgsType.CreateMany, + )) as CreateManyResolverArgs<ObjectRecord>; - const graphqlQueryParser = new GraphqlQueryParser( - fieldMetadataMap, - objectMetadataMap, + const results = (await graphqlQueryCreateManyResolverService.createMany( + computedArgs, + options, + )) as ObjectRecord[]; + + await this.triggerWebhooks<ObjectRecord>( + results, + CallWebhookJobsJobOperation.create, + options, ); - const { select, relations } = graphqlQueryParser.parseSelectedFields( + this.emitCreateEvents<ObjectRecord>( + results, + authContext, objectMetadataItem, - selectedFields, ); - const order = args.orderBy - ? graphqlQueryParser.parseOrder(args.orderBy) - : undefined; + return results?.[0] as ObjectRecord; + } - const where = args.filter - ? graphqlQueryParser.parseFilter(args.filter) - : {}; + @LogExecutionTime() + async createMany<ObjectRecord extends IRecord = IRecord>( + args: CreateManyResolverArgs<Partial<ObjectRecord>>, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord[] | undefined> { + const graphqlQueryCreateManyResolverService = + new GraphqlQueryCreateManyResolverService(this.twentyORMGlobalManager); - let cursor: Record<string, any> | undefined; + const { authContext, objectMetadataItem } = options; - if (args.after) { - cursor = decodeCursor(args.after); - } else if (args.before) { - cursor = decodeCursor(args.before); - } + assertMutationNotOnRemoteObject(objectMetadataItem); - if (args.first && args.last) { - throw new GraphqlQueryRunnerException( - 'Cannot provide both first and last', - GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT, + args.data.forEach((record) => { + if (record?.id) { + assertIsValidUuid(record.id); + } + }); + + const hookedArgs = + await this.workspaceQueryHookService.executePreQueryHooks( + authContext, + objectMetadataItem.nameSingular, + 'createMany', + args, ); - } - const take = args.first ?? args.last ?? QUERY_MAX_RECORDS; + const computedArgs = (await this.queryRunnerArgsFactory.create( + hookedArgs, + options, + ResolverArgsType.CreateMany, + )) as CreateManyResolverArgs<ObjectRecord>; - const findOptions: FindManyOptions<ObjectLiteral> = { - where, - order, - select, - relations, - take, - }; + const results = (await graphqlQueryCreateManyResolverService.createMany( + computedArgs, + options, + )) as ObjectRecord[]; - const totalCount = await repository.count({ - where, - }); + await this.workspaceQueryHookService.executePostQueryHooks( + authContext, + objectMetadataItem.nameSingular, + 'createMany', + results, + ); + + await this.triggerWebhooks<ObjectRecord>( + results, + CallWebhookJobsJobOperation.create, + options, + ); + + this.emitCreateEvents<ObjectRecord>( + results, + authContext, + objectMetadataItem, + ); + + return results; + } + + private emitCreateEvents<BaseRecord extends IRecord = IRecord>( + records: BaseRecord[], + authContext: AuthContext, + objectMetadataItem: ObjectMetadataInterface, + ) { + this.workspaceEventEmitter.emit( + `${objectMetadataItem.nameSingular}.created`, + records.map( + (record) => + ({ + userId: authContext.user?.id, + recordId: record.id, + objectMetadata: objectMetadataItem, + properties: { + after: record, + }, + }) satisfies ObjectRecordCreateEvent<any>, + ), + authContext.workspace.id, + ); + } - if (cursor) { - applyRangeFilter(where, order, cursor); + private async triggerWebhooks<Record>( + jobsData: Record[] | undefined, + operation: CallWebhookJobsJobOperation, + options: WorkspaceQueryRunnerOptions, + ) { + if (!Array.isArray(jobsData)) { + return; } + jobsData.forEach((jobData) => { + this.messageQueueService.add<CallWebhookJobsJobData>( + CallWebhookJobsJob.name, + { + record: jobData, + workspaceId: options.authContext.workspace.id, + operation, + objectMetadataItem: options.objectMetadataItem, + }, + { retryLimit: 3 }, + ); + }); + } + + @LogExecutionTime() + async destroyOne<ObjectRecord extends IRecord = IRecord>( + args: DestroyOneResolverArgs, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord | undefined> { + const graphqlQueryDestroyOneResolverService = + new GraphqlQueryDestroyOneResolverService(this.twentyORMGlobalManager); + + const { authContext, objectMetadataItem } = options; - const objectRecords = await repository.find(findOptions); + assertMutationNotOnRemoteObject(objectMetadataItem); + assertIsValidUuid(args.id); - const typeORMObjectRecordsParser = - new ObjectRecordsToGraphqlConnectionMapper(objectMetadataMap); + const hookedArgs = + await this.workspaceQueryHookService.executePreQueryHooks( + authContext, + objectMetadataItem.nameSingular, + 'destroyOne', + args, + ); + + const computedArgs = (await this.queryRunnerArgsFactory.create( + hookedArgs, + options, + ResolverArgsType.DestroyOne, + )) as DestroyOneResolverArgs; - return typeORMObjectRecordsParser.createConnection( - (objectRecords as ObjectRecord[]) ?? [], - take, - totalCount, - order, + const result = (await graphqlQueryDestroyOneResolverService.destroyOne( + computedArgs, + options, + )) as ObjectRecord; + + await this.workspaceQueryHookService.executePostQueryHooks( + authContext, objectMetadataItem.nameSingular, + 'destroyOne', + [result], + ); + + await this.triggerWebhooks<IRecord>( + [result], + CallWebhookJobsJobOperation.destroy, + options, + ); + + this.emitDestroyEvents<IRecord>([result], authContext, objectMetadataItem); + + return result; + } + + private emitDestroyEvents<BaseRecord extends IRecord = IRecord>( + records: BaseRecord[], + authContext: AuthContext, + objectMetadataItem: ObjectMetadataInterface, + ) { + this.workspaceEventEmitter.emit( + `${objectMetadataItem.nameSingular}.destroyed`, + records.map((record) => { + return { + userId: authContext.user?.id, + recordId: record.id, + objectMetadata: objectMetadataItem, + properties: { + before: this.removeNestedProperties(record), + }, + } satisfies ObjectRecordDeleteEvent<any>; + }), + authContext.workspace.id, ); } + + private removeNestedProperties<Record extends IRecord = IRecord>( + record: Record, + ) { + if (!record) { + return; + } + + const sanitizedRecord = {}; + + for (const [key, value] of Object.entries(record)) { + if (value && typeof value === 'object' && value['edges']) { + continue; + } + + if (key === '__typename') { + continue; + } + + sanitizedRecord[key] = value; + } + + return sanitizedRecord; + } } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper.ts new file mode 100644 index 000000000000..f19c7cf06eb3 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper.ts @@ -0,0 +1,194 @@ +import { + DataSource, + FindManyOptions, + FindOptionsRelations, + In, + ObjectLiteral, +} from 'typeorm'; + +import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; + +import { + getRelationMetadata, + getRelationObjectMetadata, +} from 'src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util'; +import { + ObjectMetadataMap, + ObjectMetadataMapItem, +} from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { deduceRelationDirection } from 'src/engine/utils/deduce-relation-direction.util'; + +export class ProcessNestedRelationsHelper { + private readonly twentyORMGlobalManager: TwentyORMGlobalManager; + + constructor(twentyORMGlobalManager: TwentyORMGlobalManager) { + this.twentyORMGlobalManager = twentyORMGlobalManager; + } + + private async processFromRelation<ObjectRecord extends IRecord = IRecord>( + objectMetadataMap: ObjectMetadataMap, + parentObjectMetadataItem: ObjectMetadataMapItem, + parentObjectRecords: ObjectRecord[], + relationName: string, + nestedRelations: any, + limit: number, + authContext: any, + dataSource: DataSource, + ) { + const relationFieldMetadata = parentObjectMetadataItem.fields[relationName]; + const relationMetadata = getRelationMetadata(relationFieldMetadata); + + const inverseRelationName = + objectMetadataMap[relationMetadata.toObjectMetadataId]?.fields[ + relationMetadata.toFieldMetadataId + ]?.name; + + const referenceObjectMetadata = getRelationObjectMetadata( + relationFieldMetadata, + objectMetadataMap, + ); + + const referenceObjectMetadataName = referenceObjectMetadata.nameSingular; + + const relationRepository = await dataSource.getRepository( + referenceObjectMetadataName, + ); + + const relationIds = parentObjectRecords.map((item) => item.id); + + const uniqueRelationIds = [...new Set(relationIds)]; + + const relationFindOptions: FindManyOptions = { + where: { + [`${inverseRelationName}Id`]: In(uniqueRelationIds), + }, + take: limit * parentObjectRecords.length, + }; + + const relationResults = await relationRepository.find(relationFindOptions); + + parentObjectRecords.forEach((item) => { + (item as any)[relationName] = relationResults.filter( + (rel) => rel[`${inverseRelationName}Id`] === item.id, + ); + }); + + if (Object.keys(nestedRelations).length > 0) { + await this.processNestedRelations( + objectMetadataMap, + objectMetadataMap[referenceObjectMetadataName], + relationResults as ObjectRecord[], + nestedRelations as Record<string, FindOptionsRelations<ObjectLiteral>>, + limit, + authContext, + dataSource, + ); + } + } + + private async processToRelation<ObjectRecord extends IRecord = IRecord>( + objectMetadataMap: ObjectMetadataMap, + parentObjectMetadataItem: ObjectMetadataMapItem, + parentObjectRecords: ObjectRecord[], + relationName: string, + nestedRelations: any, + limit: number, + authContext: any, + dataSource: DataSource, + ) { + const relationFieldMetadata = parentObjectMetadataItem.fields[relationName]; + + const referenceObjectMetadata = getRelationObjectMetadata( + relationFieldMetadata, + objectMetadataMap, + ); + + const referenceObjectMetadataName = referenceObjectMetadata.nameSingular; + + const relationRepository = dataSource.getRepository( + referenceObjectMetadataName, + ); + + const relationIds = parentObjectRecords.map( + (item) => item[`${relationName}Id`], + ); + + const uniqueRelationIds = [...new Set(relationIds)]; + + const relationFindOptions: FindManyOptions = { + where: { + id: In(uniqueRelationIds), + }, + take: limit, + }; + + const relationResults = await relationRepository.find(relationFindOptions); + + parentObjectRecords.forEach((item) => { + if (relationResults.length === 0) { + (item as any)[`${relationName}Id`] = null; + } + (item as any)[relationName] = relationResults.filter( + (rel) => rel.id === item[`${relationName}Id`], + )[0]; + }); + + if (Object.keys(nestedRelations).length > 0) { + await this.processNestedRelations( + objectMetadataMap, + objectMetadataMap[referenceObjectMetadataName], + relationResults as ObjectRecord[], + nestedRelations as Record<string, FindOptionsRelations<ObjectLiteral>>, + limit, + authContext, + dataSource, + ); + } + } + + public async processNestedRelations<ObjectRecord extends IRecord = IRecord>( + objectMetadataMap: ObjectMetadataMap, + parentObjectMetadataItem: ObjectMetadataMapItem, + parentObjectRecords: ObjectRecord[], + relations: Record<string, FindOptionsRelations<ObjectLiteral>>, + limit: number, + authContext: any, + dataSource: DataSource, + ) { + for (const [relationName, nestedRelations] of Object.entries(relations)) { + const relationFieldMetadata = + parentObjectMetadataItem.fields[relationName]; + const relationMetadata = getRelationMetadata(relationFieldMetadata); + + const relationDirection = deduceRelationDirection( + relationFieldMetadata, + relationMetadata, + ); + + if (relationDirection === 'to') { + await this.processToRelation( + objectMetadataMap, + parentObjectMetadataItem, + parentObjectRecords, + relationName, + nestedRelations, + limit, + authContext, + dataSource, + ); + } else { + await this.processFromRelation( + objectMetadataMap, + parentObjectMetadataItem, + parentObjectRecords, + relationName, + nestedRelations, + limit, + authContext, + dataSource, + ); + } + } + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper.ts index eecf0c0e1ff5..b9a81ef245dc 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper.ts @@ -1,6 +1,7 @@ -import { FindOptionsOrderValue } from 'typeorm'; - -import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { + Record as IRecord, + RecordOrderBy, +} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { IConnection } from 'src/engine/api/graphql/workspace-query-runner/interfaces/connection.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; @@ -9,12 +10,12 @@ import { GraphqlQueryRunnerException, GraphqlQueryRunnerExceptionCode, } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; -import { ObjectMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; import { encodeCursor } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util'; import { getRelationObjectMetadata } from 'src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { CompositeFieldMetadataType } from 'src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory'; import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; import { isPlainObject } from 'src/utils/is-plain-object'; @@ -28,19 +29,21 @@ export class ObjectRecordsToGraphqlConnectionMapper { public createConnection<ObjectRecord extends IRecord = IRecord>( objectRecords: ObjectRecord[], + objectName: string, take: number, totalCount: number, - order: Record<string, FindOptionsOrderValue> | undefined, - objectName: string, + order: RecordOrderBy | undefined, + hasNextPage: boolean, + hasPreviousPage: boolean, depth = 0, ): IConnection<ObjectRecord> { const edges = (objectRecords ?? []).map((objectRecord) => ({ node: this.processRecord( objectRecord, + objectName, take, totalCount, order, - objectName, depth, ), cursor: encodeCursor(objectRecord, order), @@ -49,8 +52,8 @@ export class ObjectRecordsToGraphqlConnectionMapper { return { edges, pageInfo: { - hasNextPage: objectRecords.length === take && totalCount > take, - hasPreviousPage: false, + hasNextPage, + hasPreviousPage, startCursor: edges[0]?.cursor, endCursor: edges[edges.length - 1]?.cursor, }, @@ -58,12 +61,12 @@ export class ObjectRecordsToGraphqlConnectionMapper { }; } - private processRecord<T extends Record<string, any>>( + public processRecord<T extends Record<string, any>>( objectRecord: T, + objectName: string, take: number, totalCount: number, - order: Record<string, FindOptionsOrderValue> | undefined, - objectName: string, + order?: RecordOrderBy, depth = 0, ): T { if (depth >= CONNECTION_MAX_DEPTH) { @@ -96,21 +99,23 @@ export class ObjectRecordsToGraphqlConnectionMapper { if (Array.isArray(value)) { processedObjectRecord[key] = this.createConnection( value, + getRelationObjectMetadata(fieldMetadata, this.objectMetadataMap) + .nameSingular, take, value.length, order, - getRelationObjectMetadata(fieldMetadata, this.objectMetadataMap) - .nameSingular, + false, + false, depth + 1, ); } else if (isPlainObject(value)) { processedObjectRecord[key] = this.processRecord( value, + getRelationObjectMetadata(fieldMetadata, this.objectMetadataMap) + .nameSingular, take, totalCount, order, - getRelationObjectMetadata(fieldMetadata, this.objectMetadataMap) - .nameSingular, depth + 1, ); } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-create-many-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-create-many-resolver.service.ts new file mode 100644 index 000000000000..f66497a6812a --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-create-many-resolver.service.ts @@ -0,0 +1,79 @@ +import graphqlFields from 'graphql-fields'; +import { In, InsertResult } from 'typeorm'; + +import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-query-runner/interfaces/query-runner-option.interface'; +import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; +import { ObjectRecordsToGraphqlConnectionMapper } from 'src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper'; +import { getObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util'; +import { generateObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; + +export class GraphqlQueryCreateManyResolverService { + private twentyORMGlobalManager: TwentyORMGlobalManager; + + constructor(twentyORMGlobalManager: TwentyORMGlobalManager) { + this.twentyORMGlobalManager = twentyORMGlobalManager; + } + + async createMany<ObjectRecord extends IRecord = IRecord>( + args: CreateManyResolverArgs<Partial<ObjectRecord>>, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord[] | undefined> { + const { authContext, objectMetadataItem, objectMetadataCollection, info } = + options; + const repository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + authContext.workspace.id, + objectMetadataItem.nameSingular, + ); + + const objectMetadataMap = generateObjectMetadataMap( + objectMetadataCollection, + ); + const objectMetadata = getObjectMetadataOrThrow( + objectMetadataMap, + objectMetadataItem.nameSingular, + ); + const graphqlQueryParser = new GraphqlQueryParser( + objectMetadata.fields, + objectMetadataMap, + ); + + const selectedFields = graphqlFields(info); + + const { select, relations } = graphqlQueryParser.parseSelectedFields( + objectMetadataItem, + selectedFields, + ); + + const objectRecords: InsertResult = !args.upsert + ? await repository.insert(args.data) + : await repository.upsert(args.data, { + conflictPaths: ['id'], + skipUpdateIfNoValuesChanged: true, + }); + + const upsertedRecords = await repository.find({ + where: { + id: In(objectRecords.generatedMaps.map((record) => record.id)), + }, + select, + relations, + }); + + const typeORMObjectRecordsParser = + new ObjectRecordsToGraphqlConnectionMapper(objectMetadataMap); + + return upsertedRecords.map((record: ObjectRecord) => + typeORMObjectRecordsParser.processRecord( + record, + objectMetadataItem.nameSingular, + 1, + 1, + ), + ); + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-destroy-one-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-destroy-one-resolver.service.ts new file mode 100644 index 000000000000..53dad3eddd0b --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-destroy-one-resolver.service.ts @@ -0,0 +1,33 @@ +import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-query-runner/interfaces/query-runner-option.interface'; +import { DestroyOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; + +export class GraphqlQueryDestroyOneResolverService { + private twentyORMGlobalManager: TwentyORMGlobalManager; + + constructor(twentyORMGlobalManager: TwentyORMGlobalManager) { + this.twentyORMGlobalManager = twentyORMGlobalManager; + } + + async destroyOne<ObjectRecord extends IRecord = IRecord>( + args: DestroyOneResolverArgs, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord> { + const { authContext, objectMetadataItem } = options; + const repository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + authContext.workspace.id, + objectMetadataItem.nameSingular, + ); + + const record = await repository.findOne({ + where: { id: args.id }, + }); + + await repository.delete(args.id); + + return record as ObjectRecord; + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts new file mode 100644 index 000000000000..5caa30e4e51e --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-many-resolver.service.ts @@ -0,0 +1,283 @@ +import { isDefined } from 'class-validator'; +import graphqlFields from 'graphql-fields'; + +import { + Record as IRecord, + OrderByDirection, + RecordFilter, + RecordOrderBy, +} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { IConnection } from 'src/engine/api/graphql/workspace-query-runner/interfaces/connection.interface'; +import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-query-runner/interfaces/query-runner-option.interface'; +import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; +import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; +import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper'; +import { ObjectRecordsToGraphqlConnectionMapper } from 'src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper'; +import { computeCursorArgFilter } from 'src/engine/api/graphql/graphql-query-runner/utils/compute-cursor-arg-filter'; +import { decodeCursor } from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util'; +import { getObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util'; +import { + ObjectMetadataMapItem, + generateObjectMetadataMap, +} from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; + +export class GraphqlQueryFindManyResolverService { + private twentyORMGlobalManager: TwentyORMGlobalManager; + + constructor(twentyORMGlobalManager: TwentyORMGlobalManager) { + this.twentyORMGlobalManager = twentyORMGlobalManager; + } + + async findMany< + ObjectRecord extends IRecord = IRecord, + Filter extends RecordFilter = RecordFilter, + OrderBy extends RecordOrderBy = RecordOrderBy, + >( + args: FindManyResolverArgs<Filter, OrderBy>, + options: WorkspaceQueryRunnerOptions, + ): Promise<IConnection<ObjectRecord>> { + const { authContext, objectMetadataItem, info, objectMetadataCollection } = + options; + + this.validateArgsOrThrow(args); + + const dataSource = + await this.twentyORMGlobalManager.getDataSourceForWorkspace( + authContext.workspace.id, + ); + + const repository = dataSource.getRepository( + objectMetadataItem.nameSingular, + ); + + const queryBuilder = repository.createQueryBuilder( + objectMetadataItem.nameSingular, + ); + + const countQueryBuilder = repository.createQueryBuilder( + objectMetadataItem.nameSingular, + ); + + const objectMetadataMap = generateObjectMetadataMap( + objectMetadataCollection, + ); + + const objectMetadata = getObjectMetadataOrThrow( + objectMetadataMap, + objectMetadataItem.nameSingular, + ); + const graphqlQueryParser = new GraphqlQueryParser( + objectMetadata.fields, + objectMetadataMap, + ); + + const withFilterCountQueryBuilder = graphqlQueryParser.applyFilterToBuilder( + countQueryBuilder, + objectMetadataItem.nameSingular, + args.filter ?? ({} as Filter), + ); + + const selectedFields = graphqlFields(info); + + const { relations } = graphqlQueryParser.parseSelectedFields( + objectMetadataItem, + selectedFields, + ); + const isForwardPagination = !isDefined(args.before); + + const limit = args.first ?? args.last ?? QUERY_MAX_RECORDS; + + const withDeletedCountQueryBuilder = + graphqlQueryParser.applyDeletedAtToBuilder( + withFilterCountQueryBuilder, + args.filter ?? ({} as Filter), + ); + + const totalCount = isDefined(selectedFields.totalCount) + ? await withDeletedCountQueryBuilder.getCount() + : 0; + + const cursor = this.getCursor(args); + + let appliedFilters = args.filter ?? ({} as Filter); + + const orderByWithIdCondition = [ + ...(args.orderBy ?? []), + { id: OrderByDirection.AscNullsFirst }, + ] as OrderBy; + + if (cursor) { + const cursorArgFilter = computeCursorArgFilter( + cursor, + orderByWithIdCondition, + objectMetadata.fields, + isForwardPagination, + ); + + appliedFilters = (args.filter + ? { + and: [args.filter, { or: cursorArgFilter }], + } + : { or: cursorArgFilter }) as unknown as Filter; + } + + const withFilterQueryBuilder = graphqlQueryParser.applyFilterToBuilder( + queryBuilder, + objectMetadataItem.nameSingular, + appliedFilters, + ); + + const withOrderByQueryBuilder = graphqlQueryParser.applyOrderToBuilder( + withFilterQueryBuilder, + orderByWithIdCondition, + objectMetadataItem.nameSingular, + isForwardPagination, + ); + + const withDeletedQueryBuilder = graphqlQueryParser.applyDeletedAtToBuilder( + withOrderByQueryBuilder, + args.filter ?? ({} as Filter), + ); + + const nonFormattedObjectRecords = await withDeletedQueryBuilder + .take(limit + 1) + .getMany(); + + const objectRecords = formatResult( + nonFormattedObjectRecords, + objectMetadata, + objectMetadataMap, + ); + + const { hasNextPage, hasPreviousPage } = this.getPaginationInfo( + objectRecords, + limit, + isForwardPagination, + ); + + if (objectRecords.length > limit) { + objectRecords.pop(); + } + + const processNestedRelationsHelper = new ProcessNestedRelationsHelper( + this.twentyORMGlobalManager, + ); + + if (relations) { + await processNestedRelationsHelper.processNestedRelations( + objectMetadataMap, + objectMetadata, + objectRecords, + relations, + limit, + authContext, + dataSource, + ); + } + + const typeORMObjectRecordsParser = + new ObjectRecordsToGraphqlConnectionMapper(objectMetadataMap); + + return typeORMObjectRecordsParser.createConnection( + objectRecords, + objectMetadataItem.nameSingular, + limit, + totalCount, + orderByWithIdCondition, + hasNextPage, + hasPreviousPage, + ); + } + + private validateArgsOrThrow(args: FindManyResolverArgs<any, any>) { + if (args.first && args.last) { + throw new GraphqlQueryRunnerException( + 'Cannot provide both first and last', + GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT, + ); + } + if (args.before && args.after) { + throw new GraphqlQueryRunnerException( + 'Cannot provide both before and after', + GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT, + ); + } + if (args.before && args.first) { + throw new GraphqlQueryRunnerException( + 'Cannot provide both before and first', + GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT, + ); + } + if (args.after && args.last) { + throw new GraphqlQueryRunnerException( + 'Cannot provide both after and last', + GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT, + ); + } + if (args.first !== undefined && args.first < 0) { + throw new GraphqlQueryRunnerException( + 'First argument must be non-negative', + GraphqlQueryRunnerExceptionCode.INVALID_ARGS_FIRST, + ); + } + if (args.last !== undefined && args.last < 0) { + throw new GraphqlQueryRunnerException( + 'Last argument must be non-negative', + GraphqlQueryRunnerExceptionCode.INVALID_ARGS_LAST, + ); + } + } + + private getCursor( + args: FindManyResolverArgs<any, any>, + ): Record<string, any> | undefined { + if (args.after) return decodeCursor(args.after); + if (args.before) return decodeCursor(args.before); + + return undefined; + } + + private addOrderByColumnsToSelect( + order: Record<string, any>, + select: Record<string, boolean>, + ) { + for (const column of Object.keys(order || {})) { + if (!select[column]) { + select[column] = true; + } + } + } + + private addForeingKeyColumnsToSelect( + relations: Record<string, any>, + select: Record<string, boolean>, + objectMetadata: ObjectMetadataMapItem, + ) { + for (const column of Object.keys(relations || {})) { + if (!select[`${column}Id`] && objectMetadata.fields[`${column}Id`]) { + select[`${column}Id`] = true; + } + } + } + + private getPaginationInfo( + objectRecords: any[], + limit: number, + isForwardPagination: boolean, + ) { + const hasMoreRecords = objectRecords.length > limit; + + return { + hasNextPage: isForwardPagination && hasMoreRecords, + hasPreviousPage: !isForwardPagination && hasMoreRecords, + }; + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts new file mode 100644 index 000000000000..b9e86e420cc9 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-find-one-resolver.service.ts @@ -0,0 +1,130 @@ +import graphqlFields from 'graphql-fields'; + +import { + Record as IRecord, + RecordFilter, +} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-query-runner/interfaces/query-runner-option.interface'; +import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { QUERY_MAX_RECORDS } from 'src/engine/api/graphql/graphql-query-runner/constants/query-max-records.constant'; +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; +import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; +import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper'; +import { ObjectRecordsToGraphqlConnectionMapper } from 'src/engine/api/graphql/graphql-query-runner/orm-mappers/object-records-to-graphql-connection.mapper'; +import { getObjectMetadataOrThrow } from 'src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util'; +import { generateObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; + +export class GraphqlQueryFindOneResolverService { + private twentyORMGlobalManager: TwentyORMGlobalManager; + + constructor(twentyORMGlobalManager: TwentyORMGlobalManager) { + this.twentyORMGlobalManager = twentyORMGlobalManager; + } + + async findOne< + ObjectRecord extends IRecord = IRecord, + Filter extends RecordFilter = RecordFilter, + >( + args: FindOneResolverArgs<Filter>, + options: WorkspaceQueryRunnerOptions, + ): Promise<ObjectRecord | undefined> { + const { authContext, objectMetadataItem, info, objectMetadataCollection } = + options; + + const dataSource = + await this.twentyORMGlobalManager.getDataSourceForWorkspace( + authContext.workspace.id, + ); + + const repository = dataSource.getRepository( + objectMetadataItem.nameSingular, + ); + + const queryBuilder = repository.createQueryBuilder( + objectMetadataItem.nameSingular, + ); + + const objectMetadataMap = generateObjectMetadataMap( + objectMetadataCollection, + ); + + const objectMetadata = getObjectMetadataOrThrow( + objectMetadataMap, + objectMetadataItem.nameSingular, + ); + + const graphqlQueryParser = new GraphqlQueryParser( + objectMetadata.fields, + objectMetadataMap, + ); + + const selectedFields = graphqlFields(info); + + const { relations } = graphqlQueryParser.parseSelectedFields( + objectMetadataItem, + selectedFields, + ); + + const withFilterQueryBuilder = graphqlQueryParser.applyFilterToBuilder( + queryBuilder, + objectMetadataItem.nameSingular, + args.filter ?? ({} as Filter), + ); + + const withDeletedQueryBuilder = graphqlQueryParser.applyDeletedAtToBuilder( + withFilterQueryBuilder, + args.filter ?? ({} as Filter), + ); + + const nonFormattedObjectRecord = await withDeletedQueryBuilder.getOne(); + + const objectRecord = formatResult( + nonFormattedObjectRecord, + objectMetadata, + objectMetadataMap, + ); + + const limit = QUERY_MAX_RECORDS; + + if (!objectRecord) { + throw new GraphqlQueryRunnerException( + 'Record not found', + GraphqlQueryRunnerExceptionCode.RECORD_NOT_FOUND, + ); + } + + const processNestedRelationsHelper = new ProcessNestedRelationsHelper( + this.twentyORMGlobalManager, + ); + + const objectRecords = [objectRecord]; + + if (relations) { + await processNestedRelationsHelper.processNestedRelations( + objectMetadataMap, + objectMetadata, + objectRecords, + relations, + limit, + authContext, + dataSource, + ); + } + + const typeORMObjectRecordsParser = + new ObjectRecordsToGraphqlConnectionMapper(objectMetadataMap); + + return typeORMObjectRecordsParser.processRecord( + objectRecords[0], + objectMetadataItem.nameSingular, + 1, + 1, + ) as ObjectRecord; + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/compute-cursor-arg-filter.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/compute-cursor-arg-filter.ts new file mode 100644 index 000000000000..c602aef7fcba --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/compute-cursor-arg-filter.ts @@ -0,0 +1,133 @@ +import { + OrderByDirection, + RecordFilter, + RecordOrderBy, +} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; + +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; +import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; +import { FieldMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; + +export const computeCursorArgFilter = ( + cursor: Record<string, any>, + orderBy: RecordOrderBy, + fieldMetadataMap: FieldMetadataMap, + isForwardPagination = true, +): RecordFilter[] => { + const cursorKeys = Object.keys(cursor ?? {}); + const cursorValues = Object.values(cursor ?? {}); + + if (cursorKeys.length === 0) { + return []; + } + + return Object.entries(cursor ?? {}).map(([key, value], index) => { + let whereCondition = {}; + + for ( + let subConditionIndex = 0; + subConditionIndex < index; + subConditionIndex++ + ) { + whereCondition = { + ...whereCondition, + ...buildWhereCondition( + cursorKeys[subConditionIndex], + cursorValues[subConditionIndex], + fieldMetadataMap, + 'eq', + ), + }; + } + + const keyOrderBy = orderBy.find((order) => key in order); + + if (!keyOrderBy) { + throw new GraphqlQueryRunnerException( + 'Invalid cursor', + GraphqlQueryRunnerExceptionCode.INVALID_CURSOR, + ); + } + + const isAscending = + keyOrderBy[key] === OrderByDirection.AscNullsFirst || + keyOrderBy[key] === OrderByDirection.AscNullsLast; + + const operator = isAscending + ? isForwardPagination + ? 'gt' + : 'lt' + : isForwardPagination + ? 'lt' + : 'gt'; + + return { + ...whereCondition, + ...buildWhereCondition(key, value, fieldMetadataMap, operator), + } as RecordFilter; + }); +}; + +const buildWhereCondition = ( + key: string, + value: any, + fieldMetadataMap: FieldMetadataMap, + operator: string, +): Record<string, any> => { + const fieldMetadata = fieldMetadataMap[key]; + + if (!fieldMetadata) { + throw new GraphqlQueryRunnerException( + `Field metadata not found for key: ${key}`, + GraphqlQueryRunnerExceptionCode.INVALID_CURSOR, + ); + } + + if (isCompositeFieldMetadataType(fieldMetadata.type)) { + return buildCompositeWhereCondition( + key, + value, + fieldMetadata.type, + operator, + ); + } + + return { [key]: { [operator]: value } }; +}; + +const buildCompositeWhereCondition = ( + key: string, + value: any, + fieldType: FieldMetadataType, + operator: string, +): Record<string, any> => { + const compositeType = compositeTypeDefinitions.get(fieldType); + + if (!compositeType) { + throw new GraphqlQueryRunnerException( + `Composite type definition not found for type: ${fieldType}`, + GraphqlQueryRunnerExceptionCode.INVALID_CURSOR, + ); + } + + const result: Record<string, any> = {}; + + compositeType.properties.forEach((property) => { + if ( + property.type !== FieldMetadataType.RAW_JSON && + value[property.name] !== undefined + ) { + result[key] = { + ...result[key], + [property.name]: { [operator]: value[property.name] }, + }; + } + }); + + return result; +}; diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/cursors.util.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/cursors.util.ts index 5adc036e4ad1..bf8eb52d0a57 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/cursors.util.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/cursors.util.ts @@ -1,13 +1,18 @@ -import { FindOptionsOrderValue } from 'typeorm'; - -import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { + Record as IRecord, + RecordOrderBy, +} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { GraphqlQueryRunnerException, GraphqlQueryRunnerExceptionCode, } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; -export const decodeCursor = (cursor: string): Record<string, any> => { +export interface CursorData { + [key: string]: any; +} + +export const decodeCursor = (cursor: string): CursorData => { try { return JSON.parse(Buffer.from(cursor, 'base64').toString()); } catch (err) { @@ -20,15 +25,22 @@ export const decodeCursor = (cursor: string): Record<string, any> => { export const encodeCursor = <ObjectRecord extends IRecord = IRecord>( objectRecord: ObjectRecord, - order: Record<string, FindOptionsOrderValue> | undefined, + order: RecordOrderBy | undefined, ): string => { - const cursor = {}; + const orderByValues: Record<string, any> = {}; + + const orderBy = order?.reduce((acc, orderBy) => ({ ...acc, ...orderBy }), {}); + + const orderByKeys = Object.keys(orderBy ?? {}); - Object.keys(order ?? []).forEach((key) => { - cursor[key] = objectRecord[key]; + orderByKeys?.forEach((key) => { + orderByValues[key] = objectRecord[key]; }); - cursor['id'] = objectRecord.id; + const cursorData: CursorData = { + ...orderByValues, + id: objectRecord.id, + }; - return Buffer.from(JSON.stringify(Object.values(cursor))).toString('base64'); + return Buffer.from(JSON.stringify(cursorData)).toString('base64'); }; diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util.ts new file mode 100644 index 000000000000..00ef040204e0 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-object-metadata-or-throw.util.ts @@ -0,0 +1,21 @@ +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; +import { ObjectMetadataMapItem } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; + +export const getObjectMetadataOrThrow = ( + objectMetadataMap: Record<string, any>, + objectName: string, +): ObjectMetadataMapItem => { + const objectMetadata = objectMetadataMap[objectName]; + + if (!objectMetadata) { + throw new GraphqlQueryRunnerException( + `Object metadata not found for ${objectName}`, + GraphqlQueryRunnerExceptionCode.OBJECT_METADATA_NOT_FOUND, + ); + } + + return objectMetadata; +}; diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util.ts index 4b502803292f..d05bdcced27a 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/utils/get-relation-object-metadata.util.ts @@ -1,6 +1,7 @@ import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; -import { ObjectMetadataMap } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-object-metadata-to-map.util'; +import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { deduceRelationDirection, RelationDirection, @@ -10,14 +11,7 @@ export const getRelationObjectMetadata = ( fieldMetadata: FieldMetadataInterface, objectMetadataMap: ObjectMetadataMap, ) => { - const relationMetadata = - fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata; - - if (!relationMetadata) { - throw new Error( - `Relation metadata not found for field ${fieldMetadata.name}`, - ); - } + const relationMetadata = getRelationMetadata(fieldMetadata); const relationDirection = deduceRelationDirection( fieldMetadata, @@ -37,3 +31,18 @@ export const getRelationObjectMetadata = ( return referencedObjectMetadata; }; + +export const getRelationMetadata = ( + fieldMetadata: FieldMetadataInterface, +): RelationMetadataEntity => { + const relationMetadata = + fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata; + + if (!relationMetadata) { + throw new Error( + `Relation metadata not found for field ${fieldMetadata.name}`, + ); + } + + return relationMetadata; +}; diff --git a/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts b/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts index 3d0627ce7336..f7ac4328f21a 100644 --- a/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts @@ -7,9 +7,9 @@ import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graph import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory'; import { DataloaderModule } from 'src/engine/dataloaders/dataloader.module'; import { DataloaderService } from 'src/engine/dataloaders/dataloader.service'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module'; diff --git a/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts b/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts index 5297b747b954..d11a092b707e 100644 --- a/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts @@ -4,11 +4,11 @@ import GraphQLJSON from 'graphql-type-json'; import { useCachedMetadata } from 'src/engine/api/graphql/graphql-config/hooks/use-cached-metadata'; import { useThrottler } from 'src/engine/api/graphql/graphql-config/hooks/use-throttler'; import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; import { DataloaderService } from 'src/engine/dataloaders/dataloader.service'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; import { renderApolloPlayground } from 'src/engine/utils/render-apollo-playground.util'; export const metadataModuleFactory = async ( diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts index 020af73eced5..f7bec67e371a 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-many-query.factory.ts @@ -34,7 +34,7 @@ export class FindManyQueryFactory { const argsString = this.argsStringFactory.create( args, options.fieldMetadataCollection, - !options.withSoftDeleted && !!options.objectMetadataItem.isSoftDeletable, + !options.withSoftDeleted, ); return ` diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts index 89b53949cb29..31f13dcbaf7d 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/find-one-query.factory.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; -import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface'; import { RecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; +import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface'; import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; @@ -29,7 +29,7 @@ export class FindOneQueryFactory { const argsString = this.argsStringFactory.create( args, options.fieldMetadataCollection, - !options.withSoftDeleted && !!options.objectMetadataItem.isSoftDeletable, + !options.withSoftDeleted, ); return ` diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts index d1d835a09811..36cae905aae1 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-builder/factories/relation-field-alias.factory.ts @@ -5,18 +5,18 @@ import { GraphQLResolveInfo } from 'graphql'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; +import { getFieldArgumentsByKey } from 'src/engine/api/graphql/workspace-query-builder/utils/get-field-arguments-by-key.util'; +import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; import { deduceRelationDirection, RelationDirection, } from 'src/engine/utils/deduce-relation-direction.util'; -import { getFieldArgumentsByKey } from 'src/engine/api/graphql/workspace-query-builder/utils/get-field-arguments-by-key.util'; -import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; -import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; -import { FieldsStringFactory } from './fields-string.factory'; import { ArgsStringFactory } from './args-string.factory'; +import { FieldsStringFactory } from './fields-string.factory'; @Injectable() export class RelationFieldAliasFactory { @@ -101,7 +101,7 @@ export class RelationFieldAliasFactory { const argsString = this.argsStringFactory.create( args, referencedObjectMetadata.fields ?? [], - !withSoftDeleted && !!referencedObjectMetadata.isSoftDeletable, + !withSoftDeleted, ); const fieldsString = await this.fieldsStringFactory.createFieldsStringRecursive( diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command.ts index ddc2f06a4dbf..a5ddfc065856 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command.ts @@ -4,9 +4,9 @@ import { RecordPositionBackfillJob, RecordPositionBackfillJobData, } from 'src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; export type RecordPositionBackfillCommandOptions = { workspaceId: string; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook-jobs.job.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook-jobs.job.ts index 74e955093e6d..a1b43eb22034 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook-jobs.job.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook-jobs.job.ts @@ -8,11 +8,11 @@ import { CallWebhookJob, CallWebhookJobData, } from 'src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WebhookWorkspaceEntity } from 'src/modules/webhook/standard-objects/webhook.workspace-entity'; @@ -20,6 +20,7 @@ export enum CallWebhookJobsJobOperation { create = 'create', update = 'update', delete = 'delete', + destroy = 'destroy', } export type CallWebhookJobsJobData = { diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job.ts index 6e0d7af5240b..bbaff49a4951 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job.ts @@ -1,9 +1,9 @@ import { HttpService } from '@nestjs/axios'; import { Logger } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export type CallWebhookJobData = { targetUrl: string; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job.ts index 8619f1182814..67cf1dd555b9 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/jobs/record-position-backfill.job.ts @@ -1,7 +1,7 @@ import { RecordPositionBackfillService } from 'src/engine/api/graphql/workspace-query-runner/services/record-position-backfill-service'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; export type RecordPositionBackfillJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts index 1804901ac1d5..8eb8be61f774 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts @@ -1,13 +1,13 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; -import { objectRecordChangedValues } from 'src/engine/integrations/event-emitter/utils/object-record-changed-values'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; +import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { CreateAuditLogFromInternalEvent } from 'src/modules/timeline/jobs/create-audit-log-from-internal-event'; import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job'; @@ -49,17 +49,30 @@ export class EntityEventsToDbListener { return this.handle(payload); } + @OnEvent('*.destroyed') + async handleDestroy( + payload: WorkspaceEventBatch<ObjectRecordUpdateEvent<any>>, + ) { + return this.handle(payload); + } + private async handle(payload: WorkspaceEventBatch<ObjectRecordBaseEvent>) { - payload.events = payload.events.filter( + const filteredEvents = payload.events.filter( (event) => event.objectMetadata?.isAuditLogged, ); await this.messageQueueService.add< WorkspaceEventBatch<ObjectRecordBaseEvent> - >(CreateAuditLogFromInternalEvent.name, payload); + >(CreateAuditLogFromInternalEvent.name, { + ...payload, + events: filteredEvents, + }); await this.messageQueueService.add< WorkspaceEventBatch<ObjectRecordBaseEvent> - >(UpsertTimelineActivityFromInternalEvent.name, payload); + >(UpsertTimelineActivityFromInternalEvent.name, { + ...payload, + events: filteredEvents, + }); } } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts index f9609794d7ac..f627caf47a42 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener.ts @@ -2,15 +2,15 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { TelemetryService } from 'src/engine/core-modules/telemetry/telemetry.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; @Injectable() export class TelemetryListener { constructor( private readonly analyticsService: AnalyticsService, - private readonly environmentService: EnvironmentService, + private readonly telemetryService: TelemetryService, ) {} @OnEvent('*.created') @@ -21,16 +21,11 @@ export class TelemetryListener { payload.events.map((eventPayload) => this.analyticsService.create( { - type: 'track', - data: { - eventName: payload.name, - }, + action: payload.name, + payload: {}, }, eventPayload.userId, payload.workspaceId, - '', // voluntarily not retrieving this - '', // to avoid slowing down - this.environmentService.get('SERVER_URL'), ), ), ); @@ -41,21 +36,29 @@ export class TelemetryListener { payload: WorkspaceEventBatch<ObjectRecordCreateEvent<any>>, ) { await Promise.all( - payload.events.map((eventPayload) => + payload.events.map(async (eventPayload) => { this.analyticsService.create( { - type: 'track', - data: { - eventName: 'user.signup', + action: 'user.signup', + payload: {}, + }, + eventPayload.userId, + payload.workspaceId, + ); + + this.telemetryService.create( + { + action: 'user.signup', + payload: { + payload, + userId: undefined, + workspaceId: undefined, }, }, eventPayload.userId, payload.workspaceId, - '', - '', - this.environmentService.get('SERVER_URL'), - ), - ), + ); + }), ); } } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util.ts index 2a52c5273055..0a05be29da2e 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util.ts @@ -1,3 +1,7 @@ +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { WorkspaceQueryRunnerException, WorkspaceQueryRunnerExceptionCode, @@ -32,5 +36,24 @@ export const workspaceQueryRunnerGraphqlApiExceptionHandler = ( } } + if (error instanceof GraphqlQueryRunnerException) { + switch (error.code) { + case GraphqlQueryRunnerExceptionCode.INVALID_ARGS_FIRST: + case GraphqlQueryRunnerExceptionCode.INVALID_ARGS_LAST: + case GraphqlQueryRunnerExceptionCode.OBJECT_METADATA_NOT_FOUND: + case GraphqlQueryRunnerExceptionCode.MAX_DEPTH_REACHED: + case GraphqlQueryRunnerExceptionCode.INVALID_CURSOR: + case GraphqlQueryRunnerExceptionCode.INVALID_DIRECTION: + case GraphqlQueryRunnerExceptionCode.UNSUPPORTED_OPERATOR: + case GraphqlQueryRunnerExceptionCode.ARGS_CONFLICT: + case GraphqlQueryRunnerExceptionCode.FIELD_NOT_FOUND: + throw new UserInputError(error.message); + case GraphqlQueryRunnerExceptionCode.RECORD_NOT_FOUND: + throw new NotFoundError(error.message); + default: + throw new InternalServerError(error.message); + } + } + throw error; }; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts index 6d6b2e86dd48..689595823385 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts @@ -9,3 +9,11 @@ export interface WorkspaceQueryHookInstance { payload: ResolverArgs, ): Promise<ResolverArgs>; } + +export interface WorkspaceQueryPostHookInstance { + execute( + authContext: AuthContext, + objectName: string, + payload: unknown[], + ): Promise<void>; +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts index e791ab3d36ff..8b42abc8ca53 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts @@ -66,4 +66,25 @@ export class WorkspaceQueryHookStorage { this.postHookInstances.get(key)?.push(data); } + + getWorkspaceQueryPostHookInstances( + key: WorkspaceQueryHookKey, + ): WorkspaceQueryHookData<WorkspaceQueryHookInstance>[] { + const methodName = key.split('.')?.[1] as + | WorkspaceResolverBuilderMethodNames + | undefined; + let wildcardInstances: WorkspaceQueryHookData<WorkspaceQueryHookInstance>[] = + []; + + if (!methodName) { + throw new Error(`Can't split workspace query hook key: ${key}`); + } + + // Retrive wildcard post-hook instances + if (this.postHookInstances.has(`*.${methodName}`)) { + wildcardInstances = this.postHookInstances.get(`*.${methodName}`)!; + } + + return [...wildcardInstances, ...(this.postHookInstances.get(key) ?? [])]; + } } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts index f155475877e0..b75c939d1ac7 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts @@ -4,6 +4,7 @@ import { DeleteManyResolverArgs, DeleteOneResolverArgs, DestroyManyResolverArgs, + DestroyOneResolverArgs, FindDuplicatesResolverArgs, FindManyResolverArgs, FindOneResolverArgs, @@ -39,4 +40,6 @@ export type WorkspacePreQueryHookPayload<T> = T extends 'createMany' ? RestoreManyResolverArgs : T extends 'destroyMany' ? DestroyManyResolverArgs - : never; + : T extends 'destroyOne' + ? DestroyOneResolverArgs + : never; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts index cd3e37f018e1..f1cc8f6e93c8 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts @@ -2,12 +2,13 @@ import { Injectable } from '@nestjs/common'; import merge from 'lodash.merge'; +import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { WorkspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage'; import { WorkspaceQueryHookKey } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; -import { WorkspaceQueryHookExplorer } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer'; +import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage'; import { WorkspacePreQueryHookPayload } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type'; +import { WorkspaceQueryHookExplorer } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; @Injectable() @@ -49,4 +50,32 @@ export class WorkspaceQueryHookService { return payload; } + + public async executePostQueryHooks< + T extends WorkspaceResolverBuilderMethodNames, + Record extends IRecord = IRecord, + >( + authContext: AuthContext, + // TODO: We should allow wildcard for object name + objectName: string, + methodName: T, + payload: Record[], + ): Promise<void> { + const key: WorkspaceQueryHookKey = `${objectName}.${methodName}`; + const postHookInstances = + this.workspaceQueryHookStorage.getWorkspaceQueryPostHookInstances(key); + + if (!postHookInstances) { + return; + } + + for (const postHookInstance of postHookInstances) { + await this.workspaceQueryHookExplorer.handleHook( + [authContext, objectName, payload], + postHookInstance.instance, + postHookInstance.host, + postHookInstance.isRequestScoped, + ); + } + } } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts index 066886e980c8..1e166806be8d 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts @@ -1,7 +1,6 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { GraphqlQueryRunnerModule } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.module'; import { WorkspaceQueryBuilderModule } from 'src/engine/api/graphql/workspace-query-builder/workspace-query-builder.module'; import { RecordPositionBackfillCommand } from 'src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command'; import { workspaceQueryRunnerFactories } from 'src/engine/api/graphql/workspace-query-runner/factories'; @@ -13,6 +12,7 @@ import { DuplicateModule } from 'src/engine/core-modules/duplicate/duplicate.mod import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { FileModule } from 'src/engine/core-modules/file/file.module'; +import { TelemetryModule } from 'src/engine/core-modules/telemetry/telemetry.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -30,9 +30,9 @@ import { EntityEventsToDbListener } from './listeners/entity-events-to-db.listen ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]), TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), AnalyticsModule, + TelemetryModule, DuplicateModule, FileModule, - GraphqlQueryRunnerModule, FeatureFlagModule, ], providers: [ @@ -42,6 +42,6 @@ import { EntityEventsToDbListener } from './listeners/entity-events-to-db.listen TelemetryListener, RecordPositionBackfillCommand, ], - exports: [WorkspaceQueryRunnerService], + exports: [WorkspaceQueryRunnerService, ...workspaceQueryRunnerFactories], }) export class WorkspaceQueryRunnerModule {} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts index 6e9a744757d2..26526cf1fb39 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts @@ -1,12 +1,11 @@ import { Injectable, Logger } from '@nestjs/common'; import isEmpty from 'lodash.isempty'; -import { DataSource } from 'typeorm'; +import { DataSource, In } from 'typeorm'; import { Record as IRecord, RecordFilter, - RecordOrderBy, } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { IConnection } from 'src/engine/api/graphql/workspace-query-runner/interfaces/connection.interface'; import { @@ -16,8 +15,6 @@ import { DeleteOneResolverArgs, DestroyManyResolverArgs, FindDuplicatesResolverArgs, - FindManyResolverArgs, - FindOneResolverArgs, ResolverArgsType, RestoreManyResolverArgs, UpdateManyResolverArgs, @@ -25,7 +22,6 @@ import { } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; import { WorkspaceQueryBuilderFactory } from 'src/engine/api/graphql/workspace-query-builder/workspace-query-builder.factory'; import { QueryResultGettersFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/query-result-getters.factory'; import { QueryRunnerArgsFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-runner-args.factory'; @@ -36,22 +32,19 @@ import { } from 'src/engine/api/graphql/workspace-query-runner/jobs/call-webhook-jobs.job'; import { assertIsValidUuid } from 'src/engine/api/graphql/workspace-query-runner/utils/assert-is-valid-uuid.util'; import { parseResult } from 'src/engine/api/graphql/workspace-query-runner/utils/parse-result.util'; -import { withSoftDeleted } from 'src/engine/api/graphql/workspace-query-runner/utils/with-soft-deleted.util'; import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service'; import { WorkspaceQueryRunnerException, WorkspaceQueryRunnerExceptionCode, } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception'; import { DuplicateService } from 'src/engine/core-modules/duplicate/duplicate.service'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; @@ -66,8 +59,8 @@ import { } from './interfaces/pg-graphql.interface'; import { WorkspaceQueryRunnerOptions } from './interfaces/query-runner-option.interface'; import { - computePgGraphQLError, PgGraphQLConfig, + computePgGraphQLError, } from './utils/compute-pg-graphql-error.util'; @Injectable() @@ -86,122 +79,8 @@ export class WorkspaceQueryRunnerService { private readonly workspaceQueryHookService: WorkspaceQueryHookService, private readonly environmentService: EnvironmentService, private readonly duplicateService: DuplicateService, - private readonly featureFlagService: FeatureFlagService, - private readonly graphqlQueryRunnerService: GraphqlQueryRunnerService, ) {} - async findMany< - Record extends IRecord = IRecord, - Filter extends RecordFilter = RecordFilter, - OrderBy extends RecordOrderBy = RecordOrderBy, - >( - args: FindManyResolverArgs<Filter, OrderBy>, - options: WorkspaceQueryRunnerOptions, - ): Promise<IConnection<Record> | undefined> { - const { authContext, objectMetadataItem } = options; - const start = performance.now(); - - const isQueryRunnerTwentyORMEnabled = - await this.featureFlagService.isFeatureEnabled( - FeatureFlagKey.IsQueryRunnerTwentyORMEnabled, - authContext.workspace.id, - ); - - const hookedArgs = - await this.workspaceQueryHookService.executePreQueryHooks( - authContext, - objectMetadataItem.nameSingular, - 'findMany', - args, - ); - - const computedArgs = (await this.queryRunnerArgsFactory.create( - hookedArgs, - options, - ResolverArgsType.FindMany, - )) as FindManyResolverArgs<Filter, OrderBy>; - - if (isQueryRunnerTwentyORMEnabled) { - return this.graphqlQueryRunnerService.findManyWithTwentyOrm( - computedArgs, - options, - ); - } - - const query = await this.workspaceQueryBuilderFactory.findMany( - computedArgs, - { - ...options, - withSoftDeleted: withSoftDeleted(args.filter), - }, - ); - - const result = await this.execute(query, authContext.workspace.id); - - const end = performance.now(); - - this.logger.log( - `query time: ${end - start} ms on query ${ - options.objectMetadataItem.nameSingular - }`, - ); - - return this.parseResult<IConnection<Record>>( - result, - objectMetadataItem, - '', - authContext.workspace.id, - ); - } - - async findOne< - Record extends IRecord = IRecord, - Filter extends RecordFilter = RecordFilter, - >( - args: FindOneResolverArgs<Filter>, - options: WorkspaceQueryRunnerOptions, - ): Promise<Record | undefined> { - if (!args.filter || Object.keys(args.filter).length === 0) { - throw new WorkspaceQueryRunnerException( - 'Missing filter argument', - WorkspaceQueryRunnerExceptionCode.INVALID_QUERY_INPUT, - ); - } - const { authContext, objectMetadataItem } = options; - - const hookedArgs = - await this.workspaceQueryHookService.executePreQueryHooks( - authContext, - objectMetadataItem.nameSingular, - 'findOne', - args, - ); - - const computedArgs = (await this.queryRunnerArgsFactory.create( - hookedArgs, - options, - ResolverArgsType.FindOne, - )) as FindOneResolverArgs<Filter>; - - const query = await this.workspaceQueryBuilderFactory.findOne( - computedArgs, - { - ...options, - withSoftDeleted: withSoftDeleted(args.filter), - }, - ); - - const result = await this.execute(query, authContext.workspace.id); - const parsedResult = await this.parseResult<IConnection<Record>>( - result, - objectMetadataItem, - '', - authContext.workspace.id, - ); - - return parsedResult?.edges?.[0]?.node; - } - async findDuplicates<TRecord extends IRecord = IRecord>( args: FindDuplicatesResolverArgs<Partial<TRecord>>, options: WorkspaceQueryRunnerOptions, @@ -222,6 +101,10 @@ export class WorkspaceQueryRunnerService { const { authContext, objectMetadataItem } = options; + console.log( + `running findDuplicates for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); + const hookedArgs = await this.workspaceQueryHookService.executePreQueryHooks( authContext, @@ -318,6 +201,13 @@ export class WorkspaceQueryRunnerService { ) )?.records; + await this.workspaceQueryHookService.executePostQueryHooks( + authContext, + objectMetadataItem.nameSingular, + 'createMany', + parsedResults, + ); + await this.triggerWebhooks<Record>( parsedResults, CallWebhookJobsJobOperation.create, @@ -347,6 +237,9 @@ export class WorkspaceQueryRunnerService { args: CreateManyResolverArgs<Partial<Record>>, options: WorkspaceQueryRunnerOptions, ): Promise<Record[] | undefined> { + console.log( + `running upsertMany for ${options.objectMetadataItem.nameSingular} on workspace ${options.authContext.workspace.id}`, + ); const ids = args.data .map((item) => item.id) .filter((id) => id !== undefined); @@ -413,6 +306,11 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise<Record | undefined> { const { authContext, objectMetadataItem } = options; + + console.log( + `running updateOne for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); + const repository = await this.twentyORMGlobalManager.getRepositoryForWorkspace( authContext.workspace.id, @@ -488,6 +386,11 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise<Record[] | undefined> { const { authContext, objectMetadataItem } = options; + + console.log( + `running updateMany for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); + const repository = await this.twentyORMGlobalManager.getRepositoryForWorkspace( authContext.workspace.id, @@ -498,7 +401,7 @@ export class WorkspaceQueryRunnerService { args.filter?.id?.in?.forEach((id) => assertIsValidUuid(id)); const existingRecords = await repository.find({ - where: { id: { in: args.filter?.id?.in } }, + where: { id: In(args.filter?.id?.in) }, }); const mappedRecords = new Map( existingRecords.map((record) => [record.id, record]), @@ -582,7 +485,10 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise<Record[] | undefined> { const { authContext, objectMetadataItem } = options; - let query: string; + + console.log( + `running deleteMany for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); assertMutationNotOnRemoteObject(objectMetadataItem); @@ -598,25 +504,31 @@ export class WorkspaceQueryRunnerService { args, ); - if (objectMetadataItem.isSoftDeletable) { - query = await this.workspaceQueryBuilderFactory.updateMany( - { - filter: hookedArgs.filter, - data: { - deletedAt: new Date().toISOString(), - }, - }, - { - ...options, - atMost: maximumRecordAffected, + const query = await this.workspaceQueryBuilderFactory.updateMany( + { + filter: hookedArgs.filter, + data: { + deletedAt: new Date().toISOString(), }, - ); - } else { - query = await this.workspaceQueryBuilderFactory.deleteMany(hookedArgs, { + }, + { ...options, atMost: maximumRecordAffected, - }); - } + }, + ); + + const repository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + authContext.workspace.id, + objectMetadataItem.nameSingular, + ); + + const existingRecords = await repository.find({ + where: { id: In(args.filter?.id?.in) }, + }); + const mappedRecords = new Map( + existingRecords.map((record) => [record.id, record]), + ); const result = await this.execute(query, authContext.workspace.id); @@ -624,7 +536,7 @@ export class WorkspaceQueryRunnerService { await this.parseResult<PGGraphQLMutation<Record>>( result, objectMetadataItem, - objectMetadataItem.isSoftDeletable ? 'update' : 'deleteFrom', + 'update', authContext.workspace.id, ) )?.records; @@ -637,17 +549,21 @@ export class WorkspaceQueryRunnerService { this.workspaceEventEmitter.emit( `${objectMetadataItem.nameSingular}.deleted`, - parsedResults.map( - (record) => - ({ - userId: authContext.user?.id, - recordId: record.id, - objectMetadata: objectMetadataItem, - properties: { - before: this.removeNestedProperties(record), - }, - }) satisfies ObjectRecordDeleteEvent<any>, - ), + parsedResults.map((record) => { + const existingRecord = mappedRecords.get(record.id); + + return { + userId: authContext.user?.id, + recordId: record.id, + objectMetadata: objectMetadataItem, + properties: { + before: this.removeNestedProperties({ + ...existingRecord, + ...record, + }), + }, + } satisfies ObjectRecordDeleteEvent<any>; + }), authContext.workspace.id, ); @@ -663,14 +579,11 @@ export class WorkspaceQueryRunnerService { ): Promise<Record[] | undefined> { const { authContext, objectMetadataItem } = options; - assertMutationNotOnRemoteObject(objectMetadataItem); + console.log( + `running destroyMany for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); - if (!objectMetadataItem.isSoftDeletable) { - throw new WorkspaceQueryRunnerException( - 'This method is reserved to objects that can be soft-deleted, use delete instead', - WorkspaceQueryRunnerExceptionCode.DATA_NOT_FOUND, - ); - } + assertMutationNotOnRemoteObject(objectMetadataItem); const maximumRecordAffected = this.environmentService.get( 'MUTATION_MAXIMUM_AFFECTED_RECORDS', @@ -726,14 +639,11 @@ export class WorkspaceQueryRunnerService { ): Promise<Record[] | undefined> { const { authContext, objectMetadataItem } = options; - assertMutationNotOnRemoteObject(objectMetadataItem); + console.log( + `running restoreMany for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); - if (!objectMetadataItem.isSoftDeletable) { - throw new WorkspaceQueryRunnerException( - 'This method is reserved to objects that can be soft-deleted', - WorkspaceQueryRunnerExceptionCode.DATA_NOT_FOUND, - ); - } + assertMutationNotOnRemoteObject(objectMetadataItem); const maximumRecordAffected = this.environmentService.get( 'MUTATION_MAXIMUM_AFFECTED_RECORDS', @@ -776,7 +686,7 @@ export class WorkspaceQueryRunnerService { await this.triggerWebhooks<Record>( parsedResults, - CallWebhookJobsJobOperation.delete, + CallWebhookJobsJobOperation.create, options, ); @@ -804,12 +714,16 @@ export class WorkspaceQueryRunnerService { options: WorkspaceQueryRunnerOptions, ): Promise<Record | undefined> { const { authContext, objectMetadataItem } = options; + + console.log( + `running deleteOne for ${objectMetadataItem.nameSingular} on workspace ${authContext.workspace.id}`, + ); + const repository = await this.twentyORMGlobalManager.getRepositoryForWorkspace( authContext.workspace.id, objectMetadataItem.nameSingular, ); - let query: string; assertMutationNotOnRemoteObject(objectMetadataItem); assertIsValidUuid(args.id); @@ -822,22 +736,15 @@ export class WorkspaceQueryRunnerService { args, ); - if (objectMetadataItem.isSoftDeletable) { - query = await this.workspaceQueryBuilderFactory.updateOne( - { - id: hookedArgs.id, - data: { - deletedAt: new Date().toISOString(), - }, + const query = await this.workspaceQueryBuilderFactory.updateOne( + { + id: hookedArgs.id, + data: { + deletedAt: new Date().toISOString(), }, - options, - ); - } else { - query = await this.workspaceQueryBuilderFactory.deleteOne( - hookedArgs, - options, - ); - } + }, + options, + ); const existingRecord = await repository.findOne({ where: { id: args.id }, @@ -849,7 +756,7 @@ export class WorkspaceQueryRunnerService { await this.parseResult<PGGraphQLMutation<Record>>( result, objectMetadataItem, - objectMetadataItem.isSoftDeletable ? 'update' : 'deleteFrom', + 'update', authContext.workspace.id, ) )?.records; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-many-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-many-resolver.factory.ts index 467488192455..872ab7906fca 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-many-resolver.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-many-resolver.factory.ts @@ -7,8 +7,11 @@ import { } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface'; +import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util'; import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; @Injectable() export class CreateManyResolverFactory @@ -18,6 +21,8 @@ export class CreateManyResolverFactory constructor( private readonly workspaceQueryRunnerService: WorkspaceQueryRunnerService, + private readonly featureFlagService: FeatureFlagService, + private readonly graphqlQueryRunnerService: GraphqlQueryRunnerService, ) {} create( @@ -25,15 +30,27 @@ export class CreateManyResolverFactory ): Resolver<CreateManyResolverArgs> { const internalContext = context; - return async (_source, args, context, info) => { + return async (_source, args, _context, info) => { try { - return await this.workspaceQueryRunnerService.createMany(args, { + const options = { authContext: internalContext.authContext, objectMetadataItem: internalContext.objectMetadataItem, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, - }); + }; + + const isQueryRunnerTwentyORMEnabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IsQueryRunnerTwentyORMEnabled, + internalContext.authContext.workspace.id, + ); + + if (isQueryRunnerTwentyORMEnabled) { + return await this.graphqlQueryRunnerService.createMany(args, options); + } + + return await this.workspaceQueryRunnerService.createMany(args, options); } catch (error) { workspaceQueryRunnerGraphqlApiExceptionHandler(error); } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-one-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-one-resolver.factory.ts index 24fdfe0239fd..edf9206a1cde 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-one-resolver.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/create-one-resolver.factory.ts @@ -7,8 +7,11 @@ import { } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface'; +import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util'; import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; @Injectable() export class CreateOneResolverFactory @@ -18,6 +21,8 @@ export class CreateOneResolverFactory constructor( private readonly workspaceQueryRunnerService: WorkspaceQueryRunnerService, + private readonly featureFlagService: FeatureFlagService, + private readonly graphqlQueryRunnerService: GraphqlQueryRunnerService, ) {} create( @@ -25,8 +30,26 @@ export class CreateOneResolverFactory ): Resolver<CreateOneResolverArgs> { const internalContext = context; - return async (_source, args, context, info) => { + return async (_source, args, _context, info) => { try { + const options = { + authContext: internalContext.authContext, + objectMetadataItem: internalContext.objectMetadataItem, + info, + fieldMetadataCollection: internalContext.fieldMetadataCollection, + objectMetadataCollection: internalContext.objectMetadataCollection, + }; + + const isQueryRunnerTwentyORMEnabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IsQueryRunnerTwentyORMEnabled, + internalContext.authContext.workspace.id, + ); + + if (isQueryRunnerTwentyORMEnabled) { + return await this.graphqlQueryRunnerService.createOne(args, options); + } + return await this.workspaceQueryRunnerService.createOne(args, { authContext: internalContext.authContext, objectMetadataItem: internalContext.objectMetadataItem, diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/destroy-one-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/destroy-one-resolver.factory.ts new file mode 100644 index 000000000000..4c204d6e8c0c --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/destroy-one-resolver.factory.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceResolverBuilderFactoryInterface } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolver-builder-factory.interface'; +import { + DestroyOneResolverArgs, + Resolver, +} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface'; + +import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; +import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util'; + +@Injectable() +export class DestroyOneResolverFactory + implements WorkspaceResolverBuilderFactoryInterface +{ + public static methodName = 'destroyOne' as const; + + constructor( + private readonly graphQLQueryRunnerService: GraphqlQueryRunnerService, + ) {} + + create( + context: WorkspaceSchemaBuilderContext, + ): Resolver<DestroyOneResolverArgs> { + const internalContext = context; + + return async (_source, args, context, info) => { + try { + return await this.graphQLQueryRunnerService.destroyOne(args, { + authContext: internalContext.authContext, + objectMetadataItem: internalContext.objectMetadataItem, + info, + fieldMetadataCollection: internalContext.fieldMetadataCollection, + objectMetadataCollection: internalContext.objectMetadataCollection, + }); + } catch (error) { + workspaceQueryRunnerGraphqlApiExceptionHandler(error); + } + }; + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts index 99d9c5419766..1724242e866d 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts @@ -1,4 +1,5 @@ import { DestroyManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/destroy-many-resolver.factory'; +import { DestroyOneResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/destroy-one-resolver.factory'; import { RestoreManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/restore-many-resolver.factory'; import { UpdateManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/update-many-resolver.factory'; @@ -21,6 +22,7 @@ export const workspaceResolverBuilderFactories = [ DeleteOneResolverFactory, UpdateManyResolverFactory, DeleteManyResolverFactory, + DestroyOneResolverFactory, DestroyManyResolverFactory, RestoreManyResolverFactory, ]; @@ -38,6 +40,7 @@ export const workspaceResolverBuilderMethodNames = { DeleteOneResolverFactory.methodName, UpdateManyResolverFactory.methodName, DeleteManyResolverFactory.methodName, + DestroyOneResolverFactory.methodName, DestroyManyResolverFactory.methodName, RestoreManyResolverFactory.methodName, ], diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-many-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-many-resolver.factory.ts index 76391b27ed2f..2dd452a2976c 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-many-resolver.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-many-resolver.factory.ts @@ -7,8 +7,8 @@ import { } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface'; +import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util'; -import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; @Injectable() export class FindManyResolverFactory @@ -17,7 +17,7 @@ export class FindManyResolverFactory public static methodName = 'findMany' as const; constructor( - private readonly workspaceQueryRunnerService: WorkspaceQueryRunnerService, + private readonly graphqlQueryRunnerService: GraphqlQueryRunnerService, ) {} create( @@ -25,15 +25,17 @@ export class FindManyResolverFactory ): Resolver<FindManyResolverArgs> { const internalContext = context; - return async (_source, args, context, info) => { + return async (_source, args, _context, info) => { try { - return await this.workspaceQueryRunnerService.findMany(args, { + const options = { authContext: internalContext.authContext, objectMetadataItem: internalContext.objectMetadataItem, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, - }); + }; + + return await this.graphqlQueryRunnerService.findMany(args, options); } catch (error) { workspaceQueryRunnerGraphqlApiExceptionHandler(error); } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-one-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-one-resolver.factory.ts index d6a679593789..3dbbc2330d06 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-one-resolver.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/find-one-resolver.factory.ts @@ -7,8 +7,8 @@ import { } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface'; +import { GraphqlQueryRunnerService } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.service'; import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util'; -import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; @Injectable() export class FindOneResolverFactory @@ -17,7 +17,7 @@ export class FindOneResolverFactory public static methodName = 'findOne' as const; constructor( - private readonly workspaceQueryRunnerService: WorkspaceQueryRunnerService, + private readonly graphqlQueryRunnerService: GraphqlQueryRunnerService, ) {} create( @@ -25,15 +25,17 @@ export class FindOneResolverFactory ): Resolver<FindOneResolverArgs> { const internalContext = context; - return async (_source, args, context, info) => { + return async (_source, args, _context, info) => { try { - return await this.workspaceQueryRunnerService.findOne(args, { + const options = { authContext: internalContext.authContext, objectMetadataItem: internalContext.objectMetadataItem, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, - }); + }; + + return await this.graphqlQueryRunnerService.findOne(args, options); } catch (error) { workspaceQueryRunnerGraphqlApiExceptionHandler(error); } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts index cbe5b1fa2e84..22c07059737d 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts @@ -22,6 +22,7 @@ export enum ResolverArgsType { DeleteMany = 'DeleteMany', RestoreMany = 'RestoreMany', DestroyMany = 'DestroyMany', + DestroyOne = 'DestroyOne', } export interface FindManyResolverArgs< @@ -88,6 +89,10 @@ export interface RestoreManyResolverArgs<Filter = any> { filter: Filter; } +export interface DestroyOneResolverArgs { + id: string; +} + export interface DestroyManyResolverArgs<Filter = any> { filter: Filter; } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts index 7b87e49a8d76..3aafdd79290d 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts @@ -1,13 +1,19 @@ import { Module } from '@nestjs/common'; +import { GraphqlQueryRunnerModule } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-runner.module'; import { WorkspaceQueryRunnerModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module'; +import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { WorkspaceResolverFactory } from './workspace-resolver.factory'; import { workspaceResolverBuilderFactories } from './factories/factories'; @Module({ - imports: [WorkspaceQueryRunnerModule], + imports: [ + WorkspaceQueryRunnerModule, + GraphqlQueryRunnerModule, + FeatureFlagModule, + ], providers: [...workspaceResolverBuilderFactories, WorkspaceResolverFactory], exports: [WorkspaceResolverFactory], }) diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts index fc405bfff689..6c06b85d9ff0 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts @@ -6,6 +6,7 @@ import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metad import { DeleteManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/delete-many-resolver.factory'; import { DestroyManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/destroy-many-resolver.factory'; +import { DestroyOneResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/destroy-one-resolver.factory'; import { RestoreManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/restore-many-resolver.factory'; import { UpdateManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/update-many-resolver.factory'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; @@ -36,6 +37,7 @@ export class WorkspaceResolverFactory { private readonly createOneResolverFactory: CreateOneResolverFactory, private readonly updateOneResolverFactory: UpdateOneResolverFactory, private readonly deleteOneResolverFactory: DeleteOneResolverFactory, + private readonly destroyOneResolverFactory: DestroyOneResolverFactory, private readonly updateManyResolverFactory: UpdateManyResolverFactory, private readonly deleteManyResolverFactory: DeleteManyResolverFactory, private readonly restoreManyResolverFactory: RestoreManyResolverFactory, @@ -58,6 +60,7 @@ export class WorkspaceResolverFactory { ['createOne', this.createOneResolverFactory], ['updateOne', this.updateOneResolverFactory], ['deleteOne', this.deleteOneResolverFactory], + ['destroyOne', this.destroyOneResolverFactory], ['updateMany', this.updateManyResolverFactory], ['deleteMany', this.deleteManyResolverFactory], ['restoreMany', this.restoreManyResolverFactory], diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory.ts index de77733d6151..aefd82efc995 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory.ts @@ -3,15 +3,16 @@ import { Injectable, Logger } from '@nestjs/common'; import { GraphQLEnumType } from 'graphql'; import { WorkspaceBuildSchemaOptions } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-build-schema-optionts.interface'; -import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; +import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { pascalCase } from 'src/utils/pascal-case'; import { FieldMetadataComplexOption, FieldMetadataDefaultOption, } from 'src/engine/metadata-modules/field-metadata/dtos/options.input'; import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util'; +import { transformEnumValue } from 'src/engine/utils/transform-enum-value'; +import { pascalCase } from 'src/utils/pascal-case'; export interface EnumTypeDefinition { target: string; @@ -53,7 +54,7 @@ export class EnumTypeDefinitionFactory { ): GraphQLEnumType { // FixMe: It's a hack until Typescript get fixed on union types for reduce function // https://github.com/microsoft/TypeScript/issues/36390 - const enumOptions = fieldMetadata.options as Array< + const enumOptions = transformEnumValue(fieldMetadata.options) as Array< FieldMetadataDefaultOption | FieldMetadataComplexOption >; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/array-filter.input-type.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/array-filter.input-type.ts new file mode 100644 index 000000000000..37b3ba8293fb --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/array-filter.input-type.ts @@ -0,0 +1,10 @@ +import { GraphQLInputObjectType, GraphQLList, GraphQLString } from 'graphql'; + +export const ArrayFilterType = new GraphQLInputObjectType({ + name: 'ArrayFilter', + fields: { + contains: { type: new GraphQLList(GraphQLString) }, + contains_any: { type: new GraphQLList(GraphQLString) }, + not_contains: { type: new GraphQLList(GraphQLString) }, + }, +}); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts index 1d1f6f51fe67..cb0e63832e22 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/input/index.ts @@ -1,3 +1,4 @@ +export * from './array-filter.input-type'; export * from './big-float-filter.input-type'; export * from './big-int-filter.input-type'; export * from './boolean-filter.input-type'; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts index 9656430d9509..fb6597e19be9 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts @@ -18,6 +18,7 @@ import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadat import { OrderByDirectionType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/enum'; import { + ArrayFilterType, BigFloatFilterType, BooleanFilterType, DateFilterType, @@ -45,6 +46,8 @@ export interface TypeOptions<T = any> { isIdField?: boolean; } +const StringArrayScalarType = new GraphQLList(GraphQLString); + @Injectable() export class TypeMapperService { mapToScalarType( @@ -55,7 +58,6 @@ export class TypeMapperService { if (isIdField || settings?.isForeignKey) { return GraphQLID; } - const typeScalarMapping = new Map<FieldMetadataType, GraphQLScalarType>([ [FieldMetadataType.UUID, UUIDScalarType], [FieldMetadataType.TEXT, GraphQLString], @@ -74,6 +76,10 @@ export class TypeMapperService { [FieldMetadataType.NUMERIC, BigFloatScalarType], [FieldMetadataType.POSITION, PositionScalarType], [FieldMetadataType.RAW_JSON, RawJSONScalar], + [ + FieldMetadataType.ARRAY, + StringArrayScalarType as unknown as GraphQLScalarType, + ], [FieldMetadataType.RICH_TEXT, GraphQLString], ]); @@ -111,6 +117,7 @@ export class TypeMapperService { [FieldMetadataType.POSITION, FloatFilterType], [FieldMetadataType.RAW_JSON, RawJsonFilterType], [FieldMetadataType.RICH_TEXT, StringFilterType], + [FieldMetadataType.ARRAY, ArrayFilterType], ]); return typeFilterMapping.get(fieldMetadataType); @@ -135,6 +142,7 @@ export class TypeMapperService { [FieldMetadataType.POSITION, OrderByDirectionType], [FieldMetadataType.RAW_JSON, OrderByDirectionType], [FieldMetadataType.RICH_TEXT, OrderByDirectionType], + [FieldMetadataType.ARRAY, OrderByDirectionType], ]); return typeOrderByMapping.get(fieldMetadataType); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts index f42377b89c20..c829e0e4088f 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts @@ -105,6 +105,13 @@ export const getResolverArgs = ( isNullable: false, }, }; + case 'destroyOne': + return { + id: { + type: GraphQLID, + isNullable: false, + }, + }; case 'updateMany': return { data: { diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema.factory.ts index 71d58e141925..336fa825f81c 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema.factory.ts @@ -4,25 +4,27 @@ import { makeExecutableSchema } from '@graphql-tools/schema'; import { GraphQLSchema, printSchema } from 'graphql'; import { gql } from 'graphql-tag'; +import { + GraphqlQueryRunnerException, + GraphqlQueryRunnerExceptionCode, +} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service'; import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/factories/factories'; import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory'; import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; -import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; @Injectable() export class WorkspaceSchemaFactory { constructor( private readonly dataSourceService: DataSourceService, - private readonly objectMetadataService: ObjectMetadataService, private readonly scalarsExplorerService: ScalarsExplorerService, private readonly workspaceGraphQLSchemaFactory: WorkspaceGraphQLSchemaFactory, private readonly workspaceResolverFactory: WorkspaceResolverFactory, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, - private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, ) {} async createGraphQLSchema(authContext: AuthContext): Promise<GraphQLSchema> { @@ -35,42 +37,57 @@ export class WorkspaceSchemaFactory { authContext.workspace.id, ); - // Can'f find any data sources for this workspace if (!dataSourcesMetadata || dataSourcesMetadata.length === 0) { return new GraphQLSchema({}); } - // Validate cache version - await this.workspaceMetadataVersionService.flushCacheIfMetadataVersionIsOutdated( - authContext.workspace.id, - ); - - // Get object metadata from cache - let objectMetadataCollection = - await this.workspaceCacheStorageService.getObjectMetadataCollection( + const currentCacheVersion = + await this.workspaceCacheStorageService.getMetadataVersion( authContext.workspace.id, ); - // If object metadata is not cached, get it from the database - if (!objectMetadataCollection) { - objectMetadataCollection = - await this.objectMetadataService.findManyWithinWorkspace( - authContext.workspace.id, - ); + if (currentCacheVersion === undefined) { + await this.workspaceMetadataCacheService.recomputeMetadataCache({ + workspaceId: authContext.workspace.id, + }); + throw new GraphqlQueryRunnerException( + 'Metadata cache version not found', + GraphqlQueryRunnerExceptionCode.METADATA_CACHE_VERSION_NOT_FOUND, + ); + } - await this.workspaceCacheStorageService.setObjectMetadataCollection( + const objectMetadataMap = + await this.workspaceCacheStorageService.getObjectMetadataMap( authContext.workspace.id, - objectMetadataCollection, + currentCacheVersion, + ); + + if (!objectMetadataMap) { + await this.workspaceMetadataCacheService.recomputeMetadataCache({ + workspaceId: authContext.workspace.id, + }); + throw new GraphqlQueryRunnerException( + 'Object metadata collection not found', + GraphqlQueryRunnerExceptionCode.METADATA_CACHE_VERSION_NOT_FOUND, ); } + const objectMetadataCollection = Object.values(objectMetadataMap).map( + (objectMetadataItem) => ({ + ...objectMetadataItem, + fields: Object.values(objectMetadataItem.fields), + }), + ); + // Get typeDefs from cache let typeDefs = await this.workspaceCacheStorageService.getGraphQLTypeDefs( authContext.workspace.id, + currentCacheVersion, ); let usedScalarNames = await this.workspaceCacheStorageService.getGraphQLUsedScalarNames( authContext.workspace.id, + currentCacheVersion, ); // If typeDefs are not cached, generate them @@ -87,10 +104,12 @@ export class WorkspaceSchemaFactory { await this.workspaceCacheStorageService.setGraphQLTypeDefs( authContext.workspace.id, + currentCacheVersion, typeDefs, ); await this.workspaceCacheStorageService.setGraphQLUsedScalarNames( authContext.workspace.id, + currentCacheVersion, usedScalarNames, ); } diff --git a/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core-batch.controller.ts b/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core-batch.controller.ts index e77ae4c8912f..1ffe60789684 100644 --- a/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core-batch.controller.ts +++ b/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core-batch.controller.ts @@ -1,11 +1,14 @@ -import { Controller, Post, Req, Res } from '@nestjs/common'; +import { Controller, Post, Req, Res, UseGuards } from '@nestjs/common'; import { Request, Response } from 'express'; import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service'; import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils'; +import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @Controller('rest/batch/*') +@UseGuards(JwtAuthGuard, WorkspaceAuthGuard) export class RestApiCoreBatchController { constructor(private readonly restApiCoreService: RestApiCoreService) {} diff --git a/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core.controller.ts b/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core.controller.ts index 766f823522b7..488b03a262f3 100644 --- a/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core.controller.ts +++ b/packages/twenty-server/src/engine/api/rest/core/controllers/rest-api-core.controller.ts @@ -7,14 +7,18 @@ import { Put, Req, Res, + UseGuards, } from '@nestjs/common'; import { Request, Response } from 'express'; import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service'; import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils'; +import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @Controller('rest/*') +@UseGuards(JwtAuthGuard, WorkspaceAuthGuard) export class RestApiCoreController { constructor(private readonly restApiCoreService: RestApiCoreService) {} diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/core-query-builder.factory.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/core-query-builder.factory.ts index 90c3069d8972..43c9b0198b5f 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/core-query-builder.factory.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/core-query-builder.factory.ts @@ -18,8 +18,8 @@ import { computeDepth } from 'src/engine/api/rest/core/query-builder/utils/compu import { parseCoreBatchPath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-batch-path.utils'; import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils'; import { Query } from 'src/engine/api/rest/core/types/query.type'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/format-field-values.utils.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/format-field-values.utils.ts index 79e351f94136..e884ebf4b6ac 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/format-field-values.utils.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/format-field-values.utils.ts @@ -23,12 +23,16 @@ export const formatFieldValue = ( if (comparator === 'is') { return value; } - if (fieldType === FieldMetadataType.NUMBER) { - return parseInt(value); - } - if (fieldType === FieldMetadataType.BOOLEAN) { - return value.toLowerCase() === 'true'; + switch (fieldType) { + case FieldMetadataType.NUMERIC: + return parseInt(value); + case FieldMetadataType.NUMBER: + case FieldMetadataType.POSITION: + return parseFloat(value); + case FieldMetadataType.BOOLEAN: + return value.toLowerCase() === 'true'; } + if ( (value[0] === '"' || value[0] === "'") && (value.charAt(value.length - 1) === '"' || diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts index c96998bed59f..6976586f5a18 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts @@ -31,6 +31,7 @@ export const mapFieldMetadataToGraphqlQuery = ( FieldMetadataType.POSITION, FieldMetadataType.RAW_JSON, FieldMetadataType.RICH_TEXT, + FieldMetadataType.ARRAY, ].includes(fieldType); if (fieldIsSimpleValue) { @@ -152,5 +153,14 @@ export const mapFieldMetadataToGraphqlQuery = ( additionalEmails } `; + } else if (fieldType === FieldMetadataType.PHONES) { + return ` + ${field.name} + { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } + `; } }; diff --git a/packages/twenty-server/src/engine/api/rest/errors/RestApiException.ts b/packages/twenty-server/src/engine/api/rest/errors/RestApiException.ts index 2cc0b571b7ea..9e900e3b7e07 100644 --- a/packages/twenty-server/src/engine/api/rest/errors/RestApiException.ts +++ b/packages/twenty-server/src/engine/api/rest/errors/RestApiException.ts @@ -2,22 +2,34 @@ import { BadRequestException } from '@nestjs/common'; import { BaseGraphQLError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; -const formatMessage = (message: BaseGraphQLError) => { - if (message.extensions) { - return message.extensions.response.message || message.extensions.response; +const formatMessage = (error: BaseGraphQLError) => { + let formattedMessage = error.extensions + ? error.extensions.response?.error || + error.extensions.response || + error.message + : error.error; + + formattedMessage = formattedMessage + .replace(/"/g, "'") + .replace("Variable '$data' got i", 'I') + .replace("Variable '$input' got i", 'I'); + + const regex = /Field '[^']+' is not defined by type .*/; + + const match = formattedMessage.match(regex); + + if (match) { + formattedMessage = match[0]; } - return message.message; + return formattedMessage; }; export class RestApiException extends BadRequestException { constructor(errors: BaseGraphQLError[]) { super({ statusCode: 400, - message: - errors.length === 1 - ? formatMessage(errors[0]) - : JSON.stringify(errors.map((error) => formatMessage(error))), + messages: errors.map((error) => formatMessage(error)), error: 'Bad Request', }); } diff --git a/packages/twenty-server/src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils.ts b/packages/twenty-server/src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils.ts index 61899096d206..718a21e6ad79 100644 --- a/packages/twenty-server/src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils.ts +++ b/packages/twenty-server/src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils.ts @@ -1,4 +1,28 @@ export const fetchMetadataFields = (objectNamePlural: string) => { + const fromRelations = ` + toObjectMetadata { + id + dataSourceId + nameSingular + namePlural + isSystem + isRemote + } + toFieldMetadataId + `; + + const toRelations = ` + fromObjectMetadata { + id + dataSourceId + nameSingular + namePlural + isSystem + isRemote + } + fromFieldMetadataId + `; + const fields = ` type name @@ -14,26 +38,12 @@ export const fetchMetadataFields = (objectNamePlural: string) => { fromRelationMetadata { id relationType - toObjectMetadata { - id - dataSourceId - nameSingular - namePlural - isSystem - } - toFieldMetadataId + ${fromRelations} } toRelationMetadata { id relationType - fromObjectMetadata { - id - dataSourceId - nameSingular - namePlural - isSystem - } - fromFieldMetadataId + ${toRelations} } defaultValue options @@ -69,25 +79,10 @@ export const fetchMetadataFields = (objectNamePlural: string) => { return fields; case 'relations': return ` + id relationType - fromObjectMetadata { - id - dataSourceId - nameSingular - namePlural - isSystem - } - fromObjectMetadataId - toObjectMetadata { - id - dataSourceId - nameSingular - namePlural - isSystem - } - toObjectMetadataId - fromFieldMetadataId - toFieldMetadataId + ${fromRelations} + ${toRelations} `; } }; diff --git a/packages/twenty-server/src/engine/api/rest/metadata/rest-api-metadata.service.ts b/packages/twenty-server/src/engine/api/rest/metadata/rest-api-metadata.service.ts index afd0e59efd77..29f117894869 100644 --- a/packages/twenty-server/src/engine/api/rest/metadata/rest-api-metadata.service.ts +++ b/packages/twenty-server/src/engine/api/rest/metadata/rest-api-metadata.service.ts @@ -2,12 +2,12 @@ import { Injectable } from '@nestjs/common'; import { Request } from 'express'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { MetadataQueryBuilderFactory } from 'src/engine/api/rest/metadata/query-builder/metadata-query-builder.factory'; import { GraphqlApiType, RestApiService, } from 'src/engine/api/rest/rest-api.service'; -import { MetadataQueryBuilderFactory } from 'src/engine/api/rest/metadata/query-builder/metadata-query-builder.factory'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; @Injectable() export class RestApiMetadataService { diff --git a/packages/twenty-server/src/engine/api/rest/rest-api.module.ts b/packages/twenty-server/src/engine/api/rest/rest-api.module.ts index c459f3286264..f54d89537531 100644 --- a/packages/twenty-server/src/engine/api/rest/rest-api.module.ts +++ b/packages/twenty-server/src/engine/api/rest/rest-api.module.ts @@ -1,23 +1,25 @@ -import { Module } from '@nestjs/common'; import { HttpModule } from '@nestjs/axios'; +import { Module } from '@nestjs/common'; +import { RestApiCoreBatchController } from 'src/engine/api/rest/core/controllers/rest-api-core-batch.controller'; import { RestApiCoreController } from 'src/engine/api/rest/core/controllers/rest-api-core.controller'; -import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service'; import { CoreQueryBuilderModule } from 'src/engine/api/rest/core/query-builder/core-query-builder.module'; -import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; -import { RestApiMetadataController } from 'src/engine/api/rest/metadata/rest-api-metadata.controller'; -import { RestApiMetadataService } from 'src/engine/api/rest/metadata/rest-api-metadata.service'; -import { RestApiCoreBatchController } from 'src/engine/api/rest/core/controllers/rest-api-core-batch.controller'; -import { RestApiService } from 'src/engine/api/rest/rest-api.service'; +import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service'; import { EndingBeforeInputFactory } from 'src/engine/api/rest/input-factories/ending-before-input.factory'; import { LimitInputFactory } from 'src/engine/api/rest/input-factories/limit-input.factory'; import { StartingAfterInputFactory } from 'src/engine/api/rest/input-factories/starting-after-input.factory'; import { MetadataQueryBuilderModule } from 'src/engine/api/rest/metadata/query-builder/metadata-query-builder.module'; +import { RestApiMetadataController } from 'src/engine/api/rest/metadata/rest-api-metadata.controller'; +import { RestApiMetadataService } from 'src/engine/api/rest/metadata/rest-api-metadata.service'; +import { RestApiService } from 'src/engine/api/rest/rest-api.service'; +import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; +import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; @Module({ imports: [ CoreQueryBuilderModule, MetadataQueryBuilderModule, + WorkspaceCacheStorageModule, AuthModule, HttpModule, ], diff --git a/packages/twenty-server/src/engine/api/rest/rest-api.service.ts b/packages/twenty-server/src/engine/api/rest/rest-api.service.ts index d6b4d21640c3..128df3f96b33 100644 --- a/packages/twenty-server/src/engine/api/rest/rest-api.service.ts +++ b/packages/twenty-server/src/engine/api/rest/rest-api.service.ts @@ -6,7 +6,7 @@ import { AxiosResponse } from 'axios'; import { Query } from 'src/engine/api/rest/core/types/query.type'; import { getServerUrl } from 'src/utils/get-server-url'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { RestApiException } from 'src/engine/api/rest/errors/RestApiException'; export enum GraphqlApiType { diff --git a/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.module.ts b/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.module.ts index f416a0898787..0e0e9997c192 100644 --- a/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.module.ts +++ b/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.module.ts @@ -7,9 +7,9 @@ import { AISQLQueryResolver } from 'src/engine/core-modules/ai-sql-query/ai-sql- import { AISQLQueryService } from 'src/engine/core-modules/ai-sql-query/ai-sql-query.service'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { WorkspaceQueryRunnerModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module'; -import { LLMChatModelModule } from 'src/engine/integrations/llm-chat-model/llm-chat-model.module'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; -import { LLMTracingModule } from 'src/engine/integrations/llm-tracing/llm-tracing.module'; +import { LLMChatModelModule } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.module'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { LLMTracingModule } from 'src/engine/core-modules/llm-tracing/llm-tracing.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module'; @Module({ diff --git a/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.resolver.ts b/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.resolver.ts index 16f8aff9bf00..c739c7e3ba06 100644 --- a/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.resolver.ts @@ -12,7 +12,8 @@ import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @ArgsType() class GetAISQLQueryArgs { @@ -20,7 +21,7 @@ class GetAISQLQueryArgs { text: string; } -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard, UserAuthGuard) @Resolver(() => AISQLQueryResult) export class AISQLQueryResolver { constructor( diff --git a/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.service.ts b/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.service.ts index 63809b96c33d..81cd32ec4a35 100644 --- a/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.service.ts +++ b/packages/twenty-server/src/engine/core-modules/ai-sql-query/ai-sql-query.service.ts @@ -11,8 +11,8 @@ import { zodToJsonSchema } from 'zod-to-json-schema'; import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; import { sqlGenerationPromptTemplate } from 'src/engine/core-modules/ai-sql-query/ai-sql-query.prompt-templates'; import { AISQLQueryResult } from 'src/engine/core-modules/ai-sql-query/dtos/ai-sql-query-result.dto'; -import { LLMChatModelService } from 'src/engine/integrations/llm-chat-model/llm-chat-model.service'; -import { LLMTracingService } from 'src/engine/integrations/llm-tracing/llm-tracing.service'; +import { LLMChatModelService } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.service'; +import { LLMTracingService } from 'src/engine/core-modules/llm-tracing/llm-tracing.service'; import { DEFAULT_LABEL_IDENTIFIER_FIELD_NAME } from 'src/engine/metadata-modules/object-metadata/object-metadata.constants'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts index cb28eacc0b82..2b4c8705d62d 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts @@ -1,14 +1,16 @@ -import { Module } from '@nestjs/common'; import { HttpModule } from '@nestjs/axios'; +import { Module } from '@nestjs/common'; -import { AnalyticsService } from './analytics.service'; import { AnalyticsResolver } from './analytics.resolver'; +import { AnalyticsService } from './analytics.service'; + +const TINYBIRD_BASE_URL = 'https://api.eu-central-1.aws.tinybird.co/v0'; @Module({ providers: [AnalyticsResolver, AnalyticsService], imports: [ HttpModule.register({ - baseURL: 'https://t.funnelmink.com/api/v1/s2s', + baseURL: TINYBIRD_BASE_URL, }), ], exports: [AnalyticsService], diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.spec.ts index f6f1e07d422f..ba23dc9a2c22 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { HttpService } from '@nestjs/axios'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { AnalyticsResolver } from './analytics.resolver'; import { AnalyticsService } from './analytics.service'; diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts index 7fcba0c9f0f5..71e76f8bd80a 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.resolver.ts @@ -1,21 +1,16 @@ -import { Resolver, Mutation, Args, Context } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; +import { Args, Mutation, Resolver } from '@nestjs/graphql'; -import { Request } from 'express'; - -import { OptionalJwtAuthGuard } from 'src/engine/guards/optional-jwt.auth.guard'; -import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { AnalyticsService } from './analytics.service'; import { Analytics } from './analytics.entity'; +import { AnalyticsService } from './analytics.service'; import { CreateAnalyticsInput } from './dtos/create-analytics.input'; -@UseGuards(OptionalJwtAuthGuard) @Resolver(() => Analytics) export class AnalyticsResolver { constructor( @@ -28,15 +23,11 @@ export class AnalyticsResolver { @Args() createAnalyticsInput: CreateAnalyticsInput, @AuthWorkspace() workspace: Workspace | undefined, @AuthUser({ allowUndefined: true }) user: User | undefined, - @Context('req') request: Request, ) { return this.analyticsService.create( createAnalyticsInput, user?.id, workspace?.id, - workspace?.displayName, - workspace?.domainName, - this.environmentService.get('SERVER_URL') ?? request.hostname, ); } } diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts index c2cbd7a2f675..a22ede293be4 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { HttpService } from '@nestjs/axios'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { AnalyticsService } from './analytics.service'; diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts index 73851f71ea5b..2b2eeb3d683e 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts @@ -1,16 +1,19 @@ -import { Injectable, Logger } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; +import { Injectable, Logger } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { AxiosRequestConfig } from 'axios'; + +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; type CreateEventInput = { - type: string; - data: object; + action: string; + payload: object; }; @Injectable() export class AnalyticsService { private readonly logger = new Logger(AnalyticsService.name); + private readonly defaultDatasource = 'event'; constructor( private readonly environmentService: EnvironmentService, @@ -21,30 +24,62 @@ export class AnalyticsService { createEventInput: CreateEventInput, userId: string | null | undefined, workspaceId: string | null | undefined, - workspaceDisplayName: string | undefined, - workspaceDomainName: string | undefined, - hostName: string | undefined, ) { - if (!this.environmentService.get('TELEMETRY_ENABLED')) { + if (!this.environmentService.get('ANALYTICS_ENABLED')) { return { success: true }; } - const data = { - type: createEventInput.type, - data: { - hostname: hostName, - userUUID: userId, - workspaceUUID: workspaceId, - workspaceDisplayName: workspaceDisplayName, - workspaceDomainName: workspaceDomainName, - ...createEventInput.data, + let data; + + switch (createEventInput.action) { + case 'pageview': + data = { + timestamp: new Date().toISOString(), + version: '1', + userId: userId, + workspaceId: workspaceId, + ...createEventInput.payload, + }; + break; + default: + data = { + action: createEventInput.action, + timestamp: new Date().toISOString(), + version: '1', + userId: userId, + workspaceId: workspaceId, + payload: { + ...createEventInput.payload, + }, + }; + break; + } + + const config: AxiosRequestConfig = { + headers: { + Authorization: + 'Bearer ' + this.environmentService.get('TINYBIRD_TOKEN'), }, }; + const datasource = + createEventInput.action === 'pageview' + ? 'pageview' + : this.defaultDatasource; + try { - await this.httpService.axiosRef.post('/v1', data); - } catch { - this.logger.error('Failed to send analytics event'); + await this.httpService.axiosRef.post( + `/events?name=${datasource}`, + data, + config, + ); + } catch (error) { + this.logger.error('Error occurred:', error); + if (error.response) { + this.logger.error( + `Error response body: ${JSON.stringify(error.response.data)}`, + ); + } return { success: false }; } diff --git a/packages/twenty-server/src/engine/core-modules/analytics/dtos/create-analytics.input.ts b/packages/twenty-server/src/engine/core-modules/analytics/dtos/create-analytics.input.ts index a870673fe17c..5e887dca0567 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/dtos/create-analytics.input.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/dtos/create-analytics.input.ts @@ -1,16 +1,16 @@ import { ArgsType, Field } from '@nestjs/graphql'; +import { IsNotEmpty, IsObject, IsString } from 'class-validator'; import graphqlTypeJson from 'graphql-type-json'; -import { IsNotEmpty, IsString, IsObject } from 'class-validator'; @ArgsType() export class CreateAnalyticsInput { @Field({ description: 'Type of the event' }) @IsNotEmpty() @IsString() - type: string; + action: string; - @Field(() => graphqlTypeJson, { description: 'Event data in JSON format' }) + @Field(() => graphqlTypeJson, { description: 'Event payload in JSON format' }) @IsObject() - data: JSON; + payload: JSON; } diff --git a/packages/twenty-server/src/engine/core-modules/app-token/app-token.auto-resolver-opts.ts b/packages/twenty-server/src/engine/core-modules/app-token/app-token.auto-resolver-opts.ts index 651fc08c61b5..f431a2e8ab9a 100644 --- a/packages/twenty-server/src/engine/core-modules/app-token/app-token.auto-resolver-opts.ts +++ b/packages/twenty-server/src/engine/core-modules/app-token/app-token.auto-resolver-opts.ts @@ -6,7 +6,7 @@ import { import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { CreateAppTokenInput } from 'src/engine/core-modules/app-token/dtos/create-app-token.input'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; export const appTokenAutoResolverOpts: AutoResolverOpts< any, @@ -34,6 +34,6 @@ export const appTokenAutoResolverOpts: AutoResolverOpts< one: { disabled: true }, }, delete: { many: { disabled: true }, one: { disabled: true } }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], }, ]; diff --git a/packages/twenty-server/src/engine/core-modules/app-token/app-token.entity.ts b/packages/twenty-server/src/engine/core-modules/app-token/app-token.entity.ts index 010effe4d7b5..998fa634a757 100644 --- a/packages/twenty-server/src/engine/core-modules/app-token/app-token.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/app-token/app-token.entity.ts @@ -21,6 +21,7 @@ export enum AppTokenType { CodeChallenge = 'CODE_CHALLENGE', AuthorizationCode = 'AUTHORIZATION_CODE', PasswordResetToken = 'PASSWORD_RESET_TOKEN', + InvitationToken = 'INVITATION_TOKEN', } @Entity({ name: 'appToken', schema: 'core' }) @@ -37,8 +38,8 @@ export class AppToken { @JoinColumn({ name: 'userId' }) user: Relation<User>; - @Column() - userId: string; + @Column({ nullable: true }) + userId: string | null; @ManyToOne(() => Workspace, (workspace) => workspace.appTokens, { onDelete: 'CASCADE', @@ -73,4 +74,7 @@ export class AppToken { @Field() @UpdateDateColumn({ type: 'timestamptz' }) updatedAt: Date; + + @Column({ nullable: true, type: 'jsonb' }) + context: { email: string } | null; } diff --git a/packages/twenty-server/src/engine/core-modules/app-token/hooks/before-create-one-app-token.hook.ts b/packages/twenty-server/src/engine/core-modules/app-token/hooks/before-create-one-app-token.hook.ts index 01399f21e4dc..0927ee8de7b4 100644 --- a/packages/twenty-server/src/engine/core-modules/app-token/hooks/before-create-one-app-token.hook.ts +++ b/packages/twenty-server/src/engine/core-modules/app-token/hooks/before-create-one-app-token.hook.ts @@ -13,7 +13,7 @@ export class BeforeCreateOneAppToken<T extends AppToken> instance: CreateOneInputType<T>, context: any, ): Promise<CreateOneInputType<T>> { - const userId = context?.req?.user?.user?.id; + const userId = context?.req?.user?.id; instance.input.userId = userId; // FIXME: These fields should be autogenerated, we need to run a migration for this diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts index e2563b888e9c..1560c7f97ced 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts @@ -12,7 +12,8 @@ import { MicrosoftAuthController } from 'src/engine/core-modules/auth/controller import { VerifyAuthController } from 'src/engine/core-modules/auth/controllers/verify-auth.controller'; import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google-apis.service'; import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { TokenModule } from 'src/engine/core-modules/auth/token/token.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module'; import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; @@ -50,6 +51,7 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy'; ConnectedAccountWorkspaceEntity, ]), HttpModule, + TokenModule, UserWorkspaceModule, WorkspaceModule, OnboardingModule, @@ -65,9 +67,9 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy'; providers: [ SignInUpService, AuthService, - TokenService, JwtAuthStrategy, AuthResolver, + TokenService, GoogleAPIsService, AppTokenService, ], diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.spec.ts index 30e521f7ba41..2d08a6b4ead4 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.spec.ts @@ -1,17 +1,17 @@ +import { CanActivate } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { CanActivate } from '@nestjs/common'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { UserService } from 'src/engine/core-modules/user/services/user.service'; +import { CaptchaGuard } from 'src/engine/core-modules/captcha/captcha.guard'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { CaptchaGuard } from 'src/engine/integrations/captcha/captcha.guard'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthResolver } from './auth.resolver'; -import { TokenService } from './services/token.service'; import { AuthService } from './services/auth.service'; +import { TokenService } from './token/services/token.service'; describe('AuthResolver', () => { let resolver: AuthResolver; diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts index 2987054701a3..033210af120a 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts @@ -16,13 +16,14 @@ import { UpdatePasswordViaResetTokenInput } from 'src/engine/core-modules/auth/d import { ValidatePasswordResetToken } from 'src/engine/core-modules/auth/dto/validate-password-reset-token.entity'; import { ValidatePasswordResetTokenInput } from 'src/engine/core-modules/auth/dto/validate-password-reset-token.input'; import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter'; +import { CaptchaGuard } from 'src/engine/core-modules/captcha/captcha.guard'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { CaptchaGuard } from 'src/engine/integrations/captcha/captcha.guard'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { ChallengeInput } from './dto/challenge.input'; import { ImpersonateInput } from './dto/impersonate.input'; @@ -36,7 +37,7 @@ import { VerifyInput } from './dto/verify.input'; import { WorkspaceInviteHashValid } from './dto/workspace-invite-hash-valid.entity'; import { WorkspaceInviteHashValidInput } from './dto/workspace-invite-hash.input'; import { AuthService } from './services/auth.service'; -import { TokenService } from './services/token.service'; +import { TokenService } from './token/services/token.service'; @Resolver() @UseFilters(AuthGraphqlApiExceptionFilter) @@ -111,11 +112,15 @@ export class AuthResolver { } @Mutation(() => TransientToken) - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard, UserAuthGuard) async generateTransientToken( @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, ): Promise<TransientToken | void> { - const workspaceMember = await this.userService.loadWorkspaceMember(user); + const workspaceMember = await this.userService.loadWorkspaceMember( + user, + workspace, + ); if (!workspaceMember) { return; @@ -123,7 +128,7 @@ export class AuthResolver { const transientToken = await this.tokenService.generateTransientToken( workspaceMember.id, user.id, - user.defaultWorkspace.id, + user.defaultWorkspaceId, ); return { transientToken }; @@ -141,7 +146,7 @@ export class AuthResolver { } @Mutation(() => AuthorizeApp) - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard, UserAuthGuard) async authorizeApp( @Args() authorizeAppInput: AuthorizeAppInput, @AuthUser() user: User, @@ -155,7 +160,7 @@ export class AuthResolver { } @Mutation(() => AuthTokens) - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard, UserAuthGuard) async generateJWT( @AuthUser() user: User, @Args() args: GenerateJwtInput, @@ -177,7 +182,7 @@ export class AuthResolver { return { tokens: tokens }; } - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard, UserAuthGuard) @Mutation(() => Verify) async impersonate( @Args() impersonateInput: ImpersonateInput, @@ -186,7 +191,7 @@ export class AuthResolver { return await this.authService.impersonate(impersonateInput.userId, user); } - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard) @Mutation(() => ApiKeyToken) async generateApiKeyToken( @Args() args: ApiKeyTokenInput, diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts index 783556dbe513..615d4c6071d0 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts @@ -17,10 +17,10 @@ import { AuthRestApiExceptionFilter } from 'src/engine/core-modules/auth/filters import { GoogleAPIsOauthExchangeCodeForTokenGuard } from 'src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard'; import { GoogleAPIsOauthRequestCodeGuard } from 'src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard'; import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google-apis.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; @Controller('auth/google-apis') @UseFilters(AuthRestApiExceptionFilter) diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-auth.controller.ts index 42674953ed31..6ae9b11d7429 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-auth.controller.ts @@ -13,8 +13,8 @@ import { AuthRestApiExceptionFilter } from 'src/engine/core-modules/auth/filters import { GoogleOauthGuard } from 'src/engine/core-modules/auth/guards/google-oauth.guard'; import { GoogleProviderEnabledGuard } from 'src/engine/core-modules/auth/guards/google-provider-enabled.guard'; import { AuthService } from 'src/engine/core-modules/auth/services/auth.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; import { GoogleRequest } from 'src/engine/core-modules/auth/strategies/google.auth.strategy'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; @Controller('auth/google') @UseFilters(AuthRestApiExceptionFilter) @@ -34,8 +34,14 @@ export class GoogleAuthController { @Get('redirect') @UseGuards(GoogleProviderEnabledGuard, GoogleOauthGuard) async googleAuthRedirect(@Req() req: GoogleRequest, @Res() res: Response) { - const { firstName, lastName, email, picture, workspaceInviteHash } = - req.user; + const { + firstName, + lastName, + email, + picture, + workspaceInviteHash, + workspacePersonalInviteToken, + } = req.user; const user = await this.authService.signInUp({ email, @@ -43,6 +49,7 @@ export class GoogleAuthController { lastName, picture, workspaceInviteHash, + workspacePersonalInviteToken, fromSSO: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-auth.controller.ts index 62f3364b6bca..49fa5384b3b4 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-auth.controller.ts @@ -14,8 +14,8 @@ import { AuthRestApiExceptionFilter } from 'src/engine/core-modules/auth/filters import { MicrosoftOAuthGuard } from 'src/engine/core-modules/auth/guards/microsoft-oauth.guard'; import { MicrosoftProviderEnabledGuard } from 'src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard'; import { AuthService } from 'src/engine/core-modules/auth/services/auth.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; import { MicrosoftRequest } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; @Controller('auth/microsoft') @UseFilters(AuthRestApiExceptionFilter) @@ -39,8 +39,14 @@ export class MicrosoftAuthController { @Req() req: MicrosoftRequest, @Res() res: Response, ) { - const { firstName, lastName, email, picture, workspaceInviteHash } = - req.user; + const { + firstName, + lastName, + email, + picture, + workspaceInviteHash, + workspacePersonalInviteToken, + } = req.user; const user = await this.authService.signInUp({ email, @@ -48,6 +54,7 @@ export class MicrosoftAuthController { lastName, picture, workspaceInviteHash, + workspacePersonalInviteToken, fromSSO: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.spec.ts index 0aef1bea10d2..a73754fbddbb 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { AuthService } from 'src/engine/core-modules/auth/services/auth.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; import { VerifyAuthController } from './verify-auth.controller'; diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.ts index 40869c5f7db4..25a52dc3b202 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/verify-auth.controller.ts @@ -4,7 +4,7 @@ import { Verify } from 'src/engine/core-modules/auth/dto/verify.entity'; import { VerifyInput } from 'src/engine/core-modules/auth/dto/verify.input'; import { AuthRestApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-rest-api-exception.filter'; import { AuthService } from 'src/engine/core-modules/auth/services/auth.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; @Controller('auth/verify') @UseFilters(AuthRestApiExceptionFilter) diff --git a/packages/twenty-server/src/engine/core-modules/auth/dto/sign-up.input.ts b/packages/twenty-server/src/engine/core-modules/auth/dto/sign-up.input.ts index 53a9a47880c8..4d952e0f2d8b 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/dto/sign-up.input.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/dto/sign-up.input.ts @@ -19,6 +19,11 @@ export class SignUpInput { @IsOptional() workspaceInviteHash?: string; + @Field(() => String, { nullable: true }) + @IsString() + @IsOptional() + workspacePersonalInviteToken?: string; + @Field(() => String, { nullable: true }) @IsString() @IsOptional() diff --git a/packages/twenty-server/src/engine/core-modules/auth/dto/workspace-invite-token.input.ts b/packages/twenty-server/src/engine/core-modules/auth/dto/workspace-invite-token.input.ts new file mode 100644 index 000000000000..756300a964bd --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/auth/dto/workspace-invite-token.input.ts @@ -0,0 +1,12 @@ +import { ArgsType, Field } from '@nestjs/graphql'; + +import { IsNotEmpty, IsString, MinLength } from 'class-validator'; + +@ArgsType() +export class WorkspaceInviteTokenInput { + @Field(() => String) + @IsString() + @IsNotEmpty() + @MinLength(10) + inviteToken: string; +} diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts index e60c41b64dce..77c6b41ce1d0 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts @@ -1,33 +1,19 @@ import { ExecutionContext, Injectable } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; -import { - GoogleAPIScopeConfig, - GoogleAPIsOauthExchangeCodeForTokenStrategy, -} from 'src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy'; +import { GoogleAPIsOauthExchangeCodeForTokenStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( 'google-apis', ) { - constructor( - private readonly environmentService: EnvironmentService, - private readonly tokenService: TokenService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository<FeatureFlagEntity>, - ) { + constructor(private readonly environmentService: EnvironmentService) { super(); } @@ -45,22 +31,9 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ); } - const { workspaceId } = await this.tokenService.verifyTransientToken( - state.transientToken, - ); - - const scopeConfig: GoogleAPIScopeConfig = { - isMessagingAliasFetchingEnabled: - !!(await this.featureFlagRepository.findOneBy({ - workspaceId, - key: FeatureFlagKey.IsMessagingAliasFetchingEnabled, - value: true, - })), - }; - new GoogleAPIsOauthExchangeCodeForTokenStrategy( this.environmentService, - scopeConfig, + {}, ); setRequestExtraParams(request, { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts index 1d70446b1111..04d860d5ebc5 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts @@ -1,29 +1,17 @@ import { ExecutionContext, Injectable } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; -import { GoogleAPIScopeConfig } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy'; import { GoogleAPIsOauthRequestCodeStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { - constructor( - private readonly environmentService: EnvironmentService, - private readonly tokenService: TokenService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository<FeatureFlagEntity>, - ) { + constructor(private readonly environmentService: EnvironmentService) { super({ prompt: 'select_account', }); @@ -42,23 +30,7 @@ export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { ); } - const { workspaceId } = await this.tokenService.verifyTransientToken( - request.query.transientToken, - ); - - const scopeConfig: GoogleAPIScopeConfig = { - isMessagingAliasFetchingEnabled: - !!(await this.featureFlagRepository.findOneBy({ - workspaceId, - key: FeatureFlagKey.IsMessagingAliasFetchingEnabled, - value: true, - })), - }; - - new GoogleAPIsOauthRequestCodeStrategy( - this.environmentService, - scopeConfig, - ); + new GoogleAPIsOauthRequestCodeStrategy(this.environmentService, {}); setRequestExtraParams(request, { transientToken: request.query.transientToken, redirectLocation: request.query.redirectLocation, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-oauth.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-oauth.guard.ts index c7185ff88309..dd9fbf17f2c0 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-oauth.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-oauth.guard.ts @@ -12,11 +12,20 @@ export class GoogleOauthGuard extends AuthGuard('google') { async canActivate(context: ExecutionContext) { const request = context.switchToHttp().getRequest(); const workspaceInviteHash = request.query.inviteHash; + const workspacePersonalInviteToken = request.query.inviteToken; if (workspaceInviteHash && typeof workspaceInviteHash === 'string') { request.params.workspaceInviteHash = workspaceInviteHash; } + if ( + workspacePersonalInviteToken && + typeof workspacePersonalInviteToken === 'string' + ) { + request.params.workspacePersonalInviteToken = + workspacePersonalInviteToken; + } + return (await super.canActivate(context)) as boolean; } } diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts index ed1db3ac9ddb..b78fa7f64af5 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts @@ -7,7 +7,7 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { GoogleStrategy } from 'src/engine/core-modules/auth/strategies/google.auth.strategy'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class GoogleProviderEnabledGuard implements CanActivate { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-oauth.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-oauth.guard.ts index 44f084a26cfa..dd67b676832e 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-oauth.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-oauth.guard.ts @@ -12,11 +12,20 @@ export class MicrosoftOAuthGuard extends AuthGuard('microsoft') { async canActivate(context: ExecutionContext) { const request = context.switchToHttp().getRequest(); const workspaceInviteHash = request.query.inviteHash; + const workspacePersonalInviteToken = request.query.inviteToken; if (workspaceInviteHash && typeof workspaceInviteHash === 'string') { request.params.workspaceInviteHash = workspaceInviteHash; } + if ( + workspacePersonalInviteToken && + typeof workspacePersonalInviteToken === 'string' + ) { + request.params.workspacePersonalInviteToken = + workspacePersonalInviteToken; + } + return (await super.canActivate(context)) as boolean; } } diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts index 435c0bb04599..9594c41bd371 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts @@ -7,7 +7,7 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { MicrosoftStrategy } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class MicrosoftProviderEnabledGuard implements CanActivate { diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts index b15cdec249a7..f52023891f6c 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts @@ -1,17 +1,17 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; -import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service'; -import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; import { AuthService } from './auth.service'; -import { TokenService } from './token.service'; describe('AuthService', () => { let service: AuthService; diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts index 0830e57fb831..bba83839a315 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts @@ -9,7 +9,7 @@ import ms from 'ms'; import { PasswordUpdateNotifyEmail } from 'twenty-emails'; import { Repository } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/integrations/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; import { AppToken, @@ -32,14 +32,12 @@ import { UserExists } from 'src/engine/core-modules/auth/dto/user-exists.entity' import { Verify } from 'src/engine/core-modules/auth/dto/verify.entity'; import { WorkspaceInviteHashValid } from 'src/engine/core-modules/auth/dto/workspace-invite-hash-valid.entity'; import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service'; -import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; - -import { TokenService } from './token.service'; @Injectable() export class AuthService { @@ -95,6 +93,7 @@ export class AuthService { email, password, workspaceInviteHash, + workspacePersonalInviteToken, firstName, lastName, picture, @@ -105,6 +104,7 @@ export class AuthService { firstName?: string | null; lastName?: string | null; workspaceInviteHash?: string | null; + workspacePersonalInviteToken?: string | null; picture?: string | null; fromSSO: boolean; }) { @@ -114,6 +114,7 @@ export class AuthService { firstName, lastName, workspaceInviteHash, + workspacePersonalInviteToken, picture, fromSSO, }); @@ -150,11 +151,6 @@ export class AuthService { // passwordHash is hidden for security reasons user.passwordHash = ''; - const workspaceMember = await this.userService.loadWorkspaceMember(user); - - if (workspaceMember) { - user.workspaceMember = workspaceMember as WorkspaceMember; - } const accessToken = await this.tokenService.generateAccessToken(user.id); const refreshToken = await this.tokenService.generateRefreshToken(user.id); diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index dcee921d280a..b20072ed54f1 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -3,10 +3,10 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts index e3bb7af39ec0..639f6cb68931 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts @@ -8,7 +8,8 @@ import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; describe('SignInUpService', () => { let service: SignInUpService; @@ -29,6 +30,10 @@ describe('SignInUpService', () => { provide: getRepositoryToken(User, 'core'), useValue: {}, }, + { + provide: getRepositoryToken(AppToken, 'core'), + useValue: {}, + }, { provide: UserWorkspaceService, useValue: {}, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts index 450b6e1a0ce4..6e0e96203876 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts @@ -5,6 +5,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import FileType from 'file-type'; import { Repository } from 'typeorm'; import { v4 } from 'uuid'; +import { isDefined } from 'class-validator'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; @@ -25,8 +26,9 @@ import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { getImageBufferFromUrl } from 'src/utils/image'; +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; export type SignInUpServiceInput = { email: string; @@ -34,6 +36,7 @@ export type SignInUpServiceInput = { firstName?: string | null; lastName?: string | null; workspaceInviteHash?: string | null; + workspacePersonalInviteToken?: string | null; picture?: string | null; fromSSO: boolean; }; @@ -45,6 +48,8 @@ export class SignInUpService { private readonly fileUploadService: FileUploadService, @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository<Workspace>, + @InjectRepository(AppToken, 'core') + private readonly appTokenRepository: Repository<AppToken>, @InjectRepository(User, 'core') private readonly userRepository: Repository<User>, private readonly userWorkspaceService: UserWorkspaceService, @@ -56,6 +61,7 @@ export class SignInUpService { async signInUp({ email, workspaceInviteHash, + workspacePersonalInviteToken, password, firstName, lastName, @@ -111,6 +117,7 @@ export class SignInUpService { email, passwordHash, workspaceInviteHash, + workspacePersonalInviteToken, firstName, lastName, picture, @@ -134,6 +141,7 @@ export class SignInUpService { email, passwordHash, workspaceInviteHash, + workspacePersonalInviteToken, firstName, lastName, picture, @@ -141,19 +149,25 @@ export class SignInUpService { }: { email: string; passwordHash: string | undefined; - workspaceInviteHash: string; + workspaceInviteHash: string | null; + workspacePersonalInviteToken: string | null | undefined; firstName: string; lastName: string; picture: SignInUpServiceInput['picture']; existingUser: User | null; }) { - const workspace = await this.workspaceRepository.findOneBy({ - inviteHash: workspaceInviteHash, + const isNewUser = !isDefined(existingUser); + let user = existingUser; + + const workspace = await this.findWorkspaceAndValidateInvitation({ + workspacePersonalInviteToken, + workspaceInviteHash, + email, }); if (!workspace) { throw new AuthException( - 'Invit hash is invalid', + 'Workspace not found', AuthExceptionCode.FORBIDDEN_EXCEPTION, ); } @@ -165,32 +179,76 @@ export class SignInUpService { ); } - if (existingUser) { - const updatedUser = await this.userWorkspaceService.addUserToWorkspace( - existingUser, - workspace, + if (isNewUser) { + const imagePath = await this.uploadPicture(picture, workspace.id); + + const userToCreate = this.userRepository.create({ + email: email, + firstName: firstName, + lastName: lastName, + defaultAvatarUrl: imagePath, + canImpersonate: false, + passwordHash, + defaultWorkspace: workspace, + }); + + user = await this.userRepository.save(userToCreate); + } + + if (!user) { + throw new AuthException( + 'User not found', + AuthExceptionCode.FORBIDDEN_EXCEPTION, ); + } + + const updatedUser = workspacePersonalInviteToken + ? await this.userWorkspaceService.addUserToWorkspaceByInviteToken( + workspacePersonalInviteToken, + user, + ) + : await this.userWorkspaceService.addUserToWorkspace(user, workspace); - return Object.assign(existingUser, updatedUser); + if (isNewUser) { + await this.activateOnboardingForNewUser(user, workspace, { + firstName, + lastName, + }); } - const imagePath = await this.uploadPicture(picture, workspace.id); + return Object.assign(user, updatedUser); + } - const userToCreate = this.userRepository.create({ - email: email, - firstName: firstName, - lastName: lastName, - defaultAvatarUrl: imagePath, - canImpersonate: false, - passwordHash, - defaultWorkspace: workspace, - }); + private async findWorkspaceAndValidateInvitation({ + workspacePersonalInviteToken, + workspaceInviteHash, + email, + }) { + if (!workspacePersonalInviteToken && !workspaceInviteHash) { + throw new Error('No invite token or hash provided'); + } - const user = await this.userRepository.save(userToCreate); + if (!workspacePersonalInviteToken && workspaceInviteHash) { + return ( + (await this.workspaceRepository.findOneBy({ + inviteHash: workspaceInviteHash, + })) ?? undefined + ); + } - await this.userWorkspaceService.create(user.id, workspace.id); - await this.userWorkspaceService.createWorkspaceMember(workspace.id, user); + const appToken = await this.userWorkspaceService.validateInvitation( + workspacePersonalInviteToken, + email, + ); + + return appToken?.workspace; + } + private async activateOnboardingForNewUser( + user: User, + workspace: Workspace, + { firstName, lastName }: { firstName: string; lastName: string }, + ) { await this.onboardingService.setOnboardingConnectAccountPending({ userId: user.id, workspaceId: workspace.id, @@ -204,8 +262,6 @@ export class SignInUpService { value: true, }); } - - return user; } private async signUpOnNewWorkspace({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts index 99bd05cab01f..8636924735f9 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts @@ -1,9 +1,9 @@ -import { PassportStrategy } from '@nestjs/passport'; import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-google-oauth20'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -24,12 +24,9 @@ export class GoogleAPIsOauthCommonStrategy extends PassportStrategy( 'profile', 'https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/calendar.events', + 'https://www.googleapis.com/auth/profile.emails.read', ]; - if (scopeConfig?.isMessagingAliasFetchingEnabled) { - scopes.push('https://www.googleapis.com/auth/profile.emails.read'); - } - super({ clientID: environmentService.get('AUTH_GOOGLE_CLIENT_ID'), clientSecret: environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts index 047a7f55fa01..244b1066d846 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts @@ -3,12 +3,11 @@ import { Injectable } from '@nestjs/common'; import { VerifyCallback } from 'passport-google-oauth20'; import { GoogleAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; - isMessagingAliasFetchingEnabled?: boolean; }; @Injectable() diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts index 128ba607cd45..f93642bc7ece 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { GoogleAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts index 6cf51366ffb7..932e4c4e3e37 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts @@ -4,7 +4,7 @@ import { PassportStrategy } from '@nestjs/passport'; import { Request } from 'express'; import { Strategy, VerifyCallback } from 'passport-google-oauth20'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export type GoogleRequest = Omit< Request, @@ -16,6 +16,7 @@ export type GoogleRequest = Omit< email: string; picture: string | null; workspaceInviteHash?: string; + workspacePersonalInviteToken?: string; }; }; @@ -36,6 +37,12 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { ...options, state: JSON.stringify({ workspaceInviteHash: req.params.workspaceInviteHash, + ...(req.params.workspacePersonalInviteToken + ? { + workspacePersonalInviteToken: + req.params.workspacePersonalInviteToken, + } + : {}), }), }; @@ -61,6 +68,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { lastName: name.familyName, picture: photos?.[0]?.value, workspaceInviteHash: state.workspaceInviteHash, + workspacePersonalInviteToken: state.workspacePersonalInviteToken, }; done(null, user); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts index 6f74363572d2..64eeac4a7839 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts @@ -11,9 +11,9 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { ApiKeyWorkspaceEntity } from 'src/modules/api-key/standard-objects/api-key.workspace-entity'; @@ -90,7 +90,6 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') { if (payload.workspaceId) { user = await this.userRepository.findOne({ where: { id: payload.sub }, - relations: ['defaultWorkspace'], }); if (!user) { throw new AuthException( diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts index 8eae65a81d44..babcf1540b71 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts @@ -8,7 +8,7 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export type MicrosoftRequest = Omit< Request, @@ -20,6 +20,7 @@ export type MicrosoftRequest = Omit< email: string; picture: string | null; workspaceInviteHash?: string; + workspacePersonalInviteToken?: string; }; }; @@ -40,6 +41,12 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') { ...options, state: JSON.stringify({ workspaceInviteHash: req.params.workspaceInviteHash, + ...(req.params.workspacePersonalInviteToken + ? { + workspacePersonalInviteToken: + req.params.workspacePersonalInviteToken, + } + : {}), }), }; @@ -75,6 +82,7 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') { lastName: name.familyName, picture: photos?.[0]?.value, workspaceInviteHash: state.workspaceInviteHash, + workspacePersonalInviteToken: state.workspacePersonalInviteToken, }; done(null, user); diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/token.service.spec.ts similarity index 98% rename from packages/twenty-server/src/engine/core-modules/auth/services/token.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/auth/token/services/token.service.spec.ts index 29e2df741b82..777b1febde7f 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/token.service.spec.ts @@ -14,8 +14,8 @@ import { JwtAuthStrategy } from 'src/engine/core-modules/auth/strategies/jwt.aut import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { TokenService } from './token.service'; diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/token.service.ts similarity index 95% rename from packages/twenty-server/src/engine/core-modules/auth/services/token.service.ts rename to packages/twenty-server/src/engine/core-modules/auth/token/services/token.service.ts index 4cf18c206060..c740cb9a0613 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/token.service.ts @@ -36,14 +36,14 @@ import { JwtPayload, } from 'src/engine/core-modules/auth/strategies/jwt.auth.strategy'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -97,7 +97,7 @@ export class TokenService { ); } - const tokenWorkspaceId = workspaceId ?? user.defaultWorkspace.id; + const tokenWorkspaceId = workspaceId ?? user.defaultWorkspaceId; let tokenWorkspaceMemberId: string | undefined; if ( @@ -128,7 +128,7 @@ export class TokenService { const jwtPayload: JwtPayload = { sub: user.id, - workspaceId: workspaceId ? workspaceId : user.defaultWorkspace.id, + workspaceId: workspaceId ? workspaceId : user.defaultWorkspaceId, workspaceMemberId: tokenWorkspaceMemberId, }; @@ -175,6 +175,33 @@ export class TokenService { }; } + async generateInvitationToken(workspaceId: string, email: string) { + const expiresIn = this.environmentService.get( + 'INVITATION_TOKEN_EXPIRES_IN', + ); + + if (!expiresIn) { + throw new AuthException( + 'Expiration time for invitation token is not set', + AuthExceptionCode.INTERNAL_SERVER_ERROR, + ); + } + + const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); + + const invitationToken = this.appTokenRepository.create({ + workspaceId, + expiresAt, + type: AppTokenType.InvitationToken, + value: crypto.randomBytes(32).toString('hex'), + context: { + email, + }, + }); + + return this.appTokenRepository.save(invitationToken); + } + async generateLoginToken(email: string): Promise<AuthToken> { const secret = this.environmentService.get('LOGIN_TOKEN_SECRET'); const expiresIn = this.environmentService.get('LOGIN_TOKEN_EXPIRES_IN'); @@ -416,7 +443,7 @@ export class TokenService { }, }); - if (!codeChallengeAppToken) { + if (!codeChallengeAppToken || !codeChallengeAppToken.userId) { throw new AuthException( 'code verifier doesnt match the challenge', AuthExceptionCode.FORBIDDEN_EXCEPTION, @@ -750,7 +777,7 @@ export class TokenService { }, }); - if (!token) { + if (!token || !token.userId) { throw new AuthException( 'Token is invalid', AuthExceptionCode.FORBIDDEN_EXCEPTION, diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/token.module.ts b/packages/twenty-server/src/engine/core-modules/auth/token/token.module.ts new file mode 100644 index 000000000000..ea104687291f --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/auth/token/token.module.ts @@ -0,0 +1,26 @@ +/* eslint-disable no-restricted-imports */ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { JwtAuthStrategy } from 'src/engine/core-modules/auth/strategies/jwt.auth.strategy'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EmailModule } from 'src/engine/core-modules/email/email.module'; +import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; + +@Module({ + imports: [ + JwtModule, + TypeOrmModule.forFeature([User, AppToken, Workspace], 'core'), + TypeORMModule, + DataSourceModule, + EmailModule, + ], + providers: [TokenService, JwtAuthStrategy], + exports: [TokenService], +}) +export class TokenModule {} diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.module.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.module.ts index c1c6760df856..ff33a896ea2d 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.module.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.module.ts @@ -13,19 +13,19 @@ import { BillingService } from 'src/engine/core-modules/billing/services/billing import { StripeModule } from 'src/engine/core-modules/billing/stripe/stripe.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module'; +import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Module({ imports: [ FeatureFlagModule, StripeModule, - UserWorkspaceModule, TypeOrmModule.forFeature( [ BillingSubscription, BillingSubscriptionItem, Workspace, + UserWorkspace, FeatureFlagEntity, ], 'core', diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts index a60992cc7090..949615dd6679 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts @@ -16,7 +16,8 @@ import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @Resolver() export class BillingResolver { @@ -37,7 +38,7 @@ export class BillingResolver { } @Query(() => SessionEntity) - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard, UserAuthGuard) async billingPortalSession( @AuthUser() user: User, @Args() { returnUrlPath }: BillingSessionInput, @@ -51,7 +52,7 @@ export class BillingResolver { } @Mutation(() => SessionEntity) - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard, UserAuthGuard) async checkoutSession( @AuthWorkspace() workspace: Workspace, @AuthUser() user: User, @@ -79,7 +80,7 @@ export class BillingResolver { } @Mutation(() => UpdateBillingEntity) - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard) async updateBillingSubscription(@AuthUser() user: User) { await this.billingSubscriptionService.applyBillingSubscription(user); diff --git a/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts b/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts index 45d723329f9b..a91446b1c572 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts @@ -3,9 +3,9 @@ import { Logger, Scope } from '@nestjs/common'; import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export type UpdateSubscriptionJobData = { workspaceId: string }; @Processor({ diff --git a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts index 0d6f03ef49a8..13d41985007b 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts @@ -5,11 +5,11 @@ import { UpdateSubscriptionJob, UpdateSubscriptionJobData, } from 'src/engine/core-modules/billing/jobs/update-subscription.job'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing-portal.workspace-service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing-portal.workspace-service.ts index d4a7a333f394..6c031463f6e1 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing-portal.workspace-service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing-portal.workspace-service.ts @@ -6,10 +6,10 @@ import { Repository } from 'typeorm'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service'; -import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { assert } from 'src/utils/assert'; export enum WebhookEvent { @@ -24,10 +24,11 @@ export class BillingPortalWorkspaceService { protected readonly logger = new Logger(BillingPortalWorkspaceService.name); constructor( private readonly stripeService: StripeService, - private readonly userWorkspaceService: UserWorkspaceService, private readonly environmentService: EnvironmentService, @InjectRepository(BillingSubscription, 'core') private readonly billingSubscriptionRepository: Repository<BillingSubscription>, + @InjectRepository(UserWorkspace, 'core') + private readonly userWorkspaceRepository: Repository<UserWorkspace>, private readonly billingSubscriptionService: BillingSubscriptionService, ) {} @@ -42,8 +43,9 @@ export class BillingPortalWorkspaceService { ? frontBaseUrl + successUrlPath : frontBaseUrl; - const quantity = - (await this.userWorkspaceService.getUserCount(workspace.id)) || 1; + const quantity = await this.userWorkspaceRepository.countBy({ + workspaceId: workspace.id, + }); const stripeCustomerId = ( await this.billingSubscriptionRepository.findOneBy({ diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing-subscription.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing-subscription.service.ts index 15fb1df7151d..248d3fa6ebbd 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing-subscription.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing-subscription.service.ts @@ -18,7 +18,7 @@ import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.ser import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class BillingSubscriptionService { diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts index 455b30cfe096..8004d46e5c70 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts @@ -6,7 +6,7 @@ import { SubscriptionStatus } from 'src/engine/core-modules/billing/entities/bil import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class BillingService { diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/stripe.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/stripe.service.ts index 7dba53b26ba7..a6b0d179936d 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/stripe.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/stripe.service.ts @@ -6,8 +6,8 @@ import { AvailableProduct } from 'src/engine/core-modules/billing/interfaces/ava import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity'; import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; @Injectable() export class StripeService { @@ -93,7 +93,7 @@ export class StripeService { mode: 'subscription', subscription_data: { metadata: { - workspaceId: user.defaultWorkspace.id, + workspaceId: user.defaultWorkspaceId, }, trial_period_days: this.environmentService.get( 'BILLING_FREE_TRIAL_DURATION_IN_DAYS', diff --git a/packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts similarity index 81% rename from packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts index 79dedaf6bdc4..ce7cb740a511 100644 --- a/packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts @@ -2,8 +2,8 @@ import { CacheModuleOptions } from '@nestjs/common'; import { redisStore } from 'cache-manager-redis-yet'; -import { CacheStorageType } from 'src/engine/integrations/cache-storage/types/cache-storage-type.enum'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { CacheStorageType } from 'src/engine/core-modules/cache-storage/types/cache-storage-type.enum'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export const cacheStorageModuleFactory = ( environmentService: EnvironmentService, @@ -29,12 +29,17 @@ export const cacheStorageModuleFactory = ( ); } + const username = environmentService.get('REDIS_USERNAME'); + const password = environmentService.get('REDIS_PASSWORD'); + return { ...cacheModuleOptions, store: redisStore, socket: { host, port, + username, + password, }, }; } diff --git a/packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.module.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts similarity index 58% rename from packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.module.ts rename to packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts index b2af3906259a..3f12d09e6d98 100644 --- a/packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.module.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts @@ -1,11 +1,12 @@ -import { Module, Global, Inject, OnModuleDestroy } from '@nestjs/common'; -import { CacheModule, CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; +import { CACHE_MANAGER, Cache, CacheModule } from '@nestjs/cache-manager'; +import { Global, Inject, Module, OnModuleDestroy } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { cacheStorageModuleFactory } from 'src/engine/integrations/cache-storage/cache-storage.module-factory'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { cacheStorageModuleFactory } from 'src/engine/core-modules/cache-storage/cache-storage.module-factory'; +import { FlushCacheCommand } from 'src/engine/core-modules/cache-storage/commands/flush-cache.command'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Global() @Module({ @@ -25,8 +26,9 @@ import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/typ }, inject: [CACHE_MANAGER], })), + FlushCacheCommand, ], - exports: [...Object.values(CacheStorageNamespace)], + exports: [...Object.values(CacheStorageNamespace), FlushCacheCommand], }) export class CacheStorageModule implements OnModuleDestroy { constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts new file mode 100644 index 000000000000..c07565936aa9 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts @@ -0,0 +1,29 @@ +import { Logger } from '@nestjs/common'; + +import { Command, CommandRunner } from 'nest-commander'; + +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; + +// TODO: implement dry-run +@Command({ + name: 'cache:flush', + description: 'Completely flush cache', +}) +export class FlushCacheCommand extends CommandRunner { + private readonly logger = new Logger(FlushCacheCommand.name); + + constructor( + @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) + private readonly cacheStorage: CacheStorageService, + ) { + super(); + } + + async run(): Promise<void> { + this.logger.log('Flushing cache...'); + await this.cacheStorage.flush(); + this.logger.log('Cache flushed'); + } +} diff --git a/packages/twenty-server/src/engine/integrations/cache-storage/decorators/cache-storage.decorator.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/decorators/cache-storage.decorator.ts similarity index 78% rename from packages/twenty-server/src/engine/integrations/cache-storage/decorators/cache-storage.decorator.ts rename to packages/twenty-server/src/engine/core-modules/cache-storage/decorators/cache-storage.decorator.ts index 4782059b269f..0cd48cce30ca 100644 --- a/packages/twenty-server/src/engine/integrations/cache-storage/decorators/cache-storage.decorator.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/decorators/cache-storage.decorator.ts @@ -1,6 +1,6 @@ import { Inject } from '@nestjs/common'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; export const InjectCacheStorage = ( cacheStorageNamespace: CacheStorageNamespace, diff --git a/packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.service.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts similarity index 96% rename from packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.service.ts rename to packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts index 6f6bd3e1e15b..e5195c18ad8a 100644 --- a/packages/twenty-server/src/engine/integrations/cache-storage/cache-storage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts @@ -3,7 +3,7 @@ import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; import { RedisCache } from 'cache-manager-redis-yet'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; @Injectable() export class CacheStorageService { diff --git a/packages/twenty-server/src/engine/integrations/cache-storage/types/cache-storage-namespace.enum.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/cache-storage/types/cache-storage-namespace.enum.ts rename to packages/twenty-server/src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum.ts diff --git a/packages/twenty-server/src/engine/integrations/cache-storage/types/cache-storage-type.enum.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/types/cache-storage-type.enum.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/cache-storage/types/cache-storage-type.enum.ts rename to packages/twenty-server/src/engine/core-modules/cache-storage/types/cache-storage-type.enum.ts diff --git a/packages/twenty-server/src/engine/core-modules/calendar/dtos/timeline-calendar-event.dto.ts b/packages/twenty-server/src/engine/core-modules/calendar/dtos/timeline-calendar-event.dto.ts index d82e1cd89063..967ca31e5903 100644 --- a/packages/twenty-server/src/engine/core-modules/calendar/dtos/timeline-calendar-event.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/calendar/dtos/timeline-calendar-event.dto.ts @@ -1,14 +1,9 @@ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; +import { Field, ObjectType } from '@nestjs/graphql'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { TimelineCalendarEventParticipant } from 'src/engine/core-modules/calendar/dtos/timeline-calendar-event-participant.dto'; import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -registerEnumType(CalendarChannelVisibility, { - name: 'CalendarChannelVisibility', - description: 'Visibility of the calendar channel', -}); - @ObjectType('LinkMetadata') class LinkMetadata { @Field() diff --git a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.resolver.ts b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.resolver.ts index 585551291b06..c6656e0ef36d 100644 --- a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.resolver.ts @@ -7,7 +7,7 @@ import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/ import { TIMELINE_CALENDAR_EVENTS_MAX_PAGE_SIZE } from 'src/engine/core-modules/calendar/constants/calendar.constants'; import { TimelineCalendarEventsWithTotal } from 'src/engine/core-modules/calendar/dtos/timeline-calendar-events-with-total.dto'; import { TimelineCalendarEventService } from 'src/engine/core-modules/calendar/timeline-calendar-event.service'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @ArgsType() class GetTimelineCalendarEventsFromPersonIdArgs { @@ -35,7 +35,7 @@ class GetTimelineCalendarEventsFromCompanyIdArgs { pageSize: number; } -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver(() => TimelineCalendarEventsWithTotal) export class TimelineCalendarEventResolver { constructor( diff --git a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts index a12c745fc213..c26c03959ef9 100644 --- a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts +++ b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts @@ -93,6 +93,8 @@ export class TimelineCalendarEventService { participant.person?.name?.lastName || participant.workspaceMember?.name.firstName || participant.workspaceMember?.name.lastName || + participant.displayName || + participant.handle || '', avatarUrl: participant.person?.avatarUrl || diff --git a/packages/twenty-server/src/engine/integrations/captcha/captcha.constants.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/captcha/captcha.constants.ts rename to packages/twenty-server/src/engine/core-modules/captcha/captcha.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/captcha/captcha.guard.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.guard.ts similarity index 91% rename from packages/twenty-server/src/engine/integrations/captcha/captcha.guard.ts rename to packages/twenty-server/src/engine/core-modules/captcha/captcha.guard.ts index 46bed4fbded6..dc4513621c31 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/captcha.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/captcha.guard.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/common'; import { GqlExecutionContext } from '@nestjs/graphql'; -import { CaptchaService } from 'src/engine/integrations/captcha/captcha.service'; +import { CaptchaService } from 'src/engine/core-modules/captcha/captcha.service'; @Injectable() export class CaptchaGuard implements CanActivate { diff --git a/packages/twenty-server/src/engine/integrations/captcha/captcha.module-factory.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts similarity index 85% rename from packages/twenty-server/src/engine/integrations/captcha/captcha.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts index fc391f4050fd..c6a1e4c23edc 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/captcha.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts @@ -1,8 +1,8 @@ import { CaptchaDriverOptions, CaptchaModuleOptions, -} from 'src/engine/integrations/captcha/interfaces'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +} from 'src/engine/core-modules/captcha/interfaces'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export const captchaModuleFactory = ( environmentService: EnvironmentService, diff --git a/packages/twenty-server/src/engine/integrations/captcha/captcha.module.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module.ts similarity index 76% rename from packages/twenty-server/src/engine/integrations/captcha/captcha.module.ts rename to packages/twenty-server/src/engine/core-modules/captcha/captcha.module.ts index 506e51f42b2f..8c9dd1935189 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/captcha.module.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module.ts @@ -1,13 +1,13 @@ import { DynamicModule, Global } from '@nestjs/common'; -import { CAPTCHA_DRIVER } from 'src/engine/integrations/captcha/captcha.constants'; -import { CaptchaService } from 'src/engine/integrations/captcha/captcha.service'; -import { GoogleRecaptchaDriver } from 'src/engine/integrations/captcha/drivers/google-recaptcha.driver'; -import { TurnstileDriver } from 'src/engine/integrations/captcha/drivers/turnstile.driver'; +import { CAPTCHA_DRIVER } from 'src/engine/core-modules/captcha/captcha.constants'; +import { CaptchaService } from 'src/engine/core-modules/captcha/captcha.service'; +import { GoogleRecaptchaDriver } from 'src/engine/core-modules/captcha/drivers/google-recaptcha.driver'; +import { TurnstileDriver } from 'src/engine/core-modules/captcha/drivers/turnstile.driver'; import { CaptchaDriverType, CaptchaModuleAsyncOptions, -} from 'src/engine/integrations/captcha/interfaces'; +} from 'src/engine/core-modules/captcha/interfaces'; @Global() export class CaptchaModule { diff --git a/packages/twenty-server/src/engine/integrations/captcha/captcha.service.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.service.ts similarity index 71% rename from packages/twenty-server/src/engine/integrations/captcha/captcha.service.ts rename to packages/twenty-server/src/engine/core-modules/captcha/captcha.service.ts index 58af667e04e1..7a0c85e5d644 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/captcha.service.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/captcha.service.ts @@ -1,9 +1,9 @@ import { Inject, Injectable } from '@nestjs/common'; -import { CaptchaDriver } from 'src/engine/integrations/captcha/drivers/interfaces/captcha-driver.interface'; +import { CaptchaDriver } from 'src/engine/core-modules/captcha/drivers/interfaces/captcha-driver.interface'; -import { CAPTCHA_DRIVER } from 'src/engine/integrations/captcha/captcha.constants'; -import { CaptchaValidateResult } from 'src/engine/integrations/captcha/interfaces'; +import { CAPTCHA_DRIVER } from 'src/engine/core-modules/captcha/captcha.constants'; +import { CaptchaValidateResult } from 'src/engine/core-modules/captcha/interfaces'; @Injectable() export class CaptchaService implements CaptchaDriver { diff --git a/packages/twenty-server/src/engine/integrations/captcha/drivers/google-recaptcha.driver.ts b/packages/twenty-server/src/engine/core-modules/captcha/drivers/google-recaptcha.driver.ts similarity index 86% rename from packages/twenty-server/src/engine/integrations/captcha/drivers/google-recaptcha.driver.ts rename to packages/twenty-server/src/engine/core-modules/captcha/drivers/google-recaptcha.driver.ts index 85b766124fd3..008d8705b419 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/drivers/google-recaptcha.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/drivers/google-recaptcha.driver.ts @@ -1,12 +1,12 @@ import axios, { AxiosInstance } from 'axios'; -import { CaptchaDriver } from 'src/engine/integrations/captcha/drivers/interfaces/captcha-driver.interface'; -import { CaptchaServerResponse } from 'src/engine/integrations/captcha/drivers/interfaces/captcha-server-response'; +import { CaptchaDriver } from 'src/engine/core-modules/captcha/drivers/interfaces/captcha-driver.interface'; +import { CaptchaServerResponse } from 'src/engine/core-modules/captcha/drivers/interfaces/captcha-server-response'; import { CaptchaDriverOptions, CaptchaValidateResult, -} from 'src/engine/integrations/captcha/interfaces'; +} from 'src/engine/core-modules/captcha/interfaces'; export class GoogleRecaptchaDriver implements CaptchaDriver { private readonly siteKey: string; diff --git a/packages/twenty-server/src/engine/integrations/captcha/drivers/interfaces/captcha-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/captcha/drivers/interfaces/captcha-driver.interface.ts similarity index 64% rename from packages/twenty-server/src/engine/integrations/captcha/drivers/interfaces/captcha-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/captcha/drivers/interfaces/captcha-driver.interface.ts index 532640a79ba6..b40d6f97301e 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/drivers/interfaces/captcha-driver.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/drivers/interfaces/captcha-driver.interface.ts @@ -1,4 +1,4 @@ -import { CaptchaValidateResult } from 'src/engine/integrations/captcha/interfaces'; +import { CaptchaValidateResult } from 'src/engine/core-modules/captcha/interfaces'; export interface CaptchaDriver { validate(token: string): Promise<CaptchaValidateResult>; diff --git a/packages/twenty-server/src/engine/integrations/captcha/drivers/interfaces/captcha-server-response.ts b/packages/twenty-server/src/engine/core-modules/captcha/drivers/interfaces/captcha-server-response.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/captcha/drivers/interfaces/captcha-server-response.ts rename to packages/twenty-server/src/engine/core-modules/captcha/drivers/interfaces/captcha-server-response.ts diff --git a/packages/twenty-server/src/engine/integrations/captcha/drivers/turnstile.driver.ts b/packages/twenty-server/src/engine/core-modules/captcha/drivers/turnstile.driver.ts similarity index 86% rename from packages/twenty-server/src/engine/integrations/captcha/drivers/turnstile.driver.ts rename to packages/twenty-server/src/engine/core-modules/captcha/drivers/turnstile.driver.ts index 5dbe5d3e1eb0..ff21d8f62efc 100644 --- a/packages/twenty-server/src/engine/integrations/captcha/drivers/turnstile.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/drivers/turnstile.driver.ts @@ -1,12 +1,12 @@ import axios, { AxiosInstance } from 'axios'; -import { CaptchaDriver } from 'src/engine/integrations/captcha/drivers/interfaces/captcha-driver.interface'; -import { CaptchaServerResponse } from 'src/engine/integrations/captcha/drivers/interfaces/captcha-server-response'; +import { CaptchaDriver } from 'src/engine/core-modules/captcha/drivers/interfaces/captcha-driver.interface'; +import { CaptchaServerResponse } from 'src/engine/core-modules/captcha/drivers/interfaces/captcha-server-response'; import { CaptchaDriverOptions, CaptchaValidateResult, -} from 'src/engine/integrations/captcha/interfaces'; +} from 'src/engine/core-modules/captcha/interfaces'; export class TurnstileDriver implements CaptchaDriver { private readonly siteKey: string; diff --git a/packages/twenty-server/src/engine/integrations/captcha/interfaces/captcha.interface.ts b/packages/twenty-server/src/engine/core-modules/captcha/interfaces/captcha.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/captcha/interfaces/captcha.interface.ts rename to packages/twenty-server/src/engine/core-modules/captcha/interfaces/captcha.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/captcha/interfaces/index.ts b/packages/twenty-server/src/engine/core-modules/captcha/interfaces/index.ts new file mode 100644 index 000000000000..27ebd3e56f6b --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/captcha/interfaces/index.ts @@ -0,0 +1 @@ +export * from 'src/engine/core-modules/captcha/interfaces/captcha.interface'; diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.entity.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.entity.ts index 478c89da0cd7..12cf5c3164dd 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.entity.ts @@ -1,6 +1,6 @@ import { Field, ObjectType } from '@nestjs/graphql'; -import { CaptchaDriverType } from 'src/engine/integrations/captcha/interfaces'; +import { CaptchaDriverType } from 'src/engine/core-modules/captcha/interfaces'; @ObjectType() class AuthProviders { @@ -76,9 +76,6 @@ export class ClientConfig { @Field(() => AuthProviders, { nullable: false }) authProviders: AuthProviders; - @Field(() => Telemetry, { nullable: false }) - telemetry: Telemetry; - @Field(() => Billing, { nullable: false }) billing: Billing; diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts index a723405b2851..d1ecf6935710 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts @@ -1,6 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ClientConfigResolver } from './client-config.resolver'; diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts index c8222a3418f8..3615066a4390 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts @@ -1,6 +1,6 @@ -import { Resolver, Query } from '@nestjs/graphql'; +import { Query, Resolver } from '@nestjs/graphql'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ClientConfig } from './client-config.entity'; @@ -17,9 +17,6 @@ export class ClientConfigResolver { password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), }, - telemetry: { - enabled: this.environmentService.get('TELEMETRY_ENABLED'), - }, billing: { isBillingEnabled: this.environmentService.get('IS_BILLING_ENABLED'), billingUrl: this.environmentService.get('BILLING_PLAN_REQUIRED_LINK'), diff --git a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts index 27312a15159d..2e2df06c4d8e 100644 --- a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts +++ b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts @@ -1,18 +1,44 @@ import { Module } from '@nestjs/common'; +import { HttpAdapterHost } from '@nestjs/core'; +import { EventEmitterModule } from '@nestjs/event-emitter'; import { ActorModule } from 'src/engine/core-modules/actor/actor.module'; import { AISQLQueryModule } from 'src/engine/core-modules/ai-sql-query/ai-sql-query.module'; import { AppTokenModule } from 'src/engine/core-modules/app-token/app-token.module'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { BillingModule } from 'src/engine/core-modules/billing/billing.module'; +import { CacheStorageModule } from 'src/engine/core-modules/cache-storage/cache-storage.module'; import { TimelineCalendarEventModule } from 'src/engine/core-modules/calendar/timeline-calendar-event.module'; +import { CaptchaModule } from 'src/engine/core-modules/captcha/captcha.module'; +import { captchaModuleFactory } from 'src/engine/core-modules/captcha/captcha.module-factory'; +import { EmailModule } from 'src/engine/core-modules/email/email.module'; +import { emailModuleFactory } from 'src/engine/core-modules/email/email.module-factory'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ExceptionHandlerModule } from 'src/engine/core-modules/exception-handler/exception-handler.module'; +import { exceptionHandlerModuleFactory } from 'src/engine/core-modules/exception-handler/exception-handler.module-factory'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; +import { FileStorageModule } from 'src/engine/core-modules/file-storage/file-storage.module'; +import { fileStorageModuleFactory } from 'src/engine/core-modules/file-storage/file-storage.module-factory'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { HealthModule } from 'src/engine/core-modules/health/health.module'; +import { LLMChatModelModule } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.module'; +import { llmChatModelModuleFactory } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory'; +import { LLMTracingModule } from 'src/engine/core-modules/llm-tracing/llm-tracing.module'; +import { llmTracingModuleFactory } from 'src/engine/core-modules/llm-tracing/llm-tracing.module-factory'; +import { LoggerModule } from 'src/engine/core-modules/logger/logger.module'; +import { loggerModuleFactory } from 'src/engine/core-modules/logger/logger.module-factory'; +import { MessageQueueModule } from 'src/engine/core-modules/message-queue/message-queue.module'; +import { messageQueueModuleFactory } from 'src/engine/core-modules/message-queue/message-queue.module-factory'; import { TimelineMessagingModule } from 'src/engine/core-modules/messaging/timeline-messaging.module'; import { OpenApiModule } from 'src/engine/core-modules/open-api/open-api.module'; import { PostgresCredentialsModule } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.module'; +import { serverlessModuleFactory } from 'src/engine/core-modules/serverless/serverless-module.factory'; +import { ServerlessModule } from 'src/engine/core-modules/serverless/serverless.module'; +import { TelemetryModule } from 'src/engine/core-modules/telemetry/telemetry.module'; import { UserModule } from 'src/engine/core-modules/user/user.module'; import { WorkflowTriggerApiModule } from 'src/engine/core-modules/workflow/workflow-trigger-api.module'; +import { WorkspaceInvitationModule } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.module'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { WorkspaceEventEmitterModule } from 'src/engine/workspace-event-emitter/workspace-event-emitter.module'; @@ -35,11 +61,54 @@ import { FileModule } from './file/file.module'; TimelineCalendarEventModule, UserModule, WorkspaceModule, + WorkspaceInvitationModule, AISQLQueryModule, PostgresCredentialsModule, WorkflowTriggerApiModule, WorkspaceEventEmitterModule, ActorModule, + TelemetryModule, + EnvironmentModule.forRoot({}), + FileStorageModule.forRootAsync({ + useFactory: fileStorageModuleFactory, + inject: [EnvironmentService], + }), + LoggerModule.forRootAsync({ + useFactory: loggerModuleFactory, + inject: [EnvironmentService], + }), + MessageQueueModule.registerAsync({ + useFactory: messageQueueModuleFactory, + inject: [EnvironmentService], + }), + ExceptionHandlerModule.forRootAsync({ + useFactory: exceptionHandlerModuleFactory, + inject: [EnvironmentService, HttpAdapterHost], + }), + EmailModule.forRoot({ + useFactory: emailModuleFactory, + inject: [EnvironmentService], + }), + CaptchaModule.forRoot({ + useFactory: captchaModuleFactory, + inject: [EnvironmentService], + }), + EventEmitterModule.forRoot({ + wildcard: true, + }), + CacheStorageModule, + LLMChatModelModule.forRoot({ + useFactory: llmChatModelModuleFactory, + inject: [EnvironmentService], + }), + LLMTracingModule.forRoot({ + useFactory: llmTracingModuleFactory, + inject: [EnvironmentService], + }), + ServerlessModule.forRootAsync({ + useFactory: serverlessModuleFactory, + inject: [EnvironmentService, FileStorageService], + }), ], exports: [ AnalyticsModule, @@ -49,6 +118,7 @@ import { FileModule } from './file/file.module'; TimelineCalendarEventModule, UserModule, WorkspaceModule, + WorkspaceInvitationModule, ], }) export class CoreEngineModule {} diff --git a/packages/twenty-server/src/engine/core-modules/cron/sentry-cron-monitor.decorator.ts b/packages/twenty-server/src/engine/core-modules/cron/sentry-cron-monitor.decorator.ts new file mode 100644 index 000000000000..ad60c242c20b --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/cron/sentry-cron-monitor.decorator.ts @@ -0,0 +1,55 @@ +import * as Sentry from '@sentry/node'; + +export function SentryCronMonitor(monitorSlug: string, schedule: string) { + return function ( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor, + ) { + const originalMethod = descriptor.value; + + descriptor.value = async function (...args: any[]) { + if (!Sentry.isInitialized()) { + return await originalMethod.apply(this, args); + } + + let checkInId: string | undefined; + + try { + checkInId = Sentry.captureCheckIn( + { + monitorSlug, + status: 'in_progress', + }, + { + schedule: { + type: 'crontab', + value: schedule, + }, + checkinMargin: 1, + maxRuntime: 5, + timezone: 'UTC', + }, + ); + const result = await originalMethod.apply(this, args); + + Sentry.captureCheckIn({ + checkInId, + monitorSlug, + status: 'ok', + }); + + return result; + } catch (error) { + Sentry.captureCheckIn({ + checkInId, + monitorSlug, + status: 'error', + }); + throw error; + } + }; + + return descriptor; + }; +} diff --git a/packages/twenty-server/src/engine/integrations/email/drivers/interfaces/email-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/email/drivers/interfaces/email-driver.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/email/drivers/interfaces/email-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/email/drivers/interfaces/email-driver.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/email/drivers/logger.driver.ts b/packages/twenty-server/src/engine/core-modules/email/drivers/logger.driver.ts similarity index 90% rename from packages/twenty-server/src/engine/integrations/email/drivers/logger.driver.ts rename to packages/twenty-server/src/engine/core-modules/email/drivers/logger.driver.ts index a3138de0bd36..c8dd1e345709 100644 --- a/packages/twenty-server/src/engine/integrations/email/drivers/logger.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/email/drivers/logger.driver.ts @@ -2,7 +2,7 @@ import { Logger } from '@nestjs/common'; import { SendMailOptions } from 'nodemailer'; -import { EmailDriver } from 'src/engine/integrations/email/drivers/interfaces/email-driver.interface'; +import { EmailDriver } from 'src/engine/core-modules/email/drivers/interfaces/email-driver.interface'; export class LoggerDriver implements EmailDriver { private readonly logger = new Logger(LoggerDriver.name); diff --git a/packages/twenty-server/src/engine/integrations/email/drivers/smtp.driver.ts b/packages/twenty-server/src/engine/core-modules/email/drivers/smtp.driver.ts similarity index 92% rename from packages/twenty-server/src/engine/integrations/email/drivers/smtp.driver.ts rename to packages/twenty-server/src/engine/core-modules/email/drivers/smtp.driver.ts index 94445854ec06..5f325170e10e 100644 --- a/packages/twenty-server/src/engine/integrations/email/drivers/smtp.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/email/drivers/smtp.driver.ts @@ -3,7 +3,7 @@ import { Logger } from '@nestjs/common'; import { createTransport, Transporter, SendMailOptions } from 'nodemailer'; import SMTPConnection from 'nodemailer/lib/smtp-connection'; -import { EmailDriver } from 'src/engine/integrations/email/drivers/interfaces/email-driver.interface'; +import { EmailDriver } from 'src/engine/core-modules/email/drivers/interfaces/email-driver.interface'; export class SmtpDriver implements EmailDriver { private readonly logger = new Logger(SmtpDriver.name); diff --git a/packages/twenty-server/src/engine/integrations/email/email-sender.job.ts b/packages/twenty-server/src/engine/core-modules/email/email-sender.job.ts similarity index 63% rename from packages/twenty-server/src/engine/integrations/email/email-sender.job.ts rename to packages/twenty-server/src/engine/core-modules/email/email-sender.job.ts index d97117d5063c..85203d80bdb6 100644 --- a/packages/twenty-server/src/engine/integrations/email/email-sender.job.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email-sender.job.ts @@ -1,9 +1,9 @@ import { SendMailOptions } from 'nodemailer'; -import { EmailSenderService } from 'src/engine/integrations/email/email-sender.service'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; +import { EmailSenderService } from 'src/engine/core-modules/email/email-sender.service'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; @Processor(MessageQueue.emailQueue) export class EmailSenderJob { diff --git a/packages/twenty-server/src/engine/integrations/email/email-sender.service.ts b/packages/twenty-server/src/engine/core-modules/email/email-sender.service.ts similarity index 76% rename from packages/twenty-server/src/engine/integrations/email/email-sender.service.ts rename to packages/twenty-server/src/engine/core-modules/email/email-sender.service.ts index 96ec2196f03d..05306fe54927 100644 --- a/packages/twenty-server/src/engine/integrations/email/email-sender.service.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email-sender.service.ts @@ -2,9 +2,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { SendMailOptions } from 'nodemailer'; -import { EmailDriver } from 'src/engine/integrations/email/drivers/interfaces/email-driver.interface'; +import { EmailDriver } from 'src/engine/core-modules/email/drivers/interfaces/email-driver.interface'; -import { EMAIL_DRIVER } from 'src/engine/integrations/email/email.constants'; +import { EMAIL_DRIVER } from 'src/engine/core-modules/email/email.constants'; @Injectable() export class EmailSenderService implements EmailDriver { diff --git a/packages/twenty-server/src/engine/integrations/email/email.constants.ts b/packages/twenty-server/src/engine/core-modules/email/email.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/email/email.constants.ts rename to packages/twenty-server/src/engine/core-modules/email/email.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/email/email.module-factory.ts b/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts similarity index 89% rename from packages/twenty-server/src/engine/integrations/email/email.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts index 870f30db2fab..447d857e837f 100644 --- a/packages/twenty-server/src/engine/integrations/email/email.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts @@ -1,9 +1,9 @@ import { EmailDriver, EmailModuleOptions, -} from 'src/engine/integrations/email/interfaces/email.interface'; +} from 'src/engine/core-modules/email/interfaces/email.interface'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export const emailModuleFactory = ( environmentService: EnvironmentService, diff --git a/packages/twenty-server/src/engine/integrations/email/email.module.ts b/packages/twenty-server/src/engine/core-modules/email/email.module.ts similarity index 65% rename from packages/twenty-server/src/engine/integrations/email/email.module.ts rename to packages/twenty-server/src/engine/core-modules/email/email.module.ts index f97c246ab664..0a6b5c3a5854 100644 --- a/packages/twenty-server/src/engine/integrations/email/email.module.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email.module.ts @@ -1,12 +1,12 @@ import { DynamicModule, Global } from '@nestjs/common'; -import { EmailModuleAsyncOptions } from 'src/engine/integrations/email/interfaces/email.interface'; +import { EmailModuleAsyncOptions } from 'src/engine/core-modules/email/interfaces/email.interface'; -import { EMAIL_DRIVER } from 'src/engine/integrations/email/email.constants'; -import { LoggerDriver } from 'src/engine/integrations/email/drivers/logger.driver'; -import { SmtpDriver } from 'src/engine/integrations/email/drivers/smtp.driver'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EmailSenderService } from 'src/engine/integrations/email/email-sender.service'; +import { EMAIL_DRIVER } from 'src/engine/core-modules/email/email.constants'; +import { LoggerDriver } from 'src/engine/core-modules/email/drivers/logger.driver'; +import { SmtpDriver } from 'src/engine/core-modules/email/drivers/smtp.driver'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EmailSenderService } from 'src/engine/core-modules/email/email-sender.service'; @Global() export class EmailModule { diff --git a/packages/twenty-server/src/engine/integrations/email/email.service.ts b/packages/twenty-server/src/engine/core-modules/email/email.service.ts similarity index 70% rename from packages/twenty-server/src/engine/integrations/email/email.service.ts rename to packages/twenty-server/src/engine/core-modules/email/email.service.ts index 79217adb8d1e..6aa24c1e6688 100644 --- a/packages/twenty-server/src/engine/integrations/email/email.service.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email.service.ts @@ -2,10 +2,10 @@ import { Injectable } from '@nestjs/common'; import { SendMailOptions } from 'nodemailer'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { EmailSenderJob } from 'src/engine/core-modules/email/email-sender.job'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; @Injectable() export class EmailService { diff --git a/packages/twenty-server/src/engine/integrations/email/interfaces/email.interface.ts b/packages/twenty-server/src/engine/core-modules/email/interfaces/email.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/email/interfaces/email.interface.ts rename to packages/twenty-server/src/engine/core-modules/email/interfaces/email.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts similarity index 96% rename from packages/twenty-server/src/engine/integrations/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts index 43447e2de1e8..a35e03676ea3 100644 --- a/packages/twenty-server/src/engine/integrations/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts @@ -1,6 +1,6 @@ import { plainToClass } from 'class-transformer'; -import { CastToLogLevelArray } from 'src/engine/integrations/environment/decorators/cast-to-log-level-array.decorator'; +import { CastToLogLevelArray } from 'src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator'; class TestClass { @CastToLogLevelArray() diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts similarity index 96% rename from packages/twenty-server/src/engine/integrations/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts index f3f77fb4c333..cf302e0fd7c6 100644 --- a/packages/twenty-server/src/engine/integrations/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts @@ -1,6 +1,6 @@ import { plainToClass } from 'class-transformer'; -import { CastToPositiveNumber } from 'src/engine/integrations/environment/decorators/cast-to-positive-number.decorator'; +import { CastToPositiveNumber } from 'src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator'; class TestClass { @CastToPositiveNumber() diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-boolean.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-boolean.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-boolean.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-boolean.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-log-level-array.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-log-level-array.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-positive-number.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-positive-number.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-string-array.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-string-array.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/cast-to-string-array.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-string-array.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/is-aws-region.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/is-aws-region.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/is-aws-region.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/is-aws-region.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/is-duration.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/is-duration.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/is-duration.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/is-duration.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/decorators/is-strictly-lower-than.decorator.ts b/packages/twenty-server/src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/decorators/is-strictly-lower-than.decorator.ts rename to packages/twenty-server/src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/environment-variables.ts b/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts similarity index 82% rename from packages/twenty-server/src/engine/integrations/environment/environment-variables.ts rename to packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts index dba4cfaf6f6e..e89d98053eef 100644 --- a/packages/twenty-server/src/engine/integrations/environment/environment-variables.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts @@ -15,30 +15,29 @@ import { validateSync, } from 'class-validator'; -import { EmailDriver } from 'src/engine/integrations/email/interfaces/email.interface'; -import { NodeEnvironment } from 'src/engine/integrations/environment/interfaces/node-environment.interface'; -import { LLMChatModelDriver } from 'src/engine/integrations/llm-chat-model/interfaces/llm-chat-model.interface'; -import { LLMTracingDriver } from 'src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface'; - -import { CacheStorageType } from 'src/engine/integrations/cache-storage/types/cache-storage-type.enum'; -import { CaptchaDriverType } from 'src/engine/integrations/captcha/interfaces'; -import { CastToStringArray } from 'src/engine/integrations/environment/decorators/cast-to-string-array.decorator'; -import { IsStrictlyLowerThan } from 'src/engine/integrations/environment/decorators/is-strictly-lower-than.decorator'; -import { ExceptionHandlerDriver } from 'src/engine/integrations/exception-handler/interfaces'; -import { StorageDriverType } from 'src/engine/integrations/file-storage/interfaces'; -import { LoggerDriverType } from 'src/engine/integrations/logger/interfaces'; -import { MessageQueueDriverType } from 'src/engine/integrations/message-queue/interfaces'; -import { ServerlessDriverType } from 'src/engine/integrations/serverless/serverless.interface'; +import { EmailDriver } from 'src/engine/core-modules/email/interfaces/email.interface'; +import { AwsRegion } from 'src/engine/core-modules/environment/interfaces/aws-region.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface'; +import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; +import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; + +import { CacheStorageType } from 'src/engine/core-modules/cache-storage/types/cache-storage-type.enum'; +import { CaptchaDriverType } from 'src/engine/core-modules/captcha/interfaces'; +import { CastToBoolean } from 'src/engine/core-modules/environment/decorators/cast-to-boolean.decorator'; +import { CastToLogLevelArray } from 'src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator'; +import { CastToPositiveNumber } from 'src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator'; +import { CastToStringArray } from 'src/engine/core-modules/environment/decorators/cast-to-string-array.decorator'; +import { IsAWSRegion } from 'src/engine/core-modules/environment/decorators/is-aws-region.decorator'; +import { IsDuration } from 'src/engine/core-modules/environment/decorators/is-duration.decorator'; +import { IsStrictlyLowerThan } from 'src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator'; +import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; +import { StorageDriverType } from 'src/engine/core-modules/file-storage/interfaces'; +import { LoggerDriverType } from 'src/engine/core-modules/logger/interfaces'; +import { MessageQueueDriverType } from 'src/engine/core-modules/message-queue/interfaces'; +import { ServerlessDriverType } from 'src/engine/core-modules/serverless/serverless.interface'; import { assert } from 'src/utils/assert'; -import { CastToBoolean } from './decorators/cast-to-boolean.decorator'; -import { CastToLogLevelArray } from './decorators/cast-to-log-level-array.decorator'; -import { CastToPositiveNumber } from './decorators/cast-to-positive-number.decorator'; -import { IsAWSRegion } from './decorators/is-aws-region.decorator'; -import { IsDuration } from './decorators/is-duration.decorator'; -import { AwsRegion } from './interfaces/aws-region.interface'; -import { SupportDriver } from './interfaces/support.interface'; - export class EnvironmentVariables { // Misc @CastToBoolean() @@ -89,6 +88,15 @@ export class EnvironmentVariables { @IsBoolean() TELEMETRY_ENABLED = true; + @CastToBoolean() + @IsOptional() + @IsBoolean() + ANALYTICS_ENABLED = false; + + @IsString() + @ValidateIf((env) => env.ANALYTICS_ENABLED) + TINYBIRD_TOKEN: string; + @CastToPositiveNumber() @IsNumber() @IsOptional() @@ -130,7 +138,7 @@ export class EnvironmentVariables { @IsDuration() @IsOptional() - REFRESH_TOKEN_EXPIRES_IN = '30m'; + REFRESH_TOKEN_EXPIRES_IN = '60d'; @IsDuration() @IsOptional() @@ -151,6 +159,10 @@ export class EnvironmentVariables { @IsOptional() FILE_TOKEN_EXPIRES_IN = '1d'; + @IsDuration() + @IsOptional() + INVITATION_TOKEN_EXPIRES_IN = '30d'; + // Auth @IsUrl({ require_tld: false }) @IsOptional() @@ -368,6 +380,10 @@ export class EnvironmentVariables { @CastToPositiveNumber() REDIS_PORT = 6379; + REDIS_USERNAME: string; + + REDIS_PASSWORD: string; + API_TOKEN_EXPIRES_IN = '100y'; SHORT_TERM_TOKEN_EXPIRES_IN = '5m'; @@ -375,7 +391,7 @@ export class EnvironmentVariables { @CastToBoolean() MESSAGING_PROVIDER_GMAIL_ENABLED = false; - MESSAGE_QUEUE_TYPE: string = MessageQueueDriverType.Sync; + MESSAGE_QUEUE_TYPE: string = MessageQueueDriverType.BullMQ; EMAIL_FROM_ADDRESS = 'noreply@yourdomain.com'; @@ -410,7 +426,7 @@ export class EnvironmentVariables { @CastToPositiveNumber() API_RATE_LIMITING_LIMIT = 500; - CACHE_STORAGE_TYPE: CacheStorageType = CacheStorageType.Memory; + CACHE_STORAGE_TYPE: CacheStorageType = CacheStorageType.Redis; @CastToPositiveNumber() CACHE_STORAGE_TTL: number = 3600 * 24 * 7; diff --git a/packages/twenty-server/src/engine/integrations/environment/environment.module-definition.ts b/packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/environment.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/environment.module.ts b/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts similarity index 50% rename from packages/twenty-server/src/engine/integrations/environment/environment.module.ts rename to packages/twenty-server/src/engine/core-modules/environment/environment.module.ts index c42fd6ee9780..841f2b0bbf83 100644 --- a/packages/twenty-server/src/engine/integrations/environment/environment.module.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts @@ -1,9 +1,9 @@ import { Global, Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { EnvironmentService } from './environment.service'; -import { ConfigurableModuleClass } from './environment.module-definition'; -import { validate } from './environment-variables'; +import { validate } from 'src/engine/core-modules/environment/environment-variables'; +import { ConfigurableModuleClass } from 'src/engine/core-modules/environment/environment.module-definition'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Global() @Module({ @@ -12,6 +12,7 @@ import { validate } from './environment-variables'; isGlobal: true, expandVariables: true, validate, + envFilePath: process.env.NODE_ENV === 'test' ? '.env.test' : '.env', }), ], providers: [EnvironmentService], diff --git a/packages/twenty-server/src/engine/integrations/environment/environment.service.spec.ts b/packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts similarity index 86% rename from packages/twenty-server/src/engine/integrations/environment/environment.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts index 9b8c737424a8..49b35947d769 100644 --- a/packages/twenty-server/src/engine/integrations/environment/environment.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConfigService } from '@nestjs/config'; -import { EnvironmentService } from './environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; describe('EnvironmentService', () => { let service: EnvironmentService; diff --git a/packages/twenty-server/src/engine/integrations/environment/environment.service.ts b/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts similarity index 88% rename from packages/twenty-server/src/engine/integrations/environment/environment.service.ts rename to packages/twenty-server/src/engine/core-modules/environment/environment.service.ts index 8440249551fa..3860fdabde0b 100644 --- a/packages/twenty-server/src/engine/integrations/environment/environment.service.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { EnvironmentVariables } from 'src/engine/integrations/environment/environment-variables'; +import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; @Injectable() export class EnvironmentService { diff --git a/packages/twenty-server/src/engine/integrations/environment/interfaces/aws-region.interface.ts b/packages/twenty-server/src/engine/core-modules/environment/interfaces/aws-region.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/interfaces/aws-region.interface.ts rename to packages/twenty-server/src/engine/core-modules/environment/interfaces/aws-region.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/environment/interfaces/node-environment.interface.ts b/packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts similarity index 84% rename from packages/twenty-server/src/engine/integrations/environment/interfaces/node-environment.interface.ts rename to packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts index 9bb17d97056b..31af6fb09659 100644 --- a/packages/twenty-server/src/engine/integrations/environment/interfaces/node-environment.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts @@ -1,4 +1,5 @@ export enum NodeEnvironment { + test = 'test', development = 'development', production = 'production', } diff --git a/packages/twenty-server/src/engine/integrations/environment/interfaces/support.interface.ts b/packages/twenty-server/src/engine/core-modules/environment/interfaces/support.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/environment/interfaces/support.interface.ts rename to packages/twenty-server/src/engine/core-modules/environment/interfaces/support.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-create.event.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-create.event.ts similarity index 70% rename from packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-create.event.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-create.event.ts index 0e3d6e22c686..62221beaabab 100644 --- a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-create.event.ts +++ b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-create.event.ts @@ -1,4 +1,4 @@ -import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; export class ObjectRecordCreateEvent<T> extends ObjectRecordBaseEvent { properties: { diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-delete.event.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-delete.event.ts similarity index 71% rename from packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-delete.event.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-delete.event.ts index 01e981bdc76e..644ab0658a0f 100644 --- a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-delete.event.ts +++ b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-delete.event.ts @@ -1,4 +1,4 @@ -import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; export class ObjectRecordDeleteEvent<T> extends ObjectRecordBaseEvent { properties: { diff --git a/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-destroy.event.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-destroy.event.ts new file mode 100644 index 000000000000..f12b1e17547f --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-destroy.event.ts @@ -0,0 +1,7 @@ +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; + +export class ObjectRecordDestroyEvent<T> extends ObjectRecordBaseEvent { + properties: { + before: T; + }; +} diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-update.event.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-update.event.ts similarity index 77% rename from packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-update.event.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-update.event.ts index aa4b59e7208c..66d9f26455d2 100644 --- a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record-update.event.ts +++ b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record-update.event.ts @@ -1,4 +1,4 @@ -import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; export class ObjectRecordUpdateEvent<T> extends ObjectRecordBaseEvent { properties: { diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/types/object-record.base.event.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record.base.event.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/event-emitter/types/object-record.base.event.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/types/object-record.base.event.ts diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/utils/__tests__/object-record-changed-values.spec.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/utils/__tests__/object-record-changed-values.spec.ts similarity index 96% rename from packages/twenty-server/src/engine/integrations/event-emitter/utils/__tests__/object-record-changed-values.spec.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/utils/__tests__/object-record-changed-values.spec.ts index 6772e1f8715e..c9c1806698f6 100644 --- a/packages/twenty-server/src/engine/integrations/event-emitter/utils/__tests__/object-record-changed-values.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/event-emitter/utils/__tests__/object-record-changed-values.spec.ts @@ -1,6 +1,6 @@ import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { objectRecordChangedValues } from 'src/engine/integrations/event-emitter/utils/object-record-changed-values'; +import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values'; const mockObjectMetadata: ObjectMetadataInterface = { id: '1', diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/utils/object-record-changed-properties.util.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/event-emitter/utils/object-record-changed-properties.util.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util.ts diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/utils/object-record-changed-values.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/utils/object-record-changed-values.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/event-emitter/utils/object-record-changed-values.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/utils/object-record-changed-values.ts diff --git a/packages/twenty-server/src/engine/integrations/event-emitter/utils/object-record-diff-merge.ts b/packages/twenty-server/src/engine/core-modules/event-emitter/utils/object-record-diff-merge.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/event-emitter/utils/object-record-diff-merge.ts rename to packages/twenty-server/src/engine/core-modules/event-emitter/utils/object-record-diff-merge.ts diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/__tests__/exception-handler.service.spec.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/__tests__/exception-handler.service.spec.ts similarity index 83% rename from packages/twenty-server/src/engine/integrations/exception-handler/__tests__/exception-handler.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/__tests__/exception-handler.service.spec.ts index bae07ba64875..5255347d511e 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/__tests__/exception-handler.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/__tests__/exception-handler.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EXCEPTION_HANDLER_DRIVER } from 'src/engine/integrations/exception-handler/exception-handler.constants'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; +import { EXCEPTION_HANDLER_DRIVER } from 'src/engine/core-modules/exception-handler/exception-handler.constants'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; describe('ExceptionHandlerService', () => { let service: ExceptionHandlerService; diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/drivers/console.driver.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/drivers/console.driver.ts similarity index 74% rename from packages/twenty-server/src/engine/integrations/exception-handler/drivers/console.driver.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/drivers/console.driver.ts index f77e02085776..8f58ebf84920 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/drivers/console.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/drivers/console.driver.ts @@ -1,8 +1,8 @@ /* eslint-disable no-console */ -import { ExceptionHandlerUser } from 'src/engine/integrations/exception-handler/interfaces/exception-handler-user.interface'; -import { ExceptionHandlerOptions } from 'src/engine/integrations/exception-handler/interfaces/exception-handler-options.interface'; +import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; +import { ExceptionHandlerOptions } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface'; -import { ExceptionHandlerDriverInterface } from 'src/engine/integrations/exception-handler/interfaces'; +import { ExceptionHandlerDriverInterface } from 'src/engine/core-modules/exception-handler/interfaces'; export class ExceptionHandlerConsoleDriver implements ExceptionHandlerDriverInterface diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/drivers/sentry.driver.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/drivers/sentry.driver.ts similarity index 71% rename from packages/twenty-server/src/engine/integrations/exception-handler/drivers/sentry.driver.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/drivers/sentry.driver.ts index 1ece102d327b..0f904a858c83 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/drivers/sentry.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/drivers/sentry.driver.ts @@ -1,35 +1,13 @@ import * as Sentry from '@sentry/node'; -import { ProfilingIntegration } from '@sentry/profiling-node'; -import { ExceptionHandlerUser } from 'src/engine/integrations/exception-handler/interfaces/exception-handler-user.interface'; -import { ExceptionHandlerOptions } from 'src/engine/integrations/exception-handler/interfaces/exception-handler-options.interface'; +import { ExceptionHandlerOptions } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface'; +import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; -import { - ExceptionHandlerDriverInterface, - ExceptionHandlerSentryDriverFactoryOptions, -} from 'src/engine/integrations/exception-handler/interfaces'; +import { ExceptionHandlerDriverInterface } from 'src/engine/core-modules/exception-handler/interfaces'; export class ExceptionHandlerSentryDriver implements ExceptionHandlerDriverInterface { - constructor(options: ExceptionHandlerSentryDriverFactoryOptions['options']) { - Sentry.init({ - environment: options.environment, - release: options.release, - dsn: options.dsn, - integrations: [ - new Sentry.Integrations.Http({ tracing: true }), - new Sentry.Integrations.Express({ app: options.serverInstance }), - new Sentry.Integrations.GraphQL(), - new Sentry.Integrations.Postgres(), - new ProfilingIntegration(), - ], - tracesSampleRate: 0.1, - profilesSampleRate: 0.3, - debug: options.debug, - }); - } - captureExceptions( exceptions: ReadonlyArray<any>, options?: ExceptionHandlerOptions, diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.constants.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.constants.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module-definition.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-definition.ts similarity index 75% rename from packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-definition.ts index 2410d6616d74..fd0d3a1ccf27 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module-definition.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-definition.ts @@ -1,6 +1,6 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; -import { ExceptionHandlerModuleOptions } from './interfaces'; +import { ExceptionHandlerModuleOptions } from 'src/engine/core-modules/exception-handler/interfaces'; export const { ConfigurableModuleClass, diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module-factory.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts similarity index 86% rename from packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts index fed287d51d1f..006eb4c6c138 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts @@ -1,8 +1,8 @@ import { HttpAdapterHost } from '@nestjs/core'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { OPTIONS_TYPE } from 'src/engine/integrations/exception-handler/exception-handler.module-definition'; -import { ExceptionHandlerDriver } from 'src/engine/integrations/exception-handler/interfaces'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { OPTIONS_TYPE } from 'src/engine/core-modules/exception-handler/exception-handler.module-definition'; +import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; /** * ExceptionHandler Module factory diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module.ts similarity index 65% rename from packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module.ts index 8c4ae87a8312..6df4e8aa761b 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.module.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module.ts @@ -1,16 +1,15 @@ import { DynamicModule, Global, Module } from '@nestjs/common'; -import { ExceptionHandlerSentryDriver } from 'src/engine/integrations/exception-handler/drivers/sentry.driver'; -import { ExceptionHandlerConsoleDriver } from 'src/engine/integrations/exception-handler/drivers/console.driver'; - -import { ExceptionHandlerService } from './exception-handler.service'; -import { ExceptionHandlerDriver } from './interfaces'; -import { EXCEPTION_HANDLER_DRIVER } from './exception-handler.constants'; +import { ExceptionHandlerConsoleDriver } from 'src/engine/core-modules/exception-handler/drivers/console.driver'; +import { ExceptionHandlerSentryDriver } from 'src/engine/core-modules/exception-handler/drivers/sentry.driver'; +import { EXCEPTION_HANDLER_DRIVER } from 'src/engine/core-modules/exception-handler/exception-handler.constants'; import { + ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE, - ASYNC_OPTIONS_TYPE, -} from './exception-handler.module-definition'; +} from 'src/engine/core-modules/exception-handler/exception-handler.module-definition'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; @Global() @Module({ @@ -24,7 +23,7 @@ export class ExceptionHandlerModule extends ConfigurableModuleClass { useValue: options.type === ExceptionHandlerDriver.Console ? new ExceptionHandlerConsoleDriver() - : new ExceptionHandlerSentryDriver(options.options), + : new ExceptionHandlerSentryDriver(), }; const dynamicModule = super.forRoot(options); @@ -46,7 +45,7 @@ export class ExceptionHandlerModule extends ConfigurableModuleClass { return config.type === ExceptionHandlerDriver.Console ? new ExceptionHandlerConsoleDriver() - : new ExceptionHandlerSentryDriver(config.options); + : new ExceptionHandlerSentryDriver(); }, inject: options.inject || [], }; diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.service.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.service.ts similarity index 69% rename from packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.service.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.service.ts index ac46ae3465de..a532587d7af4 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/exception-handler.service.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.service.ts @@ -1,9 +1,9 @@ import { Inject, Injectable } from '@nestjs/common'; -import { ExceptionHandlerOptions } from 'src/engine/integrations/exception-handler/interfaces/exception-handler-options.interface'; +import { ExceptionHandlerOptions } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface'; -import { ExceptionHandlerDriverInterface } from 'src/engine/integrations/exception-handler/interfaces'; -import { EXCEPTION_HANDLER_DRIVER } from 'src/engine/integrations/exception-handler/exception-handler.constants'; +import { ExceptionHandlerDriverInterface } from 'src/engine/core-modules/exception-handler/interfaces'; +import { EXCEPTION_HANDLER_DRIVER } from 'src/engine/core-modules/exception-handler/exception-handler.constants'; @Injectable() export class ExceptionHandlerService { diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/hooks/use-sentry-tracing.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/hooks/use-sentry-tracing.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/exception-handler/hooks/use-sentry-tracing.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/hooks/use-sentry-tracing.ts diff --git a/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-driver.interface.ts new file mode 100644 index 000000000000..361d867fff89 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-driver.interface.ts @@ -0,0 +1,10 @@ +import { ExceptionHandlerOptions } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface'; +import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; + +export interface ExceptionHandlerDriverInterface { + captureExceptions( + exceptions: ReadonlyArray<any>, + options?: ExceptionHandlerOptions, + ): string[]; + captureMessage(message: string, user?: ExceptionHandlerUser): void; +} diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-options.interface.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface.ts similarity index 63% rename from packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-options.interface.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface.ts index f01c7e169446..73dd468ac11e 100644 --- a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-options.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface.ts @@ -1,6 +1,6 @@ import { OperationTypeNode } from 'graphql'; -import { ExceptionHandlerUser } from './exception-handler-user.interface'; +import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; export interface ExceptionHandlerOptions { operation?: { diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-user.interface.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-user.interface.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler.interface.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler.interface.ts rename to packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/exception-handler.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/index.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/index.ts new file mode 100644 index 000000000000..7ebf9f6c72d8 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/interfaces/index.ts @@ -0,0 +1,2 @@ +export * from 'src/engine/core-modules/exception-handler/interfaces/exception-handler.interface'; +export * from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-driver.interface'; diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts index ae103525343a..7bd085cc4136 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts @@ -1,15 +1,13 @@ export enum FeatureFlagKey { - IsBlocklistEnabled = 'IS_BLOCKLIST_ENABLED', IsEventObjectEnabled = 'IS_EVENT_OBJECT_ENABLED', IsAirtableIntegrationEnabled = 'IS_AIRTABLE_INTEGRATION_ENABLED', IsPostgreSQLIntegrationEnabled = 'IS_POSTGRESQL_INTEGRATION_ENABLED', IsStripeIntegrationEnabled = 'IS_STRIPE_INTEGRATION_ENABLED', IsCopilotEnabled = 'IS_COPILOT_ENABLED', - IsMessagingAliasFetchingEnabled = 'IS_MESSAGING_ALIAS_FETCHING_ENABLED', - IsGoogleCalendarSyncV2Enabled = 'IS_GOOGLE_CALENDAR_SYNC_V2_ENABLED', IsFreeAccessEnabled = 'IS_FREE_ACCESS_ENABLED', IsFunctionSettingsEnabled = 'IS_FUNCTION_SETTINGS_ENABLED', IsWorkflowEnabled = 'IS_WORKFLOW_ENABLED', IsMessageThreadSubscriberEnabled = 'IS_MESSAGE_THREAD_SUBSCRIBER_ENABLED', IsQueryRunnerTwentyORMEnabled = 'IS_QUERY_RUNNER_TWENTY_ORM_ENABLED', + IsWorkspaceFavoriteEnabled = 'IS_WORKSPACE_FAVORITE_ENABLED', } diff --git a/packages/twenty-server/src/engine/integrations/file-storage/__tests__/file-storage.service.spec.ts b/packages/twenty-server/src/engine/core-modules/file-storage/__tests__/file-storage.service.spec.ts similarity index 82% rename from packages/twenty-server/src/engine/integrations/file-storage/__tests__/file-storage.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/__tests__/file-storage.service.spec.ts index 4ef268cf6ca5..21210726eb07 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/__tests__/file-storage.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/__tests__/file-storage.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { STORAGE_DRIVER } from 'src/engine/integrations/file-storage/file-storage.constants'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; +import { STORAGE_DRIVER } from 'src/engine/core-modules/file-storage/file-storage.constants'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; describe('FileStorageService', () => { let service: FileStorageService; diff --git a/packages/twenty-server/src/engine/integrations/file-storage/drivers/interfaces/storage-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/file-storage/drivers/interfaces/storage-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/file-storage/drivers/local.driver.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts similarity index 90% rename from packages/twenty-server/src/engine/integrations/file-storage/drivers/local.driver.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts index e7d9f6bf7c33..3bbcc5493646 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/drivers/local.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts @@ -6,9 +6,8 @@ import { Readable } from 'stream'; import { FileStorageException, FileStorageExceptionCode, -} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception'; - -import { StorageDriver } from './interfaces/storage-driver.interface'; +} from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; +import { StorageDriver } from 'src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface'; export interface LocalDriverOptions { storagePath: string; @@ -127,6 +126,9 @@ export class LocalDriver implements StorageDriver { from: { folderPath: string; filename?: string }; to: { folderPath: string; filename?: string }; }): Promise<void> { + if (!params.from.filename && params.to.filename) { + throw new Error('Cannot copy folder to file'); + } const fromPath = join( `${this.options.storagePath}/`, params.from.folderPath, @@ -139,6 +141,8 @@ export class LocalDriver implements StorageDriver { params.to.filename || '', ); + await this.createFolder(dirname(toPath)); + try { await fs.cp(fromPath, toPath, { recursive: true }); } catch (error) { diff --git a/packages/twenty-server/src/engine/integrations/file-storage/drivers/s3.driver.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts similarity index 72% rename from packages/twenty-server/src/engine/integrations/file-storage/drivers/s3.driver.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts index d882db903b6e..765ded5b0068 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/drivers/s3.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts @@ -18,9 +18,10 @@ import { import { FileStorageException, FileStorageExceptionCode, -} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception'; +} from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; +import { StorageDriver } from 'src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface'; -import { StorageDriver } from './interfaces/storage-driver.interface'; +import { isDefined } from 'src/utils/is-defined'; export interface S3DriverOptions extends S3ClientConfig { bucketName: string; @@ -191,35 +192,80 @@ export class S3Driver implements StorageDriver { from: { folderPath: string; filename?: string }; to: { folderPath: string; filename?: string }; }): Promise<void> { + if (!params.from.filename && params.to.filename) { + throw new Error('Cannot copy folder to file'); + } + const fromKey = `${params.from.folderPath}/${params.from.filename || ''}`; const toKey = `${params.to.folderPath}/${params.to.filename || ''}`; - try { - // Check if the source file exists - await this.s3Client.send( - new HeadObjectCommand({ - Bucket: this.bucketName, - Key: fromKey, - }), - ); + if (isDefined(params.from.filename)) { + try { + // Check if the source file exists + await this.s3Client.send( + new HeadObjectCommand({ + Bucket: this.bucketName, + Key: fromKey, + }), + ); - // Copy the object to the new location - await this.s3Client.send( - new CopyObjectCommand({ - CopySource: `${this.bucketName}/${fromKey}`, - Bucket: this.bucketName, - Key: toKey, - }), - ); - } catch (error) { - if (error.name === 'NotFound') { - throw new FileStorageException( - 'File not found', - FileStorageExceptionCode.FILE_NOT_FOUND, + // Copy the object to the new location + await this.s3Client.send( + new CopyObjectCommand({ + CopySource: `${this.bucketName}/${fromKey}`, + Bucket: this.bucketName, + Key: toKey, + }), ); + + return; + } catch (error) { + if (error.name === 'NotFound') { + throw new FileStorageException( + 'File not found', + FileStorageExceptionCode.FILE_NOT_FOUND, + ); + } + // For other errors, throw the original error + throw error; } - // For other errors, throw the original error - throw error; + } + + const listedObjects = await this.s3Client.send( + new ListObjectsV2Command({ + Bucket: this.bucketName, + Prefix: fromKey, + }), + ); + + if (!listedObjects.Contents || listedObjects.Contents.length === 0) { + throw new Error('No objects found in the source folder.'); + } + + for (const object of listedObjects.Contents) { + const match = object.Key?.match(/(.*)\/(.*)/); + + if (!isDefined(match)) { + continue; + } + const fromFolderPath = match[1]; + const filename = match[2]; + const toFolderPath = fromFolderPath.replace( + params.from.folderPath, + params.to.folderPath, + ); + + if (!isDefined(toFolderPath)) { + continue; + } + + await this.copy({ + from: { + folderPath: fromFolderPath, + filename, + }, + to: { folderPath: toFolderPath, filename }, + }); } } diff --git a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.constants.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/file-storage/file-storage.constants.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/file-storage.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.module-definition.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-definition.ts similarity index 76% rename from packages/twenty-server/src/engine/integrations/file-storage/file-storage.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-definition.ts index 2b81d2cdb487..4d453abf4631 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.module-definition.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-definition.ts @@ -1,6 +1,6 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; -import { FileStorageModuleOptions } from './interfaces'; +import { FileStorageModuleOptions } from 'src/engine/core-modules/file-storage/interfaces'; export const { ConfigurableModuleClass, diff --git a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts similarity index 93% rename from packages/twenty-server/src/engine/integrations/file-storage/file-storage.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts index f28597500da4..1683645c6ee0 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts @@ -1,10 +1,10 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageModuleOptions, StorageDriverType, -} from 'src/engine/integrations/file-storage/interfaces'; +} from 'src/engine/core-modules/file-storage/interfaces'; import { resolveAbsolutePath } from 'src/utils/resolve-absolute-path'; /** diff --git a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.module.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module.ts similarity index 73% rename from packages/twenty-server/src/engine/integrations/file-storage/file-storage.module.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module.ts index d1f0f64defa5..7c8a5e683572 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module.ts @@ -1,14 +1,13 @@ import { DynamicModule, Global } from '@nestjs/common'; -import { FileStorageService } from './file-storage.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { FileStorageModuleAsyncOptions, FileStorageModuleOptions, -} from './interfaces'; -import { STORAGE_DRIVER } from './file-storage.constants'; - -import { LocalDriver } from './drivers/local.driver'; -import { S3Driver } from './drivers/s3.driver'; +} from 'src/engine/core-modules/file-storage/interfaces'; +import { STORAGE_DRIVER } from 'src/engine/core-modules/file-storage/file-storage.constants'; +import { LocalDriver } from 'src/engine/core-modules/file-storage/drivers/local.driver'; +import { S3Driver } from 'src/engine/core-modules/file-storage/drivers/s3.driver'; @Global() export class FileStorageModule { diff --git a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.service.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts similarity index 83% rename from packages/twenty-server/src/engine/integrations/file-storage/file-storage.service.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts index a6eeb6c2041c..f23822b8a374 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/file-storage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts @@ -2,9 +2,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Readable } from 'stream'; -import { STORAGE_DRIVER } from './file-storage.constants'; +import { StorageDriver } from 'src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface'; -import { StorageDriver } from './drivers/interfaces/storage-driver.interface'; +import { STORAGE_DRIVER } from 'src/engine/core-modules/file-storage/file-storage.constants'; @Injectable() export class FileStorageService implements StorageDriver { diff --git a/packages/twenty-server/src/engine/integrations/file-storage/interfaces/file-storage-exception.ts b/packages/twenty-server/src/engine/core-modules/file-storage/interfaces/file-storage-exception.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/file-storage/interfaces/file-storage-exception.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/interfaces/file-storage-exception.ts diff --git a/packages/twenty-server/src/engine/integrations/file-storage/interfaces/file-storage.interface.ts b/packages/twenty-server/src/engine/core-modules/file-storage/interfaces/file-storage.interface.ts similarity index 85% rename from packages/twenty-server/src/engine/integrations/file-storage/interfaces/file-storage.interface.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/interfaces/file-storage.interface.ts index 9d85a83ec554..cff95d73639a 100644 --- a/packages/twenty-server/src/engine/integrations/file-storage/interfaces/file-storage.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/interfaces/file-storage.interface.ts @@ -1,7 +1,7 @@ import { FactoryProvider, ModuleMetadata } from '@nestjs/common'; -import { S3DriverOptions } from 'src/engine/integrations/file-storage/drivers/s3.driver'; -import { LocalDriverOptions } from 'src/engine/integrations/file-storage/drivers/local.driver'; +import { S3DriverOptions } from 'src/engine/core-modules/file-storage/drivers/s3.driver'; +import { LocalDriverOptions } from 'src/engine/core-modules/file-storage/drivers/local.driver'; export enum StorageDriverType { S3 = 's3', diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/interfaces/index.ts b/packages/twenty-server/src/engine/core-modules/file-storage/interfaces/index.ts new file mode 100644 index 000000000000..4ab4d7061882 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/file-storage/interfaces/index.ts @@ -0,0 +1 @@ +export * from 'src/engine/core-modules/file-storage/interfaces/file-storage.interface'; diff --git a/packages/twenty-server/src/engine/integrations/file-storage/utils/read-file-content.ts b/packages/twenty-server/src/engine/core-modules/file-storage/utils/read-file-content.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/file-storage/utils/read-file-content.ts rename to packages/twenty-server/src/engine/core-modules/file-storage/utils/read-file-content.ts diff --git a/packages/twenty-server/src/engine/core-modules/file/controllers/file.controller.ts b/packages/twenty-server/src/engine/core-modules/file/controllers/file.controller.ts index 2124c2b17969..967df311994d 100644 --- a/packages/twenty-server/src/engine/core-modules/file/controllers/file.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/file/controllers/file.controller.ts @@ -5,7 +5,7 @@ import { Response } from 'express'; import { FileStorageException, FileStorageExceptionCode, -} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception'; +} from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; import { checkFilePath, diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts index d33c45f7a1e0..d0de77e23c6d 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts @@ -3,7 +3,7 @@ import { Module } from '@nestjs/common'; import { FileUploadResolver } from 'src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileModule } from 'src/engine/core-modules/file/file.module'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Module({ imports: [FileModule], diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts index 5a62ebdc4ff4..9633227b3c8d 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileUploadResolver } from './file-upload.resolver'; @@ -15,6 +16,10 @@ describe('FileUploadResolver', () => { provide: FileUploadService, useValue: {}, }, + { + provide: EnvironmentService, + useValue: {}, + }, ], }).compile(); diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.ts index 8e5bae9400cd..41d8739a1cb6 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.ts @@ -9,10 +9,10 @@ import { FileUploadService } from 'src/engine/core-modules/file/file-upload/serv import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { streamToBuffer } from 'src/utils/stream-to-buffer'; -@UseGuards(JwtAuthGuard, DemoEnvGuard) +@UseGuards(WorkspaceAuthGuard, DemoEnvGuard) @Resolver() export class FileUploadResolver { constructor(private readonly fileUploadService: FileUploadService) {} diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/services/file-upload.service.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/services/file-upload.service.ts index e408178e8cd2..80cd2ffd9db9 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/services/file-upload.service.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/services/file-upload.service.ts @@ -9,7 +9,7 @@ import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder. import { settings } from 'src/engine/constants/settings'; import { FileService } from 'src/engine/core-modules/file/services/file.service'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { getCropSize } from 'src/utils/image'; @Injectable() diff --git a/packages/twenty-server/src/engine/core-modules/file/file.module.ts b/packages/twenty-server/src/engine/core-modules/file/file.module.ts index c7d4c838cf61..73afa155921b 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { FilePathGuard } from 'src/engine/core-modules/file/guards/file-path-guard'; import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileController } from './controllers/file.controller'; import { FileService } from './services/file.service'; diff --git a/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts b/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts index db9f466c5d3b..890d060dd84b 100644 --- a/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts +++ b/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts @@ -7,7 +7,7 @@ import { } from '@nestjs/common'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class FilePathGuard implements CanActivate { diff --git a/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts b/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts index 3a65700006a8..ecc5ee5fa422 100644 --- a/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts @@ -1,8 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { FileService } from './file.service'; diff --git a/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts b/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts index d56d769f96ed..a1c59e700806 100644 --- a/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts +++ b/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts @@ -6,8 +6,8 @@ import { addMilliseconds } from 'date-fns'; import ms from 'ms'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; @Injectable() export class FileService { diff --git a/packages/twenty-server/src/engine/core-modules/graphql/engine-graphql.module.ts b/packages/twenty-server/src/engine/core-modules/graphql/engine-graphql.module.ts index ae592e22c802..0df672199146 100644 --- a/packages/twenty-server/src/engine/core-modules/graphql/engine-graphql.module.ts +++ b/packages/twenty-server/src/engine/core-modules/graphql/engine-graphql.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; -import { ExceptionHandlerModule } from 'src/engine/integrations/exception-handler/exception-handler.module'; +import { ExceptionHandlerModule } from 'src/engine/core-modules/exception-handler/exception-handler.module'; @Module({ imports: [ExceptionHandlerModule], diff --git a/packages/twenty-server/src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook.ts b/packages/twenty-server/src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook.ts index 9785cde8a2db..ff466d3f3324 100644 --- a/packages/twenty-server/src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook.ts +++ b/packages/twenty-server/src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook.ts @@ -11,7 +11,7 @@ import { GraphQLContext } from 'src/engine/api/graphql/graphql-config/interfaces import { generateGraphQLErrorFromError } from 'src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util'; import { BaseGraphQLError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { shouldCaptureException } from 'src/engine/core-modules/graphql/utils/should-capture-exception.util'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; type GraphQLErrorHandlerHookOptions = { /** diff --git a/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts b/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts index 6acbd76a01b1..306f1640e008 100644 --- a/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts +++ b/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts @@ -3,8 +3,8 @@ import { Module } from '@nestjs/common'; import { JwtModule as NestJwtModule } from '@nestjs/jwt'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; const InternalJwtModule = NestJwtModule.registerAsync({ useFactory: async (environmentService: EnvironmentService) => { diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/drivers/openai.driver.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/drivers/openai.driver.ts similarity index 89% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/drivers/openai.driver.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/drivers/openai.driver.ts index 652a854ef831..d1510b44d686 100644 --- a/packages/twenty-server/src/engine/integrations/llm-chat-model/drivers/openai.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-chat-model/drivers/openai.driver.ts @@ -1,7 +1,7 @@ import { BaseChatModel } from '@langchain/core/language_models/chat_models'; import { ChatOpenAI } from '@langchain/openai'; -import { LLMChatModelDriver } from 'src/engine/integrations/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface'; +import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface'; export class OpenAIDriver implements LLMChatModelDriver { private chatModel: BaseChatModel; diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/interfaces/llm-chat-model.interface.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/interfaces/llm-chat-model.interface.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.constants.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.constants.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.module-factory.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts similarity index 76% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts index 2d91f280ce54..e0ea03e54ba7 100644 --- a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts @@ -1,6 +1,6 @@ -import { LLMChatModelDriver } from 'src/engine/integrations/llm-chat-model/interfaces/llm-chat-model.interface'; +import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export const llmChatModelModuleFactory = ( environmentService: EnvironmentService, diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.module.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module.ts similarity index 77% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.module.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module.ts index 279993f72868..518c3389a32d 100644 --- a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.module.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module.ts @@ -3,11 +3,11 @@ import { DynamicModule, Global } from '@nestjs/common'; import { LLMChatModelDriver, LLMChatModelModuleAsyncOptions, -} from 'src/engine/integrations/llm-chat-model/interfaces/llm-chat-model.interface'; +} from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; -import { LLM_CHAT_MODEL_DRIVER } from 'src/engine/integrations/llm-chat-model/llm-chat-model.constants'; -import { OpenAIDriver } from 'src/engine/integrations/llm-chat-model/drivers/openai.driver'; -import { LLMChatModelService } from 'src/engine/integrations/llm-chat-model/llm-chat-model.service'; +import { LLM_CHAT_MODEL_DRIVER } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.constants'; +import { OpenAIDriver } from 'src/engine/core-modules/llm-chat-model/drivers/openai.driver'; +import { LLMChatModelService } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.service'; @Global() export class LLMChatModelModule { diff --git a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.service.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.service.ts similarity index 74% rename from packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.service.ts rename to packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.service.ts index 62beea8c6eca..9a98eeb3c6e5 100644 --- a/packages/twenty-server/src/engine/integrations/llm-chat-model/llm-chat-model.service.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.service.ts @@ -1,8 +1,8 @@ import { Injectable, Inject } from '@nestjs/common'; -import { LLMChatModelDriver } from 'src/engine/integrations/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface'; +import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/drivers/interfaces/llm-prompt-template-driver.interface'; -import { LLM_CHAT_MODEL_DRIVER } from 'src/engine/integrations/llm-chat-model/llm-chat-model.constants'; +import { LLM_CHAT_MODEL_DRIVER } from 'src/engine/core-modules/llm-chat-model/llm-chat-model.constants'; @Injectable() export class LLMChatModelService { diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/drivers/console.driver.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/console.driver.ts similarity index 92% rename from packages/twenty-server/src/engine/integrations/llm-tracing/drivers/console.driver.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/console.driver.ts index 6c1ae4015018..754df2586c95 100644 --- a/packages/twenty-server/src/engine/integrations/llm-tracing/drivers/console.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/console.driver.ts @@ -3,7 +3,7 @@ import { BaseCallbackHandler } from '@langchain/core/callbacks/base'; import { Run } from '@langchain/core/tracers/base'; import { ConsoleCallbackHandler } from '@langchain/core/tracers/console'; -import { LLMTracingDriver } from 'src/engine/integrations/llm-tracing/drivers/interfaces/llm-tracing-driver.interface'; +import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/drivers/interfaces/llm-tracing-driver.interface'; class WithMetadataConsoleCallbackHandler extends ConsoleCallbackHandler { private metadata: Record<string, unknown>; diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/drivers/interfaces/llm-tracing-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/interfaces/llm-tracing-driver.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/llm-tracing/drivers/interfaces/llm-tracing-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/interfaces/llm-tracing-driver.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/drivers/langfuse.driver.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/langfuse.driver.ts similarity index 91% rename from packages/twenty-server/src/engine/integrations/llm-tracing/drivers/langfuse.driver.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/langfuse.driver.ts index b9b84aad0860..3d44ba970298 100644 --- a/packages/twenty-server/src/engine/integrations/llm-tracing/drivers/langfuse.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/drivers/langfuse.driver.ts @@ -1,7 +1,7 @@ import { BaseCallbackHandler } from '@langchain/core/callbacks/base'; import CallbackHandler from 'langfuse-langchain'; -import { LLMTracingDriver } from 'src/engine/integrations/llm-tracing/drivers/interfaces/llm-tracing-driver.interface'; +import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/drivers/interfaces/llm-tracing-driver.interface'; export interface LangfuseDriverOptions { secretKey: string; diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface.ts similarity index 91% rename from packages/twenty-server/src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface.ts index a97031499b10..99dcdbd157ea 100644 --- a/packages/twenty-server/src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface.ts @@ -1,6 +1,6 @@ import { ModuleMetadata, FactoryProvider } from '@nestjs/common'; -import { LangfuseDriverOptions } from 'src/engine/integrations/llm-tracing/drivers/langfuse.driver'; +import { LangfuseDriverOptions } from 'src/engine/core-modules/llm-tracing/drivers/langfuse.driver'; export enum LLMTracingDriver { Langfuse = 'langfuse', diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.constants.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.constants.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.module-factory.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts similarity index 88% rename from packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts index 754158e2a81e..94abe251ebb6 100644 --- a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts @@ -1,6 +1,6 @@ -import { LLMTracingDriver } from 'src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface'; +import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export const llmTracingModuleFactory = ( environmentService: EnvironmentService, diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.module.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module.ts similarity index 75% rename from packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.module.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module.ts index 9e9c452e95ba..045dfbd7c231 100644 --- a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.module.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module.ts @@ -3,12 +3,12 @@ import { Global, DynamicModule } from '@nestjs/common'; import { LLMTracingModuleAsyncOptions, LLMTracingDriver, -} from 'src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface'; +} from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; -import { LangfuseDriver } from 'src/engine/integrations/llm-tracing/drivers/langfuse.driver'; -import { ConsoleDriver } from 'src/engine/integrations/llm-tracing/drivers/console.driver'; -import { LLMTracingService } from 'src/engine/integrations/llm-tracing/llm-tracing.service'; -import { LLM_TRACING_DRIVER } from 'src/engine/integrations/llm-tracing/llm-tracing.constants'; +import { LangfuseDriver } from 'src/engine/core-modules/llm-tracing/drivers/langfuse.driver'; +import { ConsoleDriver } from 'src/engine/core-modules/llm-tracing/drivers/console.driver'; +import { LLMTracingService } from 'src/engine/core-modules/llm-tracing/llm-tracing.service'; +import { LLM_TRACING_DRIVER } from 'src/engine/core-modules/llm-tracing/llm-tracing.constants'; @Global() export class LLMTracingModule { diff --git a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.service.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.service.ts similarity index 78% rename from packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.service.ts rename to packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.service.ts index 6ff2023902d1..87d7624fb081 100644 --- a/packages/twenty-server/src/engine/integrations/llm-tracing/llm-tracing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.service.ts @@ -2,9 +2,9 @@ import { Injectable, Inject } from '@nestjs/common'; import { BaseCallbackHandler } from '@langchain/core/callbacks/base'; -import { LLMTracingDriver } from 'src/engine/integrations/llm-tracing/drivers/interfaces/llm-tracing-driver.interface'; +import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/drivers/interfaces/llm-tracing-driver.interface'; -import { LLM_TRACING_DRIVER } from 'src/engine/integrations/llm-tracing/llm-tracing.constants'; +import { LLM_TRACING_DRIVER } from 'src/engine/core-modules/llm-tracing/llm-tracing.constants'; @Injectable() export class LLMTracingService { diff --git a/packages/twenty-server/src/engine/integrations/logger/__tests__/logger.service.spec.ts b/packages/twenty-server/src/engine/core-modules/logger/__tests__/logger.service.spec.ts similarity index 80% rename from packages/twenty-server/src/engine/integrations/logger/__tests__/logger.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/logger/__tests__/logger.service.spec.ts index b5d6f94c897e..0475f386c386 100644 --- a/packages/twenty-server/src/engine/integrations/logger/__tests__/logger.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/__tests__/logger.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { LOGGER_DRIVER } from 'src/engine/integrations/logger/logger.constants'; -import { LoggerService } from 'src/engine/integrations/logger/logger.service'; +import { LOGGER_DRIVER } from 'src/engine/core-modules/logger/logger.constants'; +import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; describe('LoggerService', () => { let service: LoggerService; diff --git a/packages/twenty-server/src/engine/core-modules/logger/interfaces/index.ts b/packages/twenty-server/src/engine/core-modules/logger/interfaces/index.ts new file mode 100644 index 000000000000..b9de22413558 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/logger/interfaces/index.ts @@ -0,0 +1 @@ +export * from 'src/engine/core-modules/logger/interfaces/logger.interface'; diff --git a/packages/twenty-server/src/engine/integrations/logger/interfaces/logger.interface.ts b/packages/twenty-server/src/engine/core-modules/logger/interfaces/logger.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/logger/interfaces/logger.interface.ts rename to packages/twenty-server/src/engine/core-modules/logger/interfaces/logger.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/logger/logger.constants.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/logger/logger.constants.ts rename to packages/twenty-server/src/engine/core-modules/logger/logger.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/logger/logger.module-definition.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.module-definition.ts similarity index 78% rename from packages/twenty-server/src/engine/integrations/logger/logger.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/logger/logger.module-definition.ts index d896bff74d56..40af6dfdd131 100644 --- a/packages/twenty-server/src/engine/integrations/logger/logger.module-definition.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/logger.module-definition.ts @@ -1,6 +1,6 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; -import { LoggerModuleOptions } from './interfaces'; +import { LoggerModuleOptions } from 'src/engine/core-modules/logger/interfaces'; export const { ConfigurableModuleClass, diff --git a/packages/twenty-server/src/engine/integrations/logger/logger.module-factory.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts similarity index 85% rename from packages/twenty-server/src/engine/integrations/logger/logger.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts index aef0bcd62c82..94b490fdc37c 100644 --- a/packages/twenty-server/src/engine/integrations/logger/logger.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts @@ -1,8 +1,8 @@ -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { LoggerModuleOptions, LoggerDriverType, -} from 'src/engine/integrations/logger/interfaces'; +} from 'src/engine/core-modules/logger/interfaces'; /** * Logger Module factory diff --git a/packages/twenty-server/src/engine/integrations/logger/logger.module.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.module.ts similarity index 83% rename from packages/twenty-server/src/engine/integrations/logger/logger.module.ts rename to packages/twenty-server/src/engine/core-modules/logger/logger.module.ts index 778dbbf54d1a..4822a780b1c4 100644 --- a/packages/twenty-server/src/engine/integrations/logger/logger.module.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/logger.module.ts @@ -1,14 +1,13 @@ import { DynamicModule, Global, ConsoleLogger, Module } from '@nestjs/common'; -import { LoggerDriverType } from 'src/engine/integrations/logger/interfaces'; - -import { LoggerService } from './logger.service'; -import { LOGGER_DRIVER } from './logger.constants'; +import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; +import { LOGGER_DRIVER } from 'src/engine/core-modules/logger/logger.constants'; import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE, -} from './logger.module-definition'; +} from 'src/engine/core-modules/logger/logger.module-definition'; +import { LoggerDriverType } from 'src/engine/core-modules/logger/interfaces'; @Global() @Module({ diff --git a/packages/twenty-server/src/engine/integrations/logger/logger.service.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.service.ts similarity index 93% rename from packages/twenty-server/src/engine/integrations/logger/logger.service.ts rename to packages/twenty-server/src/engine/core-modules/logger/logger.service.ts index 882a53c17ccc..8d363bb325ab 100644 --- a/packages/twenty-server/src/engine/integrations/logger/logger.service.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/logger.service.ts @@ -5,7 +5,7 @@ import { LoggerService as LoggerServiceInterface, } from '@nestjs/common'; -import { LOGGER_DRIVER } from './logger.constants'; +import { LOGGER_DRIVER } from 'src/engine/core-modules/logger/logger.constants'; @Injectable() export class LoggerService implements LoggerServiceInterface { diff --git a/packages/twenty-server/src/engine/integrations/message-queue/decorators/message-queue.decorator.ts b/packages/twenty-server/src/engine/core-modules/message-queue/decorators/message-queue.decorator.ts similarity index 63% rename from packages/twenty-server/src/engine/integrations/message-queue/decorators/message-queue.decorator.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/decorators/message-queue.decorator.ts index 5a275d3d5b82..dd88f4cf6a63 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/decorators/message-queue.decorator.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/decorators/message-queue.decorator.ts @@ -1,7 +1,7 @@ import { Inject } from '@nestjs/common'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { getQueueToken } from 'src/engine/integrations/message-queue/utils/get-queue-token.util'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util'; export const InjectMessageQueue = (queueName: MessageQueue) => { return Inject(getQueueToken(queueName)); diff --git a/packages/twenty-server/src/engine/integrations/message-queue/decorators/process.decorator.ts b/packages/twenty-server/src/engine/core-modules/message-queue/decorators/process.decorator.ts similarity index 90% rename from packages/twenty-server/src/engine/integrations/message-queue/decorators/process.decorator.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/decorators/process.decorator.ts index 214742cb0af0..62ec636ade9a 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/decorators/process.decorator.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/decorators/process.decorator.ts @@ -1,7 +1,7 @@ import { SetMetadata } from '@nestjs/common'; import { isString } from '@nestjs/common/utils/shared.utils'; -import { PROCESS_METADATA } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { PROCESS_METADATA } from 'src/engine/core-modules/message-queue/message-queue.constants'; export interface MessageQueueProcessOptions { jobName: string; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/decorators/processor.decorator.ts b/packages/twenty-server/src/engine/core-modules/message-queue/decorators/processor.decorator.ts similarity index 91% rename from packages/twenty-server/src/engine/integrations/message-queue/decorators/processor.decorator.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/decorators/processor.decorator.ts index a244dc4d14ce..07979b452d3a 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/decorators/processor.decorator.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/decorators/processor.decorator.ts @@ -1,13 +1,13 @@ import { Scope, SetMetadata } from '@nestjs/common'; import { SCOPE_OPTIONS_METADATA } from '@nestjs/common/constants'; -import { MessageQueueWorkerOptions } from 'src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface'; +import { MessageQueueWorkerOptions } from 'src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface'; import { MessageQueue, PROCESSOR_METADATA, WORKER_METADATA, -} from 'src/engine/integrations/message-queue/message-queue.constants'; +} from 'src/engine/core-modules/message-queue/message-queue.constants'; export interface MessageQueueProcessorOptions { /** diff --git a/packages/twenty-server/src/engine/integrations/message-queue/drivers/bullmq.driver.ts b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/bullmq.driver.ts similarity index 87% rename from packages/twenty-server/src/engine/integrations/message-queue/drivers/bullmq.driver.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/drivers/bullmq.driver.ts index c3324a500604..cf4c414c8902 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/drivers/bullmq.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/bullmq.driver.ts @@ -6,13 +6,12 @@ import { JobsOptions, Queue, QueueOptions, Worker } from 'bullmq'; import { QueueCronJobOptions, QueueJobOptions, -} from 'src/engine/integrations/message-queue/drivers/interfaces/job-options.interface'; -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { MessageQueueWorkerOptions } from 'src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface'; +} from 'src/engine/core-modules/message-queue/drivers/interfaces/job-options.interface'; +import { MessageQueueJob } from 'src/engine/core-modules/message-queue/interfaces/message-queue-job.interface'; +import { MessageQueueWorkerOptions } from 'src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface'; +import { MessageQueueDriver } from 'src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; - -import { MessageQueueDriver } from './interfaces/message-queue-driver.interface'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export type BullMQDriverOptions = QueueOptions; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/drivers/interfaces/job-options.interface.ts b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/interfaces/job-options.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/message-queue/drivers/interfaces/job-options.interface.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/drivers/interfaces/job-options.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/message-queue/drivers/interfaces/message-queue-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface.ts similarity index 72% rename from packages/twenty-server/src/engine/integrations/message-queue/drivers/interfaces/message-queue-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface.ts index 1d53837d359a..49647c02141e 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/drivers/interfaces/message-queue-driver.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface.ts @@ -1,11 +1,11 @@ import { QueueCronJobOptions, QueueJobOptions, -} from 'src/engine/integrations/message-queue/drivers/interfaces/job-options.interface'; -import { MessageQueueJobData } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { MessageQueueWorkerOptions } from 'src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface'; +} from 'src/engine/core-modules/message-queue/drivers/interfaces/job-options.interface'; +import { MessageQueueJobData } from 'src/engine/core-modules/message-queue/interfaces/message-queue-job.interface'; +import { MessageQueueWorkerOptions } from 'src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export interface MessageQueueDriver { add<T extends MessageQueueJobData>( diff --git a/packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/pg-boss.driver.ts similarity index 83% rename from packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/drivers/pg-boss.driver.ts index 98631bc88121..341fbc34802b 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/pg-boss.driver.ts @@ -5,13 +5,12 @@ import PgBoss from 'pg-boss'; import { QueueCronJobOptions, QueueJobOptions, -} from 'src/engine/integrations/message-queue/drivers/interfaces/job-options.interface'; -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { MessageQueueWorkerOptions } from 'src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface'; +} from 'src/engine/core-modules/message-queue/drivers/interfaces/job-options.interface'; +import { MessageQueueJob } from 'src/engine/core-modules/message-queue/interfaces/message-queue-job.interface'; +import { MessageQueueWorkerOptions } from 'src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface'; +import { MessageQueueDriver } from 'src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; - -import { MessageQueueDriver } from './interfaces/message-queue-driver.interface'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export type PgBossDriverOptions = PgBoss.ConstructorOptions; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/drivers/sync.driver.ts b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/sync.driver.ts similarity index 86% rename from packages/twenty-server/src/engine/integrations/message-queue/drivers/sync.driver.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/drivers/sync.driver.ts index b65460687c30..1d7db2953aa6 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/drivers/sync.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/drivers/sync.driver.ts @@ -3,11 +3,10 @@ import { Logger } from '@nestjs/common'; import { MessageQueueJobData, MessageQueueJob, -} from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; +} from 'src/engine/core-modules/message-queue/interfaces/message-queue-job.interface'; +import { MessageQueueDriver } from 'src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; - -import { MessageQueueDriver } from './interfaces/message-queue-driver.interface'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export class SyncDriver implements MessageQueueDriver { private readonly logger = new Logger(SyncDriver.name); diff --git a/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/index.ts b/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/index.ts new file mode 100644 index 000000000000..dfeb67000668 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/index.ts @@ -0,0 +1 @@ +export * from 'src/engine/core-modules/message-queue/interfaces/message-queue-module-options.interface'; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-job.interface.ts b/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-job.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-job.interface.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-job.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-module-options.interface.ts b/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-module-options.interface.ts similarity index 83% rename from packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-module-options.interface.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-module-options.interface.ts index b98990385204..55027987a998 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-module-options.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-module-options.interface.ts @@ -1,5 +1,5 @@ -import { BullMQDriverOptions } from 'src/engine/integrations/message-queue/drivers/bullmq.driver'; -import { PgBossDriverOptions } from 'src/engine/integrations/message-queue/drivers/pg-boss.driver'; +import { BullMQDriverOptions } from 'src/engine/core-modules/message-queue/drivers/bullmq.driver'; +import { PgBossDriverOptions } from 'src/engine/core-modules/message-queue/drivers/pg-boss.driver'; export enum MessageQueueDriverType { PgBoss = 'pg-boss', diff --git a/packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface.ts b/packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface.ts diff --git a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts similarity index 93% rename from packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts index 6516455d55b9..71fb7c279e60 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts @@ -6,6 +6,7 @@ import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-dem import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { WorkspaceQueryRunnerJobModule } from 'src/engine/api/graphql/workspace-query-runner/jobs/workspace-query-runner-job.module'; +import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { BillingModule } from 'src/engine/core-modules/billing/billing.module'; import { UpdateSubscriptionJob } from 'src/engine/core-modules/billing/jobs/update-subscription.job'; import { StripeModule } from 'src/engine/core-modules/billing/stripe/stripe.module'; @@ -14,8 +15,8 @@ import { UserModule } from 'src/engine/core-modules/user/user.module'; import { HandleWorkspaceMemberDeletedJob } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; -import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job'; -import { EmailModule } from 'src/engine/integrations/email/email.module'; +import { EmailSenderJob } from 'src/engine/core-modules/email/email-sender.job'; +import { EmailModule } from 'src/engine/core-modules/email/email.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job'; @@ -39,6 +40,7 @@ import { WorkflowModule } from 'src/modules/workflow/workflow.module'; BillingModule, UserWorkspaceModule, WorkspaceModule, + AuthModule, MessagingModule, CalendarModule, CalendarEventParticipantManagerModule, diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue-core.module.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue-core.module.ts similarity index 84% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue-core.module.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue-core.module.ts index 6c785e23529d..fb4b7dd6ccce 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/message-queue-core.module.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue-core.module.ts @@ -6,23 +6,23 @@ import { Provider, } from '@nestjs/common'; -import { MessageQueueDriver } from 'src/engine/integrations/message-queue/drivers/interfaces/message-queue-driver.interface'; +import { MessageQueueDriver } from 'src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface'; -import { MessageQueueDriverType } from 'src/engine/integrations/message-queue/interfaces'; +import { MessageQueueDriverType } from 'src/engine/core-modules/message-queue/interfaces'; import { MessageQueue, QUEUE_DRIVER, -} from 'src/engine/integrations/message-queue/message-queue.constants'; -import { PgBossDriver } from 'src/engine/integrations/message-queue/drivers/pg-boss.driver'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { BullMQDriver } from 'src/engine/integrations/message-queue/drivers/bullmq.driver'; -import { SyncDriver } from 'src/engine/integrations/message-queue/drivers/sync.driver'; -import { getQueueToken } from 'src/engine/integrations/message-queue/utils/get-queue-token.util'; +} from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { PgBossDriver } from 'src/engine/core-modules/message-queue/drivers/pg-boss.driver'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { BullMQDriver } from 'src/engine/core-modules/message-queue/drivers/bullmq.driver'; +import { SyncDriver } from 'src/engine/core-modules/message-queue/drivers/sync.driver'; +import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util'; import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE, -} from 'src/engine/integrations/message-queue/message-queue.module-definition'; +} from 'src/engine/core-modules/message-queue/message-queue.module-definition'; @Global() @Module({}) diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue-metadata.accessor.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue-metadata.accessor.ts similarity index 77% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue-metadata.accessor.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue-metadata.accessor.ts index a63c3f16e567..2dce32e825f2 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/message-queue-metadata.accessor.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue-metadata.accessor.ts @@ -2,12 +2,12 @@ import { Injectable, Type } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; -import { MessageQueueProcessOptions } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { MessageQueueProcessorOptions } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; +import { MessageQueueProcessOptions } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { MessageQueueProcessorOptions } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { PROCESSOR_METADATA, PROCESS_METADATA, -} from 'src/engine/integrations/message-queue/message-queue.constants'; +} from 'src/engine/core-modules/message-queue/message-queue.constants'; @Injectable() export class MessageQueueMetadataAccessor { diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.constants.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue.constants.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.explorer.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.explorer.ts similarity index 91% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue.explorer.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue.explorer.ts index 30e73f6bbc7b..6e20445ebb64 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.explorer.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.explorer.ts @@ -9,19 +9,18 @@ import { Module } from '@nestjs/core/injector/module'; import { Injector } from '@nestjs/core/injector/injector'; import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper'; -import { MessageQueueWorkerOptions } from 'src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface'; +import { MessageQueueWorkerOptions } from 'src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface'; import { MessageQueueJob, MessageQueueJobData, -} from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; +} from 'src/engine/core-modules/message-queue/interfaces/message-queue-job.interface'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { getQueueToken } from 'src/engine/integrations/message-queue/utils/get-queue-token.util'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; +import { MessageQueueMetadataAccessor } from 'src/engine/core-modules/message-queue/message-queue-metadata.accessor'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { shouldFilterException } from 'src/engine/utils/global-exception-handler.util'; -import { MessageQueueMetadataAccessor } from './message-queue-metadata.accessor'; - interface ProcessorGroup { instance: object; host: Module; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.module-definition.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-definition.ts similarity index 80% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-definition.ts index b7a437032f3e..ed24da3171d2 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.module-definition.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-definition.ts @@ -1,6 +1,6 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; -import { MessageQueueModuleOptions } from 'src/engine/integrations/message-queue/interfaces'; +import { MessageQueueModuleOptions } from 'src/engine/core-modules/message-queue/interfaces'; export const { ConfigurableModuleClass, diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.module-factory.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts similarity index 81% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue.module-factory.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts index 671548449f37..ad18f6cd8224 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts @@ -1,8 +1,8 @@ -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { MessageQueueDriverType, MessageQueueModuleOptions, -} from 'src/engine/integrations/message-queue/interfaces'; +} from 'src/engine/core-modules/message-queue/interfaces'; /** * MessageQueue Module factory @@ -34,6 +34,8 @@ export const messageQueueModuleFactory = async ( case MessageQueueDriverType.BullMQ: { const host = environmentService.get('REDIS_HOST'); const port = environmentService.get('REDIS_PORT'); + const username = environmentService.get('REDIS_USERNAME'); + const password = environmentService.get('REDIS_PASSWORD'); return { type: MessageQueueDriverType.BullMQ, @@ -41,6 +43,8 @@ export const messageQueueModuleFactory = async ( connection: { host, port, + username, + password, }, }, }; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.module.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module.ts similarity index 74% rename from packages/twenty-server/src/engine/integrations/message-queue/message-queue.module.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module.ts index ee7fb385b1fb..428be7caab0b 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/message-queue.module.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module.ts @@ -1,13 +1,13 @@ import { DynamicModule, Global, Module } from '@nestjs/common'; import { DiscoveryModule } from '@nestjs/core'; -import { MessageQueueCoreModule } from 'src/engine/integrations/message-queue/message-queue-core.module'; -import { MessageQueueMetadataAccessor } from 'src/engine/integrations/message-queue/message-queue-metadata.accessor'; -import { MessageQueueExplorer } from 'src/engine/integrations/message-queue/message-queue.explorer'; +import { MessageQueueCoreModule } from 'src/engine/core-modules/message-queue/message-queue-core.module'; +import { MessageQueueMetadataAccessor } from 'src/engine/core-modules/message-queue/message-queue-metadata.accessor'; +import { MessageQueueExplorer } from 'src/engine/core-modules/message-queue/message-queue.explorer'; import { ASYNC_OPTIONS_TYPE, OPTIONS_TYPE, -} from 'src/engine/integrations/message-queue/message-queue.module-definition'; +} from 'src/engine/core-modules/message-queue/message-queue.module-definition'; @Global() @Module({}) diff --git a/packages/twenty-server/src/engine/integrations/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts b/packages/twenty-server/src/engine/core-modules/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts similarity index 85% rename from packages/twenty-server/src/engine/integrations/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts index 31e2b66ae978..f579767a0546 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/services/__tests__/message-queue-task-assigned.service.spec.ts @@ -1,12 +1,12 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { MessageQueueDriver } from 'src/engine/integrations/message-queue/drivers/interfaces/message-queue-driver.interface'; +import { MessageQueueDriver } from 'src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface'; import { QUEUE_DRIVER, MessageQueue, -} from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +} from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; describe('MessageQueueTaskAssigned queue', () => { let service: MessageQueueService; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/services/message-queue.service.ts b/packages/twenty-server/src/engine/core-modules/message-queue/services/message-queue.service.ts similarity index 78% rename from packages/twenty-server/src/engine/integrations/message-queue/services/message-queue.service.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/services/message-queue.service.ts index 6460e112d974..2030ca8dd75d 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/services/message-queue.service.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/services/message-queue.service.ts @@ -3,18 +3,18 @@ import { Inject, Injectable } from '@nestjs/common'; import { QueueCronJobOptions, QueueJobOptions, -} from 'src/engine/integrations/message-queue/drivers/interfaces/job-options.interface'; -import { MessageQueueDriver } from 'src/engine/integrations/message-queue/drivers/interfaces/message-queue-driver.interface'; +} from 'src/engine/core-modules/message-queue/drivers/interfaces/job-options.interface'; +import { MessageQueueDriver } from 'src/engine/core-modules/message-queue/drivers/interfaces/message-queue-driver.interface'; import { MessageQueueJobData, MessageQueueJob, -} from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { MessageQueueWorkerOptions } from 'src/engine/integrations/message-queue/interfaces/message-queue-worker-options.interface'; +} from 'src/engine/core-modules/message-queue/interfaces/message-queue-job.interface'; +import { MessageQueueWorkerOptions } from 'src/engine/core-modules/message-queue/interfaces/message-queue-worker-options.interface'; import { MessageQueue, QUEUE_DRIVER, -} from 'src/engine/integrations/message-queue/message-queue.constants'; +} from 'src/engine/core-modules/message-queue/message-queue.constants'; @Injectable() export class MessageQueueService { diff --git a/packages/twenty-server/src/engine/integrations/message-queue/utils/get-queue-token.util.ts b/packages/twenty-server/src/engine/core-modules/message-queue/utils/get-queue-token.util.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/message-queue/utils/get-queue-token.util.ts rename to packages/twenty-server/src/engine/core-modules/message-queue/utils/get-queue-token.util.ts diff --git a/packages/twenty-server/src/engine/core-modules/messaging/dtos/timeline-thread.dto.ts b/packages/twenty-server/src/engine/core-modules/messaging/dtos/timeline-thread.dto.ts index 431f00d5a2ea..779fadb81707 100644 --- a/packages/twenty-server/src/engine/core-modules/messaging/dtos/timeline-thread.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/messaging/dtos/timeline-thread.dto.ts @@ -1,14 +1,9 @@ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; +import { Field, ObjectType } from '@nestjs/graphql'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { TimelineThreadParticipant } from 'src/engine/core-modules/messaging/dtos/timeline-thread-participant.dto'; import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; -registerEnumType(MessageChannelVisibility, { - name: 'MessageChannelVisibility', - description: 'Visibility of the message channel', -}); - @ObjectType('TimelineThread') export class TimelineThread { @Field(() => UUIDScalarType) diff --git a/packages/twenty-server/src/engine/core-modules/messaging/timeline-messaging.resolver.ts b/packages/twenty-server/src/engine/core-modules/messaging/timeline-messaging.resolver.ts index 33a3a3caeba4..e2558e634d7c 100644 --- a/packages/twenty-server/src/engine/core-modules/messaging/timeline-messaging.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/messaging/timeline-messaging.resolver.ts @@ -9,8 +9,11 @@ import { TimelineThreadsWithTotal } from 'src/engine/core-modules/messaging/dtos import { GetMessagesService } from 'src/engine/core-modules/messaging/services/get-messages.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @ArgsType() class GetTimelineThreadsFromPersonIdArgs { @@ -38,7 +41,7 @@ class GetTimelineThreadsFromCompanyIdArgs { pageSize: number; } -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard, UserAuthGuard) @Resolver(() => TimelineThreadsWithTotal) export class TimelineMessagingResolver { constructor( @@ -49,9 +52,13 @@ export class TimelineMessagingResolver { @Query(() => TimelineThreadsWithTotal) async getTimelineThreadsFromPersonId( @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, @Args() { personId, page, pageSize }: GetTimelineThreadsFromPersonIdArgs, ) { - const workspaceMember = await this.userService.loadWorkspaceMember(user); + const workspaceMember = await this.userService.loadWorkspaceMember( + user, + workspace, + ); if (!workspaceMember) { return; @@ -71,9 +78,13 @@ export class TimelineMessagingResolver { @Query(() => TimelineThreadsWithTotal) async getTimelineThreadsFromCompanyId( @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, @Args() { companyId, page, pageSize }: GetTimelineThreadsFromCompanyIdArgs, ) { - const workspaceMember = await this.userService.loadWorkspaceMember(user); + const workspaceMember = await this.userService.loadWorkspaceMember( + user, + workspace, + ); if (!workspaceMember) { return; diff --git a/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.resolver.ts b/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.resolver.ts index fcc0a89a73dd..d61c41472499 100644 --- a/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.resolver.ts @@ -7,9 +7,10 @@ import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard, UserAuthGuard) @Resolver() export class OnboardingResolver { constructor(private readonly onboardingService: OnboardingService) {} diff --git a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts index b2252b0c6810..d4dce437eb5f 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts @@ -1,9 +1,9 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OpenApiService } from 'src/engine/core-modules/open-api/open-api.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; describe('OpenApiService', () => { let service: OpenApiService; diff --git a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts index 0c73f73ae27f..4628fef4f2fb 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts @@ -3,7 +3,8 @@ import { Injectable } from '@nestjs/common'; import { Request } from 'express'; import { OpenAPIV3_1 } from 'openapi-types'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { baseSchema } from 'src/engine/core-modules/open-api/utils/base-schema.utils'; import { computeMetadataSchemaComponents, @@ -22,7 +23,10 @@ import { computeManyResultPath, computeSingleResultPath, } from 'src/engine/core-modules/open-api/utils/path.utils'; -import { getRequestBody } from 'src/engine/core-modules/open-api/utils/request-body.utils'; +import { + getRequestBody, + getUpdateRequestBody, +} from 'src/engine/core-modules/open-api/utils/request-body.utils'; import { getCreateOneResponse201, getDeleteResponse200, @@ -30,7 +34,6 @@ import { getFindOneResponse200, getUpdateOneResponse200, } from 'src/engine/core-modules/open-api/utils/responses.utils'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { capitalize } from 'src/utils/capitalize'; import { getServerUrl } from 'src/utils/get-server-url'; @@ -165,7 +168,7 @@ export class OpenApiService { summary: `Find One ${item.nameSingular}`, parameters: [{ $ref: '#/components/parameters/idPath' }], responses: { - '200': getFindOneResponse200(item, true), + '200': getFindOneResponse200(item), '400': { $ref: '#/components/responses/400' }, '401': { $ref: '#/components/responses/401' }, }, @@ -187,7 +190,7 @@ export class OpenApiService { summary: `Update One ${item.nameSingular}`, operationId: `updateOne${capitalize(item.nameSingular)}`, parameters: [{ $ref: '#/components/parameters/idPath' }], - requestBody: getRequestBody(capitalize(item.nameSingular)), + requestBody: getUpdateRequestBody(capitalize(item.nameSingular)), responses: { '200': getUpdateOneResponse200(item, true), '400': { $ref: '#/components/responses/400' }, diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts index e481a2343859..5c885c312dfc 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts @@ -22,9 +22,6 @@ describe('computeSchemaComponents', () => { ).toEqual({ ObjectName: { type: 'object', - description: undefined, - required: ['fieldNumber'], - example: { fieldNumber: '' }, properties: { fieldUuid: { type: 'string', @@ -36,18 +33,49 @@ describe('computeSchemaComponents', () => { fieldPhone: { type: 'string', }, + fieldPhones: { + properties: { + additionalPhones: { + type: 'object', + }, + primaryPhoneCountryCode: { + type: 'string', + }, + primaryPhoneNumber: { + type: 'string', + }, + }, + type: 'object', + }, fieldEmail: { type: 'string', format: 'email', }, + fieldEmails: { + type: 'object', + properties: { + primaryEmail: { + type: 'string', + }, + additionalEmails: { + type: 'object', + }, + }, + }, fieldDateTime: { type: 'string', - format: 'date', + format: 'date-time', }, fieldDate: { type: 'string', format: 'date', }, + fieldArray: { + items: { + type: 'string', + }, + type: 'array', + }, fieldBoolean: { type: 'boolean', }, @@ -58,21 +86,44 @@ describe('computeSchemaComponents', () => { type: 'number', }, fieldLinks: { + type: 'object', properties: { - primaryLinkLabel: { type: 'string' }, - primaryLinkUrl: { type: 'string' }, - secondaryLinks: { type: 'object' }, + primaryLinkLabel: { + type: 'string', + }, + primaryLinkUrl: { + type: 'string', + }, + secondaryLinks: { + type: 'array', + items: { + type: 'object', + description: 'A secondary link', + properties: { + url: { + type: 'string', + }, + label: { + type: 'string', + }, + }, + }, + }, }, - type: 'object', }, fieldCurrency: { + type: 'object', properties: { - amountMicros: { type: 'number' }, - currencyCode: { type: 'string' }, + amountMicros: { + type: 'number', + }, + currencyCode: { + type: 'string', + }, }, - type: 'object', }, fieldFullName: { + type: 'object', properties: { firstName: { type: 'string', @@ -81,10 +132,10 @@ describe('computeSchemaComponents', () => { type: 'string', }, }, - type: 'object', }, fieldRating: { - type: 'number', + type: 'string', + enum: ['RATING_1', 'RATING_2'], }, fieldSelect: { type: 'string', @@ -98,10 +149,23 @@ describe('computeSchemaComponents', () => { type: 'number', }, fieldAddress: { + type: 'object', properties: { + addressStreet1: { + type: 'string', + }, + addressStreet2: { + type: 'string', + }, addressCity: { type: 'string', }, + addressPostcode: { + type: 'string', + }, + addressState: { + type: 'string', + }, addressCountry: { type: 'string', }, @@ -111,20 +175,189 @@ describe('computeSchemaComponents', () => { addressLng: { type: 'number', }, - addressPostcode: { + }, + }, + fieldRawJson: { + type: 'object', + }, + fieldRichText: { + type: 'string', + }, + fieldActor: { + type: 'object', + properties: { + source: { type: 'string', + enum: [ + 'EMAIL', + 'CALENDAR', + 'WORKFLOW', + 'API', + 'IMPORT', + 'MANUAL', + ], }, - addressState: { + }, + }, + }, + required: ['fieldNumber'], + }, + 'ObjectName for Update': { + type: 'object', + properties: { + fieldUuid: { + type: 'string', + format: 'uuid', + }, + fieldText: { + type: 'string', + }, + fieldPhone: { + type: 'string', + }, + fieldPhones: { + properties: { + additionalPhones: { + type: 'object', + }, + primaryPhoneCountryCode: { + type: 'string', + }, + primaryPhoneNumber: { + type: 'string', + }, + }, + type: 'object', + }, + fieldEmail: { + type: 'string', + format: 'email', + }, + fieldEmails: { + type: 'object', + properties: { + primaryEmail: { type: 'string', }, + additionalEmails: { + type: 'object', + }, + }, + }, + fieldDateTime: { + type: 'string', + format: 'date-time', + }, + fieldDate: { + type: 'string', + format: 'date', + }, + fieldArray: { + items: { + type: 'string', + }, + type: 'array', + }, + fieldBoolean: { + type: 'boolean', + }, + fieldNumber: { + type: 'integer', + }, + fieldNumeric: { + type: 'number', + }, + fieldLinks: { + type: 'object', + properties: { + primaryLinkLabel: { + type: 'string', + }, + primaryLinkUrl: { + type: 'string', + }, + secondaryLinks: { + type: 'array', + items: { + type: 'object', + description: 'A secondary link', + properties: { + url: { + type: 'string', + }, + label: { + type: 'string', + }, + }, + }, + }, + }, + }, + fieldCurrency: { + type: 'object', + properties: { + amountMicros: { + type: 'number', + }, + currencyCode: { + type: 'string', + }, + }, + }, + fieldFullName: { + type: 'object', + properties: { + firstName: { + type: 'string', + }, + lastName: { + type: 'string', + }, + }, + }, + fieldRating: { + type: 'string', + enum: ['RATING_1', 'RATING_2'], + }, + fieldSelect: { + type: 'string', + enum: ['OPTION_1', 'OPTION_2'], + }, + fieldMultiSelect: { + type: 'string', + enum: ['OPTION_1', 'OPTION_2'], + }, + fieldPosition: { + type: 'number', + }, + fieldAddress: { + type: 'object', + properties: { addressStreet1: { type: 'string', }, addressStreet2: { type: 'string', }, + addressCity: { + type: 'string', + }, + addressPostcode: { + type: 'string', + }, + addressState: { + type: 'string', + }, + addressCountry: { + type: 'string', + }, + addressLat: { + type: 'number', + }, + addressLng: { + type: 'number', + }, }, - type: 'object', }, fieldRawJson: { type: 'object', @@ -133,21 +366,56 @@ describe('computeSchemaComponents', () => { type: 'string', }, fieldActor: { + type: 'object', properties: { source: { type: 'string', + enum: [ + 'EMAIL', + 'CALENDAR', + 'WORKFLOW', + 'API', + 'IMPORT', + 'MANUAL', + ], }, - workspaceMemberId: { + }, + }, + }, + }, + 'ObjectName for Response': { + type: 'object', + properties: { + fieldUuid: { + type: 'string', + format: 'uuid', + }, + fieldText: { + type: 'string', + }, + fieldPhone: { + type: 'string', + }, + fieldPhones: { + properties: { + additionalPhones: { + type: 'object', + }, + primaryPhoneCountryCode: { type: 'string', - format: 'uuid', }, - name: { + primaryPhoneNumber: { type: 'string', }, }, type: 'object', }, + fieldEmail: { + type: 'string', + format: 'email', + }, fieldEmails: { + type: 'object', properties: { primaryEmail: { type: 'string', @@ -156,32 +424,158 @@ describe('computeSchemaComponents', () => { type: 'object', }, }, - type: 'object', }, - }, - }, - 'ObjectName with Relations': { - allOf: [ - { - $ref: '#/components/schemas/ObjectName', + fieldDateTime: { + type: 'string', + format: 'date-time', + }, + fieldDate: { + type: 'string', + format: 'date', + }, + fieldArray: { + items: { + type: 'string', + }, + type: 'array', }, - { + fieldBoolean: { + type: 'boolean', + }, + fieldNumber: { + type: 'integer', + }, + fieldNumeric: { + type: 'number', + }, + fieldLinks: { + type: 'object', properties: { - fieldRelation: { + primaryLinkLabel: { + type: 'string', + }, + primaryLinkUrl: { + type: 'string', + }, + secondaryLinks: { type: 'array', items: { - $ref: '#/components/schemas/ToObjectMetadataName', + type: 'object', + description: 'A secondary link', + properties: { + url: { + type: 'string', + }, + label: { + type: 'string', + }, + }, }, }, }, + }, + fieldCurrency: { + type: 'object', + properties: { + amountMicros: { + type: 'number', + }, + currencyCode: { + type: 'string', + }, + }, + }, + fieldFullName: { + type: 'object', + properties: { + firstName: { + type: 'string', + }, + lastName: { + type: 'string', + }, + }, + }, + fieldRating: { + type: 'string', + enum: ['RATING_1', 'RATING_2'], + }, + fieldSelect: { + type: 'string', + enum: ['OPTION_1', 'OPTION_2'], + }, + fieldMultiSelect: { + type: 'string', + enum: ['OPTION_1', 'OPTION_2'], + }, + fieldPosition: { + type: 'number', + }, + fieldAddress: { + type: 'object', + properties: { + addressStreet1: { + type: 'string', + }, + addressStreet2: { + type: 'string', + }, + addressCity: { + type: 'string', + }, + addressPostcode: { + type: 'string', + }, + addressState: { + type: 'string', + }, + addressCountry: { + type: 'string', + }, + addressLat: { + type: 'number', + }, + addressLng: { + type: 'number', + }, + }, + }, + fieldRawJson: { type: 'object', }, - ], - description: undefined, - example: { - fieldNumber: '', + fieldRichText: { + type: 'string', + }, + fieldActor: { + type: 'object', + properties: { + source: { + type: 'string', + enum: [ + 'EMAIL', + 'CALENDAR', + 'WORKFLOW', + 'API', + 'IMPORT', + 'MANUAL', + ], + }, + workspaceMemberId: { + type: 'string', + format: 'uuid', + }, + name: { + type: 'string', + }, + }, + }, + fieldRelation: { + type: 'array', + items: { + $ref: '#/components/schemas/ToObjectMetadataName for Response', + }, + }, }, - required: ['fieldNumber'], }, }); }); diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts index a4f6b6fcc00c..0a15ff0fd1b3 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts @@ -64,7 +64,10 @@ describe('computeParameters', () => { expect(computeDepthParameters()).toEqual({ name: 'depth', in: 'query', - description: 'Limits the depth objects returned.', + description: `Determines the level of nested related objects to include in the response. + - 0: Returns only the primary object's information. + - 1: Returns the primary object along with its directly related objects (with no additional nesting for related objects). + - 2: Returns the primary object, its directly related objects, and the related objects of those related objects.`, required: false, schema: { type: 'integer', diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts index cc5c91065f35..7e34e35a31fe 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/components.utils.ts @@ -1,5 +1,7 @@ import { OpenAPIV3_1 } from 'openapi-types'; +import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface'; + import { computeDepthParameters, computeEndingBeforeParameters, @@ -10,8 +12,12 @@ import { computeStartingAfterParameters, } from 'src/engine/core-modules/open-api/utils/parameters.utils'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { + FieldMetadataEntity, + FieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { capitalize } from 'src/utils/capitalize'; type Property = OpenAPIV3_1.SchemaObject; @@ -20,8 +26,33 @@ type Properties = { [name: string]: Property; }; -const getFieldProperties = (type: FieldMetadataType): Property => { +const isFieldAvailable = (field: FieldMetadataEntity, forResponse: boolean) => { + if (forResponse) { + return true; + } + switch (field.name) { + case 'id': + case 'createdAt': + case 'updatedAt': + case 'deletedAt': + return false; + default: + return true; + } +}; + +const getFieldProperties = ( + type: FieldMetadataType, + propertyName?: string, + options?: FieldMetadataOptions, +): Property => { switch (type) { + case FieldMetadataType.SELECT: + case FieldMetadataType.MULTI_SELECT: + return { + type: 'string', + enum: options?.map((option: { value: string }) => option.value), + }; case FieldMetadataType.UUID: return { type: 'string', format: 'uuid' }; case FieldMetadataType.TEXT: @@ -31,28 +62,55 @@ const getFieldProperties = (type: FieldMetadataType): Property => { case FieldMetadataType.EMAIL: return { type: 'string', format: 'email' }; case FieldMetadataType.DATE_TIME: + return { type: 'string', format: 'date-time' }; case FieldMetadataType.DATE: return { type: 'string', format: 'date' }; case FieldMetadataType.NUMBER: return { type: 'integer' }; - case FieldMetadataType.NUMERIC: case FieldMetadataType.RATING: + return { + type: 'string', + enum: options?.map((option: { value: string }) => option.value), + }; + case FieldMetadataType.NUMERIC: case FieldMetadataType.POSITION: return { type: 'number' }; case FieldMetadataType.BOOLEAN: return { type: 'boolean' }; case FieldMetadataType.RAW_JSON: + if (propertyName === 'secondaryLinks') { + return { + type: 'array', + items: { + type: 'object', + description: `A secondary link`, + properties: { + url: { type: 'string' }, + label: { type: 'string' }, + }, + }, + }; + } + return { type: 'object' }; + default: return { type: 'string' }; } }; -const getSchemaComponentsProperties = ( - item: ObjectMetadataEntity, -): Properties => { +const getSchemaComponentsProperties = ({ + item, + forResponse, +}: { + item: ObjectMetadataEntity; + forResponse: boolean; +}): Properties => { return item.fields.reduce((node, field) => { - if (field.type == FieldMetadataType.RELATION) { + if ( + !isFieldAvailable(field, forResponse) || + field.type === FieldMetadataType.RELATION + ) { return node; } @@ -66,6 +124,20 @@ const getSchemaComponentsProperties = ( enum: field.options.map((option: { value: string }) => option.value), }; break; + case FieldMetadataType.ARRAY: + itemProperty = { + type: 'array', + items: { + type: 'string', + }, + }; + break; + case FieldMetadataType.RATING: + itemProperty = { + type: 'string', + enum: field.options.map((option: { value: string }) => option.value), + }; + break; case FieldMetadataType.LINK: case FieldMetadataType.LINKS: case FieldMetadataType.CURRENCY: @@ -73,12 +145,24 @@ const getSchemaComponentsProperties = ( case FieldMetadataType.ADDRESS: case FieldMetadataType.ACTOR: case FieldMetadataType.EMAILS: + case FieldMetadataType.PHONES: itemProperty = { type: 'object', properties: compositeTypeDefinitions .get(field.type) ?.properties?.reduce((properties, property) => { - properties[property.name] = getFieldProperties(property.type); + if ( + property.hidden === true || + (property.hidden === 'input' && !forResponse) || + (property.hidden === 'output' && forResponse) + ) { + return properties; + } + properties[property.name] = getFieldProperties( + property.type, + property.name, + property.options, + ); return properties; }, {} as Properties), @@ -105,19 +189,21 @@ const getSchemaComponentsRelationProperties = ( item: ObjectMetadataEntity, ): Properties => { return item.fields.reduce((node, field) => { + if (field.type !== FieldMetadataType.RELATION) { + return node; + } + let itemProperty = {} as Property; - if (field.type == FieldMetadataType.RELATION) { - if (field.fromRelationMetadata?.toObjectMetadata.nameSingular) { - itemProperty = { - type: 'array', - items: { - $ref: `#/components/schemas/${capitalize( - field.fromRelationMetadata?.toObjectMetadata.nameSingular || '', - )}`, - }, - }; - } + if (field.fromRelationMetadata?.toObjectMetadata.nameSingular) { + itemProperty = { + type: 'array', + items: { + $ref: `#/components/schemas/${capitalize( + field.fromRelationMetadata?.toObjectMetadata.nameSingular, + )} for Response`, + }, + }; } if (field.description) { @@ -144,62 +230,38 @@ const getRequiredFields = (item: ObjectMetadataEntity): string[] => { }, [] as string[]); }; -const computeSchemaComponent = ( - item: ObjectMetadataEntity, -): OpenAPIV3_1.SchemaObject => { +const computeSchemaComponent = ({ + item, + withRequiredFields, + forResponse, + withRelations, +}: { + item: ObjectMetadataEntity; + withRequiredFields: boolean; + forResponse: boolean; + withRelations: boolean; +}): OpenAPIV3_1.SchemaObject => { const result = { type: 'object', description: item.description, - properties: getSchemaComponentsProperties(item), - example: {}, + properties: getSchemaComponentsProperties({ item, forResponse }), } as OpenAPIV3_1.SchemaObject; - const requiredFields = getRequiredFields(item); - - if (requiredFields?.length) { - result.required = requiredFields; - result.example = requiredFields.reduce( - (example, requiredField) => { - example[requiredField] = ''; - - return example; - }, - {} as Record<string, string>, - ); + if (withRelations) { + result.properties = { + ...result.properties, + ...getSchemaComponentsRelationProperties(item), + }; } - return result; -}; - -const computeRelationSchemaComponent = ( - item: ObjectMetadataEntity, -): OpenAPIV3_1.SchemaObject => { - const result = { - description: item.description, - allOf: [ - { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, - }, - { - type: 'object', - properties: getSchemaComponentsRelationProperties(item), - }, - ], - example: {}, - } as OpenAPIV3_1.SchemaObject; + if (!withRequiredFields) { + return result; + } const requiredFields = getRequiredFields(item); if (requiredFields?.length) { result.required = requiredFields; - result.example = requiredFields.reduce( - (example, requiredField) => { - example[requiredField] = ''; - - return example; - }, - {} as Record<string, string>, - ); } return result; @@ -210,9 +272,26 @@ export const computeSchemaComponents = ( ): Record<string, OpenAPIV3_1.SchemaObject> => { return objectMetadataItems.reduce( (schemas, item) => { - schemas[capitalize(item.nameSingular)] = computeSchemaComponent(item); - schemas[capitalize(item.nameSingular) + ' with Relations'] = - computeRelationSchemaComponent(item); + schemas[capitalize(item.nameSingular)] = computeSchemaComponent({ + item, + withRequiredFields: true, + forResponse: false, + withRelations: false, + }); + schemas[capitalize(item.nameSingular) + ' for Update'] = + computeSchemaComponent({ + item, + withRequiredFields: false, + forResponse: false, + withRelations: false, + }); + schemas[capitalize(item.nameSingular) + ' for Response'] = + computeSchemaComponent({ + item, + withRequiredFields: false, + forResponse: true, + withRelations: true, + }); return schemas; }, @@ -245,21 +324,47 @@ export const computeMetadataSchemaComponents = ( type: 'object', description: `An object`, properties: { - dataSourceId: { type: 'string' }, nameSingular: { type: 'string' }, namePlural: { type: 'string' }, labelSingular: { type: 'string' }, labelPlural: { type: 'string' }, description: { type: 'string' }, icon: { type: 'string' }, + labelIdentifierFieldMetadataId: { + type: 'string', + format: 'uuid', + }, + imageIdentifierFieldMetadataId: { + type: 'string', + format: 'uuid', + }, + }, + }; + schemas[`${capitalize(item.namePlural)}`] = { + type: 'array', + description: `A list of ${item.namePlural}`, + items: { + $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + }, + }; + schemas[`${capitalize(item.nameSingular)} for Update`] = { + type: 'object', + description: `An object`, + properties: { + isActive: { type: 'boolean' }, + }, + }; + schemas[`${capitalize(item.nameSingular)} for Response`] = { + ...schemas[`${capitalize(item.nameSingular)}`], + properties: { + ...schemas[`${capitalize(item.nameSingular)}`].properties, + id: { type: 'string', format: 'uuid' }, + dataSourceId: { type: 'string', format: 'uuid' }, isCustom: { type: 'boolean' }, - isRemote: { type: 'boolean' }, isActive: { type: 'boolean' }, isSystem: { type: 'boolean' }, - createdAt: { type: 'string' }, - updatedAt: { type: 'string' }, - labelIdentifierFieldMetadataId: { type: 'string' }, - imageIdentifierFieldMetadataId: { type: 'string' }, + createdAt: { type: 'string', format: 'date-time' }, + updatedAt: { type: 'string', format: 'date-time' }, fields: { type: 'object', properties: { @@ -269,7 +374,7 @@ export const computeMetadataSchemaComponents = ( node: { type: 'array', items: { - $ref: '#/components/schemas/Field', + $ref: '#/components/schemas/Field for Response', }, }, }, @@ -277,15 +382,13 @@ export const computeMetadataSchemaComponents = ( }, }, }, - example: {}, }; - schemas[`${capitalize(item.namePlural)}`] = { + schemas[`${capitalize(item.namePlural)} for Response`] = { type: 'array', description: `A list of ${item.namePlural}`, items: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + $ref: `#/components/schemas/${capitalize(item.nameSingular)} for Response`, }, - example: [{}], }; return schemas; @@ -295,65 +398,111 @@ export const computeMetadataSchemaComponents = ( type: 'object', description: `A field`, properties: { - type: { type: 'string' }, + type: { + type: 'string', + enum: Object.keys(FieldMetadataType), + }, name: { type: 'string' }, label: { type: 'string' }, description: { type: 'string' }, icon: { type: 'string' }, - isCustom: { type: 'boolean' }, + isNullable: { type: 'boolean' }, + objectMetadataId: { type: 'string', format: 'uuid' }, + }, + }; + schemas[`${capitalize(item.namePlural)}`] = { + type: 'array', + description: `A list of ${item.namePlural}`, + items: { + $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + }, + }; + schemas[`${capitalize(item.nameSingular)} for Update`] = { + type: 'object', + description: `An object`, + properties: { + description: { type: 'string' }, + icon: { type: 'string' }, isActive: { type: 'boolean' }, + isCustom: { type: 'boolean' }, + isNullable: { type: 'boolean' }, isSystem: { type: 'boolean' }, + label: { type: 'string' }, + name: { type: 'string' }, + }, + }; + schemas[`${capitalize(item.nameSingular)} for Response`] = { + ...schemas[`${capitalize(item.nameSingular)}`], + properties: { + type: { + type: 'string', + enum: Object.keys(FieldMetadataType), + }, + name: { type: 'string' }, + label: { type: 'string' }, + description: { type: 'string' }, + icon: { type: 'string' }, isNullable: { type: 'boolean' }, - createdAt: { type: 'string' }, - updatedAt: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + isCustom: { type: 'boolean' }, + isActive: { type: 'boolean' }, + isSystem: { type: 'boolean' }, + defaultValue: { type: 'object' }, + options: { type: 'object' }, + createdAt: { type: 'string', format: 'date-time' }, + updatedAt: { type: 'string', format: 'date-time' }, fromRelationMetadata: { type: 'object', properties: { - id: { type: 'string' }, - relationType: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + relationType: { + type: 'string', + enum: Object.keys(RelationMetadataType), + }, toObjectMetadata: { type: 'object', properties: { - id: { type: 'string' }, - dataSourceId: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + dataSourceId: { type: 'string', format: 'uuid' }, nameSingular: { type: 'string' }, namePlural: { type: 'string' }, isSystem: { type: 'boolean' }, + isRemote: { type: 'boolean' }, }, }, - toFieldMetadataId: { type: 'string' }, + toFieldMetadataId: { type: 'string', format: 'uuid' }, }, }, toRelationMetadata: { type: 'object', properties: { - id: { type: 'string' }, - relationType: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + relationType: { + type: 'string', + enum: Object.keys(RelationMetadataType), + }, fromObjectMetadata: { type: 'object', properties: { - id: { type: 'string' }, - dataSourceId: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + dataSourceId: { type: 'string', format: 'uuid' }, nameSingular: { type: 'string' }, namePlural: { type: 'string' }, isSystem: { type: 'boolean' }, + isRemote: { type: 'boolean' }, }, }, - fromFieldMetadataId: { type: 'string' }, + fromFieldMetadataId: { type: 'string', format: 'uuid' }, }, }, - defaultValue: { type: 'object' }, - options: { type: 'object' }, }, - example: {}, }; - schemas[`${capitalize(item.namePlural)}`] = { + schemas[`${capitalize(item.namePlural)} for Response`] = { type: 'array', description: `A list of ${item.namePlural}`, items: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + $ref: `#/components/schemas/${capitalize(item.nameSingular)} for Response`, }, - example: [{}], }; return schemas; @@ -363,41 +512,65 @@ export const computeMetadataSchemaComponents = ( type: 'object', description: 'A relation', properties: { - relationType: { type: 'string' }, + relationType: { + type: 'string', + enum: Object.keys(RelationMetadataType), + }, + fromObjectMetadataId: { type: 'string', format: 'uuid' }, + toObjectMetadataId: { type: 'string', format: 'uuid' }, + fromName: { type: 'string' }, + fromLabel: { type: 'string' }, + toName: { type: 'string' }, + toLabel: { type: 'string' }, + }, + }; + schemas[`${capitalize(item.namePlural)}`] = { + type: 'array', + description: `A list of ${item.namePlural}`, + items: { + $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + }, + }; + schemas[`${capitalize(item.nameSingular)} for Response`] = { + ...schemas[`${capitalize(item.nameSingular)}`], + properties: { + relationType: { + type: 'string', + enum: Object.keys(RelationMetadataType), + }, + id: { type: 'string', format: 'uuid' }, + fromFieldMetadataId: { type: 'string', format: 'uuid' }, + toFieldMetadataId: { type: 'string', format: 'uuid' }, fromObjectMetadata: { type: 'object', properties: { - id: { type: 'string' }, - dataSourceId: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + dataSourceId: { type: 'string', format: 'uuid' }, nameSingular: { type: 'string' }, namePlural: { type: 'string' }, isSystem: { type: 'boolean' }, + isRemote: { type: 'boolean' }, }, }, - fromObjectMetadataId: { type: 'string' }, toObjectMetadata: { type: 'object', properties: { - id: { type: 'string' }, - dataSourceId: { type: 'string' }, + id: { type: 'string', format: 'uuid' }, + dataSourceId: { type: 'string', format: 'uuid' }, nameSingular: { type: 'string' }, namePlural: { type: 'string' }, isSystem: { type: 'boolean' }, + isRemote: { type: 'boolean' }, }, }, - toObjectMetadataId: { type: 'string' }, - fromFieldMetadataId: { type: 'string' }, - toFieldMetadataId: { type: 'string' }, }, - example: {}, }; - schemas[`${capitalize(item.namePlural)}`] = { + schemas[`${capitalize(item.namePlural)} for Response`] = { type: 'array', description: `A list of ${item.namePlural}`, items: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + $ref: `#/components/schemas/${capitalize(item.nameSingular)} for Response`, }, - example: [{}], }; } } diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/get-error-responses.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/get-error-responses.utils.ts index 13f48a682335..b7026b460ee8 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/get-error-responses.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/get-error-responses.utils.ts @@ -9,7 +9,7 @@ export const get400ErrorResponses = (): OpenAPIV3_1.ResponseObject => { type: 'object', properties: { statusCode: { type: 'number' }, - message: { type: 'string' }, + messages: { type: 'array', items: { type: 'string' } }, error: { type: 'string' }, }, example: { diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts index 954e567e85a6..ca009395f3b4 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts @@ -55,7 +55,10 @@ export const computeDepthParameters = (): OpenAPIV3_1.ParameterObject => { return { name: 'depth', in: 'query', - description: 'Limits the depth objects returned.', + description: `Determines the level of nested related objects to include in the response. + - 0: Returns only the primary object's information. + - 1: Returns the primary object along with its directly related objects (with no additional nesting for related objects). + - 2: Returns the primary object, its directly related objects, and the related objects of those related objects.`, required: false, schema: { type: 'integer', diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts index 8dcf96e09341..87892fa55000 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/path.utils.ts @@ -4,6 +4,7 @@ import { getArrayRequestBody, getFindDuplicatesRequestBody, getRequestBody, + getUpdateRequestBody, } from 'src/engine/core-modules/open-api/utils/request-body.utils'; import { getCreateManyResponse201, @@ -113,7 +114,7 @@ export const computeSingleResultPath = ( { $ref: '#/components/parameters/idPath' }, { $ref: '#/components/parameters/depth' }, ], - requestBody: getRequestBody(capitalize(item.nameSingular)), + requestBody: getUpdateRequestBody(capitalize(item.nameSingular)), responses: { '200': getUpdateOneResponse200(item), '400': { $ref: '#/components/responses/400' }, diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts index 52fa223cb518..e5f46c2b3a44 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/request-body.utils.ts @@ -12,6 +12,20 @@ export const getRequestBody = (name: string) => { }; }; +export const getUpdateRequestBody = (name: string) => { + return { + description: 'body', + required: true, + content: { + 'application/json': { + schema: { + $ref: `#/components/schemas/${name} for Update`, + }, + }, + }, + }; +}; + export const getArrayRequestBody = (name: string) => { return { required: true, @@ -45,10 +59,6 @@ export const getFindDuplicatesRequestBody = (name: string) => { }, ids: { type: 'array', - items: { - type: 'string', - format: 'uuid', - }, }, }, }, diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts index d79c46a84113..1d46a332b287 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/responses.utils.ts @@ -5,6 +5,10 @@ export const getFindManyResponse200 = ( item: Pick<ObjectMetadataEntity, 'nameSingular' | 'namePlural'>, fromMetadata = false, ) => { + const schemaRef = `#/components/schemas/${capitalize( + item.nameSingular, + )} for Response`; + return { description: 'Successful operation', content: { @@ -18,9 +22,7 @@ export const getFindManyResponse200 = ( [item.namePlural]: { type: 'array', items: { - $ref: `#/components/schemas/${capitalize( - item.nameSingular, - )}${!fromMetadata ? ' with Relations' : ''}`, + $ref: schemaRef, }, }, }, @@ -29,8 +31,14 @@ export const getFindManyResponse200 = ( type: 'object', properties: { hasNextPage: { type: 'boolean' }, - startCursor: { type: 'string' }, - endCursor: { type: 'string' }, + startCursor: { + type: 'string', + format: 'uuid', + }, + endCursor: { + type: 'string', + format: 'uuid', + }, }, }, ...(!fromMetadata && { @@ -39,21 +47,6 @@ export const getFindManyResponse200 = ( }, }), }, - example: { - data: { - [item.namePlural]: [ - `${capitalize(item.nameSingular)}Object1`, - `${capitalize(item.nameSingular)}Object2`, - '...', - ], - }, - pageInfo: { - hasNextPage: true, - startCursor: '56f411fb-0900-4ffb-b942-d7e8d6709eff', - endCursor: '93adf3c6-6cf7-4a86-adcd-75f77857ba67', - }, - totalCount: 132, - }, }, }, }, @@ -62,8 +55,9 @@ export const getFindManyResponse200 = ( export const getFindOneResponse200 = ( item: Pick<ObjectMetadataEntity, 'nameSingular'>, - fromMetadata = false, ) => { + const schemaRef = `#/components/schemas/${capitalize(item.nameSingular)} for Response`; + return { description: 'Successful operation', content: { @@ -75,18 +69,11 @@ export const getFindOneResponse200 = ( type: 'object', properties: { [item.nameSingular]: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}${ - !fromMetadata ? ' with Relations' : '' - }`, + $ref: schemaRef, }, }, }, }, - example: { - data: { - [item.nameSingular]: `${capitalize(item.nameSingular)}Object`, - }, - }, }, }, }, @@ -98,6 +85,7 @@ export const getCreateOneResponse201 = ( fromMetadata = false, ) => { const one = fromMetadata ? 'One' : ''; + const schemaRef = `#/components/schemas/${capitalize(item.nameSingular)} for Response`; return { description: 'Successful operation', @@ -110,18 +98,11 @@ export const getCreateOneResponse201 = ( type: 'object', properties: { [`create${one}${capitalize(item.nameSingular)}`]: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + $ref: schemaRef, }, }, }, }, - example: { - data: { - [`create${one}${capitalize(item.nameSingular)}`]: `${capitalize( - item.nameSingular, - )}Object`, - }, - }, }, }, }, @@ -131,6 +112,10 @@ export const getCreateOneResponse201 = ( export const getCreateManyResponse201 = ( item: Pick<ObjectMetadataEntity, 'nameSingular' | 'namePlural'>, ) => { + const schemaRef = `#/components/schemas/${capitalize( + item.nameSingular, + )} for Response`; + return { description: 'Successful operation', content: { @@ -144,23 +129,12 @@ export const getCreateManyResponse201 = ( [`create${capitalize(item.namePlural)}`]: { type: 'array', items: { - $ref: `#/components/schemas/${capitalize( - item.nameSingular, - )}`, + $ref: schemaRef, }, }, }, }, }, - example: { - data: { - [`create${capitalize(item.namePlural)}`]: [ - `${capitalize(item.nameSingular)}Object1`, - `${capitalize(item.nameSingular)}Object2`, - '...', - ], - }, - }, }, }, }, @@ -172,6 +146,7 @@ export const getUpdateOneResponse200 = ( fromMetadata = false, ) => { const one = fromMetadata ? 'One' : ''; + const schemaRef = `#/components/schemas/${capitalize(item.nameSingular)} for Response`; return { description: 'Successful operation', @@ -184,18 +159,11 @@ export const getUpdateOneResponse200 = ( type: 'object', properties: { [`update${one}${capitalize(item.nameSingular)}`]: { - $ref: `#/components/schemas/${capitalize(item.nameSingular)}`, + $ref: schemaRef, }, }, }, }, - example: { - data: { - [`update${one}${capitalize(item.nameSingular)}`]: `${capitalize( - item.nameSingular, - )}Object`, - }, - }, }, }, }, @@ -230,13 +198,6 @@ export const getDeleteResponse200 = ( }, }, }, - example: { - data: { - [`delete${one}${capitalize(item.nameSingular)}`]: { - id: 'ffe75ac3-9786-4846-b56f-640685c3631e', - }, - }, - }, }, }, }, @@ -302,6 +263,10 @@ export const getJsonResponse = () => { export const getFindDuplicatesResponse200 = ( item: Pick<ObjectMetadataEntity, 'nameSingular'>, ) => { + const schemaRef = `#/components/schemas/${capitalize( + item.nameSingular, + )} for Response`; + return { description: 'Successful operation', content: { @@ -319,16 +284,20 @@ export const getFindDuplicatesResponse200 = ( type: 'object', properties: { hasNextPage: { type: 'boolean' }, - startCursor: { type: 'string' }, - endCursor: { type: 'string' }, + startCursor: { + type: 'string', + format: 'uuid', + }, + endCursor: { + type: 'string', + format: 'uuid', + }, }, }, companyDuplicates: { type: 'array', items: { - $ref: `#/components/schemas/${capitalize( - item.nameSingular, - )}`, + $ref: schemaRef, }, }, }, diff --git a/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.module.ts b/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.module.ts index fcb2bbdd4606..9034a9a1bfb3 100644 --- a/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.module.ts +++ b/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.module.ts @@ -4,7 +4,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity'; import { PostgresCredentialsResolver } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.resolver'; import { PostgresCredentialsService } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.service'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; @Module({ imports: [ diff --git a/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.resolver.ts b/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.resolver.ts index 2dece160639e..b8a6499ec457 100644 --- a/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.resolver.ts @@ -1,11 +1,11 @@ import { UseGuards } from '@nestjs/common'; -import { Resolver, Mutation, Query } from '@nestjs/graphql'; +import { Mutation, Query, Resolver } from '@nestjs/graphql'; import { PostgresCredentialsDTO } from 'src/engine/core-modules/postgres-credentials/dtos/postgres-credentials.dto'; import { PostgresCredentialsService } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; @Resolver(() => PostgresCredentialsDTO) export class PostgresCredentialsResolver { @@ -13,19 +13,19 @@ export class PostgresCredentialsResolver { private readonly postgresCredentialsService: PostgresCredentialsService, ) {} - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard) @Mutation(() => PostgresCredentialsDTO) async enablePostgresProxy(@AuthWorkspace() { id: workspaceId }: Workspace) { return this.postgresCredentialsService.enablePostgresProxy(workspaceId); } - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard) @Mutation(() => PostgresCredentialsDTO) async disablePostgresProxy(@AuthWorkspace() { id: workspaceId }: Workspace) { return this.postgresCredentialsService.disablePostgresProxy(workspaceId); } - @UseGuards(JwtAuthGuard) + @UseGuards(WorkspaceAuthGuard) @Query(() => PostgresCredentialsDTO, { nullable: true }) async getPostgresCredentials( @AuthWorkspace() { id: workspaceId }: Workspace, diff --git a/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.service.ts b/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.service.ts index 790c36ab266e..de8e78244d37 100644 --- a/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.service.ts +++ b/packages/twenty-server/src/engine/core-modules/postgres-credentials/postgres-credentials.service.ts @@ -12,7 +12,7 @@ import { import { NotFoundError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { PostgresCredentialsDTO } from 'src/engine/core-modules/postgres-credentials/dtos/postgres-credentials.dto'; import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; export class PostgresCredentialsService { constructor( diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/base-serverless.driver.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/base-serverless.driver.ts similarity index 71% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/base-serverless.driver.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/base-serverless.driver.ts index bce3c8e42d13..e7abc6743302 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/drivers/base-serverless.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/base-serverless.driver.ts @@ -1,9 +1,9 @@ -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; -import { readFileContent } from 'src/engine/integrations/file-storage/utils/read-file-content'; -import { SOURCE_FILE_NAME } from 'src/engine/integrations/serverless/drivers/constants/source-file-name'; -import { compileTypescript } from 'src/engine/integrations/serverless/drivers/utils/compile-typescript'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { readFileContent } from 'src/engine/core-modules/file-storage/utils/read-file-content'; +import { SOURCE_FILE_NAME } from 'src/engine/core-modules/serverless/drivers/constants/source-file-name'; +import { compileTypescript } from 'src/engine/core-modules/serverless/drivers/utils/compile-typescript'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; -import { getServerlessFolder } from 'src/engine/integrations/serverless/utils/serverless-get-folder.utils'; +import { getServerlessFolder } from 'src/engine/core-modules/serverless/utils/serverless-get-folder.utils'; export class BaseServerlessDriver { async getCompiledCode( diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/constants/build-file-name.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/build-file-name.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/constants/build-file-name.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/build-file-name.ts diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/common-layer-name.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/common-layer-name.ts new file mode 100644 index 000000000000..28629ed5ccbf --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/common-layer-name.ts @@ -0,0 +1 @@ +export const COMMON_LAYER_NAME = 'common-layer'; diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/serverless-tmpdir-folder.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/serverless-tmpdir-folder.ts new file mode 100644 index 000000000000..0cd4a79cda32 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/serverless-tmpdir-folder.ts @@ -0,0 +1,4 @@ +import { join } from 'path'; +import { tmpdir } from 'os'; + +export const SERVERLESS_TMPDIR_FOLDER = join(tmpdir(), 'serverless-tmpdir'); diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/constants/source-file-name.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/source-file-name.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/constants/source-file-name.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/constants/source-file-name.ts diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface.ts similarity index 96% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface.ts index 549289707fb9..0be7f3cb5b0a 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface.ts @@ -23,7 +23,7 @@ export interface ServerlessDriver { publish(serverlessFunction: ServerlessFunctionEntity): Promise<string>; execute( serverlessFunction: ServerlessFunctionEntity, - payload: object | undefined, + payload: object, version: string, ): Promise<ServerlessExecuteResult>; } diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/lambda.driver.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts similarity index 60% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/lambda.driver.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts index 8d48fe7489cc..9903309660d5 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/drivers/lambda.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/lambda.driver.ts @@ -1,17 +1,23 @@ -import fs from 'fs'; +import * as fs from 'fs/promises'; +import { join } from 'path'; import { CreateFunctionCommand, DeleteFunctionCommand, GetFunctionCommand, InvokeCommand, + InvokeCommandInput, Lambda, LambdaClientConfig, + PublishLayerVersionCommand, + PublishLayerVersionCommandInput, PublishVersionCommand, PublishVersionCommandInput, ResourceNotFoundException, UpdateFunctionCodeCommand, waitUntilFunctionUpdatedV2, + ListLayerVersionsCommandInput, + ListLayerVersionsCommand, } from '@aws-sdk/client-lambda'; import { CreateFunctionCommandInput } from '@aws-sdk/client-lambda/dist-types/commands/CreateFunctionCommand'; import { UpdateFunctionCodeCommandInput } from '@aws-sdk/client-lambda/dist-types/commands/UpdateFunctionCodeCommand'; @@ -19,22 +25,30 @@ import { UpdateFunctionCodeCommandInput } from '@aws-sdk/client-lambda/dist-type import { ServerlessDriver, ServerlessExecuteResult, -} from 'src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface'; +} from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; -import { BaseServerlessDriver } from 'src/engine/integrations/serverless/drivers/base-serverless.driver'; -import { BuildDirectoryManagerService } from 'src/engine/integrations/serverless/drivers/services/build-directory-manager.service'; -import { createZipFile } from 'src/engine/integrations/serverless/drivers/utils/create-zip-file'; +import { + ServerlessFunctionEntity, + ServerlessFunctionRuntime, +} from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { + LambdaBuildDirectoryManager, + NODE_LAYER_SUBFOLDER, +} from 'src/engine/core-modules/serverless/drivers/utils/lambda-build-directory-manager'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { BaseServerlessDriver } from 'src/engine/core-modules/serverless/drivers/base-serverless.driver'; +import { createZipFile } from 'src/engine/core-modules/serverless/drivers/utils/create-zip-file'; import { ServerlessFunctionExecutionStatus } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function-execution-result.dto'; -import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; import { ServerlessFunctionException, ServerlessFunctionExceptionCode, } from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; +import { isDefined } from 'src/utils/is-defined'; +import { COMMON_LAYER_NAME } from 'src/engine/core-modules/serverless/drivers/constants/common-layer-name'; +import { copyAndBuildDependencies } from 'src/engine/core-modules/serverless/drivers/utils/copy-and-build-dependencies'; export interface LambdaDriverOptions extends LambdaClientConfig { fileStorageService: FileStorageService; - buildDirectoryManagerService: BuildDirectoryManagerService; region: string; role: string; } @@ -46,7 +60,6 @@ export class LambdaDriver private readonly lambdaClient: Lambda; private readonly lambdaRole: string; private readonly fileStorageService: FileStorageService; - private readonly buildDirectoryManagerService: BuildDirectoryManagerService; constructor(options: LambdaDriverOptions) { super(); @@ -55,7 +68,70 @@ export class LambdaDriver this.lambdaClient = new Lambda({ ...lambdaOptions, region }); this.lambdaRole = role; this.fileStorageService = options.fileStorageService; - this.buildDirectoryManagerService = options.buildDirectoryManagerService; + } + + private async waitFunctionUpdates( + serverlessFunctionId: string, + maxWaitTime: number, + ) { + const waitParams = { FunctionName: serverlessFunctionId }; + + await waitUntilFunctionUpdatedV2( + { client: this.lambdaClient, maxWaitTime }, + waitParams, + ); + } + + private async createLayerIfNotExists(version: number): Promise<string> { + const listLayerParams: ListLayerVersionsCommandInput = { + LayerName: COMMON_LAYER_NAME, + MaxItems: 1, + }; + const listLayerCommand = new ListLayerVersionsCommand(listLayerParams); + const listLayerResult = await this.lambdaClient.send(listLayerCommand); + + if ( + isDefined(listLayerResult.LayerVersions) && + listLayerResult.LayerVersions.length > 0 && + listLayerResult.LayerVersions?.[0].Description === `${version}` && + isDefined(listLayerResult.LayerVersions[0].LayerVersionArn) + ) { + return listLayerResult.LayerVersions[0].LayerVersionArn; + } + + const lambdaBuildDirectoryManager = new LambdaBuildDirectoryManager(); + const { sourceTemporaryDir, lambdaZipPath } = + await lambdaBuildDirectoryManager.init(); + + const nodeDependenciesFolder = join( + sourceTemporaryDir, + NODE_LAYER_SUBFOLDER, + ); + + await copyAndBuildDependencies(nodeDependenciesFolder); + + await createZipFile(sourceTemporaryDir, lambdaZipPath); + + const params: PublishLayerVersionCommandInput = { + LayerName: COMMON_LAYER_NAME, + Content: { + ZipFile: await fs.readFile(lambdaZipPath), + }, + CompatibleRuntimes: [ServerlessFunctionRuntime.NODE18], + Description: `${version}`, + }; + + const command = new PublishLayerVersionCommand(params); + + const result = await this.lambdaClient.send(command); + + await lambdaBuildDirectoryManager.clean(); + + if (!isDefined(result.LayerVersionArn)) { + throw new Error('new layer version arn si undefined'); + } + + return result.LayerVersionArn; } private async checkFunctionExists(functionName: string): Promise<boolean> { @@ -95,14 +171,16 @@ export class LambdaDriver this.fileStorageService, ); + const lambdaBuildDirectoryManager = new LambdaBuildDirectoryManager(); + const { sourceTemporaryDir, lambdaZipPath, javascriptFilePath, lambdaHandler, - } = await this.buildDirectoryManagerService.init(); + } = await lambdaBuildDirectoryManager.init(); - await fs.promises.writeFile(javascriptFilePath, javascriptCode); + await fs.writeFile(javascriptFilePath, javascriptCode); await createZipFile(sourceTemporaryDir, lambdaZipPath); @@ -111,12 +189,17 @@ export class LambdaDriver ); if (!functionExists) { + const layerArn = await this.createLayerIfNotExists( + serverlessFunction.layerVersion, + ); + const params: CreateFunctionCommandInput = { Code: { - ZipFile: await fs.promises.readFile(lambdaZipPath), + ZipFile: await fs.readFile(lambdaZipPath), }, FunctionName: serverlessFunction.id, Handler: lambdaHandler, + Layers: [layerArn], Role: this.lambdaRole, Runtime: serverlessFunction.runtime, Description: 'Lambda function to run user script', @@ -128,7 +211,7 @@ export class LambdaDriver await this.lambdaClient.send(command); } else { const params: UpdateFunctionCodeCommandInput = { - ZipFile: await fs.promises.readFile(lambdaZipPath), + ZipFile: await fs.readFile(lambdaZipPath), FunctionName: serverlessFunction.id, }; @@ -137,14 +220,9 @@ export class LambdaDriver await this.lambdaClient.send(command); } - const waitParams = { FunctionName: serverlessFunction.id }; + await this.waitFunctionUpdates(serverlessFunction.id, 10); - await waitUntilFunctionUpdatedV2( - { client: this.lambdaClient, maxWaitTime: 5 }, - waitParams, - ); - - await this.buildDirectoryManagerService.clean(); + await lambdaBuildDirectoryManager.clean(); } async publish(serverlessFunction: ServerlessFunctionEntity) { @@ -167,7 +245,7 @@ export class LambdaDriver async execute( functionToExecute: ServerlessFunctionEntity, - payload: object | undefined = undefined, + payload: object, version: string, ): Promise<ServerlessExecuteResult> { const computedVersion = @@ -177,8 +255,11 @@ export class LambdaDriver computedVersion === 'draft' ? functionToExecute.id : `${functionToExecute.id}:${computedVersion}`; + + await this.waitFunctionUpdates(functionToExecute.id, 10); + const startTime = Date.now(); - const params = { + const params: InvokeCommandInput = { FunctionName: functionName, Payload: JSON.stringify(payload), }; diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/package.json b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/package.json new file mode 100644 index 000000000000..c171130b6f4d --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/package.json @@ -0,0 +1,48 @@ +{ + "dependencies": { + "@types/bcrypt": "^5.0.2", + "@types/deep-equal": "^1.0.4", + "@types/lodash.camelcase": "^4.3.9", + "@types/lodash.compact": "^3.0.9", + "@types/lodash.debounce": "^4.0.9", + "@types/lodash.groupby": "^4.6.9", + "@types/lodash.identity": "^3.0.9", + "@types/lodash.isempty": "^4.4.9", + "@types/lodash.isequal": "^4.5.8", + "@types/lodash.isobject": "^3.0.9", + "@types/lodash.kebabcase": "^4.1.9", + "@types/lodash.mapvalues": "^4.6.9", + "@types/lodash.omit": "^4.5.9", + "@types/lodash.pickby": "^4.6.9", + "@types/lodash.snakecase": "^4.1.9", + "@types/lodash.upperfirst": "^4.3.9", + "@types/uuid": "^10.0.0", + "archiver": "^7.0.1", + "axios": "^1.7.5", + "bcrypt": "^5.1.1", + "body-parser": "^1.20.2", + "deep-equal": "^2.2.3", + "jsonwebtoken": "^9.0.2", + "lodash.camelcase": "^4.3.0", + "lodash.chunk": "^4.2.0", + "lodash.compact": "^3.0.1", + "lodash.debounce": "^4.0.8", + "lodash.groupby": "^4.6.0", + "lodash.identity": "^3.0.0", + "lodash.isempty": "^4.4.0", + "lodash.isequal": "^4.5.0", + "lodash.isobject": "^3.0.2", + "lodash.kebabcase": "^4.1.1", + "lodash.mapvalues": "^4.6.0", + "lodash.merge": "^4.6.2", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "lodash.pickby": "^4.6.0", + "lodash.snakecase": "^4.1.1", + "lodash.upperfirst": "^4.3.1", + "nodemailer": "^6.9.14", + "sharp": "^0.33.5", + "uuid": "^10.0.0", + "winston": "^3.14.2" + } +} diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/yarn.lock b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/yarn.lock new file mode 100644 index 000000000000..d4fb8f9fc43d --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/1/yarn.lock @@ -0,0 +1,3211 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@colors/colors@npm:1.6.0, @colors/colors@npm:^1.6.0": + version: 1.6.0 + resolution: "@colors/colors@npm:1.6.0" + checksum: 10c0/9328a0778a5b0db243af54455b79a69e3fb21122d6c15ef9e9fcc94881d8d17352d8b2b2590f9bdd46fac5c2d6c1636dcfc14358a20c70e22daf89e1a759b629 + languageName: node + linkType: hard + +"@dabh/diagnostics@npm:^2.0.2": + version: 2.0.3 + resolution: "@dabh/diagnostics@npm:2.0.3" + dependencies: + colorspace: "npm:1.1.x" + enabled: "npm:2.0.x" + kuler: "npm:^2.0.0" + checksum: 10c0/a5133df8492802465ed01f2f0a5784585241a1030c362d54a602ed1839816d6c93d71dde05cf2ddb4fd0796238c19774406bd62fa2564b637907b495f52425fe + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.2.0": + version: 1.2.0 + resolution: "@emnapi/runtime@npm:1.2.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/7005ff8b67724c9e61b6cd79a3decbdb2ce25d24abd4d3d187472f200ee6e573329c30264335125fb136bd813aa9cf9f4f7c9391d04b07dd1e63ce0a3427be57 + languageName: node + linkType: hard + +"@img/sharp-darwin-arm64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-darwin-arm64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-darwin-arm64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-arm64": + optional: true + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-darwin-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-darwin-x64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-darwin-x64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-x64": + optional: true + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-arm64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-darwin-arm64@npm:1.0.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-x64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-darwin-x64@npm:1.0.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linux-arm64@npm:1.0.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm@npm:1.0.5": + version: 1.0.5 + resolution: "@img/sharp-libvips-linux-arm@npm:1.0.5" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-s390x@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linux-s390x@npm:1.0.4" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-x64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linux-x64@npm:1.0.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-arm64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.0.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-x64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.0.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linux-arm64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-arm64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-arm64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linux-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-arm@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-arm@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-arm": "npm:1.0.5" + dependenciesMeta: + "@img/sharp-libvips-linux-arm": + optional: true + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-s390x@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-s390x@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-s390x": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linux-s390x": + optional: true + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-x64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-x64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linux-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-arm64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linuxmusl-arm64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linuxmusl-x64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linuxmusl-x64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-wasm32@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-wasm32@npm:0.33.5" + dependencies: + "@emnapi/runtime": "npm:^1.2.0" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@img/sharp-win32-ia32@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-win32-ia32@npm:0.33.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@img/sharp-win32-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-win32-x64@npm:0.33.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@mapbox/node-pre-gyp@npm:^1.0.11": + version: 1.0.11 + resolution: "@mapbox/node-pre-gyp@npm:1.0.11" + dependencies: + detect-libc: "npm:^2.0.0" + https-proxy-agent: "npm:^5.0.0" + make-dir: "npm:^3.1.0" + node-fetch: "npm:^2.6.7" + nopt: "npm:^5.0.0" + npmlog: "npm:^5.0.1" + rimraf: "npm:^3.0.2" + semver: "npm:^7.3.5" + tar: "npm:^6.1.11" + bin: + node-pre-gyp: bin/node-pre-gyp + checksum: 10c0/2b24b93c31beca1c91336fa3b3769fda98e202fb7f9771f0f4062588d36dcc30fcf8118c36aa747fa7f7610d8cf601872bdaaf62ce7822bb08b545d1bbe086cc + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@types/bcrypt@npm:^5.0.2": + version: 5.0.2 + resolution: "@types/bcrypt@npm:5.0.2" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/dd7f05e183b9b1fc08ec499069febf197ab8e9c720766b5bbb5628395082e248f9a444c60882fe7788361fcadc302e21e055ab9c26a300f100e08791c353e6aa + languageName: node + linkType: hard + +"@types/deep-equal@npm:^1.0.4": + version: 1.0.4 + resolution: "@types/deep-equal@npm:1.0.4" + checksum: 10c0/583d41df5d7655b0bd5fdd4b173b045396108fad2191e1bd3b1bfc188f98d24fafff34a8a09c04f9c650c87d82e9f25a8119d269044522da0770a05075fbf74d + languageName: node + linkType: hard + +"@types/lodash.camelcase@npm:^4.3.9": + version: 4.3.9 + resolution: "@types/lodash.camelcase@npm:4.3.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/d6c42c800624b75b079ff7862d258d7c8236837f8485a4fe9f92e5e7d3e9ccaef2eb202e24e8f04d209ad5573c85edc7871d0cecc831454a501d594b11f1311b + languageName: node + linkType: hard + +"@types/lodash.compact@npm:^3.0.9": + version: 3.0.9 + resolution: "@types/lodash.compact@npm:3.0.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/9eff2fecd6773352f5b762a2c58f261e3c83f61d7297efe94b08f9a4b524b24ccc2de5e8d728e2ffd42472fa06973df0856e474eb74b5e614813d26d7436efc6 + languageName: node + linkType: hard + +"@types/lodash.debounce@npm:^4.0.9": + version: 4.0.9 + resolution: "@types/lodash.debounce@npm:4.0.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/9fbb24e5e52616faf60ba5c82d8c6517f4b86fc6e9ab353b4c56c0760f63d9bf53af3f2d8f6c37efa48090359fb96dba1087d497758511f6c40677002191d042 + languageName: node + linkType: hard + +"@types/lodash.groupby@npm:^4.6.9": + version: 4.6.9 + resolution: "@types/lodash.groupby@npm:4.6.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/1302531f76da99cc8f1bbd486a8c7048a833352b12c39eb5b2ded01173dd5fff76f2c7ace04f08b51c55840271170f1cfbffe4e454dde8597c3ee996e70d4e11 + languageName: node + linkType: hard + +"@types/lodash.identity@npm:^3.0.9": + version: 3.0.9 + resolution: "@types/lodash.identity@npm:3.0.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/fac961d04fe704b04bef608e9bffd8c7ea44d1d6f014c01ff520cd63e22fa58aa843d2017c18e31bcf21b35124b9c5c7dbf12b33362020d15f5c0591ff4cbc19 + languageName: node + linkType: hard + +"@types/lodash.isempty@npm:^4.4.9": + version: 4.4.9 + resolution: "@types/lodash.isempty@npm:4.4.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/581b3b1e896524b00cb32dc08f1aea328cec0ab95720f24e0f6d9e8a2c9be5b65e4ad030ec45f58f656ab8dcf555f039863862e04c91051a24ee27cac8a994ab + languageName: node + linkType: hard + +"@types/lodash.isequal@npm:^4.5.8": + version: 4.5.8 + resolution: "@types/lodash.isequal@npm:4.5.8" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/6db28cacf165d55421fbf2970ccfb1682a7b82b743bb7aba4398fa8ab98f1711fca2fe4afa1aa2b7b4afb3eff76c8aca13b22206f5efeb038d99e41300589bca + languageName: node + linkType: hard + +"@types/lodash.isobject@npm:^3.0.9": + version: 3.0.9 + resolution: "@types/lodash.isobject@npm:3.0.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/ab35ebaf0e53bce9f419194e8857da01a0f4ed668b2a61860f724e6ecedaad72bfe636bd6d98f9969cadf654595e317d19f7ba05cc3dfbea49966feb71ab687a + languageName: node + linkType: hard + +"@types/lodash.kebabcase@npm:^4.1.9": + version: 4.1.9 + resolution: "@types/lodash.kebabcase@npm:4.1.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/f00fbfb891fd1883e3fab2286fa2b23a013550b3498013c8c8c5e3ed437f52543afe8e8dc899b4f3317bab8db403bb281de863274a6fa12f088667378fd7b475 + languageName: node + linkType: hard + +"@types/lodash.mapvalues@npm:^4.6.9": + version: 4.6.9 + resolution: "@types/lodash.mapvalues@npm:4.6.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/09216965c2c64854c8c765f38f436333e931b98638a0b9d996bda7b6d538593a4cfe53cad7415d50593be48d76798763b97dc2d7925ab200dce1fa5b630ed3b4 + languageName: node + linkType: hard + +"@types/lodash.omit@npm:^4.5.9": + version: 4.5.9 + resolution: "@types/lodash.omit@npm:4.5.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/3b60c8ee8e9a691392d9a3ceabb32c85f888784bd3307eac3de01aeb7ff37383dc8899f027fe852641f5e0f56158fb19785cc3d20a4922e85b5810f14cba23f6 + languageName: node + linkType: hard + +"@types/lodash.pickby@npm:^4.6.9": + version: 4.6.9 + resolution: "@types/lodash.pickby@npm:4.6.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/a572e22a24f73e9041e1beca8bb8125875734471c440f7fe9ff48ced10e6ffe45a2392098940f4c1327252e3455afd0e2ea0cc3908a2e3bd0bafe60335e27e6c + languageName: node + linkType: hard + +"@types/lodash.snakecase@npm:^4.1.9": + version: 4.1.9 + resolution: "@types/lodash.snakecase@npm:4.1.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/69c565f5d914628314de307ac30bcaf6060d2a1e782e87bc25a9c0d287ad06a29cc9308af285ea49e485dba3d909d4fc3b0a0b279cf7545492b37926f1fb2f8f + languageName: node + linkType: hard + +"@types/lodash.upperfirst@npm:^4.3.9": + version: 4.3.9 + resolution: "@types/lodash.upperfirst@npm:4.3.9" + dependencies: + "@types/lodash": "npm:*" + checksum: 10c0/4f6be2e9d4b03a0739972fce3044c28bdf7fd96d5a3c773464f7b8e035d687e46878ad9b958a2fac448807636c0675962e3fbedf20af4fc74bc91bbaf471114f + languageName: node + linkType: hard + +"@types/lodash@npm:*": + version: 4.17.7 + resolution: "@types/lodash@npm:4.17.7" + checksum: 10c0/40c965b5ffdcf7ff5c9105307ee08b782da228c01b5c0529122c554c64f6b7168fc8f11dc79aa7bae4e67e17efafaba685dc3a47e294dbf52a65ed2b67100561 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 22.5.1 + resolution: "@types/node@npm:22.5.1" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 10c0/35373176d8a1d4e16004a1ed303e68d39e4c6341024dc056f2577982df98c1a045a6b677f12ed557796f09bbf7d621f428f6874cc37ed28f7b336fa604b5f6a6 + languageName: node + linkType: hard + +"@types/triple-beam@npm:^1.3.2": + version: 1.3.5 + resolution: "@types/triple-beam@npm:1.3.5" + checksum: 10c0/d5d7f25da612f6d79266f4f1bb9c1ef8f1684e9f60abab251e1261170631062b656ba26ff22631f2760caeafd372abc41e64867cde27fba54fafb73a35b9056a + languageName: node + linkType: hard + +"@types/uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "@types/uuid@npm:10.0.0" + checksum: 10c0/9a1404bf287164481cb9b97f6bb638f78f955be57c40c6513b7655160beb29df6f84c915aaf4089a1559c216557dc4d2f79b48d978742d3ae10b937420ddac60 + languageName: node + linkType: hard + +"abbrev@npm:1": + version: 1.1.1 + resolution: "abbrev@npm:1.1.1" + checksum: 10c0/3f762677702acb24f65e813070e306c61fafe25d4b2583f9dfc935131f774863f3addd5741572ed576bd69cabe473c5af18e1e108b829cb7b6b4747884f726e6 + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 + languageName: node + linkType: hard + +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: "npm:^5.0.0" + checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5 + languageName: node + linkType: hard + +"agent-base@npm:6": + version: 6.0.2 + resolution: "agent-base@npm:6.0.2" + dependencies: + debug: "npm:4" + checksum: 10c0/dc4f757e40b5f3e3d674bc9beb4f1048f4ee83af189bae39be99f57bf1f48dde166a8b0a5342a84b5944ee8e6ed1e5a9d801858f4ad44764e84957122fe46261 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: "npm:^4.3.4" + checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c + languageName: node + linkType: hard + +"aproba@npm:^1.0.3 || ^2.0.0": + version: 2.0.0 + resolution: "aproba@npm:2.0.0" + checksum: 10c0/d06e26384a8f6245d8c8896e138c0388824e259a329e0c9f196b4fa533c82502a6fd449586e3604950a0c42921832a458bb3aa0aa9f0ba449cfd4f50fd0d09b5 + languageName: node + linkType: hard + +"archiver-utils@npm:^5.0.0, archiver-utils@npm:^5.0.2": + version: 5.0.2 + resolution: "archiver-utils@npm:5.0.2" + dependencies: + glob: "npm:^10.0.0" + graceful-fs: "npm:^4.2.0" + is-stream: "npm:^2.0.1" + lazystream: "npm:^1.0.0" + lodash: "npm:^4.17.15" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^4.0.0" + checksum: 10c0/3782c5fa9922186aa1a8e41ed0c2867569faa5f15c8e5e6418ea4c1b730b476e21bd68270b3ea457daf459ae23aaea070b2b9f90cf90a59def8dc79b9e4ef538 + languageName: node + linkType: hard + +"archiver@npm:^7.0.1": + version: 7.0.1 + resolution: "archiver@npm:7.0.1" + dependencies: + archiver-utils: "npm:^5.0.2" + async: "npm:^3.2.4" + buffer-crc32: "npm:^1.0.0" + readable-stream: "npm:^4.0.0" + readdir-glob: "npm:^1.1.2" + tar-stream: "npm:^3.0.0" + zip-stream: "npm:^6.0.1" + checksum: 10c0/02afd87ca16f6184f752db8e26884e6eff911c476812a0e7f7b26c4beb09f06119807f388a8e26ed2558aa8ba9db28646ebd147a4f99e46813b8b43158e1438e + languageName: node + linkType: hard + +"are-we-there-yet@npm:^2.0.0": + version: 2.0.0 + resolution: "are-we-there-yet@npm:2.0.0" + dependencies: + delegates: "npm:^1.0.0" + readable-stream: "npm:^3.6.0" + checksum: 10c0/375f753c10329153c8d66dc95e8f8b6c7cc2aa66e05cb0960bd69092b10dae22900cacc7d653ad11d26b3ecbdbfe1e8bfb6ccf0265ba8077a7d979970f16b99c + languageName: node + linkType: hard + +"array-buffer-byte-length@npm:^1.0.0": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.5" + is-array-buffer: "npm:^3.0.4" + checksum: 10c0/f5cdf54527cd18a3d2852ddf73df79efec03829e7373a8322ef5df2b4ef546fb365c19c71d6b42d641cb6bfe0f1a2f19bc0ece5b533295f86d7c3d522f228917 + languageName: node + linkType: hard + +"async@npm:^3.2.3, async@npm:^3.2.4": + version: 3.2.6 + resolution: "async@npm:3.2.6" + checksum: 10c0/36484bb15ceddf07078688d95e27076379cc2f87b10c03b6dd8a83e89475a3c8df5848859dd06a4c95af1e4c16fc973de0171a77f18ea00be899aca2a4f85e70 + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10c0/d07226ef4f87daa01bd0fe80f8f310982e345f372926da2e5296aecc25c41cab440916bbaa4c5e1034b453af3392f67df5961124e4b586df1e99793a1374bdb2 + languageName: node + linkType: hard + +"axios@npm:^1.7.5": + version: 1.7.5 + resolution: "axios@npm:1.7.5" + dependencies: + follow-redirects: "npm:^1.15.6" + form-data: "npm:^4.0.0" + proxy-from-env: "npm:^1.1.0" + checksum: 10c0/1d5daeb28b3d1bb2a7b9f0743433c4bfbeaddc15461e50ebde487eec6c009af2515749d5261096dd430c90cd891bd310bcba5ec3967bae2033c4a307f58a6ad3 + languageName: node + linkType: hard + +"b4a@npm:^1.6.4": + version: 1.6.6 + resolution: "b4a@npm:1.6.6" + checksum: 10c0/56f30277666cb511a15829e38d369b114df7dc8cec4cedc09cc5d685bc0f27cb63c7bcfb58e09a19a1b3c4f2541069ab078b5328542e85d74a39620327709a38 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"bare-events@npm:^2.2.0": + version: 2.4.2 + resolution: "bare-events@npm:2.4.2" + checksum: 10c0/09fa923061f31f815e83504e2ed4a8ba87732a01db40a7fae703dbb7eef7f05d99264b5e186074cbe9698213990d1af564c62cca07a5ff88baea8099ad9a6303 + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + +"bcrypt@npm:^5.1.1": + version: 5.1.1 + resolution: "bcrypt@npm:5.1.1" + dependencies: + "@mapbox/node-pre-gyp": "npm:^1.0.11" + node-addon-api: "npm:^5.0.0" + checksum: 10c0/743231158c866bddc46f25eb8e9617fe38bc1a6f5f3052aba35e361d349b7f8fb80e96b45c48a4c23c45c29967ccd11c81cf31166454fc0ab019801c336cab40 + languageName: node + linkType: hard + +"body-parser@npm:^1.20.2": + version: 1.20.2 + resolution: "body-parser@npm:1.20.2" + dependencies: + bytes: "npm:3.1.2" + content-type: "npm:~1.0.5" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + on-finished: "npm:2.4.1" + qs: "npm:6.11.0" + raw-body: "npm:2.5.2" + type-is: "npm:~1.6.18" + unpipe: "npm:1.0.0" + checksum: 10c0/06f1438fff388a2e2354c96aa3ea8147b79bfcb1262dfcc2aae68ec13723d01d5781680657b74e9f83c808266d5baf52804032fbde2b7382b89bd8cdb273ace9 + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: "npm:^1.0.0" + concat-map: "npm:0.0.1" + checksum: 10c0/695a56cd058096a7cb71fb09d9d6a7070113c7be516699ed361317aca2ec169f618e28b8af352e02ab4233fb54eb0168460a40dc320bab0034b36ab59aaad668 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"buffer-crc32@npm:^1.0.0": + version: 1.0.0 + resolution: "buffer-crc32@npm:1.0.0" + checksum: 10c0/8b86e161cee4bb48d5fa622cbae4c18f25e4857e5203b89e23de59e627ab26beb82d9d7999f2b8de02580165f61f83f997beaf02980cdf06affd175b651921ab + languageName: node + linkType: hard + +"buffer-equal-constant-time@npm:1.0.1": + version: 1.0.1 + resolution: "buffer-equal-constant-time@npm:1.0.1" + checksum: 10c0/fb2294e64d23c573d0dd1f1e7a466c3e978fe94a4e0f8183937912ca374619773bef8e2aceb854129d2efecbbc515bbd0cc78d2734a3e3031edb0888531bbc8e + languageName: node + linkType: hard + +"buffer@npm:^6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.2.1" + checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 + languageName: node + linkType: hard + +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.4 + resolution: "cacache@npm:18.0.4" + dependencies: + "@npmcli/fs": "npm:^3.1.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f + languageName: node + linkType: hard + +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" + dependencies: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.4" + set-function-length: "npm:^1.2.1" + checksum: 10c0/a3ded2e423b8e2a265983dba81c27e125b48eefb2655e7dfab6be597088da3d47c47976c24bc51b8fd9af1061f8f87b4ab78a314f3c77784b2ae2ba535ad8b8d + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"color-convert@npm:^1.9.3": + version: 1.9.3 + resolution: "color-convert@npm:1.9.3" + dependencies: + color-name: "npm:1.1.3" + checksum: 10c0/5ad3c534949a8c68fca8fbc6f09068f435f0ad290ab8b2f76841b9e6af7e0bb57b98cb05b0e19fe33f5d91e5a8611ad457e5f69e0a484caad1f7487fd0e8253c + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:1.1.3": + version: 1.1.3 + resolution: "color-name@npm:1.1.3" + checksum: 10c0/566a3d42cca25b9b3cd5528cd7754b8e89c0eb646b7f214e8e2eaddb69994ac5f0557d9c175eb5d8f0ad73531140d9c47525085ee752a91a2ab15ab459caf6d6 + languageName: node + linkType: hard + +"color-name@npm:^1.0.0, color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"color-string@npm:^1.6.0, color-string@npm:^1.9.0": + version: 1.9.1 + resolution: "color-string@npm:1.9.1" + dependencies: + color-name: "npm:^1.0.0" + simple-swizzle: "npm:^0.2.2" + checksum: 10c0/b0bfd74c03b1f837f543898b512f5ea353f71630ccdd0d66f83028d1f0924a7d4272deb278b9aef376cacf1289b522ac3fb175e99895283645a2dc3a33af2404 + languageName: node + linkType: hard + +"color-support@npm:^1.1.2": + version: 1.1.3 + resolution: "color-support@npm:1.1.3" + bin: + color-support: bin.js + checksum: 10c0/8ffeaa270a784dc382f62d9be0a98581db43e11eee301af14734a6d089bd456478b1a8b3e7db7ca7dc5b18a75f828f775c44074020b51c05fc00e6d0992b1cc6 + languageName: node + linkType: hard + +"color@npm:^3.1.3": + version: 3.2.1 + resolution: "color@npm:3.2.1" + dependencies: + color-convert: "npm:^1.9.3" + color-string: "npm:^1.6.0" + checksum: 10c0/39345d55825884c32a88b95127d417a2c24681d8b57069413596d9fcbb721459ef9d9ec24ce3e65527b5373ce171b73e38dbcd9c830a52a6487e7f37bf00e83c + languageName: node + linkType: hard + +"color@npm:^4.2.3": + version: 4.2.3 + resolution: "color@npm:4.2.3" + dependencies: + color-convert: "npm:^2.0.1" + color-string: "npm:^1.9.0" + checksum: 10c0/7fbe7cfb811054c808349de19fb380252e5e34e61d7d168ec3353e9e9aacb1802674bddc657682e4e9730c2786592a4de6f8283e7e0d3870b829bb0b7b2f6118 + languageName: node + linkType: hard + +"colorspace@npm:1.1.x": + version: 1.1.4 + resolution: "colorspace@npm:1.1.4" + dependencies: + color: "npm:^3.1.3" + text-hex: "npm:1.0.x" + checksum: 10c0/af5f91ff7f8e146b96e439ac20ed79b197210193bde721b47380a75b21751d90fa56390c773bb67c0aedd34ff85091883a437ab56861c779bd507d639ba7e123 + languageName: node + linkType: hard + +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: "npm:~1.0.0" + checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 + languageName: node + linkType: hard + +"compress-commons@npm:^6.0.2": + version: 6.0.2 + resolution: "compress-commons@npm:6.0.2" + dependencies: + crc-32: "npm:^1.2.0" + crc32-stream: "npm:^6.0.0" + is-stream: "npm:^2.0.1" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^4.0.0" + checksum: 10c0/2347031b7c92c8ed5011b07b93ec53b298fa2cd1800897532ac4d4d1aeae06567883f481b6e35f13b65fc31b190c751df6635434d525562f0203fde76f1f0814 + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f + languageName: node + linkType: hard + +"console-control-strings@npm:^1.0.0, console-control-strings@npm:^1.1.0": + version: 1.1.0 + resolution: "console-control-strings@npm:1.1.0" + checksum: 10c0/7ab51d30b52d461412cd467721bb82afe695da78fff8f29fe6f6b9cbaac9a2328e27a22a966014df9532100f6dd85370460be8130b9c677891ba36d96a343f50 + languageName: node + linkType: hard + +"content-type@npm:~1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + +"core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 10c0/90a0e40abbddfd7618f8ccd63a74d88deea94e77d0e8dbbea059fa7ebebb8fbb4e2909667fe26f3a467073de1a542ebe6ae4c73a73745ac5833786759cd906c9 + languageName: node + linkType: hard + +"crc-32@npm:^1.2.0": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: 10c0/11dcf4a2e77ee793835d49f2c028838eae58b44f50d1ff08394a610bfd817523f105d6ae4d9b5bef0aad45510f633eb23c903e9902e4409bed1ce70cb82b9bf0 + languageName: node + linkType: hard + +"crc32-stream@npm:^6.0.0": + version: 6.0.0 + resolution: "crc32-stream@npm:6.0.0" + dependencies: + crc-32: "npm:^1.2.0" + readable-stream: "npm:^4.0.0" + checksum: 10c0/bf9c84571ede2d119c2b4f3a9ef5eeb9ff94b588493c0d3862259af86d3679dcce1c8569dd2b0a6eff2f35f5e2081cc1263b846d2538d4054da78cf34f262a3d + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 + languageName: node + linkType: hard + +"debug@npm:2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.3.4": + version: 4.3.6 + resolution: "debug@npm:4.3.6" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/3293416bff072389c101697d4611c402a6bacd1900ac20c0492f61a9cdd6b3b29750fc7f5e299f8058469ef60ff8fb79b86395a30374fbd2490113c1c7112285 + languageName: node + linkType: hard + +"deep-equal@npm:^2.2.3": + version: 2.2.3 + resolution: "deep-equal@npm:2.2.3" + dependencies: + array-buffer-byte-length: "npm:^1.0.0" + call-bind: "npm:^1.0.5" + es-get-iterator: "npm:^1.1.3" + get-intrinsic: "npm:^1.2.2" + is-arguments: "npm:^1.1.1" + is-array-buffer: "npm:^3.0.2" + is-date-object: "npm:^1.0.5" + is-regex: "npm:^1.1.4" + is-shared-array-buffer: "npm:^1.0.2" + isarray: "npm:^2.0.5" + object-is: "npm:^1.1.5" + object-keys: "npm:^1.1.1" + object.assign: "npm:^4.1.4" + regexp.prototype.flags: "npm:^1.5.1" + side-channel: "npm:^1.0.4" + which-boxed-primitive: "npm:^1.0.2" + which-collection: "npm:^1.0.1" + which-typed-array: "npm:^1.1.13" + checksum: 10c0/a48244f90fa989f63ff5ef0cc6de1e4916b48ea0220a9c89a378561960814794a5800c600254482a2c8fd2e49d6c2e196131dc983976adb024c94a42dfe4949f + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.0.1" + checksum: 10c0/dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 + languageName: node + linkType: hard + +"define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.0" + object-keys: "npm:^1.1.1" + checksum: 10c0/88a152319ffe1396ccc6ded510a3896e77efac7a1bfbaa174a7b00414a1747377e0bb525d303794a47cf30e805c2ec84e575758512c6e44a993076d29fd4e6c3 + languageName: node + linkType: hard + +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 + languageName: node + linkType: hard + +"delegates@npm:^1.0.0": + version: 1.0.0 + resolution: "delegates@npm:1.0.0" + checksum: 10c0/ba05874b91148e1db4bf254750c042bf2215febd23a6d3cda2e64896aef79745fbd4b9996488bd3cafb39ce19dbce0fd6e3b6665275638befffe1c9b312b91b5 + languageName: node + linkType: hard + +"depd@npm:2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c + languageName: node + linkType: hard + +"destroy@npm:1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 10c0/bd7633942f57418f5a3b80d5cb53898127bcf53e24cdf5d5f4396be471417671f0fee48a4ebe9a1e9defbde2a31280011af58a57e090ff822f589b443ed4e643 + languageName: node + linkType: hard + +"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.3": + version: 2.0.3 + resolution: "detect-libc@npm:2.0.3" + checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"ecdsa-sig-formatter@npm:1.0.11": + version: 1.0.11 + resolution: "ecdsa-sig-formatter@npm:1.0.11" + dependencies: + safe-buffer: "npm:^5.0.1" + checksum: 10c0/ebfbf19d4b8be938f4dd4a83b8788385da353d63307ede301a9252f9f7f88672e76f2191618fd8edfc2f24679236064176fab0b78131b161ee73daa37125408c + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"enabled@npm:2.0.x": + version: 2.0.0 + resolution: "enabled@npm:2.0.0" + checksum: 10c0/3b2c2af9bc7f8b9e291610f2dde4a75cf6ee52a68f4dd585482fbdf9a55d65388940e024e56d40bb03e05ef6671f5f53021fa8b72a20e954d7066ec28166713f + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" + dependencies: + get-intrinsic: "npm:^1.2.4" + checksum: 10c0/6bf3191feb7ea2ebda48b577f69bdfac7a2b3c9bcf97307f55fd6ef1bbca0b49f0c219a935aca506c993d8c5d8bddd937766cb760cd5e5a1071351f2df9f9aa4 + languageName: node + linkType: hard + +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + +"es-get-iterator@npm:^1.1.3": + version: 1.1.3 + resolution: "es-get-iterator@npm:1.1.3" + dependencies: + call-bind: "npm:^1.0.2" + get-intrinsic: "npm:^1.1.3" + has-symbols: "npm:^1.0.3" + is-arguments: "npm:^1.1.1" + is-map: "npm:^2.0.2" + is-set: "npm:^2.0.2" + is-string: "npm:^1.0.7" + isarray: "npm:^2.0.5" + stop-iteration-iterator: "npm:^1.0.0" + checksum: 10c0/ebd11effa79851ea75d7f079405f9d0dc185559fd65d986c6afea59a0ff2d46c2ed8675f19f03dce7429d7f6c14ff9aede8d121fbab78d75cfda6a263030bac0 + languageName: node + linkType: hard + +"event-target-shim@npm:^5.0.0": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b + languageName: node + linkType: hard + +"events@npm:^3.3.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 + languageName: node + linkType: hard + +"fast-fifo@npm:^1.2.0, fast-fifo@npm:^1.3.2": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: 10c0/d53f6f786875e8b0529f784b59b4b05d4b5c31c651710496440006a398389a579c8dbcd2081311478b5bf77f4b0b21de69109c5a4eabea9d8e8783d1eb864e4c + languageName: node + linkType: hard + +"fecha@npm:^4.2.0": + version: 4.2.3 + resolution: "fecha@npm:4.2.3" + checksum: 10c0/0e895965959cf6a22bb7b00f0bf546f2783836310f510ddf63f463e1518d4c96dec61ab33fdfd8e79a71b4856a7c865478ce2ee8498d560fe125947703c9b1cf + languageName: node + linkType: hard + +"fn.name@npm:1.x.x": + version: 1.1.0 + resolution: "fn.name@npm:1.1.0" + checksum: 10c0/8ad62aa2d4f0b2a76d09dba36cfec61c540c13a0fd72e5d94164e430f987a7ce6a743112bbeb14877c810ef500d1f73d7f56e76d029d2e3413f20d79e3460a9a + languageName: node + linkType: hard + +"follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" + peerDependenciesMeta: + debug: + optional: true + checksum: 10c0/9ff767f0d7be6aa6870c82ac79cf0368cd73e01bbc00e9eb1c2a16fbb198ec105e3c9b6628bb98e9f3ac66fe29a957b9645bcb9a490bb7aa0d35f908b6b85071 + languageName: node + linkType: hard + +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: "npm:^1.1.3" + checksum: 10c0/22330d8a2db728dbf003ec9182c2d421fbcd2969b02b4f97ec288721cda63eb28f2c08585ddccd0f77cb2930af8d958005c9e72f47141dc51816127a118f39aa + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" + dependencies: + cross-spawn: "npm:^7.0.0" + signal-exit: "npm:^4.0.1" + checksum: 10c0/028f1d41000553fcfa6c4bb5c372963bf3d9bf0b1f25a87d1a6253014343fb69dfb1b42d9625d7cf44c8ba429940f3d0ff718b62105d4d4a4f6ef8ca0a53faa2 + languageName: node + linkType: hard + +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + mime-types: "npm:^2.1.12" + checksum: 10c0/cb6f3ac49180be03ff07ba3ff125f9eba2ff0b277fb33c7fc47569fc5e616882c5b1c69b9904c4c4187e97dd0419dd03b134174756f296dec62041e6527e2c6e + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"functions-have-names@npm:^1.2.3": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: 10c0/33e77fd29bddc2d9bb78ab3eb854c165909201f88c75faa8272e35899e2d35a8a642a15e7420ef945e1f64a9670d6aa3ec744106b2aa42be68ca5114025954ca + languageName: node + linkType: hard + +"gauge@npm:^3.0.0": + version: 3.0.2 + resolution: "gauge@npm:3.0.2" + dependencies: + aproba: "npm:^1.0.3 || ^2.0.0" + color-support: "npm:^1.1.2" + console-control-strings: "npm:^1.0.0" + has-unicode: "npm:^2.0.1" + object-assign: "npm:^4.1.1" + signal-exit: "npm:^3.0.0" + string-width: "npm:^4.2.3" + strip-ansi: "npm:^6.0.1" + wide-align: "npm:^1.1.2" + checksum: 10c0/75230ccaf216471e31025c7d5fcea1629596ca20792de50c596eb18ffb14d8404f927cd55535aab2eeecd18d1e11bd6f23ec3c2e9878d2dda1dc74bccc34b913 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + has-proto: "npm:^1.0.1" + has-symbols: "npm:^1.0.3" + hasown: "npm:^2.0.0" + checksum: 10c0/0a9b82c16696ed6da5e39b1267104475c47e3a9bdbe8b509dfe1710946e38a87be70d759f4bb3cda042d76a41ef47fe769660f3b7c0d1f68750299344ffb15b7 + languageName: node + linkType: hard + +"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"glob@npm:^7.1.3": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.1.1" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe + languageName: node + linkType: hard + +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: "npm:^1.1.3" + checksum: 10c0/505c05487f7944c552cee72087bf1567debb470d4355b1335f2c262d218ebbff805cd3715448fe29b4b380bae6912561d0467233e4165830efd28da241418c63 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"has-bigints@npm:^1.0.1": + version: 1.0.2 + resolution: "has-bigints@npm:1.0.2" + checksum: 10c0/724eb1485bfa3cdff6f18d95130aa190561f00b3fcf9f19dc640baf8176b5917c143b81ec2123f8cddb6c05164a198c94b13e1377c497705ccc8e1a80306e83b + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" + dependencies: + es-define-property: "npm:^1.0.0" + checksum: 10c0/253c1f59e80bb476cf0dde8ff5284505d90c3bdb762983c3514d36414290475fe3fd6f574929d84de2a8eec00d35cf07cb6776205ff32efd7c50719125f00236 + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: 10c0/35a6989f81e9f8022c2f4027f8b48a552de714938765d019dbea6bb547bd49ce5010a3c7c32ec6ddac6e48fc546166a3583b128f5a7add8b058a6d8b4afec205 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: 10c0/e6922b4345a3f37069cdfe8600febbca791c94988c01af3394d86ca3360b4b93928bbf395859158f88099cb10b19d98e3bbab7c9ff2c1bd09cf665ee90afa2c3 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c + languageName: node + linkType: hard + +"has-unicode@npm:^2.0.1": + version: 2.0.1 + resolution: "has-unicode@npm:2.0.1" + checksum: 10c0/ebdb2f4895c26bb08a8a100b62d362e49b2190bcfd84b76bc4be1a3bd4d254ec52d0dd9f2fbcc093fc5eb878b20c52146f9dfd33e2686ed28982187be593b47c + languageName: node + linkType: hard + +"hasown@npm:^2.0.0": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc + languageName: node + linkType: hard + +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^5.0.0": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: "npm:6" + debug: "npm:4" + checksum: 10c0/6dd639f03434003577c62b27cafdb864784ef19b2de430d8ae2a1d45e31c4fd60719e5637b44db1a88a046934307da7089e03d6089ec3ddacc1189d8de8897d1 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c + languageName: node + linkType: hard + +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: "npm:^1.3.0" + wrappy: "npm:1" + checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:~2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.4": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" + dependencies: + es-errors: "npm:^1.3.0" + hasown: "npm:^2.0.0" + side-channel: "npm:^1.0.4" + checksum: 10c0/f8b294a4e6ea3855fc59551bbf35f2b832cf01fd5e6e2a97f5c201a071cc09b49048f856e484b67a6c721da5e55736c5b6ddafaf19e2dbeb4a3ff1821680de6c + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc + languageName: node + linkType: hard + +"is-arguments@npm:^1.1.1": + version: 1.1.1 + resolution: "is-arguments@npm:1.1.1" + dependencies: + call-bind: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.0" + checksum: 10c0/5ff1f341ee4475350adfc14b2328b38962564b7c2076be2f5bac7bd9b61779efba99b9f844a7b82ba7654adccf8e8eb19d1bb0cc6d1c1a085e498f6793d4328f + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" + dependencies: + call-bind: "npm:^1.0.2" + get-intrinsic: "npm:^1.2.1" + checksum: 10c0/42a49d006cc6130bc5424eae113e948c146f31f9d24460fc0958f855d9d810e6fd2e4519bf19aab75179af9c298ea6092459d8cafdec523cd19e529b26eab860 + languageName: node + linkType: hard + +"is-arrayish@npm:^0.3.1": + version: 0.3.2 + resolution: "is-arrayish@npm:0.3.2" + checksum: 10c0/f59b43dc1d129edb6f0e282595e56477f98c40278a2acdc8b0a5c57097c9eff8fe55470493df5775478cf32a4dc8eaf6d3a749f07ceee5bc263a78b2434f6a54 + languageName: node + linkType: hard + +"is-bigint@npm:^1.0.1": + version: 1.0.4 + resolution: "is-bigint@npm:1.0.4" + dependencies: + has-bigints: "npm:^1.0.1" + checksum: 10c0/eb9c88e418a0d195ca545aff2b715c9903d9b0a5033bc5922fec600eb0c3d7b1ee7f882dbf2e0d5a6e694e42391be3683e4368737bd3c4a77f8ac293e7773696 + languageName: node + linkType: hard + +"is-boolean-object@npm:^1.1.0": + version: 1.1.2 + resolution: "is-boolean-object@npm:1.1.2" + dependencies: + call-bind: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.0" + checksum: 10c0/6090587f8a8a8534c0f816da868bc94f32810f08807aa72fa7e79f7e11c466d281486ffe7a788178809c2aa71fe3e700b167fe80dd96dad68026bfff8ebf39f7 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f + languageName: node + linkType: hard + +"is-date-object@npm:^1.0.5": + version: 1.0.5 + resolution: "is-date-object@npm:1.0.5" + dependencies: + has-tostringtag: "npm:^1.0.0" + checksum: 10c0/eed21e5dcc619c48ccef804dfc83a739dbb2abee6ca202838ee1bd5f760fe8d8a93444f0d49012ad19bb7c006186e2884a1b92f6e1c056da7fd23d0a9ad5992e + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d + languageName: node + linkType: hard + +"is-map@npm:^2.0.2, is-map@npm:^2.0.3": + version: 2.0.3 + resolution: "is-map@npm:2.0.3" + checksum: 10c0/2c4d431b74e00fdda7162cd8e4b763d6f6f217edf97d4f8538b94b8702b150610e2c64961340015fe8df5b1fcee33ccd2e9b62619c4a8a3a155f8de6d6d355fc + languageName: node + linkType: hard + +"is-number-object@npm:^1.0.4": + version: 1.0.7 + resolution: "is-number-object@npm:1.0.7" + dependencies: + has-tostringtag: "npm:^1.0.0" + checksum: 10c0/aad266da1e530f1804a2b7bd2e874b4869f71c98590b3964f9d06cc9869b18f8d1f4778f838ecd2a11011bce20aeecb53cb269ba916209b79c24580416b74b1b + languageName: node + linkType: hard + +"is-regex@npm:^1.1.4": + version: 1.1.4 + resolution: "is-regex@npm:1.1.4" + dependencies: + call-bind: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.0" + checksum: 10c0/bb72aae604a69eafd4a82a93002058c416ace8cde95873589a97fc5dac96a6c6c78a9977d487b7b95426a8f5073969124dd228f043f9f604f041f32fcc465fc1 + languageName: node + linkType: hard + +"is-set@npm:^2.0.2, is-set@npm:^2.0.3": + version: 2.0.3 + resolution: "is-set@npm:2.0.3" + checksum: 10c0/f73732e13f099b2dc879c2a12341cfc22ccaca8dd504e6edae26484bd5707a35d503fba5b4daad530a9b088ced1ae6c9d8200fd92e09b428fe14ea79ce8080b7 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.2": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" + dependencies: + call-bind: "npm:^1.0.7" + checksum: 10c0/adc11ab0acbc934a7b9e5e9d6c588d4ec6682f6fea8cda5180721704fa32927582ede5b123349e32517fdadd07958973d24716c80e7ab198970c47acc09e59c7 + languageName: node + linkType: hard + +"is-stream@npm:^2.0.0, is-stream@npm:^2.0.1": + version: 2.0.1 + resolution: "is-stream@npm:2.0.1" + checksum: 10c0/7c284241313fc6efc329b8d7f08e16c0efeb6baab1b4cd0ba579eb78e5af1aa5da11e68559896a2067cd6c526bd29241dda4eb1225e627d5aa1a89a76d4635a5 + languageName: node + linkType: hard + +"is-string@npm:^1.0.5, is-string@npm:^1.0.7": + version: 1.0.7 + resolution: "is-string@npm:1.0.7" + dependencies: + has-tostringtag: "npm:^1.0.0" + checksum: 10c0/905f805cbc6eedfa678aaa103ab7f626aac9ebbdc8737abb5243acaa61d9820f8edc5819106b8fcd1839e33db21de9f0116ae20de380c8382d16dc2a601921f6 + languageName: node + linkType: hard + +"is-symbol@npm:^1.0.3": + version: 1.0.4 + resolution: "is-symbol@npm:1.0.4" + dependencies: + has-symbols: "npm:^1.0.2" + checksum: 10c0/9381dd015f7c8906154dbcbf93fad769de16b4b961edc94f88d26eb8c555935caa23af88bda0c93a18e65560f6d7cca0fd5a3f8a8e1df6f1abbb9bead4502ef7 + languageName: node + linkType: hard + +"is-weakmap@npm:^2.0.2": + version: 2.0.2 + resolution: "is-weakmap@npm:2.0.2" + checksum: 10c0/443c35bb86d5e6cc5929cd9c75a4024bb0fff9586ed50b092f94e700b89c43a33b186b76dbc6d54f3d3d09ece689ab38dcdc1af6a482cbe79c0f2da0a17f1299 + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.3": + version: 2.0.3 + resolution: "is-weakset@npm:2.0.3" + dependencies: + call-bind: "npm:^1.0.7" + get-intrinsic: "npm:^1.2.4" + checksum: 10c0/8ad6141b6a400e7ce7c7442a13928c676d07b1f315ab77d9912920bf5f4170622f43126f111615788f26c3b1871158a6797c862233124507db0bcc33a9537d1a + languageName: node + linkType: hard + +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: 10c0/4199f14a7a13da2177c66c31080008b7124331956f47bca57dd0b6ea9f11687aa25e565a2c7a2b519bc86988d10398e3049a1f5df13c9f6b7664154690ae79fd + languageName: node + linkType: hard + +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: 10c0/18b5be6669be53425f0b84098732670ed4e727e3af33bc7f948aac01782110eb9a18b3b329c5323bcdd3acdaae547ee077d3951317e7f133bff7105264b3003d + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 + languageName: node + linkType: hard + +"jsonwebtoken@npm:^9.0.2": + version: 9.0.2 + resolution: "jsonwebtoken@npm:9.0.2" + dependencies: + jws: "npm:^3.2.2" + lodash.includes: "npm:^4.3.0" + lodash.isboolean: "npm:^3.0.3" + lodash.isinteger: "npm:^4.0.4" + lodash.isnumber: "npm:^3.0.3" + lodash.isplainobject: "npm:^4.0.6" + lodash.isstring: "npm:^4.0.1" + lodash.once: "npm:^4.0.0" + ms: "npm:^2.1.1" + semver: "npm:^7.5.4" + checksum: 10c0/d287a29814895e866db2e5a0209ce730cbc158441a0e5a70d5e940eb0d28ab7498c6bf45029cc8b479639bca94056e9a7f254e2cdb92a2f5750c7f358657a131 + languageName: node + linkType: hard + +"jwa@npm:^1.4.1": + version: 1.4.1 + resolution: "jwa@npm:1.4.1" + dependencies: + buffer-equal-constant-time: "npm:1.0.1" + ecdsa-sig-formatter: "npm:1.0.11" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/5c533540bf38702e73cf14765805a94027c66a0aa8b16bc3e89d8d905e61a4ce2791e87e21be97d1293a5ee9d4f3e5e47737e671768265ca4f25706db551d5e9 + languageName: node + linkType: hard + +"jws@npm:^3.2.2": + version: 3.2.2 + resolution: "jws@npm:3.2.2" + dependencies: + jwa: "npm:^1.4.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/e770704533d92df358adad7d1261fdecad4d7b66fa153ba80d047e03ca0f1f73007ce5ed3fbc04d2eba09ba6e7e6e645f351e08e5ab51614df1b0aa4f384dfff + languageName: node + linkType: hard + +"kuler@npm:^2.0.0": + version: 2.0.0 + resolution: "kuler@npm:2.0.0" + checksum: 10c0/0a4e99d92ca373f8f74d1dc37931909c4d0d82aebc94cf2ba265771160fc12c8df34eaaac80805efbda367e2795cb1f1dd4c3d404b6b1cf38aec94035b503d2d + languageName: node + linkType: hard + +"lazystream@npm:^1.0.0": + version: 1.0.1 + resolution: "lazystream@npm:1.0.1" + dependencies: + readable-stream: "npm:^2.0.5" + checksum: 10c0/ea4e509a5226ecfcc303ba6782cc269be8867d372b9bcbd625c88955df1987ea1a20da4643bf9270336415a398d33531ebf0d5f0d393b9283dc7c98bfcbd7b69 + languageName: node + linkType: hard + +"lodash.camelcase@npm:^4.3.0": + version: 4.3.0 + resolution: "lodash.camelcase@npm:4.3.0" + checksum: 10c0/fcba15d21a458076dd309fce6b1b4bf611d84a0ec252cb92447c948c533ac250b95d2e00955801ebc367e5af5ed288b996d75d37d2035260a937008e14eaf432 + languageName: node + linkType: hard + +"lodash.chunk@npm:^4.2.0": + version: 4.2.0 + resolution: "lodash.chunk@npm:4.2.0" + checksum: 10c0/f9f99969561ad2f62af1f9a96c5bd0af776f000292b0d8db3126c28eb3b32e210d7c31b49c18d0d7901869bd769057046dc134b60cfa0c2c4ce017823a26bb23 + languageName: node + linkType: hard + +"lodash.compact@npm:^3.0.1": + version: 3.0.1 + resolution: "lodash.compact@npm:3.0.1" + checksum: 10c0/9cc32065f1a9aa90bf3caa987fb7e00f8b90a49209e7f9f37c601e595f396a83ebe8f3328b2ef7f365cf822c9f21697527620c9c9c9734f107453b4c6c4dd810 + languageName: node + linkType: hard + +"lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: 10c0/762998a63e095412b6099b8290903e0a8ddcb353ac6e2e0f2d7e7d03abd4275fe3c689d88960eb90b0dde4f177554d51a690f22a343932ecbc50a5d111849987 + languageName: node + linkType: hard + +"lodash.groupby@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.groupby@npm:4.6.0" + checksum: 10c0/3d136cad438ad6c3a078984ef60e057a3498b1312aa3621b00246ecb99e8f2c4d447e2815460db7a0b661a4fe4e2eeee96c84cb661a824bad04b6cf1f7bc6e9b + languageName: node + linkType: hard + +"lodash.identity@npm:^3.0.0": + version: 3.0.0 + resolution: "lodash.identity@npm:3.0.0" + checksum: 10c0/a09ca0f99ae495c353e4ac6888684397f3b5b0c5f7d13a866a3956b7b2aa779462c78c219a31d4aab255d027ac5e11e8c3d943e70956e2a3d42feea56a8e9c1c + languageName: node + linkType: hard + +"lodash.includes@npm:^4.3.0": + version: 4.3.0 + resolution: "lodash.includes@npm:4.3.0" + checksum: 10c0/7ca498b9b75bf602d04e48c0adb842dfc7d90f77bcb2a91a2b2be34a723ad24bc1c8b3683ec6b2552a90f216c723cdea530ddb11a3320e08fa38265703978f4b + languageName: node + linkType: hard + +"lodash.isboolean@npm:^3.0.3": + version: 3.0.3 + resolution: "lodash.isboolean@npm:3.0.3" + checksum: 10c0/0aac604c1ef7e72f9a6b798e5b676606042401dd58e49f051df3cc1e3adb497b3d7695635a5cbec4ae5f66456b951fdabe7d6b387055f13267cde521f10ec7f7 + languageName: node + linkType: hard + +"lodash.isempty@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.isempty@npm:4.4.0" + checksum: 10c0/6c7eaa0802398736809b9e8aed8b8ac1abca9be71788fd719ba9d7f5b4c23e8dc63b7f049df4131713dda30a2fdedc2f655268e9deb8cd5a985dfc934afca194 + languageName: node + linkType: hard + +"lodash.isequal@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.isequal@npm:4.5.0" + checksum: 10c0/dfdb2356db19631a4b445d5f37868a095e2402292d59539a987f134a8778c62a2810c2452d11ae9e6dcac71fc9de40a6fedcb20e2952a15b431ad8b29e50e28f + languageName: node + linkType: hard + +"lodash.isinteger@npm:^4.0.4": + version: 4.0.4 + resolution: "lodash.isinteger@npm:4.0.4" + checksum: 10c0/4c3e023a2373bf65bf366d3b8605b97ec830bca702a926939bcaa53f8e02789b6a176e7f166b082f9365bfec4121bfeb52e86e9040cb8d450e64c858583f61b7 + languageName: node + linkType: hard + +"lodash.isnumber@npm:^3.0.3": + version: 3.0.3 + resolution: "lodash.isnumber@npm:3.0.3" + checksum: 10c0/2d01530513a1ee4f72dd79528444db4e6360588adcb0e2ff663db2b3f642d4bb3d687051ae1115751ca9082db4fdef675160071226ca6bbf5f0c123dbf0aa12d + languageName: node + linkType: hard + +"lodash.isobject@npm:^3.0.2": + version: 3.0.2 + resolution: "lodash.isobject@npm:3.0.2" + checksum: 10c0/da4c8480d98b16835b59380b2fbd43c54081acd9466febb788ba77c434384349e0bec162d1c4e89f613f21687b2b6d8384d8a112b80da00c78d28d9915a5cdde + languageName: node + linkType: hard + +"lodash.isplainobject@npm:^4.0.6": + version: 4.0.6 + resolution: "lodash.isplainobject@npm:4.0.6" + checksum: 10c0/afd70b5c450d1e09f32a737bed06ff85b873ecd3d3d3400458725283e3f2e0bb6bf48e67dbe7a309eb371a822b16a26cca4a63c8c52db3fc7dc9d5f9dd324cbb + languageName: node + linkType: hard + +"lodash.isstring@npm:^4.0.1": + version: 4.0.1 + resolution: "lodash.isstring@npm:4.0.1" + checksum: 10c0/09eaf980a283f9eef58ef95b30ec7fee61df4d6bf4aba3b5f096869cc58f24c9da17900febc8ffd67819b4e29de29793190e88dc96983db92d84c95fa85d1c92 + languageName: node + linkType: hard + +"lodash.kebabcase@npm:^4.1.1": + version: 4.1.1 + resolution: "lodash.kebabcase@npm:4.1.1" + checksum: 10c0/da5d8f41dbb5bc723d4bf9203d5096ca8da804d6aec3d2b56457156ba6c8d999ff448d347ebd97490da853cb36696ea4da09a431499f1ee8deb17b094ecf4e33 + languageName: node + linkType: hard + +"lodash.mapvalues@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.mapvalues@npm:4.6.0" + checksum: 10c0/a976bfc3923d4d8d2034e049ec4700e3aaf141a6143c973d06be3b2c87697923cd0158ee770484ad1af52dfed93ae90d2b76268413db95a42a2f46d7e1754828 + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: 10c0/402fa16a1edd7538de5b5903a90228aa48eb5533986ba7fa26606a49db2572bf414ff73a2c9f5d5fd36b31c46a5d5c7e1527749c07cbcf965ccff5fbdf32c506 + languageName: node + linkType: hard + +"lodash.omit@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.omit@npm:4.5.0" + checksum: 10c0/3808b9b6faae35177174b6ab327f1177e29c91f1e98dcbccf13a72a6767bba337306449d537a4e0d8a33d2673f10d39bc732e30c4b803274ea0c1168ea60e549 + languageName: node + linkType: hard + +"lodash.once@npm:^4.0.0": + version: 4.1.1 + resolution: "lodash.once@npm:4.1.1" + checksum: 10c0/46a9a0a66c45dd812fcc016e46605d85ad599fe87d71a02f6736220554b52ffbe82e79a483ad40f52a8a95755b0d1077fba259da8bfb6694a7abbf4a48f1fc04 + languageName: node + linkType: hard + +"lodash.pick@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.pick@npm:4.4.0" + checksum: 10c0/a04c460b95d1aaa44e9513d1dacf72ea74d838da843e45831de9de64c303f13cdde1859702a6f4dcef417816898ffd47c6ae0614c957ac70245bed2809b8d2e2 + languageName: node + linkType: hard + +"lodash.pickby@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.pickby@npm:4.6.0" + checksum: 10c0/46befadb64ab0f61159977174b291f87b005cec1c7bd73d1b6949ec4cdff483c1be0e34398df8955b76ce06a3e93a4a5c5a552a4299520390d6993c5420c7ab9 + languageName: node + linkType: hard + +"lodash.snakecase@npm:^4.1.1": + version: 4.1.1 + resolution: "lodash.snakecase@npm:4.1.1" + checksum: 10c0/f0b3f2497eb20eea1a1cfc22d645ecaeb78ac14593eb0a40057977606d2f35f7aaff0913a06553c783b535aafc55b718f523f9eb78f8d5293f492af41002eaf9 + languageName: node + linkType: hard + +"lodash.upperfirst@npm:^4.3.1": + version: 4.3.1 + resolution: "lodash.upperfirst@npm:4.3.1" + checksum: 10c0/435625da4b3ee74e7a1367a780d9107ab0b13ef4359fc074b2a1a40458eb8d91b655af62f6795b7138d493303a98c0285340160341561d6896e4947e077fa975 + languageName: node + linkType: hard + +"lodash@npm:^4.17.15": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c + languageName: node + linkType: hard + +"logform@npm:^2.6.0, logform@npm:^2.6.1": + version: 2.6.1 + resolution: "logform@npm:2.6.1" + dependencies: + "@colors/colors": "npm:1.6.0" + "@types/triple-beam": "npm:^1.3.2" + fecha: "npm:^4.2.0" + ms: "npm:^2.1.1" + safe-stable-stringify: "npm:^2.3.1" + triple-beam: "npm:^1.3.0" + checksum: 10c0/c20019336b1da8c08adea67dd7de2b0effdc6e35289c0156722924b571df94ba9f900ef55620c56bceb07cae7cc46057c9859accdee37a131251ba34d6789bce + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"make-dir@npm:^3.1.0": + version: 3.1.0 + resolution: "make-dir@npm:3.1.0" + dependencies: + semver: "npm:^6.0.0" + checksum: 10c0/56aaafefc49c2dfef02c5c95f9b196c4eb6988040cf2c712185c7fe5c99b4091591a7fc4d4eafaaefa70ff763a26f6ab8c3ff60b9e75ea19876f49b18667ecaa + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" + dependencies: + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" + http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^3.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^10.0.0" + checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e + languageName: node + linkType: hard + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: 10c0/d160f31246907e79fed398470285f21bafb45a62869dc469b1c8877f3f064f5eabc4bcc122f9479b8b605bc5c76187d7871cf84c4ee3ecd3e487da1993279928 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 + languageName: node + linkType: hard + +"minimatch@npm:^3.1.1": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 + languageName: node + linkType: hard + +"minimatch@npm:^5.1.0": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^2.1.2" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: "npm:^3.0.0" + yallist: "npm:^4.0.0" + checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc + languageName: node + linkType: hard + +"ms@npm:^2.1.1": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"node-addon-api@npm:^5.0.0": + version: 5.1.0 + resolution: "node-addon-api@npm:5.1.0" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/0eb269786124ba6fad9df8007a149e03c199b3e5a3038125dfb3e747c2d5113d406a4e33f4de1ea600aa2339be1f137d55eba1a73ee34e5fff06c52a5c296d1d + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.7": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^4.1.0" + semver: "npm:^7.3.5" + tar: "npm:^6.2.1" + which: "npm:^4.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b + languageName: node + linkType: hard + +"nodemailer@npm:^6.9.14": + version: 6.9.14 + resolution: "nodemailer@npm:6.9.14" + checksum: 10c0/2542986849bc6ec2bf12fb7b72226da0ce9c6a0946216dea020d9eedee3ac1a4eb2413f59772a3ddd4bb9188d5ce859167a030c065719473f71319e052a319dc + languageName: node + linkType: hard + +"nopt@npm:^5.0.0": + version: 5.0.0 + resolution: "nopt@npm:5.0.0" + dependencies: + abbrev: "npm:1" + bin: + nopt: bin/nopt.js + checksum: 10c0/fc5c4f07155cb455bf5fc3dd149fac421c1a40fd83c6bfe83aa82b52f02c17c5e88301321318adaa27611c8a6811423d51d29deaceab5fa158b585a61a551061 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" + dependencies: + abbrev: "npm:^2.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 + languageName: node + linkType: hard + +"npmlog@npm:^5.0.1": + version: 5.0.1 + resolution: "npmlog@npm:5.0.1" + dependencies: + are-we-there-yet: "npm:^2.0.0" + console-control-strings: "npm:^1.1.0" + gauge: "npm:^3.0.0" + set-blocking: "npm:^2.0.0" + checksum: 10c0/489ba519031013001135c463406f55491a17fc7da295c18a04937fe3a4d523fd65e88dd418a28b967ab743d913fdeba1e29838ce0ad8c75557057c481f7d49fa + languageName: node + linkType: hard + +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.1": + version: 1.13.2 + resolution: "object-inspect@npm:1.13.2" + checksum: 10c0/b97835b4c91ec37b5fd71add84f21c3f1047d1d155d00c0fcd6699516c256d4fcc6ff17a1aced873197fe447f91a3964178fd2a67a1ee2120cdaf60e81a050b4 + languageName: node + linkType: hard + +"object-is@npm:^1.1.5": + version: 1.1.6 + resolution: "object-is@npm:1.1.6" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 + languageName: node + linkType: hard + +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: 10c0/b11f7ccdbc6d406d1f186cdadb9d54738e347b2692a14439ca5ac70c225fa6db46db809711b78589866d47b25fc3e8dee0b4c722ac751e11180f9380e3d8601d + languageName: node + linkType: hard + +"object.assign@npm:^4.1.4": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" + has-symbols: "npm:^1.0.3" + object-keys: "npm:^1.1.1" + checksum: 10c0/60108e1fa2706f22554a4648299b0955236c62b3685c52abf4988d14fffb0e7731e00aa8c6448397e3eb63d087dcc124a9f21e1980f36d0b2667f3c18bacd469 + languageName: node + linkType: hard + +"on-finished@npm:2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + +"one-time@npm:^1.0.0": + version: 1.0.0 + resolution: "one-time@npm:1.0.0" + dependencies: + fn.name: "npm:1.x.x" + checksum: 10c0/6e4887b331edbb954f4e915831cbec0a7b9956c36f4feb5f6de98c448ac02ff881fd8d9b55a6b1b55030af184c6b648f340a76eb211812f4ad8c9b4b8692fdaa + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: 10c0/d9aa22d31f4f7680e20269db76791b41c3a32c01a373e25f8a4813b4d45f7456bfc2b6d68f752dc4aab0e0bb0721cb3d76fb678c9101cb7a16316664bc2c73fd + languageName: node + linkType: hard + +"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 + languageName: node + linkType: hard + +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 10c0/bec089239487833d46b59d80327a1605e1c5287eaad770a291add7f45fda1bb5e28b38e0e061add0a1d0ee0984788ce74fa394d345eed1c420cacf392c554367 + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b + languageName: node + linkType: hard + +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: "npm:^1.0.4" + checksum: 10c0/4e4875e4d7c7c31c233d07a448e7e4650f456178b9dd3766b7cfa13158fdb24ecb8c4f059fa91e820dc6ab9f2d243721d071c9c0378892dcdad86e9e9a27c68f + languageName: node + linkType: hard + +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 10c0/0db998e2c9b15215317dbcf801e9b23e6bcde4044e115155dae34f8e7454b9a783f737c9a725528d677b7a66c775eb7a955cf144fe0b87f62b575ce5bfd515a9 + languageName: node + linkType: hard + +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 10c0/b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 + languageName: node + linkType: hard + +"readable-stream@npm:^2.0.5": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: "npm:~1.0.0" + inherits: "npm:~2.0.3" + isarray: "npm:~1.0.0" + process-nextick-args: "npm:~2.0.0" + safe-buffer: "npm:~5.1.1" + string_decoder: "npm:~1.1.1" + util-deprecate: "npm:~1.0.1" + checksum: 10c0/7efdb01f3853bc35ac62ea25493567bf588773213f5f4a79f9c365e1ad13bab845ac0dae7bc946270dc40c3929483228415e92a3fc600cc7e4548992f41ee3fa + languageName: node + linkType: hard + +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + +"readable-stream@npm:^4.0.0": + version: 4.5.2 + resolution: "readable-stream@npm:4.5.2" + dependencies: + abort-controller: "npm:^3.0.0" + buffer: "npm:^6.0.3" + events: "npm:^3.3.0" + process: "npm:^0.11.10" + string_decoder: "npm:^1.3.0" + checksum: 10c0/a2c80e0e53aabd91d7df0330929e32d0a73219f9477dbbb18472f6fdd6a11a699fc5d172a1beff98d50eae4f1496c950ffa85b7cc2c4c196963f289a5f39275d + languageName: node + linkType: hard + +"readdir-glob@npm:^1.1.2": + version: 1.1.3 + resolution: "readdir-glob@npm:1.1.3" + dependencies: + minimatch: "npm:^5.1.0" + checksum: 10c0/a37e0716726650845d761f1041387acd93aa91b28dd5381950733f994b6c349ddc1e21e266ec7cc1f9b92e205a7a972232f9b89d5424d07361c2c3753d5dbace + languageName: node + linkType: hard + +"regexp.prototype.flags@npm:^1.5.1": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" + dependencies: + call-bind: "npm:^1.0.6" + define-properties: "npm:^1.2.1" + es-errors: "npm:^1.3.0" + set-function-name: "npm:^2.0.1" + checksum: 10c0/0f3fc4f580d9c349f8b560b012725eb9c002f36daa0041b3fbf6f4238cb05932191a4d7d5db3b5e2caa336d5150ad0402ed2be81f711f9308fe7e1a9bf9bd552 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"rimraf@npm:^3.0.2": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: "npm:^7.1.3" + bin: + rimraf: bin.js + checksum: 10c0/9cb7757acb489bd83757ba1a274ab545eafd75598a9d817e0c3f8b164238dd90eba50d6b848bd4dcc5f3040912e882dc7ba71653e35af660d77b25c381d402e8 + languageName: node + linkType: hard + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + dependencies: + "@types/bcrypt": "npm:^5.0.2" + "@types/deep-equal": "npm:^1.0.4" + "@types/lodash.camelcase": "npm:^4.3.9" + "@types/lodash.compact": "npm:^3.0.9" + "@types/lodash.debounce": "npm:^4.0.9" + "@types/lodash.groupby": "npm:^4.6.9" + "@types/lodash.identity": "npm:^3.0.9" + "@types/lodash.isempty": "npm:^4.4.9" + "@types/lodash.isequal": "npm:^4.5.8" + "@types/lodash.isobject": "npm:^3.0.9" + "@types/lodash.kebabcase": "npm:^4.1.9" + "@types/lodash.mapvalues": "npm:^4.6.9" + "@types/lodash.omit": "npm:^4.5.9" + "@types/lodash.pickby": "npm:^4.6.9" + "@types/lodash.snakecase": "npm:^4.1.9" + "@types/lodash.upperfirst": "npm:^4.3.9" + "@types/uuid": "npm:^10.0.0" + archiver: "npm:^7.0.1" + axios: "npm:^1.7.5" + bcrypt: "npm:^5.1.1" + body-parser: "npm:^1.20.2" + deep-equal: "npm:^2.2.3" + jsonwebtoken: "npm:^9.0.2" + lodash.camelcase: "npm:^4.3.0" + lodash.chunk: "npm:^4.2.0" + lodash.compact: "npm:^3.0.1" + lodash.debounce: "npm:^4.0.8" + lodash.groupby: "npm:^4.6.0" + lodash.identity: "npm:^3.0.0" + lodash.isempty: "npm:^4.4.0" + lodash.isequal: "npm:^4.5.0" + lodash.isobject: "npm:^3.0.2" + lodash.kebabcase: "npm:^4.1.1" + lodash.mapvalues: "npm:^4.6.0" + lodash.merge: "npm:^4.6.2" + lodash.omit: "npm:^4.5.0" + lodash.pick: "npm:^4.4.0" + lodash.pickby: "npm:^4.6.0" + lodash.snakecase: "npm:^4.1.1" + lodash.upperfirst: "npm:^4.3.1" + nodemailer: "npm:^6.9.14" + sharp: "npm:^0.33.5" + uuid: "npm:^10.0.0" + winston: "npm:^3.14.2" + languageName: unknown + linkType: soft + +"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 + languageName: node + linkType: hard + +"safe-stable-stringify@npm:^2.3.1": + version: 2.5.0 + resolution: "safe-stable-stringify@npm:2.5.0" + checksum: 10c0/baea14971858cadd65df23894a40588ed791769db21bafb7fd7608397dbdce9c5aac60748abae9995e0fc37e15f2061980501e012cd48859740796bea2987f49 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^6.0.0": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d + languageName: node + linkType: hard + +"semver@npm:^7.3.5, semver@npm:^7.5.4, semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf + languageName: node + linkType: hard + +"set-blocking@npm:^2.0.0": + version: 2.0.0 + resolution: "set-blocking@npm:2.0.0" + checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454 + languageName: node + linkType: hard + +"set-function-length@npm:^1.2.1": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.4" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.2" + checksum: 10c0/82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.1": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + functions-have-names: "npm:^1.2.3" + has-property-descriptors: "npm:^1.0.2" + checksum: 10c0/fce59f90696c450a8523e754abb305e2b8c73586452619c2bad5f7bf38c7b6b4651895c9db895679c5bef9554339cf3ef1c329b66ece3eda7255785fbe299316 + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc + languageName: node + linkType: hard + +"sharp@npm:^0.33.5": + version: 0.33.5 + resolution: "sharp@npm:0.33.5" + dependencies: + "@img/sharp-darwin-arm64": "npm:0.33.5" + "@img/sharp-darwin-x64": "npm:0.33.5" + "@img/sharp-libvips-darwin-arm64": "npm:1.0.4" + "@img/sharp-libvips-darwin-x64": "npm:1.0.4" + "@img/sharp-libvips-linux-arm": "npm:1.0.5" + "@img/sharp-libvips-linux-arm64": "npm:1.0.4" + "@img/sharp-libvips-linux-s390x": "npm:1.0.4" + "@img/sharp-libvips-linux-x64": "npm:1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "npm:1.0.4" + "@img/sharp-linux-arm": "npm:0.33.5" + "@img/sharp-linux-arm64": "npm:0.33.5" + "@img/sharp-linux-s390x": "npm:0.33.5" + "@img/sharp-linux-x64": "npm:0.33.5" + "@img/sharp-linuxmusl-arm64": "npm:0.33.5" + "@img/sharp-linuxmusl-x64": "npm:0.33.5" + "@img/sharp-wasm32": "npm:0.33.5" + "@img/sharp-win32-ia32": "npm:0.33.5" + "@img/sharp-win32-x64": "npm:0.33.5" + color: "npm:^4.2.3" + detect-libc: "npm:^2.0.3" + semver: "npm:^7.6.3" + dependenciesMeta: + "@img/sharp-darwin-arm64": + optional: true + "@img/sharp-darwin-x64": + optional: true + "@img/sharp-libvips-darwin-arm64": + optional: true + "@img/sharp-libvips-darwin-x64": + optional: true + "@img/sharp-libvips-linux-arm": + optional: true + "@img/sharp-libvips-linux-arm64": + optional: true + "@img/sharp-libvips-linux-s390x": + optional: true + "@img/sharp-libvips-linux-x64": + optional: true + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + "@img/sharp-libvips-linuxmusl-x64": + optional: true + "@img/sharp-linux-arm": + optional: true + "@img/sharp-linux-arm64": + optional: true + "@img/sharp-linux-s390x": + optional: true + "@img/sharp-linux-x64": + optional: true + "@img/sharp-linuxmusl-arm64": + optional: true + "@img/sharp-linuxmusl-x64": + optional: true + "@img/sharp-wasm32": + optional: true + "@img/sharp-win32-ia32": + optional: true + "@img/sharp-win32-x64": + optional: true + checksum: 10c0/6b81421ddfe6ee524d8d77e325c5e147fef22884e1c7b1656dfd89a88d7025894115da02d5f984261bf2e6daa16f98cadd1721c4ba408b4212b1d2a60f233484 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" + dependencies: + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.4" + object-inspect: "npm:^1.13.1" + checksum: 10c0/d2afd163dc733cc0a39aa6f7e39bf0c436293510dbccbff446733daeaf295857dbccf94297092ec8c53e2503acac30f0b78830876f0485991d62a90e9cad305f + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.0": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"simple-swizzle@npm:^0.2.2": + version: 0.2.2 + resolution: "simple-swizzle@npm:0.2.2" + dependencies: + is-arrayish: "npm:^0.3.1" + checksum: 10c0/df5e4662a8c750bdba69af4e8263c5d96fe4cd0f9fe4bdfa3cbdeb45d2e869dff640beaaeb1ef0e99db4d8d2ec92f85508c269f50c972174851bc1ae5bd64308 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" + dependencies: + agent-base: "npm:^7.1.1" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.3 + resolution: "socks@npm:2.8.3" + dependencies: + ip-address: "npm:^9.0.5" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 + languageName: node + linkType: hard + +"stack-trace@npm:0.0.x": + version: 0.0.10 + resolution: "stack-trace@npm:0.0.10" + checksum: 10c0/9ff3dabfad4049b635a85456f927a075c9d0c210e3ea336412d18220b2a86cbb9b13ec46d6c37b70a302a4ea4d49e30e5d4944dd60ae784073f1cde778ac8f4b + languageName: node + linkType: hard + +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0 + languageName: node + linkType: hard + +"stop-iteration-iterator@npm:^1.0.0": + version: 1.0.0 + resolution: "stop-iteration-iterator@npm:1.0.0" + dependencies: + internal-slot: "npm:^1.0.4" + checksum: 10c0/c4158d6188aac510d9e92925b58709207bd94699e9c31186a040c80932a687f84a51356b5895e6dc72710aad83addb9411c22171832c9ae0e6e11b7d61b0dfb9 + languageName: node + linkType: hard + +"streamx@npm:^2.15.0": + version: 2.19.0 + resolution: "streamx@npm:2.19.0" + dependencies: + bare-events: "npm:^2.2.0" + fast-fifo: "npm:^1.3.2" + queue-tick: "npm:^1.0.1" + text-decoder: "npm:^1.1.0" + dependenciesMeta: + bare-events: + optional: true + checksum: 10c0/5833a2c1226488a015e8efde08c6cd4983d7d20098b2210d09594b23f598a8b028c083d542621e2e91ddcb33a266233c3524c60152203be40f1dd816b9ede9da + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: "npm:~5.1.0" + checksum: 10c0/b4f89f3a92fd101b5653ca3c99550e07bdf9e13b35037e9e2a1c7b47cec4e55e06ff3fc468e314a0b5e80bfbaf65c1ca5a84978764884ae9413bec1fc6ca924e + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 + languageName: node + linkType: hard + +"tar-stream@npm:^3.0.0": + version: 3.1.7 + resolution: "tar-stream@npm:3.1.7" + dependencies: + b4a: "npm:^1.6.4" + fast-fifo: "npm:^1.2.0" + streamx: "npm:^2.15.0" + checksum: 10c0/a09199d21f8714bd729993ac49b6c8efcb808b544b89f23378ad6ffff6d1cb540878614ba9d4cfec11a64ef39e1a6f009a5398371491eb1fda606ffc7f70f718 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 + languageName: node + linkType: hard + +"text-decoder@npm:^1.1.0": + version: 1.1.1 + resolution: "text-decoder@npm:1.1.1" + dependencies: + b4a: "npm:^1.6.4" + checksum: 10c0/e527d05454b59c0fa77456495de68c88e560a122de3dd28b3ebdbf81828aabeaa7e9bb8054b9eb52bc5029ccb5899ad04f466cbba3c53b2685270599d1710cee + languageName: node + linkType: hard + +"text-hex@npm:1.0.x": + version: 1.0.0 + resolution: "text-hex@npm:1.0.0" + checksum: 10c0/57d8d320d92c79d7c03ffb8339b825bb9637c2cbccf14304309f51d8950015c44464b6fd1b6820a3d4821241c68825634f09f5a2d9d501e84f7c6fd14376860d + languageName: node + linkType: hard + +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + +"triple-beam@npm:^1.3.0": + version: 1.4.1 + resolution: "triple-beam@npm:1.4.1" + checksum: 10c0/4bf1db71e14fe3ff1c3adbe3c302f1fdb553b74d7591a37323a7badb32dc8e9c290738996cbb64f8b10dc5a3833645b5d8c26221aaaaa12e50d1251c9aba2fea + languageName: node + linkType: hard + +"tslib@npm:^2.4.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 + languageName: node + linkType: hard + +"type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: "npm:0.3.0" + mime-types: "npm:~2.1.24" + checksum: 10c0/a23daeb538591b7efbd61ecf06b6feb2501b683ffdc9a19c74ef5baba362b4347e42f1b4ed81f5882a8c96a3bfff7f93ce3ffaf0cbbc879b532b04c97a55db9d + languageName: node + linkType: hard + +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: "npm:^4.0.0" + checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 + languageName: node + linkType: hard + +"unpipe@npm:1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 + languageName: node + linkType: hard + +"uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "uuid@npm:10.0.0" + bin: + uuid: dist/bin/uuid + checksum: 10c0/eab18c27fe4ab9fb9709a5d5f40119b45f2ec8314f8d4cf12ce27e4c6f4ffa4a6321dc7db6c515068fa373c075b49691ba969f0010bf37f44c37ca40cd6bf7fe + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + +"which-boxed-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "which-boxed-primitive@npm:1.0.2" + dependencies: + is-bigint: "npm:^1.0.1" + is-boolean-object: "npm:^1.1.0" + is-number-object: "npm:^1.0.4" + is-string: "npm:^1.0.5" + is-symbol: "npm:^1.0.3" + checksum: 10c0/0a62a03c00c91dd4fb1035b2f0733c341d805753b027eebd3a304b9cb70e8ce33e25317add2fe9b5fea6f53a175c0633ae701ff812e604410ddd049777cd435e + languageName: node + linkType: hard + +"which-collection@npm:^1.0.1": + version: 1.0.2 + resolution: "which-collection@npm:1.0.2" + dependencies: + is-map: "npm:^2.0.3" + is-set: "npm:^2.0.3" + is-weakmap: "npm:^2.0.2" + is-weakset: "npm:^2.0.3" + checksum: 10c0/3345fde20964525a04cdf7c4a96821f85f0cc198f1b2ecb4576e08096746d129eb133571998fe121c77782ac8f21cbd67745a3d35ce100d26d4e684c142ea1f2 + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.13": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" + for-each: "npm:^0.3.3" + gopd: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/4465d5348c044032032251be54d8988270e69c6b7154f8fcb2a47ff706fe36f7624b3a24246b8d9089435a8f4ec48c1c1025c5d6b499456b9e5eff4f48212983 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a + languageName: node + linkType: hard + +"wide-align@npm:^1.1.2": + version: 1.1.5 + resolution: "wide-align@npm:1.1.5" + dependencies: + string-width: "npm:^1.0.2 || 2 || 3 || 4" + checksum: 10c0/1d9c2a3e36dfb09832f38e2e699c367ef190f96b82c71f809bc0822c306f5379df87bab47bed27ea99106d86447e50eb972d3c516c2f95782807a9d082fbea95 + languageName: node + linkType: hard + +"winston-transport@npm:^4.7.0": + version: 4.7.1 + resolution: "winston-transport@npm:4.7.1" + dependencies: + logform: "npm:^2.6.1" + readable-stream: "npm:^3.6.2" + triple-beam: "npm:^1.3.0" + checksum: 10c0/99b7b55cc2ef7f38988ab1717e7fd946c81b856b42a9530aef8ee725490ef2f2811f9cb06d63aa2f76a85fe99ae15b3bef10a54afde3be8b5059ce325e78481f + languageName: node + linkType: hard + +"winston@npm:^3.14.2": + version: 3.14.2 + resolution: "winston@npm:3.14.2" + dependencies: + "@colors/colors": "npm:^1.6.0" + "@dabh/diagnostics": "npm:^2.0.2" + async: "npm:^3.2.3" + is-stream: "npm:^2.0.0" + logform: "npm:^2.6.0" + one-time: "npm:^1.0.0" + readable-stream: "npm:^3.4.0" + safe-stable-stringify: "npm:^2.3.1" + stack-trace: "npm:0.0.x" + triple-beam: "npm:^1.3.0" + winston-transport: "npm:^4.7.0" + checksum: 10c0/3f8fe505ea18310982e60452f335dd2b22fdbc9b25839b6ad882971b2416d5adc94a1f1a46e24cb37d967ad01dfe5499adaf5e53575626b5ebb2a25ff30f4e1d + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"zip-stream@npm:^6.0.1": + version: 6.0.1 + resolution: "zip-stream@npm:6.0.1" + dependencies: + archiver-utils: "npm:^5.0.0" + compress-commons: "npm:^6.0.2" + readable-stream: "npm:^4.0.0" + checksum: 10c0/50f2fb30327fb9d09879abf7ae2493705313adf403e794b030151aaae00009162419d60d0519e807673ec04d442e140c8879ca14314df0a0192de3b233e8f28b + languageName: node + linkType: hard diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarn/releases/yarn-4.4.0.cjs b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarn/releases/yarn-4.4.0.cjs new file mode 100644 index 000000000000..a735b8acc341 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarn/releases/yarn-4.4.0.cjs @@ -0,0 +1,925 @@ +#!/usr/bin/env node +/* eslint-disable */ +//prettier-ignore +(()=>{var t_e=Object.create;var vR=Object.defineProperty;var r_e=Object.getOwnPropertyDescriptor;var n_e=Object.getOwnPropertyNames;var i_e=Object.getPrototypeOf,s_e=Object.prototype.hasOwnProperty;var ve=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var Et=(t,e)=>()=>(t&&(e=t(t=0)),e);var _=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Vt=(t,e)=>{for(var r in e)vR(t,r,{get:e[r],enumerable:!0})},o_e=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of n_e(e))!s_e.call(t,a)&&a!==r&&vR(t,a,{get:()=>e[a],enumerable:!(o=r_e(e,a))||o.enumerable});return t};var Ze=(t,e,r)=>(r=t!=null?t_e(i_e(t)):{},o_e(e||!t||!t.__esModule?vR(r,"default",{value:t,enumerable:!0}):r,t));var Bi={};Vt(Bi,{SAFE_TIME:()=>D7,S_IFDIR:()=>iD,S_IFLNK:()=>sD,S_IFMT:()=>Uu,S_IFREG:()=>Dw});var Uu,iD,Dw,sD,D7,P7=Et(()=>{Uu=61440,iD=16384,Dw=32768,sD=40960,D7=456789e3});var nr={};Vt(nr,{EBADF:()=>Io,EBUSY:()=>a_e,EEXIST:()=>p_e,EINVAL:()=>c_e,EISDIR:()=>f_e,ENOENT:()=>u_e,ENOSYS:()=>l_e,ENOTDIR:()=>A_e,ENOTEMPTY:()=>g_e,EOPNOTSUPP:()=>d_e,EROFS:()=>h_e,ERR_DIR_CLOSED:()=>DR});function Tl(t,e){return Object.assign(new Error(`${t}: ${e}`),{code:t})}function a_e(t){return Tl("EBUSY",t)}function l_e(t,e){return Tl("ENOSYS",`${t}, ${e}`)}function c_e(t){return Tl("EINVAL",`invalid argument, ${t}`)}function Io(t){return Tl("EBADF",`bad file descriptor, ${t}`)}function u_e(t){return Tl("ENOENT",`no such file or directory, ${t}`)}function A_e(t){return Tl("ENOTDIR",`not a directory, ${t}`)}function f_e(t){return Tl("EISDIR",`illegal operation on a directory, ${t}`)}function p_e(t){return Tl("EEXIST",`file already exists, ${t}`)}function h_e(t){return Tl("EROFS",`read-only filesystem, ${t}`)}function g_e(t){return Tl("ENOTEMPTY",`directory not empty, ${t}`)}function d_e(t){return Tl("EOPNOTSUPP",`operation not supported, ${t}`)}function DR(){return Tl("ERR_DIR_CLOSED","Directory handle was closed")}var oD=Et(()=>{});var wa={};Vt(wa,{BigIntStatsEntry:()=>qd,DEFAULT_MODE:()=>bR,DirEntry:()=>PR,StatEntry:()=>Hd,areStatsEqual:()=>xR,clearStats:()=>aD,convertToBigIntStats:()=>y_e,makeDefaultStats:()=>S7,makeEmptyStats:()=>m_e});function S7(){return new Hd}function m_e(){return aD(S7())}function aD(t){for(let e in t)if(Object.hasOwn(t,e)){let r=t[e];typeof r=="number"?t[e]=0:typeof r=="bigint"?t[e]=BigInt(0):SR.types.isDate(r)&&(t[e]=new Date(0))}return t}function y_e(t){let e=new qd;for(let r in t)if(Object.hasOwn(t,r)){let o=t[r];typeof o=="number"?e[r]=BigInt(o):SR.types.isDate(o)&&(e[r]=new Date(o))}return e.atimeNs=e.atimeMs*BigInt(1e6),e.mtimeNs=e.mtimeMs*BigInt(1e6),e.ctimeNs=e.ctimeMs*BigInt(1e6),e.birthtimeNs=e.birthtimeMs*BigInt(1e6),e}function xR(t,e){if(t.atimeMs!==e.atimeMs||t.birthtimeMs!==e.birthtimeMs||t.blksize!==e.blksize||t.blocks!==e.blocks||t.ctimeMs!==e.ctimeMs||t.dev!==e.dev||t.gid!==e.gid||t.ino!==e.ino||t.isBlockDevice()!==e.isBlockDevice()||t.isCharacterDevice()!==e.isCharacterDevice()||t.isDirectory()!==e.isDirectory()||t.isFIFO()!==e.isFIFO()||t.isFile()!==e.isFile()||t.isSocket()!==e.isSocket()||t.isSymbolicLink()!==e.isSymbolicLink()||t.mode!==e.mode||t.mtimeMs!==e.mtimeMs||t.nlink!==e.nlink||t.rdev!==e.rdev||t.size!==e.size||t.uid!==e.uid)return!1;let r=t,o=e;return!(r.atimeNs!==o.atimeNs||r.mtimeNs!==o.mtimeNs||r.ctimeNs!==o.ctimeNs||r.birthtimeNs!==o.birthtimeNs)}var SR,bR,PR,Hd,qd,kR=Et(()=>{SR=Ze(ve("util")),bR=33188,PR=class{constructor(){this.name="";this.path="";this.mode=0}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},Hd=class{constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atimeMs=0;this.mtimeMs=0;this.ctimeMs=0;this.birthtimeMs=0;this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=0;this.ino=0;this.mode=bR;this.nlink=1;this.rdev=0;this.blocks=1}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},qd=class{constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);this.blksize=BigInt(0);this.atimeMs=BigInt(0);this.mtimeMs=BigInt(0);this.ctimeMs=BigInt(0);this.birthtimeMs=BigInt(0);this.atimeNs=BigInt(0);this.mtimeNs=BigInt(0);this.ctimeNs=BigInt(0);this.birthtimeNs=BigInt(0);this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=BigInt(0);this.ino=BigInt(0);this.mode=BigInt(bR);this.nlink=BigInt(1);this.rdev=BigInt(0);this.blocks=BigInt(1)}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&BigInt(61440))===BigInt(16384)}isFIFO(){return!1}isFile(){return(this.mode&BigInt(61440))===BigInt(32768)}isSocket(){return!1}isSymbolicLink(){return(this.mode&BigInt(61440))===BigInt(40960)}}});function B_e(t){let e,r;if(e=t.match(w_e))t=e[1];else if(r=t.match(I_e))t=`\\\\${r[1]?".\\":""}${r[2]}`;else return t;return t.replace(/\//g,"\\")}function v_e(t){t=t.replace(/\\/g,"/");let e,r;return(e=t.match(E_e))?t=`/${e[1]}`:(r=t.match(C_e))&&(t=`/unc/${r[1]?".dot/":""}${r[2]}`),t}function lD(t,e){return t===ue?x7(e):QR(e)}var Pw,It,dr,ue,K,b7,E_e,C_e,w_e,I_e,QR,x7,Ia=Et(()=>{Pw=Ze(ve("path")),It={root:"/",dot:".",parent:".."},dr={home:"~",nodeModules:"node_modules",manifest:"package.json",lockfile:"yarn.lock",virtual:"__virtual__",pnpJs:".pnp.js",pnpCjs:".pnp.cjs",pnpData:".pnp.data.json",pnpEsmLoader:".pnp.loader.mjs",rc:".yarnrc.yml",env:".env"},ue=Object.create(Pw.default),K=Object.create(Pw.default.posix);ue.cwd=()=>process.cwd();K.cwd=process.platform==="win32"?()=>QR(process.cwd()):process.cwd;process.platform==="win32"&&(K.resolve=(...t)=>t.length>0&&K.isAbsolute(t[0])?Pw.default.posix.resolve(...t):Pw.default.posix.resolve(K.cwd(),...t));b7=function(t,e,r){return e=t.normalize(e),r=t.normalize(r),e===r?".":(e.endsWith(t.sep)||(e=e+t.sep),r.startsWith(e)?r.slice(e.length):null)};ue.contains=(t,e)=>b7(ue,t,e);K.contains=(t,e)=>b7(K,t,e);E_e=/^([a-zA-Z]:.*)$/,C_e=/^\/\/(\.\/)?(.*)$/,w_e=/^\/([a-zA-Z]:.*)$/,I_e=/^\/unc\/(\.dot\/)?(.*)$/;QR=process.platform==="win32"?v_e:t=>t,x7=process.platform==="win32"?B_e:t=>t;ue.fromPortablePath=x7;ue.toPortablePath=QR});async function cD(t,e){let r="0123456789abcdef";await t.mkdirPromise(e.indexPath,{recursive:!0});let o=[];for(let a of r)for(let n of r)o.push(t.mkdirPromise(t.pathUtils.join(e.indexPath,`${a}${n}`),{recursive:!0}));return await Promise.all(o),e.indexPath}async function k7(t,e,r,o,a){let n=t.pathUtils.normalize(e),u=r.pathUtils.normalize(o),A=[],p=[],{atime:h,mtime:E}=a.stableTime?{atime:R0,mtime:R0}:await r.lstatPromise(u);await t.mkdirpPromise(t.pathUtils.dirname(e),{utimes:[h,E]}),await FR(A,p,t,n,r,u,{...a,didParentExist:!0});for(let I of A)await I();await Promise.all(p.map(I=>I()))}async function FR(t,e,r,o,a,n,u){let A=u.didParentExist?await Q7(r,o):null,p=await a.lstatPromise(n),{atime:h,mtime:E}=u.stableTime?{atime:R0,mtime:R0}:p,I;switch(!0){case p.isDirectory():I=await P_e(t,e,r,o,A,a,n,p,u);break;case p.isFile():I=await x_e(t,e,r,o,A,a,n,p,u);break;case p.isSymbolicLink():I=await k_e(t,e,r,o,A,a,n,p,u);break;default:throw new Error(`Unsupported file type (${p.mode})`)}return(u.linkStrategy?.type!=="HardlinkFromIndex"||!p.isFile())&&((I||A?.mtime?.getTime()!==E.getTime()||A?.atime?.getTime()!==h.getTime())&&(e.push(()=>r.lutimesPromise(o,h,E)),I=!0),(A===null||(A.mode&511)!==(p.mode&511))&&(e.push(()=>r.chmodPromise(o,p.mode&511)),I=!0)),I}async function Q7(t,e){try{return await t.lstatPromise(e)}catch{return null}}async function P_e(t,e,r,o,a,n,u,A,p){if(a!==null&&!a.isDirectory())if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;let h=!1;a===null&&(t.push(async()=>{try{await r.mkdirPromise(o,{mode:A.mode})}catch(v){if(v.code!=="EEXIST")throw v}}),h=!0);let E=await n.readdirPromise(u),I=p.didParentExist&&!a?{...p,didParentExist:!1}:p;if(p.stableSort)for(let v of E.sort())await FR(t,e,r,r.pathUtils.join(o,v),n,n.pathUtils.join(u,v),I)&&(h=!0);else(await Promise.all(E.map(async x=>{await FR(t,e,r,r.pathUtils.join(o,x),n,n.pathUtils.join(u,x),I)}))).some(x=>x)&&(h=!0);return h}async function S_e(t,e,r,o,a,n,u,A,p,h){let E=await n.checksumFilePromise(u,{algorithm:"sha1"}),I=420,v=A.mode&511,x=`${E}${v!==I?v.toString(8):""}`,C=r.pathUtils.join(h.indexPath,E.slice(0,2),`${x}.dat`),R;(ce=>(ce[ce.Lock=0]="Lock",ce[ce.Rename=1]="Rename"))(R||={});let L=1,U=await Q7(r,C);if(a){let ae=U&&a.dev===U.dev&&a.ino===U.ino,le=U?.mtimeMs!==D_e;if(ae&&le&&h.autoRepair&&(L=0,U=null),!ae)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1}let z=!U&&L===1?`${C}.${Math.floor(Math.random()*4294967296).toString(16).padStart(8,"0")}`:null,te=!1;return t.push(async()=>{if(!U&&(L===0&&await r.lockPromise(C,async()=>{let ae=await n.readFilePromise(u);await r.writeFilePromise(C,ae)}),L===1&&z)){let ae=await n.readFilePromise(u);await r.writeFilePromise(z,ae);try{await r.linkPromise(z,C)}catch(le){if(le.code==="EEXIST")te=!0,await r.unlinkPromise(z);else throw le}}a||await r.linkPromise(C,o)}),e.push(async()=>{U||(await r.lutimesPromise(C,R0,R0),v!==I&&await r.chmodPromise(C,v)),z&&!te&&await r.unlinkPromise(z)}),!1}async function b_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{let h=await n.readFilePromise(u);await r.writeFilePromise(o,h)}),!0}async function x_e(t,e,r,o,a,n,u,A,p){return p.linkStrategy?.type==="HardlinkFromIndex"?S_e(t,e,r,o,a,n,u,A,p,p.linkStrategy):b_e(t,e,r,o,a,n,u,A,p)}async function k_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{await r.symlinkPromise(lD(r.pathUtils,await n.readlinkPromise(u)),o)}),!0}var R0,D_e,RR=Et(()=>{Ia();R0=new Date(456789e3*1e3),D_e=R0.getTime()});function uD(t,e,r,o){let a=()=>{let n=r.shift();if(typeof n>"u")return null;let u=t.pathUtils.join(e,n);return Object.assign(t.statSync(u),{name:n,path:void 0})};return new Sw(e,a,o)}var Sw,F7=Et(()=>{oD();Sw=class{constructor(e,r,o={}){this.path=e;this.nextDirent=r;this.opts=o;this.closed=!1}throwIfClosed(){if(this.closed)throw DR()}async*[Symbol.asyncIterator](){try{let e;for(;(e=await this.read())!==null;)yield e}finally{await this.close()}}read(e){let r=this.readSync();return typeof e<"u"?e(null,r):Promise.resolve(r)}readSync(){return this.throwIfClosed(),this.nextDirent()}close(e){return this.closeSync(),typeof e<"u"?e(null):Promise.resolve()}closeSync(){this.throwIfClosed(),this.opts.onClose?.(),this.closed=!0}}});function R7(t,e){if(t!==e)throw new Error(`Invalid StatWatcher status: expected '${e}', got '${t}'`)}var T7,AD,N7=Et(()=>{T7=ve("events");kR();AD=class t extends T7.EventEmitter{constructor(r,o,{bigint:a=!1}={}){super();this.status="ready";this.changeListeners=new Map;this.startTimeout=null;this.fakeFs=r,this.path=o,this.bigint=a,this.lastStats=this.stat()}static create(r,o,a){let n=new t(r,o,a);return n.start(),n}start(){R7(this.status,"ready"),this.status="running",this.startTimeout=setTimeout(()=>{this.startTimeout=null,this.fakeFs.existsSync(this.path)||this.emit("change",this.lastStats,this.lastStats)},3)}stop(){R7(this.status,"running"),this.status="stopped",this.startTimeout!==null&&(clearTimeout(this.startTimeout),this.startTimeout=null),this.emit("stop")}stat(){try{return this.fakeFs.statSync(this.path,{bigint:this.bigint})}catch{let o=this.bigint?new qd:new Hd;return aD(o)}}makeInterval(r){let o=setInterval(()=>{let a=this.stat(),n=this.lastStats;xR(a,n)||(this.lastStats=a,this.emit("change",a,n))},r.interval);return r.persistent?o:o.unref()}registerChangeListener(r,o){this.addListener("change",r),this.changeListeners.set(r,this.makeInterval(o))}unregisterChangeListener(r){this.removeListener("change",r);let o=this.changeListeners.get(r);typeof o<"u"&&clearInterval(o),this.changeListeners.delete(r)}unregisterAllChangeListeners(){for(let r of this.changeListeners.keys())this.unregisterChangeListener(r)}hasChangeListeners(){return this.changeListeners.size>0}ref(){for(let r of this.changeListeners.values())r.ref();return this}unref(){for(let r of this.changeListeners.values())r.unref();return this}}});function jd(t,e,r,o){let a,n,u,A;switch(typeof r){case"function":a=!1,n=!0,u=5007,A=r;break;default:({bigint:a=!1,persistent:n=!0,interval:u=5007}=r),A=o;break}let p=fD.get(t);typeof p>"u"&&fD.set(t,p=new Map);let h=p.get(e);return typeof h>"u"&&(h=AD.create(t,e,{bigint:a}),p.set(e,h)),h.registerChangeListener(A,{persistent:n,interval:u}),h}function T0(t,e,r){let o=fD.get(t);if(typeof o>"u")return;let a=o.get(e);typeof a>"u"||(typeof r>"u"?a.unregisterAllChangeListeners():a.unregisterChangeListener(r),a.hasChangeListeners()||(a.stop(),o.delete(e)))}function N0(t){let e=fD.get(t);if(!(typeof e>"u"))for(let r of e.keys())T0(t,r)}var fD,TR=Et(()=>{N7();fD=new WeakMap});function Q_e(t){let e=t.match(/\r?\n/g);if(e===null)return M7.EOL;let r=e.filter(a=>a===`\r +`).length,o=e.length-r;return r>o?`\r +`:` +`}function L0(t,e){return e.replace(/\r?\n/g,Q_e(t))}var L7,M7,hf,_u,M0=Et(()=>{L7=ve("crypto"),M7=ve("os");RR();Ia();hf=class{constructor(e){this.pathUtils=e}async*genTraversePromise(e,{stableSort:r=!1}={}){let o=[e];for(;o.length>0;){let a=o.shift();if((await this.lstatPromise(a)).isDirectory()){let u=await this.readdirPromise(a);if(r)for(let A of u.sort())o.push(this.pathUtils.join(a,A));else throw new Error("Not supported")}else yield a}}async checksumFilePromise(e,{algorithm:r="sha512"}={}){let o=await this.openPromise(e,"r");try{let n=Buffer.allocUnsafeSlow(65536),u=(0,L7.createHash)(r),A=0;for(;(A=await this.readPromise(o,n,0,65536))!==0;)u.update(A===65536?n:n.slice(0,A));return u.digest("hex")}finally{await this.closePromise(o)}}async removePromise(e,{recursive:r=!0,maxRetries:o=5}={}){let a;try{a=await this.lstatPromise(e)}catch(n){if(n.code==="ENOENT")return;throw n}if(a.isDirectory()){if(r){let n=await this.readdirPromise(e);await Promise.all(n.map(u=>this.removePromise(this.pathUtils.resolve(e,u))))}for(let n=0;n<=o;n++)try{await this.rmdirPromise(e);break}catch(u){if(u.code!=="EBUSY"&&u.code!=="ENOTEMPTY")throw u;n<o&&await new Promise(A=>setTimeout(A,n*100))}}else await this.unlinkPromise(e)}removeSync(e,{recursive:r=!0}={}){let o;try{o=this.lstatSync(e)}catch(a){if(a.code==="ENOENT")return;throw a}if(o.isDirectory()){if(r)for(let a of this.readdirSync(e))this.removeSync(this.pathUtils.resolve(e,a));this.rmdirSync(e)}else this.unlinkSync(e)}async mkdirpPromise(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let u=2;u<=a.length;++u){let A=a.slice(0,u).join(this.pathUtils.sep);if(!this.existsSync(A)){try{await this.mkdirPromise(A)}catch(p){if(p.code==="EEXIST")continue;throw p}if(n??=A,r!=null&&await this.chmodPromise(A,r),o!=null)await this.utimesPromise(A,o[0],o[1]);else{let p=await this.statPromise(this.pathUtils.dirname(A));await this.utimesPromise(A,p.atime,p.mtime)}}}return n}mkdirpSync(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let u=2;u<=a.length;++u){let A=a.slice(0,u).join(this.pathUtils.sep);if(!this.existsSync(A)){try{this.mkdirSync(A)}catch(p){if(p.code==="EEXIST")continue;throw p}if(n??=A,r!=null&&this.chmodSync(A,r),o!=null)this.utimesSync(A,o[0],o[1]);else{let p=this.statSync(this.pathUtils.dirname(A));this.utimesSync(A,p.atime,p.mtime)}}}return n}async copyPromise(e,r,{baseFs:o=this,overwrite:a=!0,stableSort:n=!1,stableTime:u=!1,linkStrategy:A=null}={}){return await k7(this,e,o,r,{overwrite:a,stableSort:n,stableTime:u,linkStrategy:A})}copySync(e,r,{baseFs:o=this,overwrite:a=!0}={}){let n=o.lstatSync(r),u=this.existsSync(e);if(n.isDirectory()){this.mkdirpSync(e);let p=o.readdirSync(r);for(let h of p)this.copySync(this.pathUtils.join(e,h),o.pathUtils.join(r,h),{baseFs:o,overwrite:a})}else if(n.isFile()){if(!u||a){u&&this.removeSync(e);let p=o.readFileSync(r);this.writeFileSync(e,p)}}else if(n.isSymbolicLink()){if(!u||a){u&&this.removeSync(e);let p=o.readlinkSync(r);this.symlinkSync(lD(this.pathUtils,p),e)}}else throw new Error(`Unsupported file type (file: ${r}, mode: 0o${n.mode.toString(8).padStart(6,"0")})`);let A=n.mode&511;this.chmodSync(e,A)}async changeFilePromise(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBufferPromise(e,r,o):this.changeFileTextPromise(e,r,o)}async changeFileBufferPromise(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=await this.readFilePromise(e)}catch{}Buffer.compare(a,r)!==0&&await this.writeFilePromise(e,r,{mode:o})}async changeFileTextPromise(e,r,{automaticNewlines:o,mode:a}={}){let n="";try{n=await this.readFilePromise(e,"utf8")}catch{}let u=o?L0(n,r):r;n!==u&&await this.writeFilePromise(e,u,{mode:a})}changeFileSync(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBufferSync(e,r,o):this.changeFileTextSync(e,r,o)}changeFileBufferSync(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=this.readFileSync(e)}catch{}Buffer.compare(a,r)!==0&&this.writeFileSync(e,r,{mode:o})}changeFileTextSync(e,r,{automaticNewlines:o=!1,mode:a}={}){let n="";try{n=this.readFileSync(e,"utf8")}catch{}let u=o?L0(n,r):r;n!==u&&this.writeFileSync(e,u,{mode:a})}async movePromise(e,r){try{await this.renamePromise(e,r)}catch(o){if(o.code==="EXDEV")await this.copyPromise(r,e),await this.removePromise(e);else throw o}}moveSync(e,r){try{this.renameSync(e,r)}catch(o){if(o.code==="EXDEV")this.copySync(r,e),this.removeSync(e);else throw o}}async lockPromise(e,r){let o=`${e}.flock`,a=1e3/60,n=Date.now(),u=null,A=async()=>{let p;try{[p]=await this.readJsonPromise(o)}catch{return Date.now()-n<500}try{return process.kill(p,0),!0}catch{return!1}};for(;u===null;)try{u=await this.openPromise(o,"wx")}catch(p){if(p.code==="EEXIST"){if(!await A())try{await this.unlinkPromise(o);continue}catch{}if(Date.now()-n<60*1e3)await new Promise(h=>setTimeout(h,a));else throw new Error(`Couldn't acquire a lock in a reasonable time (via ${o})`)}else throw p}await this.writePromise(u,JSON.stringify([process.pid]));try{return await r()}finally{try{await this.closePromise(u),await this.unlinkPromise(o)}catch{}}}async readJsonPromise(e){let r=await this.readFilePromise(e,"utf8");try{return JSON.parse(r)}catch(o){throw o.message+=` (in ${e})`,o}}readJsonSync(e){let r=this.readFileSync(e,"utf8");try{return JSON.parse(r)}catch(o){throw o.message+=` (in ${e})`,o}}async writeJsonPromise(e,r,{compact:o=!1}={}){let a=o?0:2;return await this.writeFilePromise(e,`${JSON.stringify(r,null,a)} +`)}writeJsonSync(e,r,{compact:o=!1}={}){let a=o?0:2;return this.writeFileSync(e,`${JSON.stringify(r,null,a)} +`)}async preserveTimePromise(e,r){let o=await this.lstatPromise(e),a=await r();typeof a<"u"&&(e=a),await this.lutimesPromise(e,o.atime,o.mtime)}async preserveTimeSync(e,r){let o=this.lstatSync(e),a=r();typeof a<"u"&&(e=a),this.lutimesSync(e,o.atime,o.mtime)}},_u=class extends hf{constructor(){super(K)}}});var bs,gf=Et(()=>{M0();bs=class extends hf{getExtractHint(e){return this.baseFs.getExtractHint(e)}resolve(e){return this.mapFromBase(this.baseFs.resolve(this.mapToBase(e)))}getRealPath(){return this.mapFromBase(this.baseFs.getRealPath())}async openPromise(e,r,o){return this.baseFs.openPromise(this.mapToBase(e),r,o)}openSync(e,r,o){return this.baseFs.openSync(this.mapToBase(e),r,o)}async opendirPromise(e,r){return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(e),r),{path:e})}opendirSync(e,r){return Object.assign(this.baseFs.opendirSync(this.mapToBase(e),r),{path:e})}async readPromise(e,r,o,a,n){return await this.baseFs.readPromise(e,r,o,a,n)}readSync(e,r,o,a,n){return this.baseFs.readSync(e,r,o,a,n)}async writePromise(e,r,o,a,n){return typeof r=="string"?await this.baseFs.writePromise(e,r,o):await this.baseFs.writePromise(e,r,o,a,n)}writeSync(e,r,o,a,n){return typeof r=="string"?this.baseFs.writeSync(e,r,o):this.baseFs.writeSync(e,r,o,a,n)}async closePromise(e){return this.baseFs.closePromise(e)}closeSync(e){this.baseFs.closeSync(e)}createReadStream(e,r){return this.baseFs.createReadStream(e!==null?this.mapToBase(e):e,r)}createWriteStream(e,r){return this.baseFs.createWriteStream(e!==null?this.mapToBase(e):e,r)}async realpathPromise(e){return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(e)))}realpathSync(e){return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(e)))}async existsPromise(e){return this.baseFs.existsPromise(this.mapToBase(e))}existsSync(e){return this.baseFs.existsSync(this.mapToBase(e))}accessSync(e,r){return this.baseFs.accessSync(this.mapToBase(e),r)}async accessPromise(e,r){return this.baseFs.accessPromise(this.mapToBase(e),r)}async statPromise(e,r){return this.baseFs.statPromise(this.mapToBase(e),r)}statSync(e,r){return this.baseFs.statSync(this.mapToBase(e),r)}async fstatPromise(e,r){return this.baseFs.fstatPromise(e,r)}fstatSync(e,r){return this.baseFs.fstatSync(e,r)}lstatPromise(e,r){return this.baseFs.lstatPromise(this.mapToBase(e),r)}lstatSync(e,r){return this.baseFs.lstatSync(this.mapToBase(e),r)}async fchmodPromise(e,r){return this.baseFs.fchmodPromise(e,r)}fchmodSync(e,r){return this.baseFs.fchmodSync(e,r)}async chmodPromise(e,r){return this.baseFs.chmodPromise(this.mapToBase(e),r)}chmodSync(e,r){return this.baseFs.chmodSync(this.mapToBase(e),r)}async fchownPromise(e,r,o){return this.baseFs.fchownPromise(e,r,o)}fchownSync(e,r,o){return this.baseFs.fchownSync(e,r,o)}async chownPromise(e,r,o){return this.baseFs.chownPromise(this.mapToBase(e),r,o)}chownSync(e,r,o){return this.baseFs.chownSync(this.mapToBase(e),r,o)}async renamePromise(e,r){return this.baseFs.renamePromise(this.mapToBase(e),this.mapToBase(r))}renameSync(e,r){return this.baseFs.renameSync(this.mapToBase(e),this.mapToBase(r))}async copyFilePromise(e,r,o=0){return this.baseFs.copyFilePromise(this.mapToBase(e),this.mapToBase(r),o)}copyFileSync(e,r,o=0){return this.baseFs.copyFileSync(this.mapToBase(e),this.mapToBase(r),o)}async appendFilePromise(e,r,o){return this.baseFs.appendFilePromise(this.fsMapToBase(e),r,o)}appendFileSync(e,r,o){return this.baseFs.appendFileSync(this.fsMapToBase(e),r,o)}async writeFilePromise(e,r,o){return this.baseFs.writeFilePromise(this.fsMapToBase(e),r,o)}writeFileSync(e,r,o){return this.baseFs.writeFileSync(this.fsMapToBase(e),r,o)}async unlinkPromise(e){return this.baseFs.unlinkPromise(this.mapToBase(e))}unlinkSync(e){return this.baseFs.unlinkSync(this.mapToBase(e))}async utimesPromise(e,r,o){return this.baseFs.utimesPromise(this.mapToBase(e),r,o)}utimesSync(e,r,o){return this.baseFs.utimesSync(this.mapToBase(e),r,o)}async lutimesPromise(e,r,o){return this.baseFs.lutimesPromise(this.mapToBase(e),r,o)}lutimesSync(e,r,o){return this.baseFs.lutimesSync(this.mapToBase(e),r,o)}async mkdirPromise(e,r){return this.baseFs.mkdirPromise(this.mapToBase(e),r)}mkdirSync(e,r){return this.baseFs.mkdirSync(this.mapToBase(e),r)}async rmdirPromise(e,r){return this.baseFs.rmdirPromise(this.mapToBase(e),r)}rmdirSync(e,r){return this.baseFs.rmdirSync(this.mapToBase(e),r)}async rmPromise(e,r){return this.baseFs.rmPromise(this.mapToBase(e),r)}rmSync(e,r){return this.baseFs.rmSync(this.mapToBase(e),r)}async linkPromise(e,r){return this.baseFs.linkPromise(this.mapToBase(e),this.mapToBase(r))}linkSync(e,r){return this.baseFs.linkSync(this.mapToBase(e),this.mapToBase(r))}async symlinkPromise(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkPromise(this.mapToBase(e),a,o);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),u=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkPromise(u,a,o)}symlinkSync(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkSync(this.mapToBase(e),a,o);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),u=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkSync(u,a,o)}async readFilePromise(e,r){return this.baseFs.readFilePromise(this.fsMapToBase(e),r)}readFileSync(e,r){return this.baseFs.readFileSync(this.fsMapToBase(e),r)}readdirPromise(e,r){return this.baseFs.readdirPromise(this.mapToBase(e),r)}readdirSync(e,r){return this.baseFs.readdirSync(this.mapToBase(e),r)}async readlinkPromise(e){return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(e)))}readlinkSync(e){return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(e)))}async truncatePromise(e,r){return this.baseFs.truncatePromise(this.mapToBase(e),r)}truncateSync(e,r){return this.baseFs.truncateSync(this.mapToBase(e),r)}async ftruncatePromise(e,r){return this.baseFs.ftruncatePromise(e,r)}ftruncateSync(e,r){return this.baseFs.ftruncateSync(e,r)}watch(e,r,o){return this.baseFs.watch(this.mapToBase(e),r,o)}watchFile(e,r,o){return this.baseFs.watchFile(this.mapToBase(e),r,o)}unwatchFile(e,r){return this.baseFs.unwatchFile(this.mapToBase(e),r)}fsMapToBase(e){return typeof e=="number"?e:this.mapToBase(e)}}});var Hu,O7=Et(()=>{gf();Hu=class extends bs{constructor(e,{baseFs:r,pathUtils:o}){super(o),this.target=e,this.baseFs=r}getRealPath(){return this.target}getBaseFs(){return this.baseFs}mapFromBase(e){return e}mapToBase(e){return e}}});function U7(t){let e=t;return typeof t.path=="string"&&(e.path=ue.toPortablePath(t.path)),e}var _7,Tn,O0=Et(()=>{_7=Ze(ve("fs"));M0();Ia();Tn=class extends _u{constructor(e=_7.default){super(),this.realFs=e}getExtractHint(){return!1}getRealPath(){return It.root}resolve(e){return K.resolve(e)}async openPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.open(ue.fromPortablePath(e),r,o,this.makeCallback(a,n))})}openSync(e,r,o){return this.realFs.openSync(ue.fromPortablePath(e),r,o)}async opendirPromise(e,r){return await new Promise((o,a)=>{typeof r<"u"?this.realFs.opendir(ue.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.opendir(ue.fromPortablePath(e),this.makeCallback(o,a))}).then(o=>{let a=o;return Object.defineProperty(a,"path",{value:e,configurable:!0,writable:!0}),a})}opendirSync(e,r){let a=typeof r<"u"?this.realFs.opendirSync(ue.fromPortablePath(e),r):this.realFs.opendirSync(ue.fromPortablePath(e));return Object.defineProperty(a,"path",{value:e,configurable:!0,writable:!0}),a}async readPromise(e,r,o=0,a=0,n=-1){return await new Promise((u,A)=>{this.realFs.read(e,r,o,a,n,(p,h)=>{p?A(p):u(h)})})}readSync(e,r,o,a,n){return this.realFs.readSync(e,r,o,a,n)}async writePromise(e,r,o,a,n){return await new Promise((u,A)=>typeof r=="string"?this.realFs.write(e,r,o,this.makeCallback(u,A)):this.realFs.write(e,r,o,a,n,this.makeCallback(u,A)))}writeSync(e,r,o,a,n){return typeof r=="string"?this.realFs.writeSync(e,r,o):this.realFs.writeSync(e,r,o,a,n)}async closePromise(e){await new Promise((r,o)=>{this.realFs.close(e,this.makeCallback(r,o))})}closeSync(e){this.realFs.closeSync(e)}createReadStream(e,r){let o=e!==null?ue.fromPortablePath(e):e;return this.realFs.createReadStream(o,r)}createWriteStream(e,r){let o=e!==null?ue.fromPortablePath(e):e;return this.realFs.createWriteStream(o,r)}async realpathPromise(e){return await new Promise((r,o)=>{this.realFs.realpath(ue.fromPortablePath(e),{},this.makeCallback(r,o))}).then(r=>ue.toPortablePath(r))}realpathSync(e){return ue.toPortablePath(this.realFs.realpathSync(ue.fromPortablePath(e),{}))}async existsPromise(e){return await new Promise(r=>{this.realFs.exists(ue.fromPortablePath(e),r)})}accessSync(e,r){return this.realFs.accessSync(ue.fromPortablePath(e),r)}async accessPromise(e,r){return await new Promise((o,a)=>{this.realFs.access(ue.fromPortablePath(e),r,this.makeCallback(o,a))})}existsSync(e){return this.realFs.existsSync(ue.fromPortablePath(e))}async statPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.stat(ue.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.stat(ue.fromPortablePath(e),this.makeCallback(o,a))})}statSync(e,r){return r?this.realFs.statSync(ue.fromPortablePath(e),r):this.realFs.statSync(ue.fromPortablePath(e))}async fstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.fstat(e,r,this.makeCallback(o,a)):this.realFs.fstat(e,this.makeCallback(o,a))})}fstatSync(e,r){return r?this.realFs.fstatSync(e,r):this.realFs.fstatSync(e)}async lstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.lstat(ue.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.lstat(ue.fromPortablePath(e),this.makeCallback(o,a))})}lstatSync(e,r){return r?this.realFs.lstatSync(ue.fromPortablePath(e),r):this.realFs.lstatSync(ue.fromPortablePath(e))}async fchmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.fchmod(e,r,this.makeCallback(o,a))})}fchmodSync(e,r){return this.realFs.fchmodSync(e,r)}async chmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.chmod(ue.fromPortablePath(e),r,this.makeCallback(o,a))})}chmodSync(e,r){return this.realFs.chmodSync(ue.fromPortablePath(e),r)}async fchownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.fchown(e,r,o,this.makeCallback(a,n))})}fchownSync(e,r,o){return this.realFs.fchownSync(e,r,o)}async chownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.chown(ue.fromPortablePath(e),r,o,this.makeCallback(a,n))})}chownSync(e,r,o){return this.realFs.chownSync(ue.fromPortablePath(e),r,o)}async renamePromise(e,r){return await new Promise((o,a)=>{this.realFs.rename(ue.fromPortablePath(e),ue.fromPortablePath(r),this.makeCallback(o,a))})}renameSync(e,r){return this.realFs.renameSync(ue.fromPortablePath(e),ue.fromPortablePath(r))}async copyFilePromise(e,r,o=0){return await new Promise((a,n)=>{this.realFs.copyFile(ue.fromPortablePath(e),ue.fromPortablePath(r),o,this.makeCallback(a,n))})}copyFileSync(e,r,o=0){return this.realFs.copyFileSync(ue.fromPortablePath(e),ue.fromPortablePath(r),o)}async appendFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typeof e=="string"?ue.fromPortablePath(e):e;o?this.realFs.appendFile(u,r,o,this.makeCallback(a,n)):this.realFs.appendFile(u,r,this.makeCallback(a,n))})}appendFileSync(e,r,o){let a=typeof e=="string"?ue.fromPortablePath(e):e;o?this.realFs.appendFileSync(a,r,o):this.realFs.appendFileSync(a,r)}async writeFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typeof e=="string"?ue.fromPortablePath(e):e;o?this.realFs.writeFile(u,r,o,this.makeCallback(a,n)):this.realFs.writeFile(u,r,this.makeCallback(a,n))})}writeFileSync(e,r,o){let a=typeof e=="string"?ue.fromPortablePath(e):e;o?this.realFs.writeFileSync(a,r,o):this.realFs.writeFileSync(a,r)}async unlinkPromise(e){return await new Promise((r,o)=>{this.realFs.unlink(ue.fromPortablePath(e),this.makeCallback(r,o))})}unlinkSync(e){return this.realFs.unlinkSync(ue.fromPortablePath(e))}async utimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.utimes(ue.fromPortablePath(e),r,o,this.makeCallback(a,n))})}utimesSync(e,r,o){this.realFs.utimesSync(ue.fromPortablePath(e),r,o)}async lutimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.lutimes(ue.fromPortablePath(e),r,o,this.makeCallback(a,n))})}lutimesSync(e,r,o){this.realFs.lutimesSync(ue.fromPortablePath(e),r,o)}async mkdirPromise(e,r){return await new Promise((o,a)=>{this.realFs.mkdir(ue.fromPortablePath(e),r,this.makeCallback(o,a))})}mkdirSync(e,r){return this.realFs.mkdirSync(ue.fromPortablePath(e),r)}async rmdirPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rmdir(ue.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.rmdir(ue.fromPortablePath(e),this.makeCallback(o,a))})}rmdirSync(e,r){return this.realFs.rmdirSync(ue.fromPortablePath(e),r)}async rmPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rm(ue.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.rm(ue.fromPortablePath(e),this.makeCallback(o,a))})}rmSync(e,r){return this.realFs.rmSync(ue.fromPortablePath(e),r)}async linkPromise(e,r){return await new Promise((o,a)=>{this.realFs.link(ue.fromPortablePath(e),ue.fromPortablePath(r),this.makeCallback(o,a))})}linkSync(e,r){return this.realFs.linkSync(ue.fromPortablePath(e),ue.fromPortablePath(r))}async symlinkPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.symlink(ue.fromPortablePath(e.replace(/\/+$/,"")),ue.fromPortablePath(r),o,this.makeCallback(a,n))})}symlinkSync(e,r,o){return this.realFs.symlinkSync(ue.fromPortablePath(e.replace(/\/+$/,"")),ue.fromPortablePath(r),o)}async readFilePromise(e,r){return await new Promise((o,a)=>{let n=typeof e=="string"?ue.fromPortablePath(e):e;this.realFs.readFile(n,r,this.makeCallback(o,a))})}readFileSync(e,r){let o=typeof e=="string"?ue.fromPortablePath(e):e;return this.realFs.readFileSync(o,r)}async readdirPromise(e,r){return await new Promise((o,a)=>{r?r.recursive&&process.platform==="win32"?r.withFileTypes?this.realFs.readdir(ue.fromPortablePath(e),r,this.makeCallback(n=>o(n.map(U7)),a)):this.realFs.readdir(ue.fromPortablePath(e),r,this.makeCallback(n=>o(n.map(ue.toPortablePath)),a)):this.realFs.readdir(ue.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.readdir(ue.fromPortablePath(e),this.makeCallback(o,a))})}readdirSync(e,r){return r?r.recursive&&process.platform==="win32"?r.withFileTypes?this.realFs.readdirSync(ue.fromPortablePath(e),r).map(U7):this.realFs.readdirSync(ue.fromPortablePath(e),r).map(ue.toPortablePath):this.realFs.readdirSync(ue.fromPortablePath(e),r):this.realFs.readdirSync(ue.fromPortablePath(e))}async readlinkPromise(e){return await new Promise((r,o)=>{this.realFs.readlink(ue.fromPortablePath(e),this.makeCallback(r,o))}).then(r=>ue.toPortablePath(r))}readlinkSync(e){return ue.toPortablePath(this.realFs.readlinkSync(ue.fromPortablePath(e)))}async truncatePromise(e,r){return await new Promise((o,a)=>{this.realFs.truncate(ue.fromPortablePath(e),r,this.makeCallback(o,a))})}truncateSync(e,r){return this.realFs.truncateSync(ue.fromPortablePath(e),r)}async ftruncatePromise(e,r){return await new Promise((o,a)=>{this.realFs.ftruncate(e,r,this.makeCallback(o,a))})}ftruncateSync(e,r){return this.realFs.ftruncateSync(e,r)}watch(e,r,o){return this.realFs.watch(ue.fromPortablePath(e),r,o)}watchFile(e,r,o){return this.realFs.watchFile(ue.fromPortablePath(e),r,o)}unwatchFile(e,r){return this.realFs.unwatchFile(ue.fromPortablePath(e),r)}makeCallback(e,r){return(o,a)=>{o?r(o):e(a)}}}});var gn,H7=Et(()=>{O0();gf();Ia();gn=class extends bs{constructor(e,{baseFs:r=new Tn}={}){super(K),this.target=this.pathUtils.normalize(e),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.target)}resolve(e){return this.pathUtils.isAbsolute(e)?K.normalize(e):this.baseFs.resolve(K.join(this.target,e))}mapFromBase(e){return e}mapToBase(e){return this.pathUtils.isAbsolute(e)?e:this.pathUtils.join(this.target,e)}}});var q7,qu,j7=Et(()=>{O0();gf();Ia();q7=It.root,qu=class extends bs{constructor(e,{baseFs:r=new Tn}={}){super(K),this.target=this.pathUtils.resolve(It.root,e),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.pathUtils.relative(It.root,this.target))}getTarget(){return this.target}getBaseFs(){return this.baseFs}mapToBase(e){let r=this.pathUtils.normalize(e);if(this.pathUtils.isAbsolute(e))return this.pathUtils.resolve(this.target,this.pathUtils.relative(q7,e));if(r.match(/^\.\.\/?/))throw new Error(`Resolving this path (${e}) would escape the jail`);return this.pathUtils.resolve(this.target,e)}mapFromBase(e){return this.pathUtils.resolve(q7,this.pathUtils.relative(this.target,e))}}});var Gd,G7=Et(()=>{gf();Gd=class extends bs{constructor(r,o){super(o);this.instance=null;this.factory=r}get baseFs(){return this.instance||(this.instance=this.factory()),this.instance}set baseFs(r){this.instance=r}mapFromBase(r){return r}mapToBase(r){return r}}});var U0,Ba,Op,Y7=Et(()=>{U0=ve("fs");M0();O0();TR();oD();Ia();Ba=4278190080,Op=class extends _u{constructor({baseFs:r=new Tn,filter:o=null,magicByte:a=42,maxOpenFiles:n=1/0,useCache:u=!0,maxAge:A=5e3,typeCheck:p=U0.constants.S_IFREG,getMountPoint:h,factoryPromise:E,factorySync:I}){if(Math.floor(a)!==a||!(a>1&&a<=127))throw new Error("The magic byte must be set to a round value between 1 and 127 included");super();this.fdMap=new Map;this.nextFd=3;this.isMount=new Set;this.notMount=new Set;this.realPaths=new Map;this.limitOpenFilesTimeout=null;this.baseFs=r,this.mountInstances=u?new Map:null,this.factoryPromise=E,this.factorySync=I,this.filter=o,this.getMountPoint=h,this.magic=a<<24,this.maxAge=A,this.maxOpenFiles=n,this.typeCheck=p}getExtractHint(r){return this.baseFs.getExtractHint(r)}getRealPath(){return this.baseFs.getRealPath()}saveAndClose(){if(N0(this),this.mountInstances)for(let[r,{childFs:o}]of this.mountInstances.entries())o.saveAndClose?.(),this.mountInstances.delete(r)}discardAndClose(){if(N0(this),this.mountInstances)for(let[r,{childFs:o}]of this.mountInstances.entries())o.discardAndClose?.(),this.mountInstances.delete(r)}resolve(r){return this.baseFs.resolve(r)}remapFd(r,o){let a=this.nextFd++|this.magic;return this.fdMap.set(a,[r,o]),a}async openPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.openPromise(r,o,a),async(n,{subPath:u})=>this.remapFd(n,await n.openPromise(u,o,a)))}openSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.openSync(r,o,a),(n,{subPath:u})=>this.remapFd(n,n.openSync(u,o,a)))}async opendirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.opendirPromise(r,o),async(a,{subPath:n})=>await a.opendirPromise(n,o),{requireSubpath:!1})}opendirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.opendirSync(r,o),(a,{subPath:n})=>a.opendirSync(n,o),{requireSubpath:!1})}async readPromise(r,o,a,n,u){if((r&Ba)!==this.magic)return await this.baseFs.readPromise(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw Io("read");let[p,h]=A;return await p.readPromise(h,o,a,n,u)}readSync(r,o,a,n,u){if((r&Ba)!==this.magic)return this.baseFs.readSync(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw Io("readSync");let[p,h]=A;return p.readSync(h,o,a,n,u)}async writePromise(r,o,a,n,u){if((r&Ba)!==this.magic)return typeof o=="string"?await this.baseFs.writePromise(r,o,a):await this.baseFs.writePromise(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw Io("write");let[p,h]=A;return typeof o=="string"?await p.writePromise(h,o,a):await p.writePromise(h,o,a,n,u)}writeSync(r,o,a,n,u){if((r&Ba)!==this.magic)return typeof o=="string"?this.baseFs.writeSync(r,o,a):this.baseFs.writeSync(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>"u")throw Io("writeSync");let[p,h]=A;return typeof o=="string"?p.writeSync(h,o,a):p.writeSync(h,o,a,n,u)}async closePromise(r){if((r&Ba)!==this.magic)return await this.baseFs.closePromise(r);let o=this.fdMap.get(r);if(typeof o>"u")throw Io("close");this.fdMap.delete(r);let[a,n]=o;return await a.closePromise(n)}closeSync(r){if((r&Ba)!==this.magic)return this.baseFs.closeSync(r);let o=this.fdMap.get(r);if(typeof o>"u")throw Io("closeSync");this.fdMap.delete(r);let[a,n]=o;return a.closeSync(n)}createReadStream(r,o){return r===null?this.baseFs.createReadStream(r,o):this.makeCallSync(r,()=>this.baseFs.createReadStream(r,o),(a,{archivePath:n,subPath:u})=>{let A=a.createReadStream(u,o);return A.path=ue.fromPortablePath(this.pathUtils.join(n,u)),A})}createWriteStream(r,o){return r===null?this.baseFs.createWriteStream(r,o):this.makeCallSync(r,()=>this.baseFs.createWriteStream(r,o),(a,{subPath:n})=>a.createWriteStream(n,o))}async realpathPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.realpathPromise(r),async(o,{archivePath:a,subPath:n})=>{let u=this.realPaths.get(a);return typeof u>"u"&&(u=await this.baseFs.realpathPromise(a),this.realPaths.set(a,u)),this.pathUtils.join(u,this.pathUtils.relative(It.root,await o.realpathPromise(n)))})}realpathSync(r){return this.makeCallSync(r,()=>this.baseFs.realpathSync(r),(o,{archivePath:a,subPath:n})=>{let u=this.realPaths.get(a);return typeof u>"u"&&(u=this.baseFs.realpathSync(a),this.realPaths.set(a,u)),this.pathUtils.join(u,this.pathUtils.relative(It.root,o.realpathSync(n)))})}async existsPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.existsPromise(r),async(o,{subPath:a})=>await o.existsPromise(a))}existsSync(r){return this.makeCallSync(r,()=>this.baseFs.existsSync(r),(o,{subPath:a})=>o.existsSync(a))}async accessPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.accessPromise(r,o),async(a,{subPath:n})=>await a.accessPromise(n,o))}accessSync(r,o){return this.makeCallSync(r,()=>this.baseFs.accessSync(r,o),(a,{subPath:n})=>a.accessSync(n,o))}async statPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.statPromise(r,o),async(a,{subPath:n})=>await a.statPromise(n,o))}statSync(r,o){return this.makeCallSync(r,()=>this.baseFs.statSync(r,o),(a,{subPath:n})=>a.statSync(n,o))}async fstatPromise(r,o){if((r&Ba)!==this.magic)return this.baseFs.fstatPromise(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw Io("fstat");let[n,u]=a;return n.fstatPromise(u,o)}fstatSync(r,o){if((r&Ba)!==this.magic)return this.baseFs.fstatSync(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw Io("fstatSync");let[n,u]=a;return n.fstatSync(u,o)}async lstatPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.lstatPromise(r,o),async(a,{subPath:n})=>await a.lstatPromise(n,o))}lstatSync(r,o){return this.makeCallSync(r,()=>this.baseFs.lstatSync(r,o),(a,{subPath:n})=>a.lstatSync(n,o))}async fchmodPromise(r,o){if((r&Ba)!==this.magic)return this.baseFs.fchmodPromise(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw Io("fchmod");let[n,u]=a;return n.fchmodPromise(u,o)}fchmodSync(r,o){if((r&Ba)!==this.magic)return this.baseFs.fchmodSync(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw Io("fchmodSync");let[n,u]=a;return n.fchmodSync(u,o)}async chmodPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.chmodPromise(r,o),async(a,{subPath:n})=>await a.chmodPromise(n,o))}chmodSync(r,o){return this.makeCallSync(r,()=>this.baseFs.chmodSync(r,o),(a,{subPath:n})=>a.chmodSync(n,o))}async fchownPromise(r,o,a){if((r&Ba)!==this.magic)return this.baseFs.fchownPromise(r,o,a);let n=this.fdMap.get(r);if(typeof n>"u")throw Io("fchown");let[u,A]=n;return u.fchownPromise(A,o,a)}fchownSync(r,o,a){if((r&Ba)!==this.magic)return this.baseFs.fchownSync(r,o,a);let n=this.fdMap.get(r);if(typeof n>"u")throw Io("fchownSync");let[u,A]=n;return u.fchownSync(A,o,a)}async chownPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.chownPromise(r,o,a),async(n,{subPath:u})=>await n.chownPromise(u,o,a))}chownSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.chownSync(r,o,a),(n,{subPath:u})=>n.chownSync(u,o,a))}async renamePromise(r,o){return await this.makeCallPromise(r,async()=>await this.makeCallPromise(o,async()=>await this.baseFs.renamePromise(r,o),async()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})}),async(a,{subPath:n})=>await this.makeCallPromise(o,async()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})},async(u,{subPath:A})=>{if(a!==u)throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"});return await a.renamePromise(n,A)}))}renameSync(r,o){return this.makeCallSync(r,()=>this.makeCallSync(o,()=>this.baseFs.renameSync(r,o),()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})}),(a,{subPath:n})=>this.makeCallSync(o,()=>{throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"})},(u,{subPath:A})=>{if(a!==u)throw Object.assign(new Error("EEXDEV: cross-device link not permitted"),{code:"EEXDEV"});return a.renameSync(n,A)}))}async copyFilePromise(r,o,a=0){let n=async(u,A,p,h)=>{if(a&U0.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${A}' -> ${h}'`),{code:"EXDEV"});if(a&U0.constants.COPYFILE_EXCL&&await this.existsPromise(A))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${A}' -> '${h}'`),{code:"EEXIST"});let E;try{E=await u.readFilePromise(A)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${A}' -> '${h}'`),{code:"EINVAL"})}await p.writeFilePromise(h,E)};return await this.makeCallPromise(r,async()=>await this.makeCallPromise(o,async()=>await this.baseFs.copyFilePromise(r,o,a),async(u,{subPath:A})=>await n(this.baseFs,r,u,A)),async(u,{subPath:A})=>await this.makeCallPromise(o,async()=>await n(u,A,this.baseFs,o),async(p,{subPath:h})=>u!==p?await n(u,A,p,h):await u.copyFilePromise(A,h,a)))}copyFileSync(r,o,a=0){let n=(u,A,p,h)=>{if(a&U0.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${A}' -> ${h}'`),{code:"EXDEV"});if(a&U0.constants.COPYFILE_EXCL&&this.existsSync(A))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${A}' -> '${h}'`),{code:"EEXIST"});let E;try{E=u.readFileSync(A)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${A}' -> '${h}'`),{code:"EINVAL"})}p.writeFileSync(h,E)};return this.makeCallSync(r,()=>this.makeCallSync(o,()=>this.baseFs.copyFileSync(r,o,a),(u,{subPath:A})=>n(this.baseFs,r,u,A)),(u,{subPath:A})=>this.makeCallSync(o,()=>n(u,A,this.baseFs,o),(p,{subPath:h})=>u!==p?n(u,A,p,h):u.copyFileSync(A,h,a)))}async appendFilePromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.appendFilePromise(r,o,a),async(n,{subPath:u})=>await n.appendFilePromise(u,o,a))}appendFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.appendFileSync(r,o,a),(n,{subPath:u})=>n.appendFileSync(u,o,a))}async writeFilePromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.writeFilePromise(r,o,a),async(n,{subPath:u})=>await n.writeFilePromise(u,o,a))}writeFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.writeFileSync(r,o,a),(n,{subPath:u})=>n.writeFileSync(u,o,a))}async unlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.unlinkPromise(r),async(o,{subPath:a})=>await o.unlinkPromise(a))}unlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.unlinkSync(r),(o,{subPath:a})=>o.unlinkSync(a))}async utimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.utimesPromise(r,o,a),async(n,{subPath:u})=>await n.utimesPromise(u,o,a))}utimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.utimesSync(r,o,a),(n,{subPath:u})=>n.utimesSync(u,o,a))}async lutimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.lutimesPromise(r,o,a),async(n,{subPath:u})=>await n.lutimesPromise(u,o,a))}lutimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.lutimesSync(r,o,a),(n,{subPath:u})=>n.lutimesSync(u,o,a))}async mkdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.mkdirPromise(r,o),async(a,{subPath:n})=>await a.mkdirPromise(n,o))}mkdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.mkdirSync(r,o),(a,{subPath:n})=>a.mkdirSync(n,o))}async rmdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.rmdirPromise(r,o),async(a,{subPath:n})=>await a.rmdirPromise(n,o))}rmdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmdirSync(r,o),(a,{subPath:n})=>a.rmdirSync(n,o))}async rmPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.rmPromise(r,o),async(a,{subPath:n})=>await a.rmPromise(n,o))}rmSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmSync(r,o),(a,{subPath:n})=>a.rmSync(n,o))}async linkPromise(r,o){return await this.makeCallPromise(o,async()=>await this.baseFs.linkPromise(r,o),async(a,{subPath:n})=>await a.linkPromise(r,n))}linkSync(r,o){return this.makeCallSync(o,()=>this.baseFs.linkSync(r,o),(a,{subPath:n})=>a.linkSync(r,n))}async symlinkPromise(r,o,a){return await this.makeCallPromise(o,async()=>await this.baseFs.symlinkPromise(r,o,a),async(n,{subPath:u})=>await n.symlinkPromise(r,u))}symlinkSync(r,o,a){return this.makeCallSync(o,()=>this.baseFs.symlinkSync(r,o,a),(n,{subPath:u})=>n.symlinkSync(r,u))}async readFilePromise(r,o){return this.makeCallPromise(r,async()=>await this.baseFs.readFilePromise(r,o),async(a,{subPath:n})=>await a.readFilePromise(n,o))}readFileSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readFileSync(r,o),(a,{subPath:n})=>a.readFileSync(n,o))}async readdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.readdirPromise(r,o),async(a,{subPath:n})=>await a.readdirPromise(n,o),{requireSubpath:!1})}readdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readdirSync(r,o),(a,{subPath:n})=>a.readdirSync(n,o),{requireSubpath:!1})}async readlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.readlinkPromise(r),async(o,{subPath:a})=>await o.readlinkPromise(a))}readlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.readlinkSync(r),(o,{subPath:a})=>o.readlinkSync(a))}async truncatePromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.truncatePromise(r,o),async(a,{subPath:n})=>await a.truncatePromise(n,o))}truncateSync(r,o){return this.makeCallSync(r,()=>this.baseFs.truncateSync(r,o),(a,{subPath:n})=>a.truncateSync(n,o))}async ftruncatePromise(r,o){if((r&Ba)!==this.magic)return this.baseFs.ftruncatePromise(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw Io("ftruncate");let[n,u]=a;return n.ftruncatePromise(u,o)}ftruncateSync(r,o){if((r&Ba)!==this.magic)return this.baseFs.ftruncateSync(r,o);let a=this.fdMap.get(r);if(typeof a>"u")throw Io("ftruncateSync");let[n,u]=a;return n.ftruncateSync(u,o)}watch(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watch(r,o,a),(n,{subPath:u})=>n.watch(u,o,a))}watchFile(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watchFile(r,o,a),()=>jd(this,r,o,a))}unwatchFile(r,o){return this.makeCallSync(r,()=>this.baseFs.unwatchFile(r,o),()=>T0(this,r,o))}async makeCallPromise(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!="string")return await o();let u=this.resolve(r),A=this.findMount(u);return A?n&&A.subPath==="/"?await o():await this.getMountPromise(A.archivePath,async p=>await a(p,A)):await o()}makeCallSync(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!="string")return o();let u=this.resolve(r),A=this.findMount(u);return!A||n&&A.subPath==="/"?o():this.getMountSync(A.archivePath,p=>a(p,A))}findMount(r){if(this.filter&&!this.filter.test(r))return null;let o="";for(;;){let a=r.substring(o.length),n=this.getMountPoint(a,o);if(!n)return null;if(o=this.pathUtils.join(o,n),!this.isMount.has(o)){if(this.notMount.has(o))continue;try{if(this.typeCheck!==null&&(this.baseFs.lstatSync(o).mode&U0.constants.S_IFMT)!==this.typeCheck){this.notMount.add(o);continue}}catch{return null}this.isMount.add(o)}return{archivePath:o,subPath:this.pathUtils.join(It.root,r.substring(o.length))}}}limitOpenFiles(r){if(this.mountInstances===null)return;let o=Date.now(),a=o+this.maxAge,n=r===null?0:this.mountInstances.size-r;for(let[u,{childFs:A,expiresAt:p,refCount:h}]of this.mountInstances.entries())if(!(h!==0||A.hasOpenFileHandles?.())){if(o>=p){A.saveAndClose?.(),this.mountInstances.delete(u),n-=1;continue}else if(r===null||n<=0){a=p;break}A.saveAndClose?.(),this.mountInstances.delete(u),n-=1}this.limitOpenFilesTimeout===null&&(r===null&&this.mountInstances.size>0||r!==null)&&isFinite(a)&&(this.limitOpenFilesTimeout=setTimeout(()=>{this.limitOpenFilesTimeout=null,this.limitOpenFiles(null)},a-o).unref())}async getMountPromise(r,o){if(this.mountInstances){let a=this.mountInstances.get(r);if(!a){let n=await this.factoryPromise(this.baseFs,r);a=this.mountInstances.get(r),a||(a={childFs:n(),expiresAt:0,refCount:0})}this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,a.refCount+=1;try{return await o(a.childFs)}finally{a.refCount-=1}}else{let a=(await this.factoryPromise(this.baseFs,r))();try{return await o(a)}finally{a.saveAndClose?.()}}}getMountSync(r,o){if(this.mountInstances){let a=this.mountInstances.get(r);return a||(a={childFs:this.factorySync(this.baseFs,r),expiresAt:0,refCount:0}),this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,o(a.childFs)}else{let a=this.factorySync(this.baseFs,r);try{return o(a)}finally{a.saveAndClose?.()}}}}});var Zt,pD,W7=Et(()=>{M0();Ia();Zt=()=>Object.assign(new Error("ENOSYS: unsupported filesystem access"),{code:"ENOSYS"}),pD=class t extends hf{static{this.instance=new t}constructor(){super(K)}getExtractHint(){throw Zt()}getRealPath(){throw Zt()}resolve(){throw Zt()}async openPromise(){throw Zt()}openSync(){throw Zt()}async opendirPromise(){throw Zt()}opendirSync(){throw Zt()}async readPromise(){throw Zt()}readSync(){throw Zt()}async writePromise(){throw Zt()}writeSync(){throw Zt()}async closePromise(){throw Zt()}closeSync(){throw Zt()}createWriteStream(){throw Zt()}createReadStream(){throw Zt()}async realpathPromise(){throw Zt()}realpathSync(){throw Zt()}async readdirPromise(){throw Zt()}readdirSync(){throw Zt()}async existsPromise(e){throw Zt()}existsSync(e){throw Zt()}async accessPromise(){throw Zt()}accessSync(){throw Zt()}async statPromise(){throw Zt()}statSync(){throw Zt()}async fstatPromise(e){throw Zt()}fstatSync(e){throw Zt()}async lstatPromise(e){throw Zt()}lstatSync(e){throw Zt()}async fchmodPromise(){throw Zt()}fchmodSync(){throw Zt()}async chmodPromise(){throw Zt()}chmodSync(){throw Zt()}async fchownPromise(){throw Zt()}fchownSync(){throw Zt()}async chownPromise(){throw Zt()}chownSync(){throw Zt()}async mkdirPromise(){throw Zt()}mkdirSync(){throw Zt()}async rmdirPromise(){throw Zt()}rmdirSync(){throw Zt()}async rmPromise(){throw Zt()}rmSync(){throw Zt()}async linkPromise(){throw Zt()}linkSync(){throw Zt()}async symlinkPromise(){throw Zt()}symlinkSync(){throw Zt()}async renamePromise(){throw Zt()}renameSync(){throw Zt()}async copyFilePromise(){throw Zt()}copyFileSync(){throw Zt()}async appendFilePromise(){throw Zt()}appendFileSync(){throw Zt()}async writeFilePromise(){throw Zt()}writeFileSync(){throw Zt()}async unlinkPromise(){throw Zt()}unlinkSync(){throw Zt()}async utimesPromise(){throw Zt()}utimesSync(){throw Zt()}async lutimesPromise(){throw Zt()}lutimesSync(){throw Zt()}async readFilePromise(){throw Zt()}readFileSync(){throw Zt()}async readlinkPromise(){throw Zt()}readlinkSync(){throw Zt()}async truncatePromise(){throw Zt()}truncateSync(){throw Zt()}async ftruncatePromise(e,r){throw Zt()}ftruncateSync(e,r){throw Zt()}watch(){throw Zt()}watchFile(){throw Zt()}unwatchFile(){throw Zt()}}});var Up,K7=Et(()=>{gf();Ia();Up=class extends bs{constructor(e){super(ue),this.baseFs=e}mapFromBase(e){return ue.fromPortablePath(e)}mapToBase(e){return ue.toPortablePath(e)}}});var F_e,NR,R_e,zs,V7=Et(()=>{O0();gf();Ia();F_e=/^[0-9]+$/,NR=/^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/,R_e=/^([^/]+-)?[a-f0-9]+$/,zs=class t extends bs{static makeVirtualPath(e,r,o){if(K.basename(e)!=="__virtual__")throw new Error('Assertion failed: Virtual folders must be named "__virtual__"');if(!K.basename(r).match(R_e))throw new Error("Assertion failed: Virtual components must be ended by an hexadecimal hash");let n=K.relative(K.dirname(e),o).split("/"),u=0;for(;u<n.length&&n[u]==="..";)u+=1;let A=n.slice(u);return K.join(e,r,String(u),...A)}static resolveVirtual(e){let r=e.match(NR);if(!r||!r[3]&&r[5])return e;let o=K.dirname(r[1]);if(!r[3]||!r[4])return o;if(!F_e.test(r[4]))return e;let n=Number(r[4]),u="../".repeat(n),A=r[5]||".";return t.resolveVirtual(K.join(o,u,A))}constructor({baseFs:e=new Tn}={}){super(K),this.baseFs=e}getExtractHint(e){return this.baseFs.getExtractHint(e)}getRealPath(){return this.baseFs.getRealPath()}realpathSync(e){let r=e.match(NR);if(!r)return this.baseFs.realpathSync(e);if(!r[5])return e;let o=this.baseFs.realpathSync(this.mapToBase(e));return t.makeVirtualPath(r[1],r[3],o)}async realpathPromise(e){let r=e.match(NR);if(!r)return await this.baseFs.realpathPromise(e);if(!r[5])return e;let o=await this.baseFs.realpathPromise(this.mapToBase(e));return t.makeVirtualPath(r[1],r[3],o)}mapToBase(e){if(e==="")return e;if(this.pathUtils.isAbsolute(e))return t.resolveVirtual(e);let r=t.resolveVirtual(this.baseFs.resolve(It.dot)),o=t.resolveVirtual(this.baseFs.resolve(e));return K.relative(r,o)||It.dot}mapFromBase(e){return e}}});function T_e(t,e){return typeof LR.default.isUtf8<"u"?LR.default.isUtf8(t):Buffer.byteLength(e)===t.byteLength}var LR,z7,J7,hD,X7=Et(()=>{LR=Ze(ve("buffer")),z7=ve("url"),J7=ve("util");gf();Ia();hD=class extends bs{constructor(e){super(ue),this.baseFs=e}mapFromBase(e){return e}mapToBase(e){if(typeof e=="string")return e;if(e instanceof URL)return(0,z7.fileURLToPath)(e);if(Buffer.isBuffer(e)){let r=e.toString();if(!T_e(e,r))throw new Error("Non-utf8 buffers are not supported at the moment. Please upvote the following issue if you encounter this error: https://github.com/yarnpkg/berry/issues/4942");return r}throw new Error(`Unsupported path type: ${(0,J7.inspect)(e)}`)}}});var rY,Bo,df,_p,gD,dD,Yd,Nc,Lc,Z7,$7,eY,tY,bw,nY=Et(()=>{rY=ve("readline"),Bo=Symbol("kBaseFs"),df=Symbol("kFd"),_p=Symbol("kClosePromise"),gD=Symbol("kCloseResolve"),dD=Symbol("kCloseReject"),Yd=Symbol("kRefs"),Nc=Symbol("kRef"),Lc=Symbol("kUnref"),bw=class{constructor(e,r){this[tY]=1;this[eY]=void 0;this[$7]=void 0;this[Z7]=void 0;this[Bo]=r,this[df]=e}get fd(){return this[df]}async appendFile(e,r){try{this[Nc](this.appendFile);let o=(typeof r=="string"?r:r?.encoding)??void 0;return await this[Bo].appendFilePromise(this.fd,e,o?{encoding:o}:void 0)}finally{this[Lc]()}}async chown(e,r){try{return this[Nc](this.chown),await this[Bo].fchownPromise(this.fd,e,r)}finally{this[Lc]()}}async chmod(e){try{return this[Nc](this.chmod),await this[Bo].fchmodPromise(this.fd,e)}finally{this[Lc]()}}createReadStream(e){return this[Bo].createReadStream(null,{...e,fd:this.fd})}createWriteStream(e){return this[Bo].createWriteStream(null,{...e,fd:this.fd})}datasync(){throw new Error("Method not implemented.")}sync(){throw new Error("Method not implemented.")}async read(e,r,o,a){try{this[Nc](this.read);let n;return Buffer.isBuffer(e)?n=e:(e??={},n=e.buffer??Buffer.alloc(16384),r=e.offset||0,o=e.length??n.byteLength,a=e.position??null),r??=0,o??=0,o===0?{bytesRead:o,buffer:n}:{bytesRead:await this[Bo].readPromise(this.fd,n,r,o,a),buffer:n}}finally{this[Lc]()}}async readFile(e){try{this[Nc](this.readFile);let r=(typeof e=="string"?e:e?.encoding)??void 0;return await this[Bo].readFilePromise(this.fd,r)}finally{this[Lc]()}}readLines(e){return(0,rY.createInterface)({input:this.createReadStream(e),crlfDelay:1/0})}async stat(e){try{return this[Nc](this.stat),await this[Bo].fstatPromise(this.fd,e)}finally{this[Lc]()}}async truncate(e){try{return this[Nc](this.truncate),await this[Bo].ftruncatePromise(this.fd,e)}finally{this[Lc]()}}utimes(e,r){throw new Error("Method not implemented.")}async writeFile(e,r){try{this[Nc](this.writeFile);let o=(typeof r=="string"?r:r?.encoding)??void 0;await this[Bo].writeFilePromise(this.fd,e,o)}finally{this[Lc]()}}async write(...e){try{if(this[Nc](this.write),ArrayBuffer.isView(e[0])){let[r,o,a,n]=e;return{bytesWritten:await this[Bo].writePromise(this.fd,r,o??void 0,a??void 0,n??void 0),buffer:r}}else{let[r,o,a]=e;return{bytesWritten:await this[Bo].writePromise(this.fd,r,o,a),buffer:r}}}finally{this[Lc]()}}async writev(e,r){try{this[Nc](this.writev);let o=0;if(typeof r<"u")for(let a of e){let n=await this.write(a,void 0,void 0,r);o+=n.bytesWritten,r+=n.bytesWritten}else for(let a of e){let n=await this.write(a);o+=n.bytesWritten}return{buffers:e,bytesWritten:o}}finally{this[Lc]()}}readv(e,r){throw new Error("Method not implemented.")}close(){if(this[df]===-1)return Promise.resolve();if(this[_p])return this[_p];if(this[Yd]--,this[Yd]===0){let e=this[df];this[df]=-1,this[_p]=this[Bo].closePromise(e).finally(()=>{this[_p]=void 0})}else this[_p]=new Promise((e,r)=>{this[gD]=e,this[dD]=r}).finally(()=>{this[_p]=void 0,this[dD]=void 0,this[gD]=void 0});return this[_p]}[(Bo,df,tY=Yd,eY=_p,$7=gD,Z7=dD,Nc)](e){if(this[df]===-1){let r=new Error("file closed");throw r.code="EBADF",r.syscall=e.name,r}this[Yd]++}[Lc](){if(this[Yd]--,this[Yd]===0){let e=this[df];this[df]=-1,this[Bo].closePromise(e).then(this[gD],this[dD])}}}});function xw(t,e){e=new hD(e);let r=(o,a,n)=>{let u=o[a];o[a]=n,typeof u?.[Wd.promisify.custom]<"u"&&(n[Wd.promisify.custom]=u[Wd.promisify.custom])};{r(t,"exists",(o,...a)=>{let u=typeof a[a.length-1]=="function"?a.pop():()=>{};process.nextTick(()=>{e.existsPromise(o).then(A=>{u(A)},()=>{u(!1)})})}),r(t,"read",(...o)=>{let[a,n,u,A,p,h]=o;if(o.length<=3){let E={};o.length<3?h=o[1]:(E=o[1],h=o[2]),{buffer:n=Buffer.alloc(16384),offset:u=0,length:A=n.byteLength,position:p}=E}if(u==null&&(u=0),A|=0,A===0){process.nextTick(()=>{h(null,0,n)});return}p==null&&(p=-1),process.nextTick(()=>{e.readPromise(a,n,u,A,p).then(E=>{h(null,E,n)},E=>{h(E,0,n)})})});for(let o of iY){let a=o.replace(/Promise$/,"");if(typeof t[a]>"u")continue;let n=e[o];if(typeof n>"u")continue;r(t,a,(...A)=>{let h=typeof A[A.length-1]=="function"?A.pop():()=>{};process.nextTick(()=>{n.apply(e,A).then(E=>{h(null,E)},E=>{h(E)})})})}t.realpath.native=t.realpath}{r(t,"existsSync",o=>{try{return e.existsSync(o)}catch{return!1}}),r(t,"readSync",(...o)=>{let[a,n,u,A,p]=o;return o.length<=3&&({offset:u=0,length:A=n.byteLength,position:p}=o[2]||{}),u==null&&(u=0),A|=0,A===0?0:(p==null&&(p=-1),e.readSync(a,n,u,A,p))});for(let o of N_e){let a=o;if(typeof t[a]>"u")continue;let n=e[o];typeof n>"u"||r(t,a,n.bind(e))}t.realpathSync.native=t.realpathSync}{let o=t.promises;for(let a of iY){let n=a.replace(/Promise$/,"");if(typeof o[n]>"u")continue;let u=e[a];typeof u>"u"||a!=="open"&&r(o,n,(A,...p)=>A instanceof bw?A[n].apply(A,p):u.call(e,A,...p))}r(o,"open",async(...a)=>{let n=await e.openPromise(...a);return new bw(n,e)})}t.read[Wd.promisify.custom]=async(o,a,...n)=>({bytesRead:await e.readPromise(o,a,...n),buffer:a}),t.write[Wd.promisify.custom]=async(o,a,...n)=>({bytesWritten:await e.writePromise(o,a,...n),buffer:a})}function mD(t,e){let r=Object.create(t);return xw(r,e),r}var Wd,N_e,iY,sY=Et(()=>{Wd=ve("util");X7();nY();N_e=new Set(["accessSync","appendFileSync","createReadStream","createWriteStream","chmodSync","fchmodSync","chownSync","fchownSync","closeSync","copyFileSync","linkSync","lstatSync","fstatSync","lutimesSync","mkdirSync","openSync","opendirSync","readlinkSync","readFileSync","readdirSync","readlinkSync","realpathSync","renameSync","rmdirSync","rmSync","statSync","symlinkSync","truncateSync","ftruncateSync","unlinkSync","unwatchFile","utimesSync","watch","watchFile","writeFileSync","writeSync"]),iY=new Set(["accessPromise","appendFilePromise","fchmodPromise","chmodPromise","fchownPromise","chownPromise","closePromise","copyFilePromise","linkPromise","fstatPromise","lstatPromise","lutimesPromise","mkdirPromise","openPromise","opendirPromise","readdirPromise","realpathPromise","readFilePromise","readdirPromise","readlinkPromise","renamePromise","rmdirPromise","rmPromise","statPromise","symlinkPromise","truncatePromise","ftruncatePromise","unlinkPromise","utimesPromise","writeFilePromise","writeSync"])});function oY(t){let e=Math.ceil(Math.random()*4294967296).toString(16).padStart(8,"0");return`${t}${e}`}function aY(){if(MR)return MR;let t=ue.toPortablePath(lY.default.tmpdir()),e=oe.realpathSync(t);return process.once("exit",()=>{oe.rmtempSync()}),MR={tmpdir:t,realTmpdir:e}}var lY,Mc,MR,oe,cY=Et(()=>{lY=Ze(ve("os"));O0();Ia();Mc=new Set,MR=null;oe=Object.assign(new Tn,{detachTemp(t){Mc.delete(t)},mktempSync(t){let{tmpdir:e,realTmpdir:r}=aY();for(;;){let o=oY("xfs-");try{this.mkdirSync(K.join(e,o))}catch(n){if(n.code==="EEXIST")continue;throw n}let a=K.join(r,o);if(Mc.add(a),typeof t>"u")return a;try{return t(a)}finally{if(Mc.has(a)){Mc.delete(a);try{this.removeSync(a)}catch{}}}}},async mktempPromise(t){let{tmpdir:e,realTmpdir:r}=aY();for(;;){let o=oY("xfs-");try{await this.mkdirPromise(K.join(e,o))}catch(n){if(n.code==="EEXIST")continue;throw n}let a=K.join(r,o);if(Mc.add(a),typeof t>"u")return a;try{return await t(a)}finally{if(Mc.has(a)){Mc.delete(a);try{await this.removePromise(a)}catch{}}}}},async rmtempPromise(){await Promise.all(Array.from(Mc.values()).map(async t=>{try{await oe.removePromise(t,{maxRetries:0}),Mc.delete(t)}catch{}}))},rmtempSync(){for(let t of Mc)try{oe.removeSync(t),Mc.delete(t)}catch{}}})});var kw={};Vt(kw,{AliasFS:()=>Hu,BasePortableFakeFS:()=>_u,CustomDir:()=>Sw,CwdFS:()=>gn,FakeFS:()=>hf,Filename:()=>dr,JailFS:()=>qu,LazyFS:()=>Gd,MountFS:()=>Op,NoFS:()=>pD,NodeFS:()=>Tn,PortablePath:()=>It,PosixFS:()=>Up,ProxiedFS:()=>bs,VirtualFS:()=>zs,constants:()=>Bi,errors:()=>nr,extendFs:()=>mD,normalizeLineEndings:()=>L0,npath:()=>ue,opendir:()=>uD,patchFs:()=>xw,ppath:()=>K,setupCopyIndex:()=>cD,statUtils:()=>wa,unwatchAllFiles:()=>N0,unwatchFile:()=>T0,watchFile:()=>jd,xfs:()=>oe});var Pt=Et(()=>{P7();oD();kR();RR();F7();TR();M0();Ia();Ia();O7();M0();H7();j7();G7();Y7();W7();O0();K7();gf();V7();sY();cY()});var hY=_((fbt,pY)=>{pY.exports=fY;fY.sync=M_e;var uY=ve("fs");function L_e(t,e){var r=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!r||(r=r.split(";"),r.indexOf("")!==-1))return!0;for(var o=0;o<r.length;o++){var a=r[o].toLowerCase();if(a&&t.substr(-a.length).toLowerCase()===a)return!0}return!1}function AY(t,e,r){return!t.isSymbolicLink()&&!t.isFile()?!1:L_e(e,r)}function fY(t,e,r){uY.stat(t,function(o,a){r(o,o?!1:AY(a,t,e))})}function M_e(t,e){return AY(uY.statSync(t),t,e)}});var EY=_((pbt,yY)=>{yY.exports=dY;dY.sync=O_e;var gY=ve("fs");function dY(t,e,r){gY.stat(t,function(o,a){r(o,o?!1:mY(a,e))})}function O_e(t,e){return mY(gY.statSync(t),e)}function mY(t,e){return t.isFile()&&U_e(t,e)}function U_e(t,e){var r=t.mode,o=t.uid,a=t.gid,n=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),u=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),A=parseInt("100",8),p=parseInt("010",8),h=parseInt("001",8),E=A|p,I=r&h||r&p&&a===u||r&A&&o===n||r&E&&n===0;return I}});var wY=_((gbt,CY)=>{var hbt=ve("fs"),yD;process.platform==="win32"||global.TESTING_WINDOWS?yD=hY():yD=EY();CY.exports=OR;OR.sync=__e;function OR(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(o,a){OR(t,e||{},function(n,u){n?a(n):o(u)})})}yD(t,e||{},function(o,a){o&&(o.code==="EACCES"||e&&e.ignoreErrors)&&(o=null,a=!1),r(o,a)})}function __e(t,e){try{return yD.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code==="EACCES")return!1;throw r}}});var bY=_((dbt,SY)=>{var Kd=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",IY=ve("path"),H_e=Kd?";":":",BY=wY(),vY=t=>Object.assign(new Error(`not found: ${t}`),{code:"ENOENT"}),DY=(t,e)=>{let r=e.colon||H_e,o=t.match(/\//)||Kd&&t.match(/\\/)?[""]:[...Kd?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(r)],a=Kd?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",n=Kd?a.split(r):[""];return Kd&&t.indexOf(".")!==-1&&n[0]!==""&&n.unshift(""),{pathEnv:o,pathExt:n,pathExtExe:a}},PY=(t,e,r)=>{typeof e=="function"&&(r=e,e={}),e||(e={});let{pathEnv:o,pathExt:a,pathExtExe:n}=DY(t,e),u=[],A=h=>new Promise((E,I)=>{if(h===o.length)return e.all&&u.length?E(u):I(vY(t));let v=o[h],x=/^".*"$/.test(v)?v.slice(1,-1):v,C=IY.join(x,t),R=!x&&/^\.[\\\/]/.test(t)?t.slice(0,2)+C:C;E(p(R,h,0))}),p=(h,E,I)=>new Promise((v,x)=>{if(I===a.length)return v(A(E+1));let C=a[I];BY(h+C,{pathExt:n},(R,L)=>{if(!R&&L)if(e.all)u.push(h+C);else return v(h+C);return v(p(h,E,I+1))})});return r?A(0).then(h=>r(null,h),r):A(0)},q_e=(t,e)=>{e=e||{};let{pathEnv:r,pathExt:o,pathExtExe:a}=DY(t,e),n=[];for(let u=0;u<r.length;u++){let A=r[u],p=/^".*"$/.test(A)?A.slice(1,-1):A,h=IY.join(p,t),E=!p&&/^\.[\\\/]/.test(t)?t.slice(0,2)+h:h;for(let I=0;I<o.length;I++){let v=E+o[I];try{if(BY.sync(v,{pathExt:a}))if(e.all)n.push(v);else return v}catch{}}}if(e.all&&n.length)return n;if(e.nothrow)return null;throw vY(t)};SY.exports=PY;PY.sync=q_e});var kY=_((mbt,UR)=>{"use strict";var xY=(t={})=>{let e=t.env||process.env;return(t.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(o=>o.toUpperCase()==="PATH")||"Path"};UR.exports=xY;UR.exports.default=xY});var TY=_((ybt,RY)=>{"use strict";var QY=ve("path"),j_e=bY(),G_e=kY();function FY(t,e){let r=t.options.env||process.env,o=process.cwd(),a=t.options.cwd!=null,n=a&&process.chdir!==void 0&&!process.chdir.disabled;if(n)try{process.chdir(t.options.cwd)}catch{}let u;try{u=j_e.sync(t.command,{path:r[G_e({env:r})],pathExt:e?QY.delimiter:void 0})}catch{}finally{n&&process.chdir(o)}return u&&(u=QY.resolve(a?t.options.cwd:"",u)),u}function Y_e(t){return FY(t)||FY(t,!0)}RY.exports=Y_e});var NY=_((Ebt,HR)=>{"use strict";var _R=/([()\][%!^"`<>&|;, *?])/g;function W_e(t){return t=t.replace(_R,"^$1"),t}function K_e(t,e){return t=`${t}`,t=t.replace(/(\\*)"/g,'$1$1\\"'),t=t.replace(/(\\*)$/,"$1$1"),t=`"${t}"`,t=t.replace(_R,"^$1"),e&&(t=t.replace(_R,"^$1")),t}HR.exports.command=W_e;HR.exports.argument=K_e});var MY=_((Cbt,LY)=>{"use strict";LY.exports=/^#!(.*)/});var UY=_((wbt,OY)=>{"use strict";var V_e=MY();OY.exports=(t="")=>{let e=t.match(V_e);if(!e)return null;let[r,o]=e[0].replace(/#! ?/,"").split(" "),a=r.split("/").pop();return a==="env"?o:o?`${a} ${o}`:a}});var HY=_((Ibt,_Y)=>{"use strict";var qR=ve("fs"),z_e=UY();function J_e(t){let r=Buffer.alloc(150),o;try{o=qR.openSync(t,"r"),qR.readSync(o,r,0,150,0),qR.closeSync(o)}catch{}return z_e(r.toString())}_Y.exports=J_e});var YY=_((Bbt,GY)=>{"use strict";var X_e=ve("path"),qY=TY(),jY=NY(),Z_e=HY(),$_e=process.platform==="win32",e8e=/\.(?:com|exe)$/i,t8e=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function r8e(t){t.file=qY(t);let e=t.file&&Z_e(t.file);return e?(t.args.unshift(t.file),t.command=e,qY(t)):t.file}function n8e(t){if(!$_e)return t;let e=r8e(t),r=!e8e.test(e);if(t.options.forceShell||r){let o=t8e.test(e);t.command=X_e.normalize(t.command),t.command=jY.command(t.command),t.args=t.args.map(n=>jY.argument(n,o));let a=[t.command].concat(t.args).join(" ");t.args=["/d","/s","/c",`"${a}"`],t.command=process.env.comspec||"cmd.exe",t.options.windowsVerbatimArguments=!0}return t}function i8e(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);let o={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?o:n8e(o)}GY.exports=i8e});var VY=_((vbt,KY)=>{"use strict";var jR=process.platform==="win32";function GR(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function s8e(t,e){if(!jR)return;let r=t.emit;t.emit=function(o,a){if(o==="exit"){let n=WY(a,e,"spawn");if(n)return r.call(t,"error",n)}return r.apply(t,arguments)}}function WY(t,e){return jR&&t===1&&!e.file?GR(e.original,"spawn"):null}function o8e(t,e){return jR&&t===1&&!e.file?GR(e.original,"spawnSync"):null}KY.exports={hookChildProcess:s8e,verifyENOENT:WY,verifyENOENTSync:o8e,notFoundError:GR}});var KR=_((Dbt,Vd)=>{"use strict";var zY=ve("child_process"),YR=YY(),WR=VY();function JY(t,e,r){let o=YR(t,e,r),a=zY.spawn(o.command,o.args,o.options);return WR.hookChildProcess(a,o),a}function a8e(t,e,r){let o=YR(t,e,r),a=zY.spawnSync(o.command,o.args,o.options);return a.error=a.error||WR.verifyENOENTSync(a.status,o),a}Vd.exports=JY;Vd.exports.spawn=JY;Vd.exports.sync=a8e;Vd.exports._parse=YR;Vd.exports._enoent=WR});var ZY=_((Pbt,XY)=>{"use strict";function l8e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function _0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,_0)}l8e(_0,Error);_0.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I<h.parts.length;I++)E+=h.parts[I]instanceof Array?n(h.parts[I][0])+"-"+n(h.parts[I][1]):n(h.parts[I]);return"["+(h.inverted?"^":"")+E+"]"},any:function(h){return"any character"},end:function(h){return"end of input"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),I,v;for(I=0;I<h.length;I++)E[I]=u(h[I]);if(E.sort(),E.length>0){for(I=1,v=1;I<E.length;I++)E[I-1]!==E[I]&&(E[v]=E[I],v++);E.length=v}switch(E.length){case 1:return E[0];case 2:return E[0]+" or "+E[1];default:return E.slice(0,-1).join(", ")+", or "+E[E.length-1]}}function p(h){return h?'"'+a(h)+'"':"end of input"}return"Expected "+A(t)+" but "+p(e)+" found."};function c8e(t,e){e=e!==void 0?e:{};var r={},o={Start:u0},a=u0,n=function(N){return N||[]},u=function(N,V,re){return[{command:N,type:V}].concat(re||[])},A=function(N,V){return[{command:N,type:V||";"}]},p=function(N){return N},h=";",E=Br(";",!1),I="&",v=Br("&",!1),x=function(N,V){return V?{chain:N,then:V}:{chain:N}},C=function(N,V){return{type:N,line:V}},R="&&",L=Br("&&",!1),U="||",z=Br("||",!1),te=function(N,V){return V?{...N,then:V}:N},ae=function(N,V){return{type:N,chain:V}},le="|&",ce=Br("|&",!1),Ce="|",de=Br("|",!1),Be="=",Ee=Br("=",!1),g=function(N,V){return{name:N,args:[V]}},me=function(N){return{name:N,args:[]}},we="(",Ae=Br("(",!1),ne=")",Z=Br(")",!1),xe=function(N,V){return{type:"subshell",subshell:N,args:V}},Ne="{",ht=Br("{",!1),H="}",rt=Br("}",!1),Te=function(N,V){return{type:"group",group:N,args:V}},Fe=function(N,V){return{type:"command",args:V,envs:N}},ke=function(N){return{type:"envs",envs:N}},Ye=function(N){return N},Se=function(N){return N},et=/^[0-9]/,Ue=Is([["0","9"]],!1,!1),b=function(N,V,re){return{type:"redirection",subtype:V,fd:N!==null?parseInt(N):null,args:[re]}},w=">>",S=Br(">>",!1),y=">&",F=Br(">&",!1),J=">",X=Br(">",!1),$="<<<",ie=Br("<<<",!1),be="<&",Re=Br("<&",!1),at="<",dt=Br("<",!1),jt=function(N){return{type:"argument",segments:[].concat(...N)}},tr=function(N){return N},St="$'",ln=Br("$'",!1),kr="'",mr=Br("'",!1),br=function(N){return[{type:"text",text:N}]},Kr='""',Kn=Br('""',!1),Ms=function(){return{type:"text",text:""}},Ri='"',gs=Br('"',!1),io=function(N){return N},Pi=function(N){return{type:"arithmetic",arithmetic:N,quoted:!0}},Os=function(N){return{type:"shell",shell:N,quoted:!0}},so=function(N){return{type:"variable",...N,quoted:!0}},uc=function(N){return{type:"text",text:N}},Au=function(N){return{type:"arithmetic",arithmetic:N,quoted:!1}},sp=function(N){return{type:"shell",shell:N,quoted:!1}},op=function(N){return{type:"variable",...N,quoted:!1}},Us=function(N){return{type:"glob",pattern:N}},Dn=/^[^']/,oo=Is(["'"],!0,!1),_s=function(N){return N.join("")},ml=/^[^$"]/,yl=Is(["$",'"'],!0,!1),ao=`\\ +`,Vn=Br(`\\ +`,!1),Mn=function(){return""},Ti="\\",On=Br("\\",!1),_i=/^[\\$"`]/,ir=Is(["\\","$",'"',"`"],!1,!1),Me=function(N){return N},ii="\\a",Ha=Br("\\a",!1),hr=function(){return"a"},Ac="\\b",fu=Br("\\b",!1),fc=function(){return"\b"},El=/^[Ee]/,vA=Is(["E","e"],!1,!1),pu=function(){return"\x1B"},Ie="\\f",Tt=Br("\\f",!1),pc=function(){return"\f"},Hi="\\n",hu=Br("\\n",!1),Yt=function(){return` +`},Cl="\\r",DA=Br("\\r",!1),ap=function(){return"\r"},hc="\\t",PA=Br("\\t",!1),Qn=function(){return" "},hi="\\v",gc=Br("\\v",!1),SA=function(){return"\v"},aa=/^[\\'"?]/,Ni=Is(["\\","'",'"',"?"],!1,!1),_o=function(N){return String.fromCharCode(parseInt(N,16))},Xe="\\x",lo=Br("\\x",!1),dc="\\u",gu=Br("\\u",!1),qi="\\U",du=Br("\\U",!1),bA=function(N){return String.fromCodePoint(parseInt(N,16))},qa=/^[0-7]/,mc=Is([["0","7"]],!1,!1),ds=/^[0-9a-fA-f]/,Ht=Is([["0","9"],["a","f"],["A","f"]],!1,!1),Fn=o0(),Ei="{}",la=Br("{}",!1),co=function(){return"{}"},Hs="-",ca=Br("-",!1),ua="+",Ho=Br("+",!1),Ci=".",ms=Br(".",!1),ys=function(N,V,re){return{type:"number",value:(N==="-"?-1:1)*parseFloat(V.join("")+"."+re.join(""))}},Es=function(N,V){return{type:"number",value:(N==="-"?-1:1)*parseInt(V.join(""))}},qs=function(N){return{type:"variable",...N}},Un=function(N){return{type:"variable",name:N}},Pn=function(N){return N},Cs="*",We=Br("*",!1),tt="/",Bt=Br("/",!1),or=function(N,V,re){return{type:V==="*"?"multiplication":"division",right:re}},ee=function(N,V){return V.reduce((re,he)=>({left:re,...he}),N)},ye=function(N,V,re){return{type:V==="+"?"addition":"subtraction",right:re}},Le="$((",ft=Br("$((",!1),pt="))",Nt=Br("))",!1),rr=function(N){return N},$r="$(",ji=Br("$(",!1),rs=function(N){return N},Si="${",qo=Br("${",!1),xA=":-",kA=Br(":-",!1),lp=function(N,V){return{name:N,defaultValue:V}},e0=":-}",mu=Br(":-}",!1),t0=function(N){return{name:N,defaultValue:[]}},yu=":+",uo=Br(":+",!1),QA=function(N,V){return{name:N,alternativeValue:V}},yc=":+}",Aa=Br(":+}",!1),r0=function(N){return{name:N,alternativeValue:[]}},Ec=function(N){return{name:N}},hd="$",n0=Br("$",!1),$n=function(N){return e.isGlobPattern(N)},cp=function(N){return N},i0=/^[a-zA-Z0-9_]/,FA=Is([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),js=function(){return s0()},Eu=/^[$@*?#a-zA-Z0-9_\-]/,ja=Is(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),Gi=/^[()}<>$|&; \t"']/,fa=Is(["(",")","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),Cu=/^[<>&; \t"']/,ws=Is(["<",">","&",";"," "," ",'"',"'"],!1,!1),Cc=/^[ \t]/,wc=Is([" "," "],!1,!1),Y=0,Dt=0,wl=[{line:1,column:1}],bi=0,Ic=[],ct=0,wu;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function s0(){return t.substring(Dt,Y)}function tw(){return Bc(Dt,Y)}function RA(N,V){throw V=V!==void 0?V:Bc(Dt,Y),c0([l0(N)],t.substring(Dt,Y),V)}function up(N,V){throw V=V!==void 0?V:Bc(Dt,Y),gd(N,V)}function Br(N,V){return{type:"literal",text:N,ignoreCase:V}}function Is(N,V,re){return{type:"class",parts:N,inverted:V,ignoreCase:re}}function o0(){return{type:"any"}}function a0(){return{type:"end"}}function l0(N){return{type:"other",description:N}}function Ap(N){var V=wl[N],re;if(V)return V;for(re=N-1;!wl[re];)re--;for(V=wl[re],V={line:V.line,column:V.column};re<N;)t.charCodeAt(re)===10?(V.line++,V.column=1):V.column++,re++;return wl[N]=V,V}function Bc(N,V){var re=Ap(N),he=Ap(V);return{start:{offset:N,line:re.line,column:re.column},end:{offset:V,line:he.line,column:he.column}}}function Ct(N){Y<bi||(Y>bi&&(bi=Y,Ic=[]),Ic.push(N))}function gd(N,V){return new _0(N,null,null,V)}function c0(N,V,re){return new _0(_0.buildMessage(N,V),N,V,re)}function u0(){var N,V,re;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();return V!==r?(re=Iu(),re===r&&(re=null),re!==r?(Dt=N,V=n(re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function Iu(){var N,V,re,he,ze;if(N=Y,V=Bu(),V!==r){for(re=[],he=Qt();he!==r;)re.push(he),he=Qt();re!==r?(he=A0(),he!==r?(ze=dd(),ze===r&&(ze=null),ze!==r?(Dt=N,V=u(V,he,ze),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;if(N===r)if(N=Y,V=Bu(),V!==r){for(re=[],he=Qt();he!==r;)re.push(he),he=Qt();re!==r?(he=A0(),he===r&&(he=null),he!==r?(Dt=N,V=A(V,he),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;return N}function dd(){var N,V,re,he,ze;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r)if(re=Iu(),re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();he!==r?(Dt=N,V=p(re),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r;return N}function A0(){var N;return t.charCodeAt(Y)===59?(N=h,Y++):(N=r,ct===0&&Ct(E)),N===r&&(t.charCodeAt(Y)===38?(N=I,Y++):(N=r,ct===0&&Ct(v))),N}function Bu(){var N,V,re;return N=Y,V=pa(),V!==r?(re=rw(),re===r&&(re=null),re!==r?(Dt=N,V=x(V,re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function rw(){var N,V,re,he,ze,mt,fr;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r)if(re=md(),re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();if(he!==r)if(ze=Bu(),ze!==r){for(mt=[],fr=Qt();fr!==r;)mt.push(fr),fr=Qt();mt!==r?(Dt=N,V=C(re,ze),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;return N}function md(){var N;return t.substr(Y,2)===R?(N=R,Y+=2):(N=r,ct===0&&Ct(L)),N===r&&(t.substr(Y,2)===U?(N=U,Y+=2):(N=r,ct===0&&Ct(z))),N}function pa(){var N,V,re;return N=Y,V=f0(),V!==r?(re=vc(),re===r&&(re=null),re!==r?(Dt=N,V=te(V,re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function vc(){var N,V,re,he,ze,mt,fr;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r)if(re=Il(),re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();if(he!==r)if(ze=pa(),ze!==r){for(mt=[],fr=Qt();fr!==r;)mt.push(fr),fr=Qt();mt!==r?(Dt=N,V=ae(re,ze),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;return N}function Il(){var N;return t.substr(Y,2)===le?(N=le,Y+=2):(N=r,ct===0&&Ct(ce)),N===r&&(t.charCodeAt(Y)===124?(N=Ce,Y++):(N=r,ct===0&&Ct(de))),N}function vu(){var N,V,re,he,ze,mt;if(N=Y,V=d0(),V!==r)if(t.charCodeAt(Y)===61?(re=Be,Y++):(re=r,ct===0&&Ct(Ee)),re!==r)if(he=jo(),he!==r){for(ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();ze!==r?(Dt=N,V=g(V,he),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r;else Y=N,N=r;if(N===r)if(N=Y,V=d0(),V!==r)if(t.charCodeAt(Y)===61?(re=Be,Y++):(re=r,ct===0&&Ct(Ee)),re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();he!==r?(Dt=N,V=me(V),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r;return N}function f0(){var N,V,re,he,ze,mt,fr,Cr,yn,oi,Li;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r)if(t.charCodeAt(Y)===40?(re=we,Y++):(re=r,ct===0&&Ct(Ae)),re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();if(he!==r)if(ze=Iu(),ze!==r){for(mt=[],fr=Qt();fr!==r;)mt.push(fr),fr=Qt();if(mt!==r)if(t.charCodeAt(Y)===41?(fr=ne,Y++):(fr=r,ct===0&&Ct(Z)),fr!==r){for(Cr=[],yn=Qt();yn!==r;)Cr.push(yn),yn=Qt();if(Cr!==r){for(yn=[],oi=Ga();oi!==r;)yn.push(oi),oi=Ga();if(yn!==r){for(oi=[],Li=Qt();Li!==r;)oi.push(Li),Li=Qt();oi!==r?(Dt=N,V=xe(ze,yn),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;if(N===r){for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r)if(t.charCodeAt(Y)===123?(re=Ne,Y++):(re=r,ct===0&&Ct(ht)),re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();if(he!==r)if(ze=Iu(),ze!==r){for(mt=[],fr=Qt();fr!==r;)mt.push(fr),fr=Qt();if(mt!==r)if(t.charCodeAt(Y)===125?(fr=H,Y++):(fr=r,ct===0&&Ct(rt)),fr!==r){for(Cr=[],yn=Qt();yn!==r;)Cr.push(yn),yn=Qt();if(Cr!==r){for(yn=[],oi=Ga();oi!==r;)yn.push(oi),oi=Ga();if(yn!==r){for(oi=[],Li=Qt();Li!==r;)oi.push(Li),Li=Qt();oi!==r?(Dt=N,V=Te(ze,yn),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;else Y=N,N=r;if(N===r){for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r){for(re=[],he=vu();he!==r;)re.push(he),he=vu();if(re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();if(he!==r){if(ze=[],mt=fp(),mt!==r)for(;mt!==r;)ze.push(mt),mt=fp();else ze=r;if(ze!==r){for(mt=[],fr=Qt();fr!==r;)mt.push(fr),fr=Qt();mt!==r?(Dt=N,V=Fe(re,ze),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r}else Y=N,N=r;if(N===r){for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r){if(re=[],he=vu(),he!==r)for(;he!==r;)re.push(he),he=vu();else re=r;if(re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();he!==r?(Dt=N,V=ke(re),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r}}}return N}function TA(){var N,V,re,he,ze;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r){if(re=[],he=pp(),he!==r)for(;he!==r;)re.push(he),he=pp();else re=r;if(re!==r){for(he=[],ze=Qt();ze!==r;)he.push(ze),ze=Qt();he!==r?(Dt=N,V=Ye(re),N=V):(Y=N,N=r)}else Y=N,N=r}else Y=N,N=r;return N}function fp(){var N,V,re;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();if(V!==r?(re=Ga(),re!==r?(Dt=N,V=Se(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r){for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();V!==r?(re=pp(),re!==r?(Dt=N,V=Se(re),N=V):(Y=N,N=r)):(Y=N,N=r)}return N}function Ga(){var N,V,re,he,ze;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();return V!==r?(et.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(Ue)),re===r&&(re=null),re!==r?(he=p0(),he!==r?(ze=pp(),ze!==r?(Dt=N,V=b(re,he,ze),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function p0(){var N;return t.substr(Y,2)===w?(N=w,Y+=2):(N=r,ct===0&&Ct(S)),N===r&&(t.substr(Y,2)===y?(N=y,Y+=2):(N=r,ct===0&&Ct(F)),N===r&&(t.charCodeAt(Y)===62?(N=J,Y++):(N=r,ct===0&&Ct(X)),N===r&&(t.substr(Y,3)===$?(N=$,Y+=3):(N=r,ct===0&&Ct(ie)),N===r&&(t.substr(Y,2)===be?(N=be,Y+=2):(N=r,ct===0&&Ct(Re)),N===r&&(t.charCodeAt(Y)===60?(N=at,Y++):(N=r,ct===0&&Ct(dt))))))),N}function pp(){var N,V,re;for(N=Y,V=[],re=Qt();re!==r;)V.push(re),re=Qt();return V!==r?(re=jo(),re!==r?(Dt=N,V=Se(re),N=V):(Y=N,N=r)):(Y=N,N=r),N}function jo(){var N,V,re;if(N=Y,V=[],re=Bs(),re!==r)for(;re!==r;)V.push(re),re=Bs();else V=r;return V!==r&&(Dt=N,V=jt(V)),N=V,N}function Bs(){var N,V;return N=Y,V=wi(),V!==r&&(Dt=N,V=tr(V)),N=V,N===r&&(N=Y,V=yd(),V!==r&&(Dt=N,V=tr(V)),N=V,N===r&&(N=Y,V=Ed(),V!==r&&(Dt=N,V=tr(V)),N=V,N===r&&(N=Y,V=Go(),V!==r&&(Dt=N,V=tr(V)),N=V))),N}function wi(){var N,V,re,he;return N=Y,t.substr(Y,2)===St?(V=St,Y+=2):(V=r,ct===0&&Ct(ln)),V!==r?(re=cn(),re!==r?(t.charCodeAt(Y)===39?(he=kr,Y++):(he=r,ct===0&&Ct(mr)),he!==r?(Dt=N,V=br(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function yd(){var N,V,re,he;return N=Y,t.charCodeAt(Y)===39?(V=kr,Y++):(V=r,ct===0&&Ct(mr)),V!==r?(re=gp(),re!==r?(t.charCodeAt(Y)===39?(he=kr,Y++):(he=r,ct===0&&Ct(mr)),he!==r?(Dt=N,V=br(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function Ed(){var N,V,re,he;if(N=Y,t.substr(Y,2)===Kr?(V=Kr,Y+=2):(V=r,ct===0&&Ct(Kn)),V!==r&&(Dt=N,V=Ms()),N=V,N===r)if(N=Y,t.charCodeAt(Y)===34?(V=Ri,Y++):(V=r,ct===0&&Ct(gs)),V!==r){for(re=[],he=NA();he!==r;)re.push(he),he=NA();re!==r?(t.charCodeAt(Y)===34?(he=Ri,Y++):(he=r,ct===0&&Ct(gs)),he!==r?(Dt=N,V=io(re),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;return N}function Go(){var N,V,re;if(N=Y,V=[],re=hp(),re!==r)for(;re!==r;)V.push(re),re=hp();else V=r;return V!==r&&(Dt=N,V=io(V)),N=V,N}function NA(){var N,V;return N=Y,V=Yr(),V!==r&&(Dt=N,V=Pi(V)),N=V,N===r&&(N=Y,V=dp(),V!==r&&(Dt=N,V=Os(V)),N=V,N===r&&(N=Y,V=Pc(),V!==r&&(Dt=N,V=so(V)),N=V,N===r&&(N=Y,V=h0(),V!==r&&(Dt=N,V=uc(V)),N=V))),N}function hp(){var N,V;return N=Y,V=Yr(),V!==r&&(Dt=N,V=Au(V)),N=V,N===r&&(N=Y,V=dp(),V!==r&&(Dt=N,V=sp(V)),N=V,N===r&&(N=Y,V=Pc(),V!==r&&(Dt=N,V=op(V)),N=V,N===r&&(N=Y,V=nw(),V!==r&&(Dt=N,V=Us(V)),N=V,N===r&&(N=Y,V=ga(),V!==r&&(Dt=N,V=uc(V)),N=V)))),N}function gp(){var N,V,re;for(N=Y,V=[],Dn.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(oo));re!==r;)V.push(re),Dn.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(oo));return V!==r&&(Dt=N,V=_s(V)),N=V,N}function h0(){var N,V,re;if(N=Y,V=[],re=ha(),re===r&&(ml.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(yl))),re!==r)for(;re!==r;)V.push(re),re=ha(),re===r&&(ml.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(yl)));else V=r;return V!==r&&(Dt=N,V=_s(V)),N=V,N}function ha(){var N,V,re;return N=Y,t.substr(Y,2)===ao?(V=ao,Y+=2):(V=r,ct===0&&Ct(Vn)),V!==r&&(Dt=N,V=Mn()),N=V,N===r&&(N=Y,t.charCodeAt(Y)===92?(V=Ti,Y++):(V=r,ct===0&&Ct(On)),V!==r?(_i.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(ir)),re!==r?(Dt=N,V=Me(re),N=V):(Y=N,N=r)):(Y=N,N=r)),N}function cn(){var N,V,re;for(N=Y,V=[],re=Ao(),re===r&&(Dn.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(oo)));re!==r;)V.push(re),re=Ao(),re===r&&(Dn.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(oo)));return V!==r&&(Dt=N,V=_s(V)),N=V,N}function Ao(){var N,V,re;return N=Y,t.substr(Y,2)===ii?(V=ii,Y+=2):(V=r,ct===0&&Ct(Ha)),V!==r&&(Dt=N,V=hr()),N=V,N===r&&(N=Y,t.substr(Y,2)===Ac?(V=Ac,Y+=2):(V=r,ct===0&&Ct(fu)),V!==r&&(Dt=N,V=fc()),N=V,N===r&&(N=Y,t.charCodeAt(Y)===92?(V=Ti,Y++):(V=r,ct===0&&Ct(On)),V!==r?(El.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(vA)),re!==r?(Dt=N,V=pu(),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Ie?(V=Ie,Y+=2):(V=r,ct===0&&Ct(Tt)),V!==r&&(Dt=N,V=pc()),N=V,N===r&&(N=Y,t.substr(Y,2)===Hi?(V=Hi,Y+=2):(V=r,ct===0&&Ct(hu)),V!==r&&(Dt=N,V=Yt()),N=V,N===r&&(N=Y,t.substr(Y,2)===Cl?(V=Cl,Y+=2):(V=r,ct===0&&Ct(DA)),V!==r&&(Dt=N,V=ap()),N=V,N===r&&(N=Y,t.substr(Y,2)===hc?(V=hc,Y+=2):(V=r,ct===0&&Ct(PA)),V!==r&&(Dt=N,V=Qn()),N=V,N===r&&(N=Y,t.substr(Y,2)===hi?(V=hi,Y+=2):(V=r,ct===0&&Ct(gc)),V!==r&&(Dt=N,V=SA()),N=V,N===r&&(N=Y,t.charCodeAt(Y)===92?(V=Ti,Y++):(V=r,ct===0&&Ct(On)),V!==r?(aa.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(Ni)),re!==r?(Dt=N,V=Me(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=LA()))))))))),N}function LA(){var N,V,re,he,ze,mt,fr,Cr,yn,oi,Li,y0;return N=Y,t.charCodeAt(Y)===92?(V=Ti,Y++):(V=r,ct===0&&Ct(On)),V!==r?(re=Ya(),re!==r?(Dt=N,V=_o(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Xe?(V=Xe,Y+=2):(V=r,ct===0&&Ct(lo)),V!==r?(re=Y,he=Y,ze=Ya(),ze!==r?(mt=si(),mt!==r?(ze=[ze,mt],he=ze):(Y=he,he=r)):(Y=he,he=r),he===r&&(he=Ya()),he!==r?re=t.substring(re,Y):re=he,re!==r?(Dt=N,V=_o(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===dc?(V=dc,Y+=2):(V=r,ct===0&&Ct(gu)),V!==r?(re=Y,he=Y,ze=si(),ze!==r?(mt=si(),mt!==r?(fr=si(),fr!==r?(Cr=si(),Cr!==r?(ze=[ze,mt,fr,Cr],he=ze):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r),he!==r?re=t.substring(re,Y):re=he,re!==r?(Dt=N,V=_o(re),N=V):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===qi?(V=qi,Y+=2):(V=r,ct===0&&Ct(du)),V!==r?(re=Y,he=Y,ze=si(),ze!==r?(mt=si(),mt!==r?(fr=si(),fr!==r?(Cr=si(),Cr!==r?(yn=si(),yn!==r?(oi=si(),oi!==r?(Li=si(),Li!==r?(y0=si(),y0!==r?(ze=[ze,mt,fr,Cr,yn,oi,Li,y0],he=ze):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r)):(Y=he,he=r),he!==r?re=t.substring(re,Y):re=he,re!==r?(Dt=N,V=bA(re),N=V):(Y=N,N=r)):(Y=N,N=r)))),N}function Ya(){var N;return qa.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,ct===0&&Ct(mc)),N}function si(){var N;return ds.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,ct===0&&Ct(Ht)),N}function ga(){var N,V,re,he,ze;if(N=Y,V=[],re=Y,t.charCodeAt(Y)===92?(he=Ti,Y++):(he=r,ct===0&&Ct(On)),he!==r?(t.length>Y?(ze=t.charAt(Y),Y++):(ze=r,ct===0&&Ct(Fn)),ze!==r?(Dt=re,he=Me(ze),re=he):(Y=re,re=r)):(Y=re,re=r),re===r&&(re=Y,t.substr(Y,2)===Ei?(he=Ei,Y+=2):(he=r,ct===0&&Ct(la)),he!==r&&(Dt=re,he=co()),re=he,re===r&&(re=Y,he=Y,ct++,ze=Cd(),ct--,ze===r?he=void 0:(Y=he,he=r),he!==r?(t.length>Y?(ze=t.charAt(Y),Y++):(ze=r,ct===0&&Ct(Fn)),ze!==r?(Dt=re,he=Me(ze),re=he):(Y=re,re=r)):(Y=re,re=r))),re!==r)for(;re!==r;)V.push(re),re=Y,t.charCodeAt(Y)===92?(he=Ti,Y++):(he=r,ct===0&&Ct(On)),he!==r?(t.length>Y?(ze=t.charAt(Y),Y++):(ze=r,ct===0&&Ct(Fn)),ze!==r?(Dt=re,he=Me(ze),re=he):(Y=re,re=r)):(Y=re,re=r),re===r&&(re=Y,t.substr(Y,2)===Ei?(he=Ei,Y+=2):(he=r,ct===0&&Ct(la)),he!==r&&(Dt=re,he=co()),re=he,re===r&&(re=Y,he=Y,ct++,ze=Cd(),ct--,ze===r?he=void 0:(Y=he,he=r),he!==r?(t.length>Y?(ze=t.charAt(Y),Y++):(ze=r,ct===0&&Ct(Fn)),ze!==r?(Dt=re,he=Me(ze),re=he):(Y=re,re=r)):(Y=re,re=r)));else V=r;return V!==r&&(Dt=N,V=_s(V)),N=V,N}function Dc(){var N,V,re,he,ze,mt;if(N=Y,t.charCodeAt(Y)===45?(V=Hs,Y++):(V=r,ct===0&&Ct(ca)),V===r&&(t.charCodeAt(Y)===43?(V=ua,Y++):(V=r,ct===0&&Ct(Ho))),V===r&&(V=null),V!==r){if(re=[],et.test(t.charAt(Y))?(he=t.charAt(Y),Y++):(he=r,ct===0&&Ct(Ue)),he!==r)for(;he!==r;)re.push(he),et.test(t.charAt(Y))?(he=t.charAt(Y),Y++):(he=r,ct===0&&Ct(Ue));else re=r;if(re!==r)if(t.charCodeAt(Y)===46?(he=Ci,Y++):(he=r,ct===0&&Ct(ms)),he!==r){if(ze=[],et.test(t.charAt(Y))?(mt=t.charAt(Y),Y++):(mt=r,ct===0&&Ct(Ue)),mt!==r)for(;mt!==r;)ze.push(mt),et.test(t.charAt(Y))?(mt=t.charAt(Y),Y++):(mt=r,ct===0&&Ct(Ue));else ze=r;ze!==r?(Dt=N,V=ys(V,re,ze),N=V):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;if(N===r){if(N=Y,t.charCodeAt(Y)===45?(V=Hs,Y++):(V=r,ct===0&&Ct(ca)),V===r&&(t.charCodeAt(Y)===43?(V=ua,Y++):(V=r,ct===0&&Ct(Ho))),V===r&&(V=null),V!==r){if(re=[],et.test(t.charAt(Y))?(he=t.charAt(Y),Y++):(he=r,ct===0&&Ct(Ue)),he!==r)for(;he!==r;)re.push(he),et.test(t.charAt(Y))?(he=t.charAt(Y),Y++):(he=r,ct===0&&Ct(Ue));else re=r;re!==r?(Dt=N,V=Es(V,re),N=V):(Y=N,N=r)}else Y=N,N=r;if(N===r&&(N=Y,V=Pc(),V!==r&&(Dt=N,V=qs(V)),N=V,N===r&&(N=Y,V=Wa(),V!==r&&(Dt=N,V=Un(V)),N=V,N===r)))if(N=Y,t.charCodeAt(Y)===40?(V=we,Y++):(V=r,ct===0&&Ct(Ae)),V!==r){for(re=[],he=Qt();he!==r;)re.push(he),he=Qt();if(re!==r)if(he=ns(),he!==r){for(ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();ze!==r?(t.charCodeAt(Y)===41?(mt=ne,Y++):(mt=r,ct===0&&Ct(Z)),mt!==r?(Dt=N,V=Pn(he),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r}return N}function Bl(){var N,V,re,he,ze,mt,fr,Cr;if(N=Y,V=Dc(),V!==r){for(re=[],he=Y,ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();if(ze!==r)if(t.charCodeAt(Y)===42?(mt=Cs,Y++):(mt=r,ct===0&&Ct(We)),mt===r&&(t.charCodeAt(Y)===47?(mt=tt,Y++):(mt=r,ct===0&&Ct(Bt))),mt!==r){for(fr=[],Cr=Qt();Cr!==r;)fr.push(Cr),Cr=Qt();fr!==r?(Cr=Dc(),Cr!==r?(Dt=he,ze=or(V,mt,Cr),he=ze):(Y=he,he=r)):(Y=he,he=r)}else Y=he,he=r;else Y=he,he=r;for(;he!==r;){for(re.push(he),he=Y,ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();if(ze!==r)if(t.charCodeAt(Y)===42?(mt=Cs,Y++):(mt=r,ct===0&&Ct(We)),mt===r&&(t.charCodeAt(Y)===47?(mt=tt,Y++):(mt=r,ct===0&&Ct(Bt))),mt!==r){for(fr=[],Cr=Qt();Cr!==r;)fr.push(Cr),Cr=Qt();fr!==r?(Cr=Dc(),Cr!==r?(Dt=he,ze=or(V,mt,Cr),he=ze):(Y=he,he=r)):(Y=he,he=r)}else Y=he,he=r;else Y=he,he=r}re!==r?(Dt=N,V=ee(V,re),N=V):(Y=N,N=r)}else Y=N,N=r;return N}function ns(){var N,V,re,he,ze,mt,fr,Cr;if(N=Y,V=Bl(),V!==r){for(re=[],he=Y,ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();if(ze!==r)if(t.charCodeAt(Y)===43?(mt=ua,Y++):(mt=r,ct===0&&Ct(Ho)),mt===r&&(t.charCodeAt(Y)===45?(mt=Hs,Y++):(mt=r,ct===0&&Ct(ca))),mt!==r){for(fr=[],Cr=Qt();Cr!==r;)fr.push(Cr),Cr=Qt();fr!==r?(Cr=Bl(),Cr!==r?(Dt=he,ze=ye(V,mt,Cr),he=ze):(Y=he,he=r)):(Y=he,he=r)}else Y=he,he=r;else Y=he,he=r;for(;he!==r;){for(re.push(he),he=Y,ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();if(ze!==r)if(t.charCodeAt(Y)===43?(mt=ua,Y++):(mt=r,ct===0&&Ct(Ho)),mt===r&&(t.charCodeAt(Y)===45?(mt=Hs,Y++):(mt=r,ct===0&&Ct(ca))),mt!==r){for(fr=[],Cr=Qt();Cr!==r;)fr.push(Cr),Cr=Qt();fr!==r?(Cr=Bl(),Cr!==r?(Dt=he,ze=ye(V,mt,Cr),he=ze):(Y=he,he=r)):(Y=he,he=r)}else Y=he,he=r;else Y=he,he=r}re!==r?(Dt=N,V=ee(V,re),N=V):(Y=N,N=r)}else Y=N,N=r;return N}function Yr(){var N,V,re,he,ze,mt;if(N=Y,t.substr(Y,3)===Le?(V=Le,Y+=3):(V=r,ct===0&&Ct(ft)),V!==r){for(re=[],he=Qt();he!==r;)re.push(he),he=Qt();if(re!==r)if(he=ns(),he!==r){for(ze=[],mt=Qt();mt!==r;)ze.push(mt),mt=Qt();ze!==r?(t.substr(Y,2)===pt?(mt=pt,Y+=2):(mt=r,ct===0&&Ct(Nt)),mt!==r?(Dt=N,V=rr(he),N=V):(Y=N,N=r)):(Y=N,N=r)}else Y=N,N=r;else Y=N,N=r}else Y=N,N=r;return N}function dp(){var N,V,re,he;return N=Y,t.substr(Y,2)===$r?(V=$r,Y+=2):(V=r,ct===0&&Ct(ji)),V!==r?(re=Iu(),re!==r?(t.charCodeAt(Y)===41?(he=ne,Y++):(he=r,ct===0&&Ct(Z)),he!==r?(Dt=N,V=rs(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N}function Pc(){var N,V,re,he,ze,mt;return N=Y,t.substr(Y,2)===Si?(V=Si,Y+=2):(V=r,ct===0&&Ct(qo)),V!==r?(re=Wa(),re!==r?(t.substr(Y,2)===xA?(he=xA,Y+=2):(he=r,ct===0&&Ct(kA)),he!==r?(ze=TA(),ze!==r?(t.charCodeAt(Y)===125?(mt=H,Y++):(mt=r,ct===0&&Ct(rt)),mt!==r?(Dt=N,V=lp(re,ze),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Si?(V=Si,Y+=2):(V=r,ct===0&&Ct(qo)),V!==r?(re=Wa(),re!==r?(t.substr(Y,3)===e0?(he=e0,Y+=3):(he=r,ct===0&&Ct(mu)),he!==r?(Dt=N,V=t0(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Si?(V=Si,Y+=2):(V=r,ct===0&&Ct(qo)),V!==r?(re=Wa(),re!==r?(t.substr(Y,2)===yu?(he=yu,Y+=2):(he=r,ct===0&&Ct(uo)),he!==r?(ze=TA(),ze!==r?(t.charCodeAt(Y)===125?(mt=H,Y++):(mt=r,ct===0&&Ct(rt)),mt!==r?(Dt=N,V=QA(re,ze),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Si?(V=Si,Y+=2):(V=r,ct===0&&Ct(qo)),V!==r?(re=Wa(),re!==r?(t.substr(Y,3)===yc?(he=yc,Y+=3):(he=r,ct===0&&Ct(Aa)),he!==r?(Dt=N,V=r0(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.substr(Y,2)===Si?(V=Si,Y+=2):(V=r,ct===0&&Ct(qo)),V!==r?(re=Wa(),re!==r?(t.charCodeAt(Y)===125?(he=H,Y++):(he=r,ct===0&&Ct(rt)),he!==r?(Dt=N,V=Ec(re),N=V):(Y=N,N=r)):(Y=N,N=r)):(Y=N,N=r),N===r&&(N=Y,t.charCodeAt(Y)===36?(V=hd,Y++):(V=r,ct===0&&Ct(n0)),V!==r?(re=Wa(),re!==r?(Dt=N,V=Ec(re),N=V):(Y=N,N=r)):(Y=N,N=r)))))),N}function nw(){var N,V,re;return N=Y,V=g0(),V!==r?(Dt=Y,re=$n(V),re?re=void 0:re=r,re!==r?(Dt=N,V=cp(V),N=V):(Y=N,N=r)):(Y=N,N=r),N}function g0(){var N,V,re,he,ze;if(N=Y,V=[],re=Y,he=Y,ct++,ze=m0(),ct--,ze===r?he=void 0:(Y=he,he=r),he!==r?(t.length>Y?(ze=t.charAt(Y),Y++):(ze=r,ct===0&&Ct(Fn)),ze!==r?(Dt=re,he=Me(ze),re=he):(Y=re,re=r)):(Y=re,re=r),re!==r)for(;re!==r;)V.push(re),re=Y,he=Y,ct++,ze=m0(),ct--,ze===r?he=void 0:(Y=he,he=r),he!==r?(t.length>Y?(ze=t.charAt(Y),Y++):(ze=r,ct===0&&Ct(Fn)),ze!==r?(Dt=re,he=Me(ze),re=he):(Y=re,re=r)):(Y=re,re=r);else V=r;return V!==r&&(Dt=N,V=_s(V)),N=V,N}function d0(){var N,V,re;if(N=Y,V=[],i0.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(FA)),re!==r)for(;re!==r;)V.push(re),i0.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(FA));else V=r;return V!==r&&(Dt=N,V=js()),N=V,N}function Wa(){var N,V,re;if(N=Y,V=[],Eu.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(ja)),re!==r)for(;re!==r;)V.push(re),Eu.test(t.charAt(Y))?(re=t.charAt(Y),Y++):(re=r,ct===0&&Ct(ja));else V=r;return V!==r&&(Dt=N,V=js()),N=V,N}function Cd(){var N;return Gi.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,ct===0&&Ct(fa)),N}function m0(){var N;return Cu.test(t.charAt(Y))?(N=t.charAt(Y),Y++):(N=r,ct===0&&Ct(ws)),N}function Qt(){var N,V;if(N=[],Cc.test(t.charAt(Y))?(V=t.charAt(Y),Y++):(V=r,ct===0&&Ct(wc)),V!==r)for(;V!==r;)N.push(V),Cc.test(t.charAt(Y))?(V=t.charAt(Y),Y++):(V=r,ct===0&&Ct(wc));else N=r;return N}if(wu=a(),wu!==r&&Y===t.length)return wu;throw wu!==r&&Y<t.length&&Ct(a0()),c0(Ic,bi<t.length?t.charAt(bi):null,bi<t.length?Bc(bi,bi+1):Bc(bi,bi))}XY.exports={SyntaxError:_0,parse:c8e}});function CD(t,e={isGlobPattern:()=>!1}){try{return(0,$Y.parse)(t,e)}catch(r){throw r.location&&(r.message=r.message.replace(/(\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function zd(t,{endSemicolon:e=!1}={}){return t.map(({command:r,type:o},a)=>`${wD(r)}${o===";"?a!==t.length-1||e?";":"":" &"}`).join(" ")}function wD(t){return`${Jd(t.chain)}${t.then?` ${VR(t.then)}`:""}`}function VR(t){return`${t.type} ${wD(t.line)}`}function Jd(t){return`${JR(t)}${t.then?` ${zR(t.then)}`:""}`}function zR(t){return`${t.type} ${Jd(t.chain)}`}function JR(t){switch(t.type){case"command":return`${t.envs.length>0?`${t.envs.map(e=>ED(e)).join(" ")} `:""}${t.args.map(e=>XR(e)).join(" ")}`;case"subshell":return`(${zd(t.subshell)})${t.args.length>0?` ${t.args.map(e=>Qw(e)).join(" ")}`:""}`;case"group":return`{ ${zd(t.group,{endSemicolon:!0})} }${t.args.length>0?` ${t.args.map(e=>Qw(e)).join(" ")}`:""}`;case"envs":return t.envs.map(e=>ED(e)).join(" ");default:throw new Error(`Unsupported command type: "${t.type}"`)}}function ED(t){return`${t.name}=${t.args[0]?H0(t.args[0]):""}`}function XR(t){switch(t.type){case"redirection":return Qw(t);case"argument":return H0(t);default:throw new Error(`Unsupported argument type: "${t.type}"`)}}function Qw(t){return`${t.subtype} ${t.args.map(e=>H0(e)).join(" ")}`}function H0(t){return t.segments.map(e=>ZR(e)).join("")}function ZR(t){let e=(o,a)=>a?`"${o}"`:o,r=o=>o===""?"''":o.match(/[()}<>$|&;"'\n\t ]/)?o.match(/['\t\p{C}]/u)?o.match(/'/)?`"${o.replace(/["$\t\p{C}]/u,A8e)}"`:`$'${o.replace(/[\t\p{C}]/u,tW)}'`:`'${o}'`:o;switch(t.type){case"text":return r(t.text);case"glob":return t.pattern;case"shell":return e(`$(${zd(t.shell)})`,t.quoted);case"variable":return e(typeof t.defaultValue>"u"?typeof t.alternativeValue>"u"?`\${${t.name}}`:t.alternativeValue.length===0?`\${${t.name}:+}`:`\${${t.name}:+${t.alternativeValue.map(o=>H0(o)).join(" ")}}`:t.defaultValue.length===0?`\${${t.name}:-}`:`\${${t.name}:-${t.defaultValue.map(o=>H0(o)).join(" ")}}`,t.quoted);case"arithmetic":return`$(( ${ID(t.arithmetic)} ))`;default:throw new Error(`Unsupported argument segment type: "${t.type}"`)}}function ID(t){let e=a=>{switch(a){case"addition":return"+";case"subtraction":return"-";case"multiplication":return"*";case"division":return"/";default:throw new Error(`Can't extract operator from arithmetic expression of type "${a}"`)}},r=(a,n)=>n?`( ${a} )`:a,o=a=>r(ID(a),!["number","variable"].includes(a.type));switch(t.type){case"number":return String(t.value);case"variable":return t.name;default:return`${o(t.left)} ${e(t.type)} ${o(t.right)}`}}var $Y,eW,u8e,tW,A8e,rW=Et(()=>{$Y=Ze(ZY());eW=new Map([["\f","\\f"],[` +`,"\\n"],["\r","\\r"],[" ","\\t"],["\v","\\v"],["\0","\\0"]]),u8e=new Map([["\\","\\\\"],["$","\\$"],['"','\\"'],...Array.from(eW,([t,e])=>[t,`"$'${e}'"`])]),tW=t=>eW.get(t)??`\\x${t.charCodeAt(0).toString(16).padStart(2,"0")}`,A8e=t=>u8e.get(t)??`"$'${tW(t)}'"`});var iW=_((_bt,nW)=>{"use strict";function f8e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function q0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,q0)}f8e(q0,Error);q0.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I<h.parts.length;I++)E+=h.parts[I]instanceof Array?n(h.parts[I][0])+"-"+n(h.parts[I][1]):n(h.parts[I]);return"["+(h.inverted?"^":"")+E+"]"},any:function(h){return"any character"},end:function(h){return"end of input"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),I,v;for(I=0;I<h.length;I++)E[I]=u(h[I]);if(E.sort(),E.length>0){for(I=1,v=1;I<E.length;I++)E[I-1]!==E[I]&&(E[v]=E[I],v++);E.length=v}switch(E.length){case 1:return E[0];case 2:return E[0]+" or "+E[1];default:return E.slice(0,-1).join(", ")+", or "+E[E.length-1]}}function p(h){return h?'"'+a(h)+'"':"end of input"}return"Expected "+A(t)+" but "+p(e)+" found."};function p8e(t,e){e=e!==void 0?e:{};var r={},o={resolution:Fe},a=Fe,n="/",u=we("/",!1),A=function(Ue,b){return{from:Ue,descriptor:b}},p=function(Ue){return{descriptor:Ue}},h="@",E=we("@",!1),I=function(Ue,b){return{fullName:Ue,description:b}},v=function(Ue){return{fullName:Ue}},x=function(){return Be()},C=/^[^\/@]/,R=Ae(["/","@"],!0,!1),L=/^[^\/]/,U=Ae(["/"],!0,!1),z=0,te=0,ae=[{line:1,column:1}],le=0,ce=[],Ce=0,de;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function Be(){return t.substring(te,z)}function Ee(){return ht(te,z)}function g(Ue,b){throw b=b!==void 0?b:ht(te,z),Te([xe(Ue)],t.substring(te,z),b)}function me(Ue,b){throw b=b!==void 0?b:ht(te,z),rt(Ue,b)}function we(Ue,b){return{type:"literal",text:Ue,ignoreCase:b}}function Ae(Ue,b,w){return{type:"class",parts:Ue,inverted:b,ignoreCase:w}}function ne(){return{type:"any"}}function Z(){return{type:"end"}}function xe(Ue){return{type:"other",description:Ue}}function Ne(Ue){var b=ae[Ue],w;if(b)return b;for(w=Ue-1;!ae[w];)w--;for(b=ae[w],b={line:b.line,column:b.column};w<Ue;)t.charCodeAt(w)===10?(b.line++,b.column=1):b.column++,w++;return ae[Ue]=b,b}function ht(Ue,b){var w=Ne(Ue),S=Ne(b);return{start:{offset:Ue,line:w.line,column:w.column},end:{offset:b,line:S.line,column:S.column}}}function H(Ue){z<le||(z>le&&(le=z,ce=[]),ce.push(Ue))}function rt(Ue,b){return new q0(Ue,null,null,b)}function Te(Ue,b,w){return new q0(q0.buildMessage(Ue,b),Ue,b,w)}function Fe(){var Ue,b,w,S;return Ue=z,b=ke(),b!==r?(t.charCodeAt(z)===47?(w=n,z++):(w=r,Ce===0&&H(u)),w!==r?(S=ke(),S!==r?(te=Ue,b=A(b,S),Ue=b):(z=Ue,Ue=r)):(z=Ue,Ue=r)):(z=Ue,Ue=r),Ue===r&&(Ue=z,b=ke(),b!==r&&(te=Ue,b=p(b)),Ue=b),Ue}function ke(){var Ue,b,w,S;return Ue=z,b=Ye(),b!==r?(t.charCodeAt(z)===64?(w=h,z++):(w=r,Ce===0&&H(E)),w!==r?(S=et(),S!==r?(te=Ue,b=I(b,S),Ue=b):(z=Ue,Ue=r)):(z=Ue,Ue=r)):(z=Ue,Ue=r),Ue===r&&(Ue=z,b=Ye(),b!==r&&(te=Ue,b=v(b)),Ue=b),Ue}function Ye(){var Ue,b,w,S,y;return Ue=z,t.charCodeAt(z)===64?(b=h,z++):(b=r,Ce===0&&H(E)),b!==r?(w=Se(),w!==r?(t.charCodeAt(z)===47?(S=n,z++):(S=r,Ce===0&&H(u)),S!==r?(y=Se(),y!==r?(te=Ue,b=x(),Ue=b):(z=Ue,Ue=r)):(z=Ue,Ue=r)):(z=Ue,Ue=r)):(z=Ue,Ue=r),Ue===r&&(Ue=z,b=Se(),b!==r&&(te=Ue,b=x()),Ue=b),Ue}function Se(){var Ue,b,w;if(Ue=z,b=[],C.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&H(R)),w!==r)for(;w!==r;)b.push(w),C.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&H(R));else b=r;return b!==r&&(te=Ue,b=x()),Ue=b,Ue}function et(){var Ue,b,w;if(Ue=z,b=[],L.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&H(U)),w!==r)for(;w!==r;)b.push(w),L.test(t.charAt(z))?(w=t.charAt(z),z++):(w=r,Ce===0&&H(U));else b=r;return b!==r&&(te=Ue,b=x()),Ue=b,Ue}if(de=a(),de!==r&&z===t.length)return de;throw de!==r&&z<t.length&&H(Z()),Te(ce,le<t.length?t.charAt(le):null,le<t.length?ht(le,le+1):ht(le,le))}nW.exports={SyntaxError:q0,parse:p8e}});function BD(t){let e=t.match(/^\*{1,2}\/(.*)/);if(e)throw new Error(`The override for '${t}' includes a glob pattern. Glob patterns have been removed since their behaviours don't match what you'd expect. Set the override to '${e[1]}' instead.`);try{return(0,sW.parse)(t)}catch(r){throw r.location&&(r.message=r.message.replace(/(\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function vD(t){let e="";return t.from&&(e+=t.from.fullName,t.from.description&&(e+=`@${t.from.description}`),e+="/"),e+=t.descriptor.fullName,t.descriptor.description&&(e+=`@${t.descriptor.description}`),e}var sW,oW=Et(()=>{sW=Ze(iW())});var G0=_((qbt,j0)=>{"use strict";function aW(t){return typeof t>"u"||t===null}function h8e(t){return typeof t=="object"&&t!==null}function g8e(t){return Array.isArray(t)?t:aW(t)?[]:[t]}function d8e(t,e){var r,o,a,n;if(e)for(n=Object.keys(e),r=0,o=n.length;r<o;r+=1)a=n[r],t[a]=e[a];return t}function m8e(t,e){var r="",o;for(o=0;o<e;o+=1)r+=t;return r}function y8e(t){return t===0&&Number.NEGATIVE_INFINITY===1/t}j0.exports.isNothing=aW;j0.exports.isObject=h8e;j0.exports.toArray=g8e;j0.exports.repeat=m8e;j0.exports.isNegativeZero=y8e;j0.exports.extend=d8e});var Xd=_((jbt,lW)=>{"use strict";function Fw(t,e){Error.call(this),this.name="YAMLException",this.reason=t,this.mark=e,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}Fw.prototype=Object.create(Error.prototype);Fw.prototype.constructor=Fw;Fw.prototype.toString=function(e){var r=this.name+": ";return r+=this.reason||"(unknown reason)",!e&&this.mark&&(r+=" "+this.mark.toString()),r};lW.exports=Fw});var AW=_((Gbt,uW)=>{"use strict";var cW=G0();function $R(t,e,r,o,a){this.name=t,this.buffer=e,this.position=r,this.line=o,this.column=a}$R.prototype.getSnippet=function(e,r){var o,a,n,u,A;if(!this.buffer)return null;for(e=e||4,r=r||75,o="",a=this.position;a>0&&`\0\r +\x85\u2028\u2029`.indexOf(this.buffer.charAt(a-1))===-1;)if(a-=1,this.position-a>r/2-1){o=" ... ",a+=5;break}for(n="",u=this.position;u<this.buffer.length&&`\0\r +\x85\u2028\u2029`.indexOf(this.buffer.charAt(u))===-1;)if(u+=1,u-this.position>r/2-1){n=" ... ",u-=5;break}return A=this.buffer.slice(a,u),cW.repeat(" ",e)+o+A+n+` +`+cW.repeat(" ",e+this.position-a+o.length)+"^"};$R.prototype.toString=function(e){var r,o="";return this.name&&(o+='in "'+this.name+'" '),o+="at line "+(this.line+1)+", column "+(this.column+1),e||(r=this.getSnippet(),r&&(o+=`: +`+r)),o};uW.exports=$R});var ls=_((Ybt,pW)=>{"use strict";var fW=Xd(),E8e=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],C8e=["scalar","sequence","mapping"];function w8e(t){var e={};return t!==null&&Object.keys(t).forEach(function(r){t[r].forEach(function(o){e[String(o)]=r})}),e}function I8e(t,e){if(e=e||{},Object.keys(e).forEach(function(r){if(E8e.indexOf(r)===-1)throw new fW('Unknown option "'+r+'" is met in definition of "'+t+'" YAML type.')}),this.tag=t,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(r){return r},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.defaultStyle=e.defaultStyle||null,this.styleAliases=w8e(e.styleAliases||null),C8e.indexOf(this.kind)===-1)throw new fW('Unknown kind "'+this.kind+'" is specified for "'+t+'" YAML type.')}pW.exports=I8e});var Y0=_((Wbt,gW)=>{"use strict";var hW=G0(),DD=Xd(),B8e=ls();function eT(t,e,r){var o=[];return t.include.forEach(function(a){r=eT(a,e,r)}),t[e].forEach(function(a){r.forEach(function(n,u){n.tag===a.tag&&n.kind===a.kind&&o.push(u)}),r.push(a)}),r.filter(function(a,n){return o.indexOf(n)===-1})}function v8e(){var t={scalar:{},sequence:{},mapping:{},fallback:{}},e,r;function o(a){t[a.kind][a.tag]=t.fallback[a.tag]=a}for(e=0,r=arguments.length;e<r;e+=1)arguments[e].forEach(o);return t}function Zd(t){this.include=t.include||[],this.implicit=t.implicit||[],this.explicit=t.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&e.loadKind!=="scalar")throw new DD("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")}),this.compiledImplicit=eT(this,"implicit",[]),this.compiledExplicit=eT(this,"explicit",[]),this.compiledTypeMap=v8e(this.compiledImplicit,this.compiledExplicit)}Zd.DEFAULT=null;Zd.create=function(){var e,r;switch(arguments.length){case 1:e=Zd.DEFAULT,r=arguments[0];break;case 2:e=arguments[0],r=arguments[1];break;default:throw new DD("Wrong number of arguments for Schema.create function")}if(e=hW.toArray(e),r=hW.toArray(r),!e.every(function(o){return o instanceof Zd}))throw new DD("Specified list of super schemas (or a single Schema object) contains a non-Schema object.");if(!r.every(function(o){return o instanceof B8e}))throw new DD("Specified list of YAML types (or a single Type object) contains a non-Type object.");return new Zd({include:e,explicit:r})};gW.exports=Zd});var mW=_((Kbt,dW)=>{"use strict";var D8e=ls();dW.exports=new D8e("tag:yaml.org,2002:str",{kind:"scalar",construct:function(t){return t!==null?t:""}})});var EW=_((Vbt,yW)=>{"use strict";var P8e=ls();yW.exports=new P8e("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(t){return t!==null?t:[]}})});var wW=_((zbt,CW)=>{"use strict";var S8e=ls();CW.exports=new S8e("tag:yaml.org,2002:map",{kind:"mapping",construct:function(t){return t!==null?t:{}}})});var PD=_((Jbt,IW)=>{"use strict";var b8e=Y0();IW.exports=new b8e({explicit:[mW(),EW(),wW()]})});var vW=_((Xbt,BW)=>{"use strict";var x8e=ls();function k8e(t){if(t===null)return!0;var e=t.length;return e===1&&t==="~"||e===4&&(t==="null"||t==="Null"||t==="NULL")}function Q8e(){return null}function F8e(t){return t===null}BW.exports=new x8e("tag:yaml.org,2002:null",{kind:"scalar",resolve:k8e,construct:Q8e,predicate:F8e,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})});var PW=_((Zbt,DW)=>{"use strict";var R8e=ls();function T8e(t){if(t===null)return!1;var e=t.length;return e===4&&(t==="true"||t==="True"||t==="TRUE")||e===5&&(t==="false"||t==="False"||t==="FALSE")}function N8e(t){return t==="true"||t==="True"||t==="TRUE"}function L8e(t){return Object.prototype.toString.call(t)==="[object Boolean]"}DW.exports=new R8e("tag:yaml.org,2002:bool",{kind:"scalar",resolve:T8e,construct:N8e,predicate:L8e,represent:{lowercase:function(t){return t?"true":"false"},uppercase:function(t){return t?"TRUE":"FALSE"},camelcase:function(t){return t?"True":"False"}},defaultStyle:"lowercase"})});var bW=_(($bt,SW)=>{"use strict";var M8e=G0(),O8e=ls();function U8e(t){return 48<=t&&t<=57||65<=t&&t<=70||97<=t&&t<=102}function _8e(t){return 48<=t&&t<=55}function H8e(t){return 48<=t&&t<=57}function q8e(t){if(t===null)return!1;var e=t.length,r=0,o=!1,a;if(!e)return!1;if(a=t[r],(a==="-"||a==="+")&&(a=t[++r]),a==="0"){if(r+1===e)return!0;if(a=t[++r],a==="b"){for(r++;r<e;r++)if(a=t[r],a!=="_"){if(a!=="0"&&a!=="1")return!1;o=!0}return o&&a!=="_"}if(a==="x"){for(r++;r<e;r++)if(a=t[r],a!=="_"){if(!U8e(t.charCodeAt(r)))return!1;o=!0}return o&&a!=="_"}for(;r<e;r++)if(a=t[r],a!=="_"){if(!_8e(t.charCodeAt(r)))return!1;o=!0}return o&&a!=="_"}if(a==="_")return!1;for(;r<e;r++)if(a=t[r],a!=="_"){if(a===":")break;if(!H8e(t.charCodeAt(r)))return!1;o=!0}return!o||a==="_"?!1:a!==":"?!0:/^(:[0-5]?[0-9])+$/.test(t.slice(r))}function j8e(t){var e=t,r=1,o,a,n=[];return e.indexOf("_")!==-1&&(e=e.replace(/_/g,"")),o=e[0],(o==="-"||o==="+")&&(o==="-"&&(r=-1),e=e.slice(1),o=e[0]),e==="0"?0:o==="0"?e[1]==="b"?r*parseInt(e.slice(2),2):e[1]==="x"?r*parseInt(e,16):r*parseInt(e,8):e.indexOf(":")!==-1?(e.split(":").forEach(function(u){n.unshift(parseInt(u,10))}),e=0,a=1,n.forEach(function(u){e+=u*a,a*=60}),r*e):r*parseInt(e,10)}function G8e(t){return Object.prototype.toString.call(t)==="[object Number]"&&t%1===0&&!M8e.isNegativeZero(t)}SW.exports=new O8e("tag:yaml.org,2002:int",{kind:"scalar",resolve:q8e,construct:j8e,predicate:G8e,represent:{binary:function(t){return t>=0?"0b"+t.toString(2):"-0b"+t.toString(2).slice(1)},octal:function(t){return t>=0?"0"+t.toString(8):"-0"+t.toString(8).slice(1)},decimal:function(t){return t.toString(10)},hexadecimal:function(t){return t>=0?"0x"+t.toString(16).toUpperCase():"-0x"+t.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})});var QW=_((ext,kW)=>{"use strict";var xW=G0(),Y8e=ls(),W8e=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function K8e(t){return!(t===null||!W8e.test(t)||t[t.length-1]==="_")}function V8e(t){var e,r,o,a;return e=t.replace(/_/g,"").toLowerCase(),r=e[0]==="-"?-1:1,a=[],"+-".indexOf(e[0])>=0&&(e=e.slice(1)),e===".inf"?r===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:e===".nan"?NaN:e.indexOf(":")>=0?(e.split(":").forEach(function(n){a.unshift(parseFloat(n,10))}),e=0,o=1,a.forEach(function(n){e+=n*o,o*=60}),r*e):r*parseFloat(e,10)}var z8e=/^[-+]?[0-9]+e/;function J8e(t,e){var r;if(isNaN(t))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===t)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===t)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(xW.isNegativeZero(t))return"-0.0";return r=t.toString(10),z8e.test(r)?r.replace("e",".e"):r}function X8e(t){return Object.prototype.toString.call(t)==="[object Number]"&&(t%1!==0||xW.isNegativeZero(t))}kW.exports=new Y8e("tag:yaml.org,2002:float",{kind:"scalar",resolve:K8e,construct:V8e,predicate:X8e,represent:J8e,defaultStyle:"lowercase"})});var tT=_((txt,FW)=>{"use strict";var Z8e=Y0();FW.exports=new Z8e({include:[PD()],implicit:[vW(),PW(),bW(),QW()]})});var rT=_((rxt,RW)=>{"use strict";var $8e=Y0();RW.exports=new $8e({include:[tT()]})});var MW=_((nxt,LW)=>{"use strict";var eHe=ls(),TW=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),NW=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function tHe(t){return t===null?!1:TW.exec(t)!==null||NW.exec(t)!==null}function rHe(t){var e,r,o,a,n,u,A,p=0,h=null,E,I,v;if(e=TW.exec(t),e===null&&(e=NW.exec(t)),e===null)throw new Error("Date resolve error");if(r=+e[1],o=+e[2]-1,a=+e[3],!e[4])return new Date(Date.UTC(r,o,a));if(n=+e[4],u=+e[5],A=+e[6],e[7]){for(p=e[7].slice(0,3);p.length<3;)p+="0";p=+p}return e[9]&&(E=+e[10],I=+(e[11]||0),h=(E*60+I)*6e4,e[9]==="-"&&(h=-h)),v=new Date(Date.UTC(r,o,a,n,u,A,p)),h&&v.setTime(v.getTime()-h),v}function nHe(t){return t.toISOString()}LW.exports=new eHe("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:tHe,construct:rHe,instanceOf:Date,represent:nHe})});var UW=_((ixt,OW)=>{"use strict";var iHe=ls();function sHe(t){return t==="<<"||t===null}OW.exports=new iHe("tag:yaml.org,2002:merge",{kind:"scalar",resolve:sHe})});var qW=_((sxt,HW)=>{"use strict";var W0;try{_W=ve,W0=_W("buffer").Buffer}catch{}var _W,oHe=ls(),nT=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function aHe(t){if(t===null)return!1;var e,r,o=0,a=t.length,n=nT;for(r=0;r<a;r++)if(e=n.indexOf(t.charAt(r)),!(e>64)){if(e<0)return!1;o+=6}return o%8===0}function lHe(t){var e,r,o=t.replace(/[\r\n=]/g,""),a=o.length,n=nT,u=0,A=[];for(e=0;e<a;e++)e%4===0&&e&&(A.push(u>>16&255),A.push(u>>8&255),A.push(u&255)),u=u<<6|n.indexOf(o.charAt(e));return r=a%4*6,r===0?(A.push(u>>16&255),A.push(u>>8&255),A.push(u&255)):r===18?(A.push(u>>10&255),A.push(u>>2&255)):r===12&&A.push(u>>4&255),W0?W0.from?W0.from(A):new W0(A):A}function cHe(t){var e="",r=0,o,a,n=t.length,u=nT;for(o=0;o<n;o++)o%3===0&&o&&(e+=u[r>>18&63],e+=u[r>>12&63],e+=u[r>>6&63],e+=u[r&63]),r=(r<<8)+t[o];return a=n%3,a===0?(e+=u[r>>18&63],e+=u[r>>12&63],e+=u[r>>6&63],e+=u[r&63]):a===2?(e+=u[r>>10&63],e+=u[r>>4&63],e+=u[r<<2&63],e+=u[64]):a===1&&(e+=u[r>>2&63],e+=u[r<<4&63],e+=u[64],e+=u[64]),e}function uHe(t){return W0&&W0.isBuffer(t)}HW.exports=new oHe("tag:yaml.org,2002:binary",{kind:"scalar",resolve:aHe,construct:lHe,predicate:uHe,represent:cHe})});var GW=_((axt,jW)=>{"use strict";var AHe=ls(),fHe=Object.prototype.hasOwnProperty,pHe=Object.prototype.toString;function hHe(t){if(t===null)return!0;var e=[],r,o,a,n,u,A=t;for(r=0,o=A.length;r<o;r+=1){if(a=A[r],u=!1,pHe.call(a)!=="[object Object]")return!1;for(n in a)if(fHe.call(a,n))if(!u)u=!0;else return!1;if(!u)return!1;if(e.indexOf(n)===-1)e.push(n);else return!1}return!0}function gHe(t){return t!==null?t:[]}jW.exports=new AHe("tag:yaml.org,2002:omap",{kind:"sequence",resolve:hHe,construct:gHe})});var WW=_((lxt,YW)=>{"use strict";var dHe=ls(),mHe=Object.prototype.toString;function yHe(t){if(t===null)return!0;var e,r,o,a,n,u=t;for(n=new Array(u.length),e=0,r=u.length;e<r;e+=1){if(o=u[e],mHe.call(o)!=="[object Object]"||(a=Object.keys(o),a.length!==1))return!1;n[e]=[a[0],o[a[0]]]}return!0}function EHe(t){if(t===null)return[];var e,r,o,a,n,u=t;for(n=new Array(u.length),e=0,r=u.length;e<r;e+=1)o=u[e],a=Object.keys(o),n[e]=[a[0],o[a[0]]];return n}YW.exports=new dHe("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:yHe,construct:EHe})});var VW=_((cxt,KW)=>{"use strict";var CHe=ls(),wHe=Object.prototype.hasOwnProperty;function IHe(t){if(t===null)return!0;var e,r=t;for(e in r)if(wHe.call(r,e)&&r[e]!==null)return!1;return!0}function BHe(t){return t!==null?t:{}}KW.exports=new CHe("tag:yaml.org,2002:set",{kind:"mapping",resolve:IHe,construct:BHe})});var $d=_((uxt,zW)=>{"use strict";var vHe=Y0();zW.exports=new vHe({include:[rT()],implicit:[MW(),UW()],explicit:[qW(),GW(),WW(),VW()]})});var XW=_((Axt,JW)=>{"use strict";var DHe=ls();function PHe(){return!0}function SHe(){}function bHe(){return""}function xHe(t){return typeof t>"u"}JW.exports=new DHe("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:PHe,construct:SHe,predicate:xHe,represent:bHe})});var $W=_((fxt,ZW)=>{"use strict";var kHe=ls();function QHe(t){if(t===null||t.length===0)return!1;var e=t,r=/\/([gim]*)$/.exec(t),o="";return!(e[0]==="/"&&(r&&(o=r[1]),o.length>3||e[e.length-o.length-1]!=="/"))}function FHe(t){var e=t,r=/\/([gim]*)$/.exec(t),o="";return e[0]==="/"&&(r&&(o=r[1]),e=e.slice(1,e.length-o.length-1)),new RegExp(e,o)}function RHe(t){var e="/"+t.source+"/";return t.global&&(e+="g"),t.multiline&&(e+="m"),t.ignoreCase&&(e+="i"),e}function THe(t){return Object.prototype.toString.call(t)==="[object RegExp]"}ZW.exports=new kHe("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:QHe,construct:FHe,predicate:THe,represent:RHe})});var rK=_((pxt,tK)=>{"use strict";var SD;try{eK=ve,SD=eK("esprima")}catch{typeof window<"u"&&(SD=window.esprima)}var eK,NHe=ls();function LHe(t){if(t===null)return!1;try{var e="("+t+")",r=SD.parse(e,{range:!0});return!(r.type!=="Program"||r.body.length!==1||r.body[0].type!=="ExpressionStatement"||r.body[0].expression.type!=="ArrowFunctionExpression"&&r.body[0].expression.type!=="FunctionExpression")}catch{return!1}}function MHe(t){var e="("+t+")",r=SD.parse(e,{range:!0}),o=[],a;if(r.type!=="Program"||r.body.length!==1||r.body[0].type!=="ExpressionStatement"||r.body[0].expression.type!=="ArrowFunctionExpression"&&r.body[0].expression.type!=="FunctionExpression")throw new Error("Failed to resolve function");return r.body[0].expression.params.forEach(function(n){o.push(n.name)}),a=r.body[0].expression.body.range,r.body[0].expression.body.type==="BlockStatement"?new Function(o,e.slice(a[0]+1,a[1]-1)):new Function(o,"return "+e.slice(a[0],a[1]))}function OHe(t){return t.toString()}function UHe(t){return Object.prototype.toString.call(t)==="[object Function]"}tK.exports=new NHe("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:LHe,construct:MHe,predicate:UHe,represent:OHe})});var Rw=_((gxt,iK)=>{"use strict";var nK=Y0();iK.exports=nK.DEFAULT=new nK({include:[$d()],explicit:[XW(),$W(),rK()]})});var BK=_((dxt,Tw)=>{"use strict";var mf=G0(),AK=Xd(),_He=AW(),fK=$d(),HHe=Rw(),qp=Object.prototype.hasOwnProperty,bD=1,pK=2,hK=3,xD=4,iT=1,qHe=2,sK=3,jHe=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,GHe=/[\x85\u2028\u2029]/,YHe=/[,\[\]\{\}]/,gK=/^(?:!|!!|![a-z\-]+!)$/i,dK=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function oK(t){return Object.prototype.toString.call(t)}function ju(t){return t===10||t===13}function V0(t){return t===9||t===32}function va(t){return t===9||t===32||t===10||t===13}function em(t){return t===44||t===91||t===93||t===123||t===125}function WHe(t){var e;return 48<=t&&t<=57?t-48:(e=t|32,97<=e&&e<=102?e-97+10:-1)}function KHe(t){return t===120?2:t===117?4:t===85?8:0}function VHe(t){return 48<=t&&t<=57?t-48:-1}function aK(t){return t===48?"\0":t===97?"\x07":t===98?"\b":t===116||t===9?" ":t===110?` +`:t===118?"\v":t===102?"\f":t===114?"\r":t===101?"\x1B":t===32?" ":t===34?'"':t===47?"/":t===92?"\\":t===78?"\x85":t===95?"\xA0":t===76?"\u2028":t===80?"\u2029":""}function zHe(t){return t<=65535?String.fromCharCode(t):String.fromCharCode((t-65536>>10)+55296,(t-65536&1023)+56320)}var mK=new Array(256),yK=new Array(256);for(K0=0;K0<256;K0++)mK[K0]=aK(K0)?1:0,yK[K0]=aK(K0);var K0;function JHe(t,e){this.input=t,this.filename=e.filename||null,this.schema=e.schema||HHe,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=t.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function EK(t,e){return new AK(e,new _He(t.filename,t.input,t.position,t.line,t.position-t.lineStart))}function Sr(t,e){throw EK(t,e)}function kD(t,e){t.onWarning&&t.onWarning.call(null,EK(t,e))}var lK={YAML:function(e,r,o){var a,n,u;e.version!==null&&Sr(e,"duplication of %YAML directive"),o.length!==1&&Sr(e,"YAML directive accepts exactly one argument"),a=/^([0-9]+)\.([0-9]+)$/.exec(o[0]),a===null&&Sr(e,"ill-formed argument of the YAML directive"),n=parseInt(a[1],10),u=parseInt(a[2],10),n!==1&&Sr(e,"unacceptable YAML version of the document"),e.version=o[0],e.checkLineBreaks=u<2,u!==1&&u!==2&&kD(e,"unsupported YAML version of the document")},TAG:function(e,r,o){var a,n;o.length!==2&&Sr(e,"TAG directive accepts exactly two arguments"),a=o[0],n=o[1],gK.test(a)||Sr(e,"ill-formed tag handle (first argument) of the TAG directive"),qp.call(e.tagMap,a)&&Sr(e,'there is a previously declared suffix for "'+a+'" tag handle'),dK.test(n)||Sr(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[a]=n}};function Hp(t,e,r,o){var a,n,u,A;if(e<r){if(A=t.input.slice(e,r),o)for(a=0,n=A.length;a<n;a+=1)u=A.charCodeAt(a),u===9||32<=u&&u<=1114111||Sr(t,"expected valid JSON character");else jHe.test(A)&&Sr(t,"the stream contains non-printable characters");t.result+=A}}function cK(t,e,r,o){var a,n,u,A;for(mf.isObject(r)||Sr(t,"cannot merge mappings; the provided source object is unacceptable"),a=Object.keys(r),u=0,A=a.length;u<A;u+=1)n=a[u],qp.call(e,n)||(e[n]=r[n],o[n]=!0)}function tm(t,e,r,o,a,n,u,A){var p,h;if(Array.isArray(a))for(a=Array.prototype.slice.call(a),p=0,h=a.length;p<h;p+=1)Array.isArray(a[p])&&Sr(t,"nested arrays are not supported inside keys"),typeof a=="object"&&oK(a[p])==="[object Object]"&&(a[p]="[object Object]");if(typeof a=="object"&&oK(a)==="[object Object]"&&(a="[object Object]"),a=String(a),e===null&&(e={}),o==="tag:yaml.org,2002:merge")if(Array.isArray(n))for(p=0,h=n.length;p<h;p+=1)cK(t,e,n[p],r);else cK(t,e,n,r);else!t.json&&!qp.call(r,a)&&qp.call(e,a)&&(t.line=u||t.line,t.position=A||t.position,Sr(t,"duplicated mapping key")),e[a]=n,delete r[a];return e}function sT(t){var e;e=t.input.charCodeAt(t.position),e===10?t.position++:e===13?(t.position++,t.input.charCodeAt(t.position)===10&&t.position++):Sr(t,"a line break is expected"),t.line+=1,t.lineStart=t.position}function Wi(t,e,r){for(var o=0,a=t.input.charCodeAt(t.position);a!==0;){for(;V0(a);)a=t.input.charCodeAt(++t.position);if(e&&a===35)do a=t.input.charCodeAt(++t.position);while(a!==10&&a!==13&&a!==0);if(ju(a))for(sT(t),a=t.input.charCodeAt(t.position),o++,t.lineIndent=0;a===32;)t.lineIndent++,a=t.input.charCodeAt(++t.position);else break}return r!==-1&&o!==0&&t.lineIndent<r&&kD(t,"deficient indentation"),o}function QD(t){var e=t.position,r;return r=t.input.charCodeAt(e),!!((r===45||r===46)&&r===t.input.charCodeAt(e+1)&&r===t.input.charCodeAt(e+2)&&(e+=3,r=t.input.charCodeAt(e),r===0||va(r)))}function oT(t,e){e===1?t.result+=" ":e>1&&(t.result+=mf.repeat(` +`,e-1))}function XHe(t,e,r){var o,a,n,u,A,p,h,E,I=t.kind,v=t.result,x;if(x=t.input.charCodeAt(t.position),va(x)||em(x)||x===35||x===38||x===42||x===33||x===124||x===62||x===39||x===34||x===37||x===64||x===96||(x===63||x===45)&&(a=t.input.charCodeAt(t.position+1),va(a)||r&&em(a)))return!1;for(t.kind="scalar",t.result="",n=u=t.position,A=!1;x!==0;){if(x===58){if(a=t.input.charCodeAt(t.position+1),va(a)||r&&em(a))break}else if(x===35){if(o=t.input.charCodeAt(t.position-1),va(o))break}else{if(t.position===t.lineStart&&QD(t)||r&&em(x))break;if(ju(x))if(p=t.line,h=t.lineStart,E=t.lineIndent,Wi(t,!1,-1),t.lineIndent>=e){A=!0,x=t.input.charCodeAt(t.position);continue}else{t.position=u,t.line=p,t.lineStart=h,t.lineIndent=E;break}}A&&(Hp(t,n,u,!1),oT(t,t.line-p),n=u=t.position,A=!1),V0(x)||(u=t.position+1),x=t.input.charCodeAt(++t.position)}return Hp(t,n,u,!1),t.result?!0:(t.kind=I,t.result=v,!1)}function ZHe(t,e){var r,o,a;if(r=t.input.charCodeAt(t.position),r!==39)return!1;for(t.kind="scalar",t.result="",t.position++,o=a=t.position;(r=t.input.charCodeAt(t.position))!==0;)if(r===39)if(Hp(t,o,t.position,!0),r=t.input.charCodeAt(++t.position),r===39)o=t.position,t.position++,a=t.position;else return!0;else ju(r)?(Hp(t,o,a,!0),oT(t,Wi(t,!1,e)),o=a=t.position):t.position===t.lineStart&&QD(t)?Sr(t,"unexpected end of the document within a single quoted scalar"):(t.position++,a=t.position);Sr(t,"unexpected end of the stream within a single quoted scalar")}function $He(t,e){var r,o,a,n,u,A;if(A=t.input.charCodeAt(t.position),A!==34)return!1;for(t.kind="scalar",t.result="",t.position++,r=o=t.position;(A=t.input.charCodeAt(t.position))!==0;){if(A===34)return Hp(t,r,t.position,!0),t.position++,!0;if(A===92){if(Hp(t,r,t.position,!0),A=t.input.charCodeAt(++t.position),ju(A))Wi(t,!1,e);else if(A<256&&mK[A])t.result+=yK[A],t.position++;else if((u=KHe(A))>0){for(a=u,n=0;a>0;a--)A=t.input.charCodeAt(++t.position),(u=WHe(A))>=0?n=(n<<4)+u:Sr(t,"expected hexadecimal character");t.result+=zHe(n),t.position++}else Sr(t,"unknown escape sequence");r=o=t.position}else ju(A)?(Hp(t,r,o,!0),oT(t,Wi(t,!1,e)),r=o=t.position):t.position===t.lineStart&&QD(t)?Sr(t,"unexpected end of the document within a double quoted scalar"):(t.position++,o=t.position)}Sr(t,"unexpected end of the stream within a double quoted scalar")}function e6e(t,e){var r=!0,o,a=t.tag,n,u=t.anchor,A,p,h,E,I,v={},x,C,R,L;if(L=t.input.charCodeAt(t.position),L===91)p=93,I=!1,n=[];else if(L===123)p=125,I=!0,n={};else return!1;for(t.anchor!==null&&(t.anchorMap[t.anchor]=n),L=t.input.charCodeAt(++t.position);L!==0;){if(Wi(t,!0,e),L=t.input.charCodeAt(t.position),L===p)return t.position++,t.tag=a,t.anchor=u,t.kind=I?"mapping":"sequence",t.result=n,!0;r||Sr(t,"missed comma between flow collection entries"),C=x=R=null,h=E=!1,L===63&&(A=t.input.charCodeAt(t.position+1),va(A)&&(h=E=!0,t.position++,Wi(t,!0,e))),o=t.line,rm(t,e,bD,!1,!0),C=t.tag,x=t.result,Wi(t,!0,e),L=t.input.charCodeAt(t.position),(E||t.line===o)&&L===58&&(h=!0,L=t.input.charCodeAt(++t.position),Wi(t,!0,e),rm(t,e,bD,!1,!0),R=t.result),I?tm(t,n,v,C,x,R):h?n.push(tm(t,null,v,C,x,R)):n.push(x),Wi(t,!0,e),L=t.input.charCodeAt(t.position),L===44?(r=!0,L=t.input.charCodeAt(++t.position)):r=!1}Sr(t,"unexpected end of the stream within a flow collection")}function t6e(t,e){var r,o,a=iT,n=!1,u=!1,A=e,p=0,h=!1,E,I;if(I=t.input.charCodeAt(t.position),I===124)o=!1;else if(I===62)o=!0;else return!1;for(t.kind="scalar",t.result="";I!==0;)if(I=t.input.charCodeAt(++t.position),I===43||I===45)iT===a?a=I===43?sK:qHe:Sr(t,"repeat of a chomping mode identifier");else if((E=VHe(I))>=0)E===0?Sr(t,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?Sr(t,"repeat of an indentation width identifier"):(A=e+E-1,u=!0);else break;if(V0(I)){do I=t.input.charCodeAt(++t.position);while(V0(I));if(I===35)do I=t.input.charCodeAt(++t.position);while(!ju(I)&&I!==0)}for(;I!==0;){for(sT(t),t.lineIndent=0,I=t.input.charCodeAt(t.position);(!u||t.lineIndent<A)&&I===32;)t.lineIndent++,I=t.input.charCodeAt(++t.position);if(!u&&t.lineIndent>A&&(A=t.lineIndent),ju(I)){p++;continue}if(t.lineIndent<A){a===sK?t.result+=mf.repeat(` +`,n?1+p:p):a===iT&&n&&(t.result+=` +`);break}for(o?V0(I)?(h=!0,t.result+=mf.repeat(` +`,n?1+p:p)):h?(h=!1,t.result+=mf.repeat(` +`,p+1)):p===0?n&&(t.result+=" "):t.result+=mf.repeat(` +`,p):t.result+=mf.repeat(` +`,n?1+p:p),n=!0,u=!0,p=0,r=t.position;!ju(I)&&I!==0;)I=t.input.charCodeAt(++t.position);Hp(t,r,t.position,!1)}return!0}function uK(t,e){var r,o=t.tag,a=t.anchor,n=[],u,A=!1,p;for(t.anchor!==null&&(t.anchorMap[t.anchor]=n),p=t.input.charCodeAt(t.position);p!==0&&!(p!==45||(u=t.input.charCodeAt(t.position+1),!va(u)));){if(A=!0,t.position++,Wi(t,!0,-1)&&t.lineIndent<=e){n.push(null),p=t.input.charCodeAt(t.position);continue}if(r=t.line,rm(t,e,hK,!1,!0),n.push(t.result),Wi(t,!0,-1),p=t.input.charCodeAt(t.position),(t.line===r||t.lineIndent>e)&&p!==0)Sr(t,"bad indentation of a sequence entry");else if(t.lineIndent<e)break}return A?(t.tag=o,t.anchor=a,t.kind="sequence",t.result=n,!0):!1}function r6e(t,e,r){var o,a,n,u,A=t.tag,p=t.anchor,h={},E={},I=null,v=null,x=null,C=!1,R=!1,L;for(t.anchor!==null&&(t.anchorMap[t.anchor]=h),L=t.input.charCodeAt(t.position);L!==0;){if(o=t.input.charCodeAt(t.position+1),n=t.line,u=t.position,(L===63||L===58)&&va(o))L===63?(C&&(tm(t,h,E,I,v,null),I=v=x=null),R=!0,C=!0,a=!0):C?(C=!1,a=!0):Sr(t,"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"),t.position+=1,L=o;else if(rm(t,r,pK,!1,!0))if(t.line===n){for(L=t.input.charCodeAt(t.position);V0(L);)L=t.input.charCodeAt(++t.position);if(L===58)L=t.input.charCodeAt(++t.position),va(L)||Sr(t,"a whitespace character is expected after the key-value separator within a block mapping"),C&&(tm(t,h,E,I,v,null),I=v=x=null),R=!0,C=!1,a=!1,I=t.tag,v=t.result;else if(R)Sr(t,"can not read an implicit mapping pair; a colon is missed");else return t.tag=A,t.anchor=p,!0}else if(R)Sr(t,"can not read a block mapping entry; a multiline key may not be an implicit key");else return t.tag=A,t.anchor=p,!0;else break;if((t.line===n||t.lineIndent>e)&&(rm(t,e,xD,!0,a)&&(C?v=t.result:x=t.result),C||(tm(t,h,E,I,v,x,n,u),I=v=x=null),Wi(t,!0,-1),L=t.input.charCodeAt(t.position)),t.lineIndent>e&&L!==0)Sr(t,"bad indentation of a mapping entry");else if(t.lineIndent<e)break}return C&&tm(t,h,E,I,v,null),R&&(t.tag=A,t.anchor=p,t.kind="mapping",t.result=h),R}function n6e(t){var e,r=!1,o=!1,a,n,u;if(u=t.input.charCodeAt(t.position),u!==33)return!1;if(t.tag!==null&&Sr(t,"duplication of a tag property"),u=t.input.charCodeAt(++t.position),u===60?(r=!0,u=t.input.charCodeAt(++t.position)):u===33?(o=!0,a="!!",u=t.input.charCodeAt(++t.position)):a="!",e=t.position,r){do u=t.input.charCodeAt(++t.position);while(u!==0&&u!==62);t.position<t.length?(n=t.input.slice(e,t.position),u=t.input.charCodeAt(++t.position)):Sr(t,"unexpected end of the stream within a verbatim tag")}else{for(;u!==0&&!va(u);)u===33&&(o?Sr(t,"tag suffix cannot contain exclamation marks"):(a=t.input.slice(e-1,t.position+1),gK.test(a)||Sr(t,"named tag handle cannot contain such characters"),o=!0,e=t.position+1)),u=t.input.charCodeAt(++t.position);n=t.input.slice(e,t.position),YHe.test(n)&&Sr(t,"tag suffix cannot contain flow indicator characters")}return n&&!dK.test(n)&&Sr(t,"tag name cannot contain such characters: "+n),r?t.tag=n:qp.call(t.tagMap,a)?t.tag=t.tagMap[a]+n:a==="!"?t.tag="!"+n:a==="!!"?t.tag="tag:yaml.org,2002:"+n:Sr(t,'undeclared tag handle "'+a+'"'),!0}function i6e(t){var e,r;if(r=t.input.charCodeAt(t.position),r!==38)return!1;for(t.anchor!==null&&Sr(t,"duplication of an anchor property"),r=t.input.charCodeAt(++t.position),e=t.position;r!==0&&!va(r)&&!em(r);)r=t.input.charCodeAt(++t.position);return t.position===e&&Sr(t,"name of an anchor node must contain at least one character"),t.anchor=t.input.slice(e,t.position),!0}function s6e(t){var e,r,o;if(o=t.input.charCodeAt(t.position),o!==42)return!1;for(o=t.input.charCodeAt(++t.position),e=t.position;o!==0&&!va(o)&&!em(o);)o=t.input.charCodeAt(++t.position);return t.position===e&&Sr(t,"name of an alias node must contain at least one character"),r=t.input.slice(e,t.position),qp.call(t.anchorMap,r)||Sr(t,'unidentified alias "'+r+'"'),t.result=t.anchorMap[r],Wi(t,!0,-1),!0}function rm(t,e,r,o,a){var n,u,A,p=1,h=!1,E=!1,I,v,x,C,R;if(t.listener!==null&&t.listener("open",t),t.tag=null,t.anchor=null,t.kind=null,t.result=null,n=u=A=xD===r||hK===r,o&&Wi(t,!0,-1)&&(h=!0,t.lineIndent>e?p=1:t.lineIndent===e?p=0:t.lineIndent<e&&(p=-1)),p===1)for(;n6e(t)||i6e(t);)Wi(t,!0,-1)?(h=!0,A=n,t.lineIndent>e?p=1:t.lineIndent===e?p=0:t.lineIndent<e&&(p=-1)):A=!1;if(A&&(A=h||a),(p===1||xD===r)&&(bD===r||pK===r?C=e:C=e+1,R=t.position-t.lineStart,p===1?A&&(uK(t,R)||r6e(t,R,C))||e6e(t,C)?E=!0:(u&&t6e(t,C)||ZHe(t,C)||$He(t,C)?E=!0:s6e(t)?(E=!0,(t.tag!==null||t.anchor!==null)&&Sr(t,"alias node should not have any properties")):XHe(t,C,bD===r)&&(E=!0,t.tag===null&&(t.tag="?")),t.anchor!==null&&(t.anchorMap[t.anchor]=t.result)):p===0&&(E=A&&uK(t,R))),t.tag!==null&&t.tag!=="!")if(t.tag==="?"){for(t.result!==null&&t.kind!=="scalar"&&Sr(t,'unacceptable node kind for !<?> tag; it should be "scalar", not "'+t.kind+'"'),I=0,v=t.implicitTypes.length;I<v;I+=1)if(x=t.implicitTypes[I],x.resolve(t.result)){t.result=x.construct(t.result),t.tag=x.tag,t.anchor!==null&&(t.anchorMap[t.anchor]=t.result);break}}else qp.call(t.typeMap[t.kind||"fallback"],t.tag)?(x=t.typeMap[t.kind||"fallback"][t.tag],t.result!==null&&x.kind!==t.kind&&Sr(t,"unacceptable node kind for !<"+t.tag+'> tag; it should be "'+x.kind+'", not "'+t.kind+'"'),x.resolve(t.result)?(t.result=x.construct(t.result),t.anchor!==null&&(t.anchorMap[t.anchor]=t.result)):Sr(t,"cannot resolve a node with !<"+t.tag+"> explicit tag")):Sr(t,"unknown tag !<"+t.tag+">");return t.listener!==null&&t.listener("close",t),t.tag!==null||t.anchor!==null||E}function o6e(t){var e=t.position,r,o,a,n=!1,u;for(t.version=null,t.checkLineBreaks=t.legacy,t.tagMap={},t.anchorMap={};(u=t.input.charCodeAt(t.position))!==0&&(Wi(t,!0,-1),u=t.input.charCodeAt(t.position),!(t.lineIndent>0||u!==37));){for(n=!0,u=t.input.charCodeAt(++t.position),r=t.position;u!==0&&!va(u);)u=t.input.charCodeAt(++t.position);for(o=t.input.slice(r,t.position),a=[],o.length<1&&Sr(t,"directive name must not be less than one character in length");u!==0;){for(;V0(u);)u=t.input.charCodeAt(++t.position);if(u===35){do u=t.input.charCodeAt(++t.position);while(u!==0&&!ju(u));break}if(ju(u))break;for(r=t.position;u!==0&&!va(u);)u=t.input.charCodeAt(++t.position);a.push(t.input.slice(r,t.position))}u!==0&&sT(t),qp.call(lK,o)?lK[o](t,o,a):kD(t,'unknown document directive "'+o+'"')}if(Wi(t,!0,-1),t.lineIndent===0&&t.input.charCodeAt(t.position)===45&&t.input.charCodeAt(t.position+1)===45&&t.input.charCodeAt(t.position+2)===45?(t.position+=3,Wi(t,!0,-1)):n&&Sr(t,"directives end mark is expected"),rm(t,t.lineIndent-1,xD,!1,!0),Wi(t,!0,-1),t.checkLineBreaks&&GHe.test(t.input.slice(e,t.position))&&kD(t,"non-ASCII line breaks are interpreted as content"),t.documents.push(t.result),t.position===t.lineStart&&QD(t)){t.input.charCodeAt(t.position)===46&&(t.position+=3,Wi(t,!0,-1));return}if(t.position<t.length-1)Sr(t,"end of the stream or a document separator is expected");else return}function CK(t,e){t=String(t),e=e||{},t.length!==0&&(t.charCodeAt(t.length-1)!==10&&t.charCodeAt(t.length-1)!==13&&(t+=` +`),t.charCodeAt(0)===65279&&(t=t.slice(1)));var r=new JHe(t,e),o=t.indexOf("\0");for(o!==-1&&(r.position=o,Sr(r,"null byte is not allowed in input")),r.input+="\0";r.input.charCodeAt(r.position)===32;)r.lineIndent+=1,r.position+=1;for(;r.position<r.length-1;)o6e(r);return r.documents}function wK(t,e,r){e!==null&&typeof e=="object"&&typeof r>"u"&&(r=e,e=null);var o=CK(t,r);if(typeof e!="function")return o;for(var a=0,n=o.length;a<n;a+=1)e(o[a])}function IK(t,e){var r=CK(t,e);if(r.length!==0){if(r.length===1)return r[0];throw new AK("expected a single document in the stream, but found more")}}function a6e(t,e,r){return typeof e=="object"&&e!==null&&typeof r>"u"&&(r=e,e=null),wK(t,e,mf.extend({schema:fK},r))}function l6e(t,e){return IK(t,mf.extend({schema:fK},e))}Tw.exports.loadAll=wK;Tw.exports.load=IK;Tw.exports.safeLoadAll=a6e;Tw.exports.safeLoad=l6e});var WK=_((mxt,uT)=>{"use strict";var Lw=G0(),Mw=Xd(),c6e=Rw(),u6e=$d(),QK=Object.prototype.toString,FK=Object.prototype.hasOwnProperty,A6e=9,Nw=10,f6e=13,p6e=32,h6e=33,g6e=34,RK=35,d6e=37,m6e=38,y6e=39,E6e=42,TK=44,C6e=45,NK=58,w6e=61,I6e=62,B6e=63,v6e=64,LK=91,MK=93,D6e=96,OK=123,P6e=124,UK=125,vo={};vo[0]="\\0";vo[7]="\\a";vo[8]="\\b";vo[9]="\\t";vo[10]="\\n";vo[11]="\\v";vo[12]="\\f";vo[13]="\\r";vo[27]="\\e";vo[34]='\\"';vo[92]="\\\\";vo[133]="\\N";vo[160]="\\_";vo[8232]="\\L";vo[8233]="\\P";var S6e=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function b6e(t,e){var r,o,a,n,u,A,p;if(e===null)return{};for(r={},o=Object.keys(e),a=0,n=o.length;a<n;a+=1)u=o[a],A=String(e[u]),u.slice(0,2)==="!!"&&(u="tag:yaml.org,2002:"+u.slice(2)),p=t.compiledTypeMap.fallback[u],p&&FK.call(p.styleAliases,A)&&(A=p.styleAliases[A]),r[u]=A;return r}function vK(t){var e,r,o;if(e=t.toString(16).toUpperCase(),t<=255)r="x",o=2;else if(t<=65535)r="u",o=4;else if(t<=4294967295)r="U",o=8;else throw new Mw("code point within a string may not be greater than 0xFFFFFFFF");return"\\"+r+Lw.repeat("0",o-e.length)+e}function x6e(t){this.schema=t.schema||c6e,this.indent=Math.max(1,t.indent||2),this.noArrayIndent=t.noArrayIndent||!1,this.skipInvalid=t.skipInvalid||!1,this.flowLevel=Lw.isNothing(t.flowLevel)?-1:t.flowLevel,this.styleMap=b6e(this.schema,t.styles||null),this.sortKeys=t.sortKeys||!1,this.lineWidth=t.lineWidth||80,this.noRefs=t.noRefs||!1,this.noCompatMode=t.noCompatMode||!1,this.condenseFlow=t.condenseFlow||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function DK(t,e){for(var r=Lw.repeat(" ",e),o=0,a=-1,n="",u,A=t.length;o<A;)a=t.indexOf(` +`,o),a===-1?(u=t.slice(o),o=A):(u=t.slice(o,a+1),o=a+1),u.length&&u!==` +`&&(n+=r),n+=u;return n}function aT(t,e){return` +`+Lw.repeat(" ",t.indent*e)}function k6e(t,e){var r,o,a;for(r=0,o=t.implicitTypes.length;r<o;r+=1)if(a=t.implicitTypes[r],a.resolve(e))return!0;return!1}function cT(t){return t===p6e||t===A6e}function nm(t){return 32<=t&&t<=126||161<=t&&t<=55295&&t!==8232&&t!==8233||57344<=t&&t<=65533&&t!==65279||65536<=t&&t<=1114111}function Q6e(t){return nm(t)&&!cT(t)&&t!==65279&&t!==f6e&&t!==Nw}function PK(t,e){return nm(t)&&t!==65279&&t!==TK&&t!==LK&&t!==MK&&t!==OK&&t!==UK&&t!==NK&&(t!==RK||e&&Q6e(e))}function F6e(t){return nm(t)&&t!==65279&&!cT(t)&&t!==C6e&&t!==B6e&&t!==NK&&t!==TK&&t!==LK&&t!==MK&&t!==OK&&t!==UK&&t!==RK&&t!==m6e&&t!==E6e&&t!==h6e&&t!==P6e&&t!==w6e&&t!==I6e&&t!==y6e&&t!==g6e&&t!==d6e&&t!==v6e&&t!==D6e}function _K(t){var e=/^\n* /;return e.test(t)}var HK=1,qK=2,jK=3,GK=4,FD=5;function R6e(t,e,r,o,a){var n,u,A,p=!1,h=!1,E=o!==-1,I=-1,v=F6e(t.charCodeAt(0))&&!cT(t.charCodeAt(t.length-1));if(e)for(n=0;n<t.length;n++){if(u=t.charCodeAt(n),!nm(u))return FD;A=n>0?t.charCodeAt(n-1):null,v=v&&PK(u,A)}else{for(n=0;n<t.length;n++){if(u=t.charCodeAt(n),u===Nw)p=!0,E&&(h=h||n-I-1>o&&t[I+1]!==" ",I=n);else if(!nm(u))return FD;A=n>0?t.charCodeAt(n-1):null,v=v&&PK(u,A)}h=h||E&&n-I-1>o&&t[I+1]!==" "}return!p&&!h?v&&!a(t)?HK:qK:r>9&&_K(t)?FD:h?GK:jK}function T6e(t,e,r,o){t.dump=function(){if(e.length===0)return"''";if(!t.noCompatMode&&S6e.indexOf(e)!==-1)return"'"+e+"'";var a=t.indent*Math.max(1,r),n=t.lineWidth===-1?-1:Math.max(Math.min(t.lineWidth,40),t.lineWidth-a),u=o||t.flowLevel>-1&&r>=t.flowLevel;function A(p){return k6e(t,p)}switch(R6e(e,u,t.indent,n,A)){case HK:return e;case qK:return"'"+e.replace(/'/g,"''")+"'";case jK:return"|"+SK(e,t.indent)+bK(DK(e,a));case GK:return">"+SK(e,t.indent)+bK(DK(N6e(e,n),a));case FD:return'"'+L6e(e,n)+'"';default:throw new Mw("impossible error: invalid scalar style")}}()}function SK(t,e){var r=_K(t)?String(e):"",o=t[t.length-1]===` +`,a=o&&(t[t.length-2]===` +`||t===` +`),n=a?"+":o?"":"-";return r+n+` +`}function bK(t){return t[t.length-1]===` +`?t.slice(0,-1):t}function N6e(t,e){for(var r=/(\n+)([^\n]*)/g,o=function(){var h=t.indexOf(` +`);return h=h!==-1?h:t.length,r.lastIndex=h,xK(t.slice(0,h),e)}(),a=t[0]===` +`||t[0]===" ",n,u;u=r.exec(t);){var A=u[1],p=u[2];n=p[0]===" ",o+=A+(!a&&!n&&p!==""?` +`:"")+xK(p,e),a=n}return o}function xK(t,e){if(t===""||t[0]===" ")return t;for(var r=/ [^ ]/g,o,a=0,n,u=0,A=0,p="";o=r.exec(t);)A=o.index,A-a>e&&(n=u>a?u:A,p+=` +`+t.slice(a,n),a=n+1),u=A;return p+=` +`,t.length-a>e&&u>a?p+=t.slice(a,u)+` +`+t.slice(u+1):p+=t.slice(a),p.slice(1)}function L6e(t){for(var e="",r,o,a,n=0;n<t.length;n++){if(r=t.charCodeAt(n),r>=55296&&r<=56319&&(o=t.charCodeAt(n+1),o>=56320&&o<=57343)){e+=vK((r-55296)*1024+o-56320+65536),n++;continue}a=vo[r],e+=!a&&nm(r)?t[n]:a||vK(r)}return e}function M6e(t,e,r){var o="",a=t.tag,n,u;for(n=0,u=r.length;n<u;n+=1)z0(t,e,r[n],!1,!1)&&(n!==0&&(o+=","+(t.condenseFlow?"":" ")),o+=t.dump);t.tag=a,t.dump="["+o+"]"}function O6e(t,e,r,o){var a="",n=t.tag,u,A;for(u=0,A=r.length;u<A;u+=1)z0(t,e+1,r[u],!0,!0)&&((!o||u!==0)&&(a+=aT(t,e)),t.dump&&Nw===t.dump.charCodeAt(0)?a+="-":a+="- ",a+=t.dump);t.tag=n,t.dump=a||"[]"}function U6e(t,e,r){var o="",a=t.tag,n=Object.keys(r),u,A,p,h,E;for(u=0,A=n.length;u<A;u+=1)E="",u!==0&&(E+=", "),t.condenseFlow&&(E+='"'),p=n[u],h=r[p],z0(t,e,p,!1,!1)&&(t.dump.length>1024&&(E+="? "),E+=t.dump+(t.condenseFlow?'"':"")+":"+(t.condenseFlow?"":" "),z0(t,e,h,!1,!1)&&(E+=t.dump,o+=E));t.tag=a,t.dump="{"+o+"}"}function _6e(t,e,r,o){var a="",n=t.tag,u=Object.keys(r),A,p,h,E,I,v;if(t.sortKeys===!0)u.sort();else if(typeof t.sortKeys=="function")u.sort(t.sortKeys);else if(t.sortKeys)throw new Mw("sortKeys must be a boolean or a function");for(A=0,p=u.length;A<p;A+=1)v="",(!o||A!==0)&&(v+=aT(t,e)),h=u[A],E=r[h],z0(t,e+1,h,!0,!0,!0)&&(I=t.tag!==null&&t.tag!=="?"||t.dump&&t.dump.length>1024,I&&(t.dump&&Nw===t.dump.charCodeAt(0)?v+="?":v+="? "),v+=t.dump,I&&(v+=aT(t,e)),z0(t,e+1,E,!0,I)&&(t.dump&&Nw===t.dump.charCodeAt(0)?v+=":":v+=": ",v+=t.dump,a+=v));t.tag=n,t.dump=a||"{}"}function kK(t,e,r){var o,a,n,u,A,p;for(a=r?t.explicitTypes:t.implicitTypes,n=0,u=a.length;n<u;n+=1)if(A=a[n],(A.instanceOf||A.predicate)&&(!A.instanceOf||typeof e=="object"&&e instanceof A.instanceOf)&&(!A.predicate||A.predicate(e))){if(t.tag=r?A.tag:"?",A.represent){if(p=t.styleMap[A.tag]||A.defaultStyle,QK.call(A.represent)==="[object Function]")o=A.represent(e,p);else if(FK.call(A.represent,p))o=A.represent[p](e,p);else throw new Mw("!<"+A.tag+'> tag resolver accepts not "'+p+'" style');t.dump=o}return!0}return!1}function z0(t,e,r,o,a,n){t.tag=null,t.dump=r,kK(t,r,!1)||kK(t,r,!0);var u=QK.call(t.dump);o&&(o=t.flowLevel<0||t.flowLevel>e);var A=u==="[object Object]"||u==="[object Array]",p,h;if(A&&(p=t.duplicates.indexOf(r),h=p!==-1),(t.tag!==null&&t.tag!=="?"||h||t.indent!==2&&e>0)&&(a=!1),h&&t.usedDuplicates[p])t.dump="*ref_"+p;else{if(A&&h&&!t.usedDuplicates[p]&&(t.usedDuplicates[p]=!0),u==="[object Object]")o&&Object.keys(t.dump).length!==0?(_6e(t,e,t.dump,a),h&&(t.dump="&ref_"+p+t.dump)):(U6e(t,e,t.dump),h&&(t.dump="&ref_"+p+" "+t.dump));else if(u==="[object Array]"){var E=t.noArrayIndent&&e>0?e-1:e;o&&t.dump.length!==0?(O6e(t,E,t.dump,a),h&&(t.dump="&ref_"+p+t.dump)):(M6e(t,E,t.dump),h&&(t.dump="&ref_"+p+" "+t.dump))}else if(u==="[object String]")t.tag!=="?"&&T6e(t,t.dump,e,n);else{if(t.skipInvalid)return!1;throw new Mw("unacceptable kind of an object to dump "+u)}t.tag!==null&&t.tag!=="?"&&(t.dump="!<"+t.tag+"> "+t.dump)}return!0}function H6e(t,e){var r=[],o=[],a,n;for(lT(t,r,o),a=0,n=o.length;a<n;a+=1)e.duplicates.push(r[o[a]]);e.usedDuplicates=new Array(n)}function lT(t,e,r){var o,a,n;if(t!==null&&typeof t=="object")if(a=e.indexOf(t),a!==-1)r.indexOf(a)===-1&&r.push(a);else if(e.push(t),Array.isArray(t))for(a=0,n=t.length;a<n;a+=1)lT(t[a],e,r);else for(o=Object.keys(t),a=0,n=o.length;a<n;a+=1)lT(t[o[a]],e,r)}function YK(t,e){e=e||{};var r=new x6e(e);return r.noRefs||H6e(t,r),z0(r,0,t,!0,!0)?r.dump+` +`:""}function q6e(t,e){return YK(t,Lw.extend({schema:u6e},e))}uT.exports.dump=YK;uT.exports.safeDump=q6e});var VK=_((yxt,xi)=>{"use strict";var RD=BK(),KK=WK();function TD(t){return function(){throw new Error("Function "+t+" is deprecated and cannot be used.")}}xi.exports.Type=ls();xi.exports.Schema=Y0();xi.exports.FAILSAFE_SCHEMA=PD();xi.exports.JSON_SCHEMA=tT();xi.exports.CORE_SCHEMA=rT();xi.exports.DEFAULT_SAFE_SCHEMA=$d();xi.exports.DEFAULT_FULL_SCHEMA=Rw();xi.exports.load=RD.load;xi.exports.loadAll=RD.loadAll;xi.exports.safeLoad=RD.safeLoad;xi.exports.safeLoadAll=RD.safeLoadAll;xi.exports.dump=KK.dump;xi.exports.safeDump=KK.safeDump;xi.exports.YAMLException=Xd();xi.exports.MINIMAL_SCHEMA=PD();xi.exports.SAFE_SCHEMA=$d();xi.exports.DEFAULT_SCHEMA=Rw();xi.exports.scan=TD("scan");xi.exports.parse=TD("parse");xi.exports.compose=TD("compose");xi.exports.addConstructor=TD("addConstructor")});var JK=_((Ext,zK)=>{"use strict";var j6e=VK();zK.exports=j6e});var ZK=_((Cxt,XK)=>{"use strict";function G6e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function J0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,J0)}G6e(J0,Error);J0.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I<h.parts.length;I++)E+=h.parts[I]instanceof Array?n(h.parts[I][0])+"-"+n(h.parts[I][1]):n(h.parts[I]);return"["+(h.inverted?"^":"")+E+"]"},any:function(h){return"any character"},end:function(h){return"end of input"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),I,v;for(I=0;I<h.length;I++)E[I]=u(h[I]);if(E.sort(),E.length>0){for(I=1,v=1;I<E.length;I++)E[I-1]!==E[I]&&(E[v]=E[I],v++);E.length=v}switch(E.length){case 1:return E[0];case 2:return E[0]+" or "+E[1];default:return E.slice(0,-1).join(", ")+", or "+E[E.length-1]}}function p(h){return h?'"'+a(h)+'"':"end of input"}return"Expected "+A(t)+" but "+p(e)+" found."};function Y6e(t,e){e=e!==void 0?e:{};var r={},o={Start:gu},a=gu,n=function(ee){return[].concat(...ee)},u="-",A=Qn("-",!1),p=function(ee){return ee},h=function(ee){return Object.assign({},...ee)},E="#",I=Qn("#",!1),v=gc(),x=function(){return{}},C=":",R=Qn(":",!1),L=function(ee,ye){return{[ee]:ye}},U=",",z=Qn(",",!1),te=function(ee,ye){return ye},ae=function(ee,ye,Le){return Object.assign({},...[ee].concat(ye).map(ft=>({[ft]:Le})))},le=function(ee){return ee},ce=function(ee){return ee},Ce=aa("correct indentation"),de=" ",Be=Qn(" ",!1),Ee=function(ee){return ee.length===or*Bt},g=function(ee){return ee.length===(or+1)*Bt},me=function(){return or++,!0},we=function(){return or--,!0},Ae=function(){return DA()},ne=aa("pseudostring"),Z=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,xe=hi(["\r",` +`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),Ne=/^[^\r\n\t ,\][{}:#"']/,ht=hi(["\r",` +`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),H=function(){return DA().replace(/^ *| *$/g,"")},rt="--",Te=Qn("--",!1),Fe=/^[a-zA-Z\/0-9]/,ke=hi([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),Ye=/^[^\r\n\t :,]/,Se=hi(["\r",` +`," "," ",":",","],!0,!1),et="null",Ue=Qn("null",!1),b=function(){return null},w="true",S=Qn("true",!1),y=function(){return!0},F="false",J=Qn("false",!1),X=function(){return!1},$=aa("string"),ie='"',be=Qn('"',!1),Re=function(){return""},at=function(ee){return ee},dt=function(ee){return ee.join("")},jt=/^[^"\\\0-\x1F\x7F]/,tr=hi(['"',"\\",["\0",""],"\x7F"],!0,!1),St='\\"',ln=Qn('\\"',!1),kr=function(){return'"'},mr="\\\\",br=Qn("\\\\",!1),Kr=function(){return"\\"},Kn="\\/",Ms=Qn("\\/",!1),Ri=function(){return"/"},gs="\\b",io=Qn("\\b",!1),Pi=function(){return"\b"},Os="\\f",so=Qn("\\f",!1),uc=function(){return"\f"},Au="\\n",sp=Qn("\\n",!1),op=function(){return` +`},Us="\\r",Dn=Qn("\\r",!1),oo=function(){return"\r"},_s="\\t",ml=Qn("\\t",!1),yl=function(){return" "},ao="\\u",Vn=Qn("\\u",!1),Mn=function(ee,ye,Le,ft){return String.fromCharCode(parseInt(`0x${ee}${ye}${Le}${ft}`))},Ti=/^[0-9a-fA-F]/,On=hi([["0","9"],["a","f"],["A","F"]],!1,!1),_i=aa("blank space"),ir=/^[ \t]/,Me=hi([" "," "],!1,!1),ii=aa("white space"),Ha=/^[ \t\n\r]/,hr=hi([" "," ",` +`,"\r"],!1,!1),Ac=`\r +`,fu=Qn(`\r +`,!1),fc=` +`,El=Qn(` +`,!1),vA="\r",pu=Qn("\r",!1),Ie=0,Tt=0,pc=[{line:1,column:1}],Hi=0,hu=[],Yt=0,Cl;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function DA(){return t.substring(Tt,Ie)}function ap(){return _o(Tt,Ie)}function hc(ee,ye){throw ye=ye!==void 0?ye:_o(Tt,Ie),dc([aa(ee)],t.substring(Tt,Ie),ye)}function PA(ee,ye){throw ye=ye!==void 0?ye:_o(Tt,Ie),lo(ee,ye)}function Qn(ee,ye){return{type:"literal",text:ee,ignoreCase:ye}}function hi(ee,ye,Le){return{type:"class",parts:ee,inverted:ye,ignoreCase:Le}}function gc(){return{type:"any"}}function SA(){return{type:"end"}}function aa(ee){return{type:"other",description:ee}}function Ni(ee){var ye=pc[ee],Le;if(ye)return ye;for(Le=ee-1;!pc[Le];)Le--;for(ye=pc[Le],ye={line:ye.line,column:ye.column};Le<ee;)t.charCodeAt(Le)===10?(ye.line++,ye.column=1):ye.column++,Le++;return pc[ee]=ye,ye}function _o(ee,ye){var Le=Ni(ee),ft=Ni(ye);return{start:{offset:ee,line:Le.line,column:Le.column},end:{offset:ye,line:ft.line,column:ft.column}}}function Xe(ee){Ie<Hi||(Ie>Hi&&(Hi=Ie,hu=[]),hu.push(ee))}function lo(ee,ye){return new J0(ee,null,null,ye)}function dc(ee,ye,Le){return new J0(J0.buildMessage(ee,ye),ee,ye,Le)}function gu(){var ee;return ee=bA(),ee}function qi(){var ee,ye,Le;for(ee=Ie,ye=[],Le=du();Le!==r;)ye.push(Le),Le=du();return ye!==r&&(Tt=ee,ye=n(ye)),ee=ye,ee}function du(){var ee,ye,Le,ft,pt;return ee=Ie,ye=ds(),ye!==r?(t.charCodeAt(Ie)===45?(Le=u,Ie++):(Le=r,Yt===0&&Xe(A)),Le!==r?(ft=Pn(),ft!==r?(pt=mc(),pt!==r?(Tt=ee,ye=p(pt),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee}function bA(){var ee,ye,Le;for(ee=Ie,ye=[],Le=qa();Le!==r;)ye.push(Le),Le=qa();return ye!==r&&(Tt=ee,ye=h(ye)),ee=ye,ee}function qa(){var ee,ye,Le,ft,pt,Nt,rr,$r,ji;if(ee=Ie,ye=Pn(),ye===r&&(ye=null),ye!==r){if(Le=Ie,t.charCodeAt(Ie)===35?(ft=E,Ie++):(ft=r,Yt===0&&Xe(I)),ft!==r){if(pt=[],Nt=Ie,rr=Ie,Yt++,$r=tt(),Yt--,$r===r?rr=void 0:(Ie=rr,rr=r),rr!==r?(t.length>Ie?($r=t.charAt(Ie),Ie++):($r=r,Yt===0&&Xe(v)),$r!==r?(rr=[rr,$r],Nt=rr):(Ie=Nt,Nt=r)):(Ie=Nt,Nt=r),Nt!==r)for(;Nt!==r;)pt.push(Nt),Nt=Ie,rr=Ie,Yt++,$r=tt(),Yt--,$r===r?rr=void 0:(Ie=rr,rr=r),rr!==r?(t.length>Ie?($r=t.charAt(Ie),Ie++):($r=r,Yt===0&&Xe(v)),$r!==r?(rr=[rr,$r],Nt=rr):(Ie=Nt,Nt=r)):(Ie=Nt,Nt=r);else pt=r;pt!==r?(ft=[ft,pt],Le=ft):(Ie=Le,Le=r)}else Ie=Le,Le=r;if(Le===r&&(Le=null),Le!==r){if(ft=[],pt=We(),pt!==r)for(;pt!==r;)ft.push(pt),pt=We();else ft=r;ft!==r?(Tt=ee,ye=x(),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r}else Ie=ee,ee=r;if(ee===r&&(ee=Ie,ye=ds(),ye!==r?(Le=la(),Le!==r?(ft=Pn(),ft===r&&(ft=null),ft!==r?(t.charCodeAt(Ie)===58?(pt=C,Ie++):(pt=r,Yt===0&&Xe(R)),pt!==r?(Nt=Pn(),Nt===r&&(Nt=null),Nt!==r?(rr=mc(),rr!==r?(Tt=ee,ye=L(Le,rr),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r&&(ee=Ie,ye=ds(),ye!==r?(Le=co(),Le!==r?(ft=Pn(),ft===r&&(ft=null),ft!==r?(t.charCodeAt(Ie)===58?(pt=C,Ie++):(pt=r,Yt===0&&Xe(R)),pt!==r?(Nt=Pn(),Nt===r&&(Nt=null),Nt!==r?(rr=mc(),rr!==r?(Tt=ee,ye=L(Le,rr),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r))){if(ee=Ie,ye=ds(),ye!==r)if(Le=co(),Le!==r)if(ft=Pn(),ft!==r)if(pt=ca(),pt!==r){if(Nt=[],rr=We(),rr!==r)for(;rr!==r;)Nt.push(rr),rr=We();else Nt=r;Nt!==r?(Tt=ee,ye=L(Le,pt),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;else Ie=ee,ee=r;else Ie=ee,ee=r;else Ie=ee,ee=r;if(ee===r)if(ee=Ie,ye=ds(),ye!==r)if(Le=co(),Le!==r){if(ft=[],pt=Ie,Nt=Pn(),Nt===r&&(Nt=null),Nt!==r?(t.charCodeAt(Ie)===44?(rr=U,Ie++):(rr=r,Yt===0&&Xe(z)),rr!==r?($r=Pn(),$r===r&&($r=null),$r!==r?(ji=co(),ji!==r?(Tt=pt,Nt=te(Le,ji),pt=Nt):(Ie=pt,pt=r)):(Ie=pt,pt=r)):(Ie=pt,pt=r)):(Ie=pt,pt=r),pt!==r)for(;pt!==r;)ft.push(pt),pt=Ie,Nt=Pn(),Nt===r&&(Nt=null),Nt!==r?(t.charCodeAt(Ie)===44?(rr=U,Ie++):(rr=r,Yt===0&&Xe(z)),rr!==r?($r=Pn(),$r===r&&($r=null),$r!==r?(ji=co(),ji!==r?(Tt=pt,Nt=te(Le,ji),pt=Nt):(Ie=pt,pt=r)):(Ie=pt,pt=r)):(Ie=pt,pt=r)):(Ie=pt,pt=r);else ft=r;ft!==r?(pt=Pn(),pt===r&&(pt=null),pt!==r?(t.charCodeAt(Ie)===58?(Nt=C,Ie++):(Nt=r,Yt===0&&Xe(R)),Nt!==r?(rr=Pn(),rr===r&&(rr=null),rr!==r?($r=mc(),$r!==r?(Tt=ee,ye=ae(Le,ft,$r),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)}else Ie=ee,ee=r;else Ie=ee,ee=r}return ee}function mc(){var ee,ye,Le,ft,pt,Nt,rr;if(ee=Ie,ye=Ie,Yt++,Le=Ie,ft=tt(),ft!==r?(pt=Ht(),pt!==r?(t.charCodeAt(Ie)===45?(Nt=u,Ie++):(Nt=r,Yt===0&&Xe(A)),Nt!==r?(rr=Pn(),rr!==r?(ft=[ft,pt,Nt,rr],Le=ft):(Ie=Le,Le=r)):(Ie=Le,Le=r)):(Ie=Le,Le=r)):(Ie=Le,Le=r),Yt--,Le!==r?(Ie=ye,ye=void 0):ye=r,ye!==r?(Le=We(),Le!==r?(ft=Fn(),ft!==r?(pt=qi(),pt!==r?(Nt=Ei(),Nt!==r?(Tt=ee,ye=le(pt),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r&&(ee=Ie,ye=tt(),ye!==r?(Le=Fn(),Le!==r?(ft=bA(),ft!==r?(pt=Ei(),pt!==r?(Tt=ee,ye=le(ft),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r))if(ee=Ie,ye=Hs(),ye!==r){if(Le=[],ft=We(),ft!==r)for(;ft!==r;)Le.push(ft),ft=We();else Le=r;Le!==r?(Tt=ee,ye=ce(ye),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;return ee}function ds(){var ee,ye,Le;for(Yt++,ee=Ie,ye=[],t.charCodeAt(Ie)===32?(Le=de,Ie++):(Le=r,Yt===0&&Xe(Be));Le!==r;)ye.push(Le),t.charCodeAt(Ie)===32?(Le=de,Ie++):(Le=r,Yt===0&&Xe(Be));return ye!==r?(Tt=Ie,Le=Ee(ye),Le?Le=void 0:Le=r,Le!==r?(ye=[ye,Le],ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r),Yt--,ee===r&&(ye=r,Yt===0&&Xe(Ce)),ee}function Ht(){var ee,ye,Le;for(ee=Ie,ye=[],t.charCodeAt(Ie)===32?(Le=de,Ie++):(Le=r,Yt===0&&Xe(Be));Le!==r;)ye.push(Le),t.charCodeAt(Ie)===32?(Le=de,Ie++):(Le=r,Yt===0&&Xe(Be));return ye!==r?(Tt=Ie,Le=g(ye),Le?Le=void 0:Le=r,Le!==r?(ye=[ye,Le],ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee}function Fn(){var ee;return Tt=Ie,ee=me(),ee?ee=void 0:ee=r,ee}function Ei(){var ee;return Tt=Ie,ee=we(),ee?ee=void 0:ee=r,ee}function la(){var ee;return ee=ys(),ee===r&&(ee=ua()),ee}function co(){var ee,ye,Le;if(ee=ys(),ee===r){if(ee=Ie,ye=[],Le=Ho(),Le!==r)for(;Le!==r;)ye.push(Le),Le=Ho();else ye=r;ye!==r&&(Tt=ee,ye=Ae()),ee=ye}return ee}function Hs(){var ee;return ee=Ci(),ee===r&&(ee=ms(),ee===r&&(ee=ys(),ee===r&&(ee=ua()))),ee}function ca(){var ee;return ee=Ci(),ee===r&&(ee=ys(),ee===r&&(ee=Ho())),ee}function ua(){var ee,ye,Le,ft,pt,Nt;if(Yt++,ee=Ie,Z.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Yt===0&&Xe(xe)),ye!==r){for(Le=[],ft=Ie,pt=Pn(),pt===r&&(pt=null),pt!==r?(Ne.test(t.charAt(Ie))?(Nt=t.charAt(Ie),Ie++):(Nt=r,Yt===0&&Xe(ht)),Nt!==r?(pt=[pt,Nt],ft=pt):(Ie=ft,ft=r)):(Ie=ft,ft=r);ft!==r;)Le.push(ft),ft=Ie,pt=Pn(),pt===r&&(pt=null),pt!==r?(Ne.test(t.charAt(Ie))?(Nt=t.charAt(Ie),Ie++):(Nt=r,Yt===0&&Xe(ht)),Nt!==r?(pt=[pt,Nt],ft=pt):(Ie=ft,ft=r)):(Ie=ft,ft=r);Le!==r?(Tt=ee,ye=H(),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;return Yt--,ee===r&&(ye=r,Yt===0&&Xe(ne)),ee}function Ho(){var ee,ye,Le,ft,pt;if(ee=Ie,t.substr(Ie,2)===rt?(ye=rt,Ie+=2):(ye=r,Yt===0&&Xe(Te)),ye===r&&(ye=null),ye!==r)if(Fe.test(t.charAt(Ie))?(Le=t.charAt(Ie),Ie++):(Le=r,Yt===0&&Xe(ke)),Le!==r){for(ft=[],Ye.test(t.charAt(Ie))?(pt=t.charAt(Ie),Ie++):(pt=r,Yt===0&&Xe(Se));pt!==r;)ft.push(pt),Ye.test(t.charAt(Ie))?(pt=t.charAt(Ie),Ie++):(pt=r,Yt===0&&Xe(Se));ft!==r?(Tt=ee,ye=H(),ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;else Ie=ee,ee=r;return ee}function Ci(){var ee,ye;return ee=Ie,t.substr(Ie,4)===et?(ye=et,Ie+=4):(ye=r,Yt===0&&Xe(Ue)),ye!==r&&(Tt=ee,ye=b()),ee=ye,ee}function ms(){var ee,ye;return ee=Ie,t.substr(Ie,4)===w?(ye=w,Ie+=4):(ye=r,Yt===0&&Xe(S)),ye!==r&&(Tt=ee,ye=y()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,5)===F?(ye=F,Ie+=5):(ye=r,Yt===0&&Xe(J)),ye!==r&&(Tt=ee,ye=X()),ee=ye),ee}function ys(){var ee,ye,Le,ft;return Yt++,ee=Ie,t.charCodeAt(Ie)===34?(ye=ie,Ie++):(ye=r,Yt===0&&Xe(be)),ye!==r?(t.charCodeAt(Ie)===34?(Le=ie,Ie++):(Le=r,Yt===0&&Xe(be)),Le!==r?(Tt=ee,ye=Re(),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r),ee===r&&(ee=Ie,t.charCodeAt(Ie)===34?(ye=ie,Ie++):(ye=r,Yt===0&&Xe(be)),ye!==r?(Le=Es(),Le!==r?(t.charCodeAt(Ie)===34?(ft=ie,Ie++):(ft=r,Yt===0&&Xe(be)),ft!==r?(Tt=ee,ye=at(Le),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)),Yt--,ee===r&&(ye=r,Yt===0&&Xe($)),ee}function Es(){var ee,ye,Le;if(ee=Ie,ye=[],Le=qs(),Le!==r)for(;Le!==r;)ye.push(Le),Le=qs();else ye=r;return ye!==r&&(Tt=ee,ye=dt(ye)),ee=ye,ee}function qs(){var ee,ye,Le,ft,pt,Nt;return jt.test(t.charAt(Ie))?(ee=t.charAt(Ie),Ie++):(ee=r,Yt===0&&Xe(tr)),ee===r&&(ee=Ie,t.substr(Ie,2)===St?(ye=St,Ie+=2):(ye=r,Yt===0&&Xe(ln)),ye!==r&&(Tt=ee,ye=kr()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===mr?(ye=mr,Ie+=2):(ye=r,Yt===0&&Xe(br)),ye!==r&&(Tt=ee,ye=Kr()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Kn?(ye=Kn,Ie+=2):(ye=r,Yt===0&&Xe(Ms)),ye!==r&&(Tt=ee,ye=Ri()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===gs?(ye=gs,Ie+=2):(ye=r,Yt===0&&Xe(io)),ye!==r&&(Tt=ee,ye=Pi()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Os?(ye=Os,Ie+=2):(ye=r,Yt===0&&Xe(so)),ye!==r&&(Tt=ee,ye=uc()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Au?(ye=Au,Ie+=2):(ye=r,Yt===0&&Xe(sp)),ye!==r&&(Tt=ee,ye=op()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===Us?(ye=Us,Ie+=2):(ye=r,Yt===0&&Xe(Dn)),ye!==r&&(Tt=ee,ye=oo()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===_s?(ye=_s,Ie+=2):(ye=r,Yt===0&&Xe(ml)),ye!==r&&(Tt=ee,ye=yl()),ee=ye,ee===r&&(ee=Ie,t.substr(Ie,2)===ao?(ye=ao,Ie+=2):(ye=r,Yt===0&&Xe(Vn)),ye!==r?(Le=Un(),Le!==r?(ft=Un(),ft!==r?(pt=Un(),pt!==r?(Nt=Un(),Nt!==r?(Tt=ee,ye=Mn(Le,ft,pt,Nt),ee=ye):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)):(Ie=ee,ee=r)))))))))),ee}function Un(){var ee;return Ti.test(t.charAt(Ie))?(ee=t.charAt(Ie),Ie++):(ee=r,Yt===0&&Xe(On)),ee}function Pn(){var ee,ye;if(Yt++,ee=[],ir.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Yt===0&&Xe(Me)),ye!==r)for(;ye!==r;)ee.push(ye),ir.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Yt===0&&Xe(Me));else ee=r;return Yt--,ee===r&&(ye=r,Yt===0&&Xe(_i)),ee}function Cs(){var ee,ye;if(Yt++,ee=[],Ha.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Yt===0&&Xe(hr)),ye!==r)for(;ye!==r;)ee.push(ye),Ha.test(t.charAt(Ie))?(ye=t.charAt(Ie),Ie++):(ye=r,Yt===0&&Xe(hr));else ee=r;return Yt--,ee===r&&(ye=r,Yt===0&&Xe(ii)),ee}function We(){var ee,ye,Le,ft,pt,Nt;if(ee=Ie,ye=tt(),ye!==r){for(Le=[],ft=Ie,pt=Pn(),pt===r&&(pt=null),pt!==r?(Nt=tt(),Nt!==r?(pt=[pt,Nt],ft=pt):(Ie=ft,ft=r)):(Ie=ft,ft=r);ft!==r;)Le.push(ft),ft=Ie,pt=Pn(),pt===r&&(pt=null),pt!==r?(Nt=tt(),Nt!==r?(pt=[pt,Nt],ft=pt):(Ie=ft,ft=r)):(Ie=ft,ft=r);Le!==r?(ye=[ye,Le],ee=ye):(Ie=ee,ee=r)}else Ie=ee,ee=r;return ee}function tt(){var ee;return t.substr(Ie,2)===Ac?(ee=Ac,Ie+=2):(ee=r,Yt===0&&Xe(fu)),ee===r&&(t.charCodeAt(Ie)===10?(ee=fc,Ie++):(ee=r,Yt===0&&Xe(El)),ee===r&&(t.charCodeAt(Ie)===13?(ee=vA,Ie++):(ee=r,Yt===0&&Xe(pu)))),ee}let Bt=2,or=0;if(Cl=a(),Cl!==r&&Ie===t.length)return Cl;throw Cl!==r&&Ie<t.length&&Xe(SA()),dc(hu,Hi<t.length?t.charAt(Hi):null,Hi<t.length?_o(Hi,Hi+1):_o(Hi,Hi))}XK.exports={SyntaxError:J0,parse:Y6e}});function eV(t){return t.match(W6e)?t:JSON.stringify(t)}function rV(t){return typeof t>"u"?!0:typeof t=="object"&&t!==null&&!Array.isArray(t)?Object.keys(t).every(e=>rV(t[e])):!1}function AT(t,e,r){if(t===null)return`null +`;if(typeof t=="number"||typeof t=="boolean")return`${t.toString()} +`;if(typeof t=="string")return`${eV(t)} +`;if(Array.isArray(t)){if(t.length===0)return`[] +`;let o=" ".repeat(e);return` +${t.map(n=>`${o}- ${AT(n,e+1,!1)}`).join("")}`}if(typeof t=="object"&&t){let[o,a]=t instanceof ND?[t.data,!1]:[t,!0],n=" ".repeat(e),u=Object.keys(o);a&&u.sort((p,h)=>{let E=$K.indexOf(p),I=$K.indexOf(h);return E===-1&&I===-1?p<h?-1:p>h?1:0:E!==-1&&I===-1?-1:E===-1&&I!==-1?1:E-I});let A=u.filter(p=>!rV(o[p])).map((p,h)=>{let E=o[p],I=eV(p),v=AT(E,e+1,!0),x=h>0||r?n:"",C=I.length>1024?`? ${I} +${x}:`:`${I}:`,R=v.startsWith(` +`)?v:` ${v}`;return`${x}${C}${R}`}).join(e===0?` +`:"")||` +`;return r?` +${A}`:`${A}`}throw new Error(`Unsupported value type (${t})`)}function Da(t){try{let e=AT(t,0,!1);return e!==` +`?e:""}catch(e){throw e.location&&(e.message=e.message.replace(/(\.)?$/,` (line ${e.location.start.line}, column ${e.location.start.column})$1`)),e}}function K6e(t){return t.endsWith(` +`)||(t+=` +`),(0,tV.parse)(t)}function z6e(t){if(V6e.test(t))return K6e(t);let e=(0,LD.safeLoad)(t,{schema:LD.FAILSAFE_SCHEMA,json:!0});if(e==null)return{};if(typeof e!="object")throw new Error(`Expected an indexed object, got a ${typeof e} instead. Does your file follow Yaml's rules?`);if(Array.isArray(e))throw new Error("Expected an indexed object, got an array instead. Does your file follow Yaml's rules?");return e}function Ki(t){return z6e(t)}var LD,tV,W6e,$K,ND,V6e,nV=Et(()=>{LD=Ze(JK()),tV=Ze(ZK()),W6e=/^(?![-?:,\][{}#&*!|>'"%@` \t\r\n]).([ \t]*(?![,\][{}:# \t\r\n]).)*$/,$K=["__metadata","version","resolution","dependencies","peerDependencies","dependenciesMeta","peerDependenciesMeta","binaries"],ND=class{constructor(e){this.data=e}};Da.PreserveOrdering=ND;V6e=/^(#.*(\r?\n))*?#\s+yarn\s+lockfile\s+v1\r?\n/i});var Ow={};Vt(Ow,{parseResolution:()=>BD,parseShell:()=>CD,parseSyml:()=>Ki,stringifyArgument:()=>XR,stringifyArgumentSegment:()=>ZR,stringifyArithmeticExpression:()=>ID,stringifyCommand:()=>JR,stringifyCommandChain:()=>Jd,stringifyCommandChainThen:()=>zR,stringifyCommandLine:()=>wD,stringifyCommandLineThen:()=>VR,stringifyEnvSegment:()=>ED,stringifyRedirectArgument:()=>Qw,stringifyResolution:()=>vD,stringifyShell:()=>zd,stringifyShellLine:()=>zd,stringifySyml:()=>Da,stringifyValueArgument:()=>H0});var Nl=Et(()=>{rW();oW();nV()});var sV=_((Dxt,fT)=>{"use strict";var J6e=t=>{let e=!1,r=!1,o=!1;for(let a=0;a<t.length;a++){let n=t[a];e&&/[a-zA-Z]/.test(n)&&n.toUpperCase()===n?(t=t.slice(0,a)+"-"+t.slice(a),e=!1,o=r,r=!0,a++):r&&o&&/[a-zA-Z]/.test(n)&&n.toLowerCase()===n?(t=t.slice(0,a-1)+"-"+t.slice(a-1),o=r,r=!1,e=!0):(e=n.toLowerCase()===n&&n.toUpperCase()!==n,o=r,r=n.toUpperCase()===n&&n.toLowerCase()!==n)}return t},iV=(t,e)=>{if(!(typeof t=="string"||Array.isArray(t)))throw new TypeError("Expected the input to be `string | string[]`");e=Object.assign({pascalCase:!1},e);let r=a=>e.pascalCase?a.charAt(0).toUpperCase()+a.slice(1):a;return Array.isArray(t)?t=t.map(a=>a.trim()).filter(a=>a.length).join("-"):t=t.trim(),t.length===0?"":t.length===1?e.pascalCase?t.toUpperCase():t.toLowerCase():(t!==t.toLowerCase()&&(t=J6e(t)),t=t.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(a,n)=>n.toUpperCase()).replace(/\d+(\w|$)/g,a=>a.toUpperCase()),r(t))};fT.exports=iV;fT.exports.default=iV});var oV=_((Pxt,X6e)=>{X6e.exports=[{name:"Agola CI",constant:"AGOLA",env:"AGOLA_GIT_REF",pr:"AGOLA_PULL_REQUEST_ID"},{name:"Appcircle",constant:"APPCIRCLE",env:"AC_APPCIRCLE"},{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"TF_BUILD",pr:{BUILD_REASON:"PullRequest"}},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"Codefresh",constant:"CODEFRESH",env:"CF_BUILD_ID",pr:{any:["CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_ID"]}},{name:"Codemagic",constant:"CODEMAGIC",env:"CM_BUILD_ID",pr:"CM_PULL_REQUEST"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"Earthly",constant:"EARTHLY",env:"EARTHLY_CI"},{name:"Expo Application Services",constant:"EAS",env:"EAS_BUILD"},{name:"Gerrit",constant:"GERRIT",env:"GERRIT_PROJECT"},{name:"Gitea Actions",constant:"GITEA_ACTIONS",env:"GITEA_ACTIONS"},{name:"GitHub Actions",constant:"GITHUB_ACTIONS",env:"GITHUB_ACTIONS",pr:{GITHUB_EVENT_NAME:"pull_request"}},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI",pr:"CI_MERGE_REQUEST_ID"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Google Cloud Build",constant:"GOOGLE_CLOUD_BUILD",env:"BUILDER_OUTPUT"},{name:"Harness CI",constant:"HARNESS",env:"HARNESS_BUILD_ID"},{name:"Heroku",constant:"HEROKU",env:{env:"NODE",includes:"/app/.heroku/node/bin/node"}},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"LayerCI",constant:"LAYERCI",env:"LAYERCI",pr:"LAYERCI_PULL_REQUEST"},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Nevercode",constant:"NEVERCODE",env:"NEVERCODE",pr:{env:"NEVERCODE_PULL_REQUEST",ne:"false"}},{name:"Prow",constant:"PROW",env:"PROW_JOB_ID"},{name:"ReleaseHub",constant:"RELEASEHUB",env:"RELEASE_BUILD_ID"},{name:"Render",constant:"RENDER",env:"RENDER",pr:{IS_PULL_REQUEST:"true"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Screwdriver",constant:"SCREWDRIVER",env:"SCREWDRIVER",pr:{env:"SD_PULL_REQUEST",ne:"false"}},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Sourcehut",constant:"SOURCEHUT",env:{CI_NAME:"sourcehut"}},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}},{name:"Vela",constant:"VELA",env:"VELA",pr:{VELA_PULL_REQUEST:"1"}},{name:"Vercel",constant:"VERCEL",env:{any:["NOW_BUILDER","VERCEL"]},pr:"VERCEL_GIT_PULL_REQUEST_ID"},{name:"Visual Studio App Center",constant:"APPCENTER",env:"APPCENTER_BUILD_ID"},{name:"Woodpecker",constant:"WOODPECKER",env:{CI:"woodpecker"},pr:{CI_BUILD_EVENT:"pull_request"}},{name:"Xcode Cloud",constant:"XCODE_CLOUD",env:"CI_XCODE_PROJECT",pr:"CI_PULL_REQUEST_NUMBER"},{name:"Xcode Server",constant:"XCODE_SERVER",env:"XCS"}]});var X0=_($a=>{"use strict";var lV=oV(),cs=process.env;Object.defineProperty($a,"_vendors",{value:lV.map(function(t){return t.constant})});$a.name=null;$a.isPR=null;lV.forEach(function(t){let r=(Array.isArray(t.env)?t.env:[t.env]).every(function(o){return aV(o)});if($a[t.constant]=r,!!r)switch($a.name=t.name,typeof t.pr){case"string":$a.isPR=!!cs[t.pr];break;case"object":"env"in t.pr?$a.isPR=t.pr.env in cs&&cs[t.pr.env]!==t.pr.ne:"any"in t.pr?$a.isPR=t.pr.any.some(function(o){return!!cs[o]}):$a.isPR=aV(t.pr);break;default:$a.isPR=null}});$a.isCI=!!(cs.CI!=="false"&&(cs.BUILD_ID||cs.BUILD_NUMBER||cs.CI||cs.CI_APP_ID||cs.CI_BUILD_ID||cs.CI_BUILD_NUMBER||cs.CI_NAME||cs.CONTINUOUS_INTEGRATION||cs.RUN_ID||$a.name));function aV(t){return typeof t=="string"?!!cs[t]:"env"in t?cs[t.env]&&cs[t.env].includes(t.includes):"any"in t?t.any.some(function(e){return!!cs[e]}):Object.keys(t).every(function(e){return cs[e]===t[e]})}});var Hn,un,Z0,pT,MD,cV,hT,gT,OD=Et(()=>{(function(t){t.StartOfInput="\0",t.EndOfInput="",t.EndOfPartialInput=""})(Hn||(Hn={}));(function(t){t[t.InitialNode=0]="InitialNode",t[t.SuccessNode=1]="SuccessNode",t[t.ErrorNode=2]="ErrorNode",t[t.CustomNode=3]="CustomNode"})(un||(un={}));Z0=-1,pT=/^(-h|--help)(?:=([0-9]+))?$/,MD=/^(--[a-z]+(?:-[a-z]+)*|-[a-zA-Z]+)$/,cV=/^-[a-zA-Z]{2,}$/,hT=/^([^=]+)=([\s\S]*)$/,gT=process.env.DEBUG_CLI==="1"});var st,im,UD,dT,_D=Et(()=>{OD();st=class extends Error{constructor(e){super(e),this.clipanion={type:"usage"},this.name="UsageError"}},im=class extends Error{constructor(e,r){if(super(),this.input=e,this.candidates=r,this.clipanion={type:"none"},this.name="UnknownSyntaxError",this.candidates.length===0)this.message="Command not found, but we're not sure what's the alternative.";else if(this.candidates.every(o=>o.reason!==null&&o.reason===r[0].reason)){let[{reason:o}]=this.candidates;this.message=`${o} + +${this.candidates.map(({usage:a})=>`$ ${a}`).join(` +`)}`}else if(this.candidates.length===1){let[{usage:o}]=this.candidates;this.message=`Command not found; did you mean: + +$ ${o} +${dT(e)}`}else this.message=`Command not found; did you mean one of: + +${this.candidates.map(({usage:o},a)=>`${`${a}.`.padStart(4)} ${o}`).join(` +`)} + +${dT(e)}`}},UD=class extends Error{constructor(e,r){super(),this.input=e,this.usages=r,this.clipanion={type:"none"},this.name="AmbiguousSyntaxError",this.message=`Cannot find which to pick amongst the following alternatives: + +${this.usages.map((o,a)=>`${`${a}.`.padStart(4)} ${o}`).join(` +`)} + +${dT(e)}`}},dT=t=>`While running ${t.filter(e=>e!==Hn.EndOfInput&&e!==Hn.EndOfPartialInput).map(e=>{let r=JSON.stringify(e);return e.match(/\s/)||e.length===0||r!==`"${e}"`?r:e}).join(" ")}`});function Z6e(t){let e=t.split(` +`),r=e.filter(a=>a.match(/\S/)),o=r.length>0?r.reduce((a,n)=>Math.min(a,n.length-n.trimStart().length),Number.MAX_VALUE):0;return e.map(a=>a.slice(o).trimRight()).join(` +`)}function Do(t,{format:e,paragraphs:r}){return t=t.replace(/\r\n?/g,` +`),t=Z6e(t),t=t.replace(/^\n+|\n+$/g,""),t=t.replace(/^(\s*)-([^\n]*?)\n+/gm,`$1-$2 + +`),t=t.replace(/\n(\n)?\n*/g,(o,a)=>a||" "),r&&(t=t.split(/\n/).map(o=>{let a=o.match(/^\s*[*-][\t ]+(.*)/);if(!a)return o.match(/(.{1,80})(?: |$)/g).join(` +`);let n=o.length-o.trimStart().length;return a[1].match(new RegExp(`(.{1,${78-n}})(?: |$)`,"g")).map((u,A)=>" ".repeat(n)+(A===0?"- ":" ")+u).join(` +`)}).join(` + +`)),t=t.replace(/(`+)((?:.|[\n])*?)\1/g,(o,a,n)=>e.code(a+n+a)),t=t.replace(/(\*\*)((?:.|[\n])*?)\1/g,(o,a,n)=>e.bold(a+n+a)),t?`${t} +`:""}var mT,uV,AV,yT=Et(()=>{mT=Array(80).fill("\u2501");for(let t=0;t<=24;++t)mT[mT.length-t]=`\x1B[38;5;${232+t}m\u2501`;uV={header:t=>`\x1B[1m\u2501\u2501\u2501 ${t}${t.length<75?` ${mT.slice(t.length+5).join("")}`:":"}\x1B[0m`,bold:t=>`\x1B[1m${t}\x1B[22m`,error:t=>`\x1B[31m\x1B[1m${t}\x1B[22m\x1B[39m`,code:t=>`\x1B[36m${t}\x1B[39m`},AV={header:t=>t,bold:t=>t,error:t=>t,code:t=>t}});function Ko(t){return{...t,[Uw]:!0}}function Gu(t,e){return typeof t>"u"?[t,e]:typeof t=="object"&&t!==null&&!Array.isArray(t)?[void 0,t]:[t,e]}function HD(t,{mergeName:e=!1}={}){let r=t.match(/^([^:]+): (.*)$/m);if(!r)return"validation failed";let[,o,a]=r;return e&&(a=a[0].toLowerCase()+a.slice(1)),a=o!=="."||!e?`${o.replace(/^\.(\[|$)/,"$1")}: ${a}`:`: ${a}`,a}function _w(t,e){return e.length===1?new st(`${t}${HD(e[0],{mergeName:!0})}`):new st(`${t}: +${e.map(r=>` +- ${HD(r)}`).join("")}`)}function $0(t,e,r){if(typeof r>"u")return e;let o=[],a=[],n=A=>{let p=e;return e=A,n.bind(null,p)};if(!r(e,{errors:o,coercions:a,coercion:n}))throw _w(`Invalid value for ${t}`,o);for(let[,A]of a)A();return e}var Uw,yf=Et(()=>{_D();Uw=Symbol("clipanion/isOption")});var Vo={};Vt(Vo,{KeyRelationship:()=>Yu,TypeAssertionError:()=>Gp,applyCascade:()=>jw,as:()=>mqe,assert:()=>hqe,assertWithErrors:()=>gqe,cascade:()=>YD,fn:()=>yqe,hasAtLeastOneKey:()=>DT,hasExactLength:()=>dV,hasForbiddenKeys:()=>Mqe,hasKeyRelationship:()=>Yw,hasMaxLength:()=>Cqe,hasMinLength:()=>Eqe,hasMutuallyExclusiveKeys:()=>Oqe,hasRequiredKeys:()=>Lqe,hasUniqueItems:()=>wqe,isArray:()=>qD,isAtLeast:()=>BT,isAtMost:()=>vqe,isBase64:()=>Fqe,isBoolean:()=>oqe,isDate:()=>lqe,isDict:()=>Aqe,isEnum:()=>Js,isHexColor:()=>Qqe,isISO8601:()=>kqe,isInExclusiveRange:()=>Pqe,isInInclusiveRange:()=>Dqe,isInstanceOf:()=>pqe,isInteger:()=>vT,isJSON:()=>Rqe,isLiteral:()=>pV,isLowerCase:()=>Sqe,isMap:()=>uqe,isNegative:()=>Iqe,isNullable:()=>Nqe,isNumber:()=>wT,isObject:()=>hV,isOneOf:()=>IT,isOptional:()=>Tqe,isPartial:()=>fqe,isPayload:()=>aqe,isPositive:()=>Bqe,isRecord:()=>GD,isSet:()=>cqe,isString:()=>om,isTuple:()=>jD,isUUID4:()=>xqe,isUnknown:()=>CT,isUpperCase:()=>bqe,makeTrait:()=>gV,makeValidator:()=>Hr,matchesRegExp:()=>qw,softAssert:()=>dqe});function qn(t){return t===null?"null":t===void 0?"undefined":t===""?"an empty string":typeof t=="symbol"?`<${t.toString()}>`:Array.isArray(t)?"an array":JSON.stringify(t)}function sm(t,e){if(t.length===0)return"nothing";if(t.length===1)return qn(t[0]);let r=t.slice(0,-1),o=t[t.length-1],a=t.length>2?`, ${e} `:` ${e} `;return`${r.map(n=>qn(n)).join(", ")}${a}${qn(o)}`}function jp(t,e){var r,o,a;return typeof e=="number"?`${(r=t?.p)!==null&&r!==void 0?r:"."}[${e}]`:$6e.test(e)?`${(o=t?.p)!==null&&o!==void 0?o:""}.${e}`:`${(a=t?.p)!==null&&a!==void 0?a:"."}[${JSON.stringify(e)}]`}function ET(t,e,r){return t===1?e:r}function pr({errors:t,p:e}={},r){return t?.push(`${e??"."}: ${r}`),!1}function iqe(t,e){return r=>{t[e]=r}}function Wu(t,e){return r=>{let o=t[e];return t[e]=r,Wu(t,e).bind(null,o)}}function Hw(t,e,r){let o=()=>(t(r()),a),a=()=>(t(e),o);return o}function CT(){return Hr({test:(t,e)=>!0})}function pV(t){return Hr({test:(e,r)=>e!==t?pr(r,`Expected ${qn(t)} (got ${qn(e)})`):!0})}function om(){return Hr({test:(t,e)=>typeof t!="string"?pr(e,`Expected a string (got ${qn(t)})`):!0})}function Js(t){let e=Array.isArray(t)?t:Object.values(t),r=e.every(a=>typeof a=="string"||typeof a=="number"),o=new Set(e);return o.size===1?pV([...o][0]):Hr({test:(a,n)=>o.has(a)?!0:r?pr(n,`Expected one of ${sm(e,"or")} (got ${qn(a)})`):pr(n,`Expected a valid enumeration value (got ${qn(a)})`)})}function oqe(){return Hr({test:(t,e)=>{var r;if(typeof t!="boolean"){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return pr(e,"Unbound coercion result");let o=sqe.get(t);if(typeof o<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,o)]),!0}return pr(e,`Expected a boolean (got ${qn(t)})`)}return!0}})}function wT(){return Hr({test:(t,e)=>{var r;if(typeof t!="number"){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return pr(e,"Unbound coercion result");let o;if(typeof t=="string"){let a;try{a=JSON.parse(t)}catch{}if(typeof a=="number")if(JSON.stringify(a)===t)o=a;else return pr(e,`Received a number that can't be safely represented by the runtime (${t})`)}if(typeof o<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,o)]),!0}return pr(e,`Expected a number (got ${qn(t)})`)}return!0}})}function aqe(t){return Hr({test:(e,r)=>{var o;if(typeof r?.coercions>"u")return pr(r,"The isPayload predicate can only be used with coercion enabled");if(typeof r.coercion>"u")return pr(r,"Unbound coercion result");if(typeof e!="string")return pr(r,`Expected a string (got ${qn(e)})`);let a;try{a=JSON.parse(e)}catch{return pr(r,`Expected a JSON string (got ${qn(e)})`)}let n={value:a};return t(a,Object.assign(Object.assign({},r),{coercion:Wu(n,"value")}))?(r.coercions.push([(o=r.p)!==null&&o!==void 0?o:".",r.coercion.bind(null,n.value)]),!0):!1}})}function lqe(){return Hr({test:(t,e)=>{var r;if(!(t instanceof Date)){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return pr(e,"Unbound coercion result");let o;if(typeof t=="string"&&fV.test(t))o=new Date(t);else{let a;if(typeof t=="string"){let n;try{n=JSON.parse(t)}catch{}typeof n=="number"&&(a=n)}else typeof t=="number"&&(a=t);if(typeof a<"u")if(Number.isSafeInteger(a)||!Number.isSafeInteger(a*1e3))o=new Date(a*1e3);else return pr(e,`Received a timestamp that can't be safely represented by the runtime (${t})`)}if(typeof o<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,o)]),!0}return pr(e,`Expected a date (got ${qn(t)})`)}return!0}})}function qD(t,{delimiter:e}={}){return Hr({test:(r,o)=>{var a;let n=r;if(typeof r=="string"&&typeof e<"u"&&typeof o?.coercions<"u"){if(typeof o?.coercion>"u")return pr(o,"Unbound coercion result");r=r.split(e)}if(!Array.isArray(r))return pr(o,`Expected an array (got ${qn(r)})`);let u=!0;for(let A=0,p=r.length;A<p&&(u=t(r[A],Object.assign(Object.assign({},o),{p:jp(o,A),coercion:Wu(r,A)}))&&u,!(!u&&o?.errors==null));++A);return r!==n&&o.coercions.push([(a=o.p)!==null&&a!==void 0?a:".",o.coercion.bind(null,r)]),u}})}function cqe(t,{delimiter:e}={}){let r=qD(t,{delimiter:e});return Hr({test:(o,a)=>{var n,u;if(Object.getPrototypeOf(o).toString()==="[object Set]")if(typeof a?.coercions<"u"){if(typeof a?.coercion>"u")return pr(a,"Unbound coercion result");let A=[...o],p=[...o];if(!r(p,Object.assign(Object.assign({},a),{coercion:void 0})))return!1;let h=()=>p.some((E,I)=>E!==A[I])?new Set(p):o;return a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",Hw(a.coercion,o,h)]),!0}else{let A=!0;for(let p of o)if(A=t(p,Object.assign({},a))&&A,!A&&a?.errors==null)break;return A}if(typeof a?.coercions<"u"){if(typeof a?.coercion>"u")return pr(a,"Unbound coercion result");let A={value:o};return r(o,Object.assign(Object.assign({},a),{coercion:Wu(A,"value")}))?(a.coercions.push([(u=a.p)!==null&&u!==void 0?u:".",Hw(a.coercion,o,()=>new Set(A.value))]),!0):!1}return pr(a,`Expected a set (got ${qn(o)})`)}})}function uqe(t,e){let r=qD(jD([t,e])),o=GD(e,{keys:t});return Hr({test:(a,n)=>{var u,A,p;if(Object.getPrototypeOf(a).toString()==="[object Map]")if(typeof n?.coercions<"u"){if(typeof n?.coercion>"u")return pr(n,"Unbound coercion result");let h=[...a],E=[...a];if(!r(E,Object.assign(Object.assign({},n),{coercion:void 0})))return!1;let I=()=>E.some((v,x)=>v[0]!==h[x][0]||v[1]!==h[x][1])?new Map(E):a;return n.coercions.push([(u=n.p)!==null&&u!==void 0?u:".",Hw(n.coercion,a,I)]),!0}else{let h=!0;for(let[E,I]of a)if(h=t(E,Object.assign({},n))&&h,!h&&n?.errors==null||(h=e(I,Object.assign(Object.assign({},n),{p:jp(n,E)}))&&h,!h&&n?.errors==null))break;return h}if(typeof n?.coercions<"u"){if(typeof n?.coercion>"u")return pr(n,"Unbound coercion result");let h={value:a};return Array.isArray(a)?r(a,Object.assign(Object.assign({},n),{coercion:void 0}))?(n.coercions.push([(A=n.p)!==null&&A!==void 0?A:".",Hw(n.coercion,a,()=>new Map(h.value))]),!0):!1:o(a,Object.assign(Object.assign({},n),{coercion:Wu(h,"value")}))?(n.coercions.push([(p=n.p)!==null&&p!==void 0?p:".",Hw(n.coercion,a,()=>new Map(Object.entries(h.value)))]),!0):!1}return pr(n,`Expected a map (got ${qn(a)})`)}})}function jD(t,{delimiter:e}={}){let r=dV(t.length);return Hr({test:(o,a)=>{var n;if(typeof o=="string"&&typeof e<"u"&&typeof a?.coercions<"u"){if(typeof a?.coercion>"u")return pr(a,"Unbound coercion result");o=o.split(e),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",a.coercion.bind(null,o)])}if(!Array.isArray(o))return pr(a,`Expected a tuple (got ${qn(o)})`);let u=r(o,Object.assign({},a));for(let A=0,p=o.length;A<p&&A<t.length&&(u=t[A](o[A],Object.assign(Object.assign({},a),{p:jp(a,A),coercion:Wu(o,A)}))&&u,!(!u&&a?.errors==null));++A);return u}})}function GD(t,{keys:e=null}={}){let r=qD(jD([e??om(),t]));return Hr({test:(o,a)=>{var n;if(Array.isArray(o)&&typeof a?.coercions<"u")return typeof a?.coercion>"u"?pr(a,"Unbound coercion result"):r(o,Object.assign(Object.assign({},a),{coercion:void 0}))?(o=Object.fromEntries(o),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",a.coercion.bind(null,o)]),!0):!1;if(typeof o!="object"||o===null)return pr(a,`Expected an object (got ${qn(o)})`);let u=Object.keys(o),A=!0;for(let p=0,h=u.length;p<h&&(A||a?.errors!=null);++p){let E=u[p],I=o[E];if(E==="__proto__"||E==="constructor"){A=pr(Object.assign(Object.assign({},a),{p:jp(a,E)}),"Unsafe property name");continue}if(e!==null&&!e(E,a)){A=!1;continue}if(!t(I,Object.assign(Object.assign({},a),{p:jp(a,E),coercion:Wu(o,E)}))){A=!1;continue}}return A}})}function Aqe(t,e={}){return GD(t,e)}function hV(t,{extra:e=null}={}){let r=Object.keys(t),o=Hr({test:(a,n)=>{if(typeof a!="object"||a===null)return pr(n,`Expected an object (got ${qn(a)})`);let u=new Set([...r,...Object.keys(a)]),A={},p=!0;for(let h of u){if(h==="constructor"||h==="__proto__")p=pr(Object.assign(Object.assign({},n),{p:jp(n,h)}),"Unsafe property name");else{let E=Object.prototype.hasOwnProperty.call(t,h)?t[h]:void 0,I=Object.prototype.hasOwnProperty.call(a,h)?a[h]:void 0;typeof E<"u"?p=E(I,Object.assign(Object.assign({},n),{p:jp(n,h),coercion:Wu(a,h)}))&&p:e===null?p=pr(Object.assign(Object.assign({},n),{p:jp(n,h)}),`Extraneous property (got ${qn(I)})`):Object.defineProperty(A,h,{enumerable:!0,get:()=>I,set:iqe(a,h)})}if(!p&&n?.errors==null)break}return e!==null&&(p||n?.errors!=null)&&(p=e(A,n)&&p),p}});return Object.assign(o,{properties:t})}function fqe(t){return hV(t,{extra:GD(CT())})}function gV(t){return()=>t}function Hr({test:t}){return gV(t)()}function hqe(t,e){if(!e(t))throw new Gp}function gqe(t,e){let r=[];if(!e(t,{errors:r}))throw new Gp({errors:r})}function dqe(t,e){}function mqe(t,e,{coerce:r=!1,errors:o,throw:a}={}){let n=o?[]:void 0;if(!r){if(e(t,{errors:n}))return a?t:{value:t,errors:void 0};if(a)throw new Gp({errors:n});return{value:void 0,errors:n??!0}}let u={value:t},A=Wu(u,"value"),p=[];if(!e(t,{errors:n,coercion:A,coercions:p})){if(a)throw new Gp({errors:n});return{value:void 0,errors:n??!0}}for(let[,h]of p)h();return a?u.value:{value:u.value,errors:void 0}}function yqe(t,e){let r=jD(t);return(...o)=>{if(!r(o))throw new Gp;return e(...o)}}function Eqe(t){return Hr({test:(e,r)=>e.length>=t?!0:pr(r,`Expected to have a length of at least ${t} elements (got ${e.length})`)})}function Cqe(t){return Hr({test:(e,r)=>e.length<=t?!0:pr(r,`Expected to have a length of at most ${t} elements (got ${e.length})`)})}function dV(t){return Hr({test:(e,r)=>e.length!==t?pr(r,`Expected to have a length of exactly ${t} elements (got ${e.length})`):!0})}function wqe({map:t}={}){return Hr({test:(e,r)=>{let o=new Set,a=new Set;for(let n=0,u=e.length;n<u;++n){let A=e[n],p=typeof t<"u"?t(A):A;if(o.has(p)){if(a.has(p))continue;pr(r,`Expected to contain unique elements; got a duplicate with ${qn(e)}`),a.add(p)}else o.add(p)}return a.size===0}})}function Iqe(){return Hr({test:(t,e)=>t<=0?!0:pr(e,`Expected to be negative (got ${t})`)})}function Bqe(){return Hr({test:(t,e)=>t>=0?!0:pr(e,`Expected to be positive (got ${t})`)})}function BT(t){return Hr({test:(e,r)=>e>=t?!0:pr(r,`Expected to be at least ${t} (got ${e})`)})}function vqe(t){return Hr({test:(e,r)=>e<=t?!0:pr(r,`Expected to be at most ${t} (got ${e})`)})}function Dqe(t,e){return Hr({test:(r,o)=>r>=t&&r<=e?!0:pr(o,`Expected to be in the [${t}; ${e}] range (got ${r})`)})}function Pqe(t,e){return Hr({test:(r,o)=>r>=t&&r<e?!0:pr(o,`Expected to be in the [${t}; ${e}[ range (got ${r})`)})}function vT({unsafe:t=!1}={}){return Hr({test:(e,r)=>e!==Math.round(e)?pr(r,`Expected to be an integer (got ${e})`):!t&&!Number.isSafeInteger(e)?pr(r,`Expected to be a safe integer (got ${e})`):!0})}function qw(t){return Hr({test:(e,r)=>t.test(e)?!0:pr(r,`Expected to match the pattern ${t.toString()} (got ${qn(e)})`)})}function Sqe(){return Hr({test:(t,e)=>t!==t.toLowerCase()?pr(e,`Expected to be all-lowercase (got ${t})`):!0})}function bqe(){return Hr({test:(t,e)=>t!==t.toUpperCase()?pr(e,`Expected to be all-uppercase (got ${t})`):!0})}function xqe(){return Hr({test:(t,e)=>nqe.test(t)?!0:pr(e,`Expected to be a valid UUID v4 (got ${qn(t)})`)})}function kqe(){return Hr({test:(t,e)=>fV.test(t)?!0:pr(e,`Expected to be a valid ISO 8601 date string (got ${qn(t)})`)})}function Qqe({alpha:t=!1}){return Hr({test:(e,r)=>(t?eqe.test(e):tqe.test(e))?!0:pr(r,`Expected to be a valid hexadecimal color string (got ${qn(e)})`)})}function Fqe(){return Hr({test:(t,e)=>rqe.test(t)?!0:pr(e,`Expected to be a valid base 64 string (got ${qn(t)})`)})}function Rqe(t=CT()){return Hr({test:(e,r)=>{let o;try{o=JSON.parse(e)}catch{return pr(r,`Expected to be a valid JSON string (got ${qn(e)})`)}return t(o,r)}})}function YD(t,...e){let r=Array.isArray(e[0])?e[0]:e;return Hr({test:(o,a)=>{var n,u;let A={value:o},p=typeof a?.coercions<"u"?Wu(A,"value"):void 0,h=typeof a?.coercions<"u"?[]:void 0;if(!t(o,Object.assign(Object.assign({},a),{coercion:p,coercions:h})))return!1;let E=[];if(typeof h<"u")for(let[,I]of h)E.push(I());try{if(typeof a?.coercions<"u"){if(A.value!==o){if(typeof a?.coercion>"u")return pr(a,"Unbound coercion result");a.coercions.push([(n=a.p)!==null&&n!==void 0?n:".",a.coercion.bind(null,A.value)])}(u=a?.coercions)===null||u===void 0||u.push(...h)}return r.every(I=>I(A.value,a))}finally{for(let I of E)I()}}})}function jw(t,...e){let r=Array.isArray(e[0])?e[0]:e;return YD(t,r)}function Tqe(t){return Hr({test:(e,r)=>typeof e>"u"?!0:t(e,r)})}function Nqe(t){return Hr({test:(e,r)=>e===null?!0:t(e,r)})}function Lqe(t,e){var r;let o=new Set(t),a=Gw[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return Hr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)||p.push(h);return p.length>0?pr(u,`Missing required ${ET(p.length,"property","properties")} ${sm(p,"and")}`):!0}})}function DT(t,e){var r;let o=new Set(t),a=Gw[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return Hr({test:(n,u)=>Object.keys(n).some(h=>a(o,h,n))?!0:pr(u,`Missing at least one property from ${sm(Array.from(o),"or")}`)})}function Mqe(t,e){var r;let o=new Set(t),a=Gw[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return Hr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)&&p.push(h);return p.length>0?pr(u,`Forbidden ${ET(p.length,"property","properties")} ${sm(p,"and")}`):!0}})}function Oqe(t,e){var r;let o=new Set(t),a=Gw[(r=e?.missingIf)!==null&&r!==void 0?r:"missing"];return Hr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)&&p.push(h);return p.length>1?pr(u,`Mutually exclusive properties ${sm(p,"and")}`):!0}})}function Yw(t,e,r,o){var a,n;let u=new Set((a=o?.ignore)!==null&&a!==void 0?a:[]),A=Gw[(n=o?.missingIf)!==null&&n!==void 0?n:"missing"],p=new Set(r),h=Uqe[e],E=e===Yu.Forbids?"or":"and";return Hr({test:(I,v)=>{let x=new Set(Object.keys(I));if(!A(x,t,I)||u.has(I[t]))return!0;let C=[];for(let R of p)(A(x,R,I)&&!u.has(I[R]))!==h.expect&&C.push(R);return C.length>=1?pr(v,`Property "${t}" ${h.message} ${ET(C.length,"property","properties")} ${sm(C,E)}`):!0}})}var $6e,eqe,tqe,rqe,nqe,fV,sqe,pqe,IT,Gp,Gw,Yu,Uqe,el=Et(()=>{$6e=/^[a-zA-Z_][a-zA-Z0-9_]*$/;eqe=/^#[0-9a-f]{6}$/i,tqe=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,rqe=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,nqe=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,fV=/^(?:[1-9]\d{3}(-?)(?:(?:0[1-9]|1[0-2])\1(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])\1(?:29|30)|(?:0[13578]|1[02])(?:\1)31|00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[0-5]))|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\2)29|-?366))T(?:[01]\d|2[0-3])(:?)[0-5]\d(?:\3[0-5]\d)?(?:Z|[+-][01]\d(?:\3[0-5]\d)?)$/;sqe=new Map([["true",!0],["True",!0],["1",!0],[1,!0],["false",!1],["False",!1],["0",!1],[0,!1]]);pqe=t=>Hr({test:(e,r)=>e instanceof t?!0:pr(r,`Expected an instance of ${t.name} (got ${qn(e)})`)}),IT=(t,{exclusive:e=!1}={})=>Hr({test:(r,o)=>{var a,n,u;let A=[],p=typeof o?.errors<"u"?[]:void 0;for(let h=0,E=t.length;h<E;++h){let I=typeof o?.errors<"u"?[]:void 0,v=typeof o?.coercions<"u"?[]:void 0;if(t[h](r,Object.assign(Object.assign({},o),{errors:I,coercions:v,p:`${(a=o?.p)!==null&&a!==void 0?a:"."}#${h+1}`}))){if(A.push([`#${h+1}`,v]),!e)break}else p?.push(I[0])}if(A.length===1){let[,h]=A[0];return typeof h<"u"&&((n=o?.coercions)===null||n===void 0||n.push(...h)),!0}return A.length>1?pr(o,`Expected to match exactly a single predicate (matched ${A.join(", ")})`):(u=o?.errors)===null||u===void 0||u.push(...p),!1}});Gp=class extends Error{constructor({errors:e}={}){let r="Type mismatch";if(e&&e.length>0){r+=` +`;for(let o of e)r+=` +- ${o}`}super(r)}};Gw={missing:(t,e)=>t.has(e),undefined:(t,e,r)=>t.has(e)&&typeof r[e]<"u",nil:(t,e,r)=>t.has(e)&&r[e]!=null,falsy:(t,e,r)=>t.has(e)&&!!r[e]};(function(t){t.Forbids="Forbids",t.Requires="Requires"})(Yu||(Yu={}));Uqe={[Yu.Forbids]:{expect:!1,message:"forbids using"},[Yu.Requires]:{expect:!0,message:"requires using"}}});var it,Yp=Et(()=>{yf();it=class{constructor(){this.help=!1}static Usage(e){return e}async catch(e){throw e}async validateAndExecute(){let r=this.constructor.schema;if(Array.isArray(r)){let{isDict:a,isUnknown:n,applyCascade:u}=await Promise.resolve().then(()=>(el(),Vo)),A=u(a(n()),r),p=[],h=[];if(!A(this,{errors:p,coercions:h}))throw _w("Invalid option schema",p);for(let[,I]of h)I()}else if(r!=null)throw new Error("Invalid command schema");let o=await this.execute();return typeof o<"u"?o:0}};it.isOption=Uw;it.Default=[]});function Pa(t){gT&&console.log(t)}function yV(){let t={nodes:[]};for(let e=0;e<un.CustomNode;++e)t.nodes.push(tl());return t}function _qe(t){let e=yV(),r=[],o=e.nodes.length;for(let a of t){r.push(o);for(let n=0;n<a.nodes.length;++n)CV(n)||e.nodes.push(Vqe(a.nodes[n],o));o+=a.nodes.length-un.CustomNode+1}for(let a of r)am(e,un.InitialNode,a);return e}function Oc(t,e){return t.nodes.push(e),t.nodes.length-1}function Hqe(t){let e=new Set,r=o=>{if(e.has(o))return;e.add(o);let a=t.nodes[o];for(let u of Object.values(a.statics))for(let{to:A}of u)r(A);for(let[,{to:u}]of a.dynamics)r(u);for(let{to:u}of a.shortcuts)r(u);let n=new Set(a.shortcuts.map(({to:u})=>u));for(;a.shortcuts.length>0;){let{to:u}=a.shortcuts.shift(),A=t.nodes[u];for(let[p,h]of Object.entries(A.statics)){let E=Object.prototype.hasOwnProperty.call(a.statics,p)?a.statics[p]:a.statics[p]=[];for(let I of h)E.some(({to:v})=>I.to===v)||E.push(I)}for(let[p,h]of A.dynamics)a.dynamics.some(([E,{to:I}])=>p===E&&h.to===I)||a.dynamics.push([p,h]);for(let p of A.shortcuts)n.has(p.to)||(a.shortcuts.push(p),n.add(p.to))}};r(un.InitialNode)}function qqe(t,{prefix:e=""}={}){if(gT){Pa(`${e}Nodes are:`);for(let r=0;r<t.nodes.length;++r)Pa(`${e} ${r}: ${JSON.stringify(t.nodes[r])}`)}}function jqe(t,e,r=!1){Pa(`Running a vm on ${JSON.stringify(e)}`);let o=[{node:un.InitialNode,state:{candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,options:[],path:[],positionals:[],remainder:null,selectedIndex:null,partial:!1,tokens:[]}}];qqe(t,{prefix:" "});let a=[Hn.StartOfInput,...e];for(let n=0;n<a.length;++n){let u=a[n],A=u===Hn.EndOfInput||u===Hn.EndOfPartialInput,p=n-1;Pa(` Processing ${JSON.stringify(u)}`);let h=[];for(let{node:E,state:I}of o){Pa(` Current node is ${E}`);let v=t.nodes[E];if(E===un.ErrorNode){h.push({node:E,state:I});continue}console.assert(v.shortcuts.length===0,"Shortcuts should have been eliminated by now");let x=Object.prototype.hasOwnProperty.call(v.statics,u);if(!r||n<a.length-1||x)if(x){let C=v.statics[u];for(let{to:R,reducer:L}of C)h.push({node:R,state:typeof L<"u"?WD(ST,L,I,u,p):I}),Pa(` Static transition to ${R} found`)}else Pa(" No static transition found");else{let C=!1;for(let R of Object.keys(v.statics))if(R.startsWith(u)){if(u===R)for(let{to:L,reducer:U}of v.statics[R])h.push({node:L,state:typeof U<"u"?WD(ST,U,I,u,p):I}),Pa(` Static transition to ${L} found`);else for(let{to:L}of v.statics[R])h.push({node:L,state:{...I,remainder:R.slice(u.length)}}),Pa(` Static transition to ${L} found (partial match)`);C=!0}C||Pa(" No partial static transition found")}if(!A)for(let[C,{to:R,reducer:L}]of v.dynamics)WD(zqe,C,I,u,p)&&(h.push({node:R,state:typeof L<"u"?WD(ST,L,I,u,p):I}),Pa(` Dynamic transition to ${R} found (via ${C})`))}if(h.length===0&&A&&e.length===1)return[{node:un.InitialNode,state:mV}];if(h.length===0)throw new im(e,o.filter(({node:E})=>E!==un.ErrorNode).map(({state:E})=>({usage:E.candidateUsage,reason:null})));if(h.every(({node:E})=>E===un.ErrorNode))throw new im(e,h.map(({state:E})=>({usage:E.candidateUsage,reason:E.errorMessage})));o=Yqe(h)}if(o.length>0){Pa(" Results:");for(let n of o)Pa(` - ${n.node} -> ${JSON.stringify(n.state)}`)}else Pa(" No results");return o}function Gqe(t,e,{endToken:r=Hn.EndOfInput}={}){let o=jqe(t,[...e,r]);return Wqe(e,o.map(({state:a})=>a))}function Yqe(t){let e=0;for(let{state:r}of t)r.path.length>e&&(e=r.path.length);return t.filter(({state:r})=>r.path.length===e)}function Wqe(t,e){let r=e.filter(v=>v.selectedIndex!==null),o=r.filter(v=>!v.partial);if(o.length>0&&(r=o),r.length===0)throw new Error;let a=r.filter(v=>v.selectedIndex===Z0||v.requiredOptions.every(x=>x.some(C=>v.options.find(R=>R.name===C))));if(a.length===0)throw new im(t,r.map(v=>({usage:v.candidateUsage,reason:null})));let n=0;for(let v of a)v.path.length>n&&(n=v.path.length);let u=a.filter(v=>v.path.length===n),A=v=>v.positionals.filter(({extra:x})=>!x).length+v.options.length,p=u.map(v=>({state:v,positionalCount:A(v)})),h=0;for(let{positionalCount:v}of p)v>h&&(h=v);let E=p.filter(({positionalCount:v})=>v===h).map(({state:v})=>v),I=Kqe(E);if(I.length>1)throw new UD(t,I.map(v=>v.candidateUsage));return I[0]}function Kqe(t){let e=[],r=[];for(let o of t)o.selectedIndex===Z0?r.push(o):e.push(o);return r.length>0&&e.push({...mV,path:EV(...r.map(o=>o.path)),options:r.reduce((o,a)=>o.concat(a.options),[])}),e}function EV(t,e,...r){return e===void 0?Array.from(t):EV(t.filter((o,a)=>o===e[a]),...r)}function tl(){return{dynamics:[],shortcuts:[],statics:{}}}function CV(t){return t===un.SuccessNode||t===un.ErrorNode}function PT(t,e=0){return{to:CV(t.to)?t.to:t.to>=un.CustomNode?t.to+e-un.CustomNode+1:t.to+e,reducer:t.reducer}}function Vqe(t,e=0){let r=tl();for(let[o,a]of t.dynamics)r.dynamics.push([o,PT(a,e)]);for(let o of t.shortcuts)r.shortcuts.push(PT(o,e));for(let[o,a]of Object.entries(t.statics))r.statics[o]=a.map(n=>PT(n,e));return r}function xs(t,e,r,o,a){t.nodes[e].dynamics.push([r,{to:o,reducer:a}])}function am(t,e,r,o){t.nodes[e].shortcuts.push({to:r,reducer:o})}function zo(t,e,r,o,a){(Object.prototype.hasOwnProperty.call(t.nodes[e].statics,r)?t.nodes[e].statics[r]:t.nodes[e].statics[r]=[]).push({to:o,reducer:a})}function WD(t,e,r,o,a){if(Array.isArray(e)){let[n,...u]=e;return t[n](r,o,a,...u)}else return t[e](r,o,a)}var mV,zqe,ST,rl,bT,KD,VD=Et(()=>{OD();_D();mV={candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,path:[],positionals:[],options:[],remainder:null,selectedIndex:Z0,partial:!1,tokens:[]};zqe={always:()=>!0,isOptionLike:(t,e)=>!t.ignoreOptions&&e!=="-"&&e.startsWith("-"),isNotOptionLike:(t,e)=>t.ignoreOptions||e==="-"||!e.startsWith("-"),isOption:(t,e,r,o)=>!t.ignoreOptions&&e===o,isBatchOption:(t,e,r,o)=>!t.ignoreOptions&&cV.test(e)&&[...e.slice(1)].every(a=>o.has(`-${a}`)),isBoundOption:(t,e,r,o,a)=>{let n=e.match(hT);return!t.ignoreOptions&&!!n&&MD.test(n[1])&&o.has(n[1])&&a.filter(u=>u.nameSet.includes(n[1])).every(u=>u.allowBinding)},isNegatedOption:(t,e,r,o)=>!t.ignoreOptions&&e===`--no-${o.slice(2)}`,isHelp:(t,e)=>!t.ignoreOptions&&pT.test(e),isUnsupportedOption:(t,e,r,o)=>!t.ignoreOptions&&e.startsWith("-")&&MD.test(e)&&!o.has(e),isInvalidOption:(t,e)=>!t.ignoreOptions&&e.startsWith("-")&&!MD.test(e)},ST={setCandidateState:(t,e,r,o)=>({...t,...o}),setSelectedIndex:(t,e,r,o)=>({...t,selectedIndex:o}),setPartialIndex:(t,e,r,o)=>({...t,selectedIndex:o,partial:!0}),pushBatch:(t,e,r,o)=>{let a=t.options.slice(),n=t.tokens.slice();for(let u=1;u<e.length;++u){let A=o.get(`-${e[u]}`),p=u===1?[0,2]:[u,u+1];a.push({name:A,value:!0}),n.push({segmentIndex:r,type:"option",option:A,slice:p})}return{...t,options:a,tokens:n}},pushBound:(t,e,r)=>{let[,o,a]=e.match(hT),n=t.options.concat({name:o,value:a}),u=t.tokens.concat([{segmentIndex:r,type:"option",slice:[0,o.length],option:o},{segmentIndex:r,type:"assign",slice:[o.length,o.length+1]},{segmentIndex:r,type:"value",slice:[o.length+1,o.length+a.length+1]}]);return{...t,options:n,tokens:u}},pushPath:(t,e,r)=>{let o=t.path.concat(e),a=t.tokens.concat({segmentIndex:r,type:"path"});return{...t,path:o,tokens:a}},pushPositional:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:!1}),a=t.tokens.concat({segmentIndex:r,type:"positional"});return{...t,positionals:o,tokens:a}},pushExtra:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:!0}),a=t.tokens.concat({segmentIndex:r,type:"positional"});return{...t,positionals:o,tokens:a}},pushExtraNoLimits:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:rl}),a=t.tokens.concat({segmentIndex:r,type:"positional"});return{...t,positionals:o,tokens:a}},pushTrue:(t,e,r,o)=>{let a=t.options.concat({name:o,value:!0}),n=t.tokens.concat({segmentIndex:r,type:"option",option:o});return{...t,options:a,tokens:n}},pushFalse:(t,e,r,o)=>{let a=t.options.concat({name:o,value:!1}),n=t.tokens.concat({segmentIndex:r,type:"option",option:o});return{...t,options:a,tokens:n}},pushUndefined:(t,e,r,o)=>{let a=t.options.concat({name:e,value:void 0}),n=t.tokens.concat({segmentIndex:r,type:"option",option:e});return{...t,options:a,tokens:n}},pushStringValue:(t,e,r)=>{var o;let a=t.options[t.options.length-1],n=t.options.slice(),u=t.tokens.concat({segmentIndex:r,type:"value"});return a.value=((o=a.value)!==null&&o!==void 0?o:[]).concat([e]),{...t,options:n,tokens:u}},setStringValue:(t,e,r)=>{let o=t.options[t.options.length-1],a=t.options.slice(),n=t.tokens.concat({segmentIndex:r,type:"value"});return o.value=e,{...t,options:a,tokens:n}},inhibateOptions:t=>({...t,ignoreOptions:!0}),useHelp:(t,e,r,o)=>{let[,,a]=e.match(pT);return typeof a<"u"?{...t,options:[{name:"-c",value:String(o)},{name:"-i",value:a}]}:{...t,options:[{name:"-c",value:String(o)}]}},setError:(t,e,r,o)=>e===Hn.EndOfInput||e===Hn.EndOfPartialInput?{...t,errorMessage:`${o}.`}:{...t,errorMessage:`${o} ("${e}").`},setOptionArityError:(t,e)=>{let r=t.options[t.options.length-1];return{...t,errorMessage:`Not enough arguments to option ${r.name}.`}}},rl=Symbol(),bT=class{constructor(e,r){this.allOptionNames=new Map,this.arity={leading:[],trailing:[],extra:[],proxy:!1},this.options=[],this.paths=[],this.cliIndex=e,this.cliOpts=r}addPath(e){this.paths.push(e)}setArity({leading:e=this.arity.leading,trailing:r=this.arity.trailing,extra:o=this.arity.extra,proxy:a=this.arity.proxy}){Object.assign(this.arity,{leading:e,trailing:r,extra:o,proxy:a})}addPositional({name:e="arg",required:r=!0}={}){if(!r&&this.arity.extra===rl)throw new Error("Optional parameters cannot be declared when using .rest() or .proxy()");if(!r&&this.arity.trailing.length>0)throw new Error("Optional parameters cannot be declared after the required trailing positional arguments");!r&&this.arity.extra!==rl?this.arity.extra.push(e):this.arity.extra!==rl&&this.arity.extra.length===0?this.arity.leading.push(e):this.arity.trailing.push(e)}addRest({name:e="arg",required:r=0}={}){if(this.arity.extra===rl)throw new Error("Infinite lists cannot be declared multiple times in the same command");if(this.arity.trailing.length>0)throw new Error("Infinite lists cannot be declared after the required trailing positional arguments");for(let o=0;o<r;++o)this.addPositional({name:e});this.arity.extra=rl}addProxy({required:e=0}={}){this.addRest({required:e}),this.arity.proxy=!0}addOption({names:e,description:r,arity:o=0,hidden:a=!1,required:n=!1,allowBinding:u=!0}){if(!u&&o>1)throw new Error("The arity cannot be higher than 1 when the option only supports the --arg=value syntax");if(!Number.isInteger(o))throw new Error(`The arity must be an integer, got ${o}`);if(o<0)throw new Error(`The arity must be positive, got ${o}`);let A=e.reduce((p,h)=>h.length>p.length?h:p,"");for(let p of e)this.allOptionNames.set(p,A);this.options.push({preferredName:A,nameSet:e,description:r,arity:o,hidden:a,required:n,allowBinding:u})}setContext(e){this.context=e}usage({detailed:e=!0,inlineOptions:r=!0}={}){let o=[this.cliOpts.binaryName],a=[];if(this.paths.length>0&&o.push(...this.paths[0]),e){for(let{preferredName:u,nameSet:A,arity:p,hidden:h,description:E,required:I}of this.options){if(h)continue;let v=[];for(let C=0;C<p;++C)v.push(` #${C}`);let x=`${A.join(",")}${v.join("")}`;!r&&E?a.push({preferredName:u,nameSet:A,definition:x,description:E,required:I}):o.push(I?`<${x}>`:`[${x}]`)}o.push(...this.arity.leading.map(u=>`<${u}>`)),this.arity.extra===rl?o.push("..."):o.push(...this.arity.extra.map(u=>`[${u}]`)),o.push(...this.arity.trailing.map(u=>`<${u}>`))}return{usage:o.join(" "),options:a}}compile(){if(typeof this.context>"u")throw new Error("Assertion failed: No context attached");let e=yV(),r=un.InitialNode,o=this.usage().usage,a=this.options.filter(A=>A.required).map(A=>A.nameSet);r=Oc(e,tl()),zo(e,un.InitialNode,Hn.StartOfInput,r,["setCandidateState",{candidateUsage:o,requiredOptions:a}]);let n=this.arity.proxy?"always":"isNotOptionLike",u=this.paths.length>0?this.paths:[[]];for(let A of u){let p=r;if(A.length>0){let v=Oc(e,tl());am(e,p,v),this.registerOptions(e,v),p=v}for(let v=0;v<A.length;++v){let x=Oc(e,tl());zo(e,p,A[v],x,"pushPath"),p=x}if(this.arity.leading.length>0||!this.arity.proxy){let v=Oc(e,tl());xs(e,p,"isHelp",v,["useHelp",this.cliIndex]),xs(e,v,"always",v,"pushExtra"),zo(e,v,Hn.EndOfInput,un.SuccessNode,["setSelectedIndex",Z0]),this.registerOptions(e,p)}this.arity.leading.length>0&&(zo(e,p,Hn.EndOfInput,un.ErrorNode,["setError","Not enough positional arguments"]),zo(e,p,Hn.EndOfPartialInput,un.SuccessNode,["setPartialIndex",this.cliIndex]));let h=p;for(let v=0;v<this.arity.leading.length;++v){let x=Oc(e,tl());(!this.arity.proxy||v+1!==this.arity.leading.length)&&this.registerOptions(e,x),(this.arity.trailing.length>0||v+1!==this.arity.leading.length)&&(zo(e,x,Hn.EndOfInput,un.ErrorNode,["setError","Not enough positional arguments"]),zo(e,x,Hn.EndOfPartialInput,un.SuccessNode,["setPartialIndex",this.cliIndex])),xs(e,h,"isNotOptionLike",x,"pushPositional"),h=x}let E=h;if(this.arity.extra===rl||this.arity.extra.length>0){let v=Oc(e,tl());if(am(e,h,v),this.arity.extra===rl){let x=Oc(e,tl());this.arity.proxy||this.registerOptions(e,x),xs(e,h,n,x,"pushExtraNoLimits"),xs(e,x,n,x,"pushExtraNoLimits"),am(e,x,v)}else for(let x=0;x<this.arity.extra.length;++x){let C=Oc(e,tl());(!this.arity.proxy||x>0)&&this.registerOptions(e,C),xs(e,E,n,C,"pushExtra"),am(e,C,v),E=C}E=v}this.arity.trailing.length>0&&(zo(e,E,Hn.EndOfInput,un.ErrorNode,["setError","Not enough positional arguments"]),zo(e,E,Hn.EndOfPartialInput,un.SuccessNode,["setPartialIndex",this.cliIndex]));let I=E;for(let v=0;v<this.arity.trailing.length;++v){let x=Oc(e,tl());this.arity.proxy||this.registerOptions(e,x),v+1<this.arity.trailing.length&&(zo(e,x,Hn.EndOfInput,un.ErrorNode,["setError","Not enough positional arguments"]),zo(e,x,Hn.EndOfPartialInput,un.SuccessNode,["setPartialIndex",this.cliIndex])),xs(e,I,"isNotOptionLike",x,"pushPositional"),I=x}xs(e,I,n,un.ErrorNode,["setError","Extraneous positional argument"]),zo(e,I,Hn.EndOfInput,un.SuccessNode,["setSelectedIndex",this.cliIndex]),zo(e,I,Hn.EndOfPartialInput,un.SuccessNode,["setSelectedIndex",this.cliIndex])}return{machine:e,context:this.context}}registerOptions(e,r){xs(e,r,["isOption","--"],r,"inhibateOptions"),xs(e,r,["isBatchOption",this.allOptionNames],r,["pushBatch",this.allOptionNames]),xs(e,r,["isBoundOption",this.allOptionNames,this.options],r,"pushBound"),xs(e,r,["isUnsupportedOption",this.allOptionNames],un.ErrorNode,["setError","Unsupported option name"]),xs(e,r,["isInvalidOption"],un.ErrorNode,["setError","Invalid option name"]);for(let o of this.options)if(o.arity===0)for(let a of o.nameSet)xs(e,r,["isOption",a],r,["pushTrue",o.preferredName]),a.startsWith("--")&&!a.startsWith("--no-")&&xs(e,r,["isNegatedOption",a],r,["pushFalse",o.preferredName]);else{let a=Oc(e,tl());for(let n of o.nameSet)xs(e,r,["isOption",n],a,["pushUndefined",o.preferredName]);for(let n=0;n<o.arity;++n){let u=Oc(e,tl());zo(e,a,Hn.EndOfInput,un.ErrorNode,"setOptionArityError"),zo(e,a,Hn.EndOfPartialInput,un.ErrorNode,"setOptionArityError"),xs(e,a,"isOptionLike",un.ErrorNode,"setOptionArityError");let A=o.arity===1?"setStringValue":"pushStringValue";xs(e,a,"isNotOptionLike",u,A),a=u}am(e,a,r)}}},KD=class t{constructor({binaryName:e="..."}={}){this.builders=[],this.opts={binaryName:e}}static build(e,r={}){return new t(r).commands(e).compile()}getBuilderByIndex(e){if(!(e>=0&&e<this.builders.length))throw new Error(`Assertion failed: Out-of-bound command index (${e})`);return this.builders[e]}commands(e){for(let r of e)r(this.command());return this}command(){let e=new bT(this.builders.length,this.opts);return this.builders.push(e),e}compile(){let e=[],r=[];for(let a of this.builders){let{machine:n,context:u}=a.compile();e.push(n),r.push(u)}let o=_qe(e);return Hqe(o),{machine:o,contexts:r,process:(a,{partial:n}={})=>{let u=n?Hn.EndOfPartialInput:Hn.EndOfInput;return Gqe(o,a,{endToken:u})}}}}});function IV(){return zD.default&&"getColorDepth"in zD.default.WriteStream.prototype?zD.default.WriteStream.prototype.getColorDepth():process.env.FORCE_COLOR==="0"?1:process.env.FORCE_COLOR==="1"||typeof process.stdout<"u"&&process.stdout.isTTY?8:1}function BV(t){let e=wV;if(typeof e>"u"){if(t.stdout===process.stdout&&t.stderr===process.stderr)return null;let{AsyncLocalStorage:r}=ve("async_hooks");e=wV=new r;let o=process.stdout._write;process.stdout._write=function(n,u,A){let p=e.getStore();return typeof p>"u"?o.call(this,n,u,A):p.stdout.write(n,u,A)};let a=process.stderr._write;process.stderr._write=function(n,u,A){let p=e.getStore();return typeof p>"u"?a.call(this,n,u,A):p.stderr.write(n,u,A)}}return r=>e.run(t,r)}var zD,wV,vV=Et(()=>{zD=Ze(ve("tty"),1)});var JD,DV=Et(()=>{Yp();JD=class t extends it{constructor(e){super(),this.contexts=e,this.commands=[]}static from(e,r){let o=new t(r);o.path=e.path;for(let a of e.options)switch(a.name){case"-c":o.commands.push(Number(a.value));break;case"-i":o.index=Number(a.value);break}return o}async execute(){let e=this.commands;if(typeof this.index<"u"&&this.index>=0&&this.index<e.length&&(e=[e[this.index]]),e.length===0)this.context.stdout.write(this.cli.usage());else if(e.length===1)this.context.stdout.write(this.cli.usage(this.contexts[e[0]].commandClass,{detailed:!0}));else if(e.length>1){this.context.stdout.write(`Multiple commands match your selection: +`),this.context.stdout.write(` +`);let r=0;for(let o of this.commands)this.context.stdout.write(this.cli.usage(this.contexts[o].commandClass,{prefix:`${r++}. `.padStart(5)}));this.context.stdout.write(` +`),this.context.stdout.write(`Run again with -h=<index> to see the longer details of any of those commands. +`)}}}});async function bV(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}=kV(t);return Jo.from(r,e).runExit(o,a)}async function xV(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}=kV(t);return Jo.from(r,e).run(o,a)}function kV(t){let e,r,o,a;switch(typeof process<"u"&&typeof process.argv<"u"&&(o=process.argv.slice(2)),t.length){case 1:r=t[0];break;case 2:t[0]&&t[0].prototype instanceof it||Array.isArray(t[0])?(r=t[0],Array.isArray(t[1])?o=t[1]:a=t[1]):(e=t[0],r=t[1]);break;case 3:Array.isArray(t[2])?(e=t[0],r=t[1],o=t[2]):t[0]&&t[0].prototype instanceof it||Array.isArray(t[0])?(r=t[0],o=t[1],a=t[2]):(e=t[0],r=t[1],a=t[2]);break;default:e=t[0],r=t[1],o=t[2],a=t[3];break}if(typeof o>"u")throw new Error("The argv parameter must be provided when running Clipanion outside of a Node context");return{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}}function SV(t){return t()}var PV,Jo,QV=Et(()=>{OD();VD();yT();vV();Yp();DV();PV=Symbol("clipanion/errorCommand");Jo=class t{constructor({binaryLabel:e,binaryName:r="...",binaryVersion:o,enableCapture:a=!1,enableColors:n}={}){this.registrations=new Map,this.builder=new KD({binaryName:r}),this.binaryLabel=e,this.binaryName=r,this.binaryVersion=o,this.enableCapture=a,this.enableColors=n}static from(e,r={}){let o=new t(r),a=Array.isArray(e)?e:[e];for(let n of a)o.register(n);return o}register(e){var r;let o=new Map,a=new e;for(let p in a){let h=a[p];typeof h=="object"&&h!==null&&h[it.isOption]&&o.set(p,h)}let n=this.builder.command(),u=n.cliIndex,A=(r=e.paths)!==null&&r!==void 0?r:a.paths;if(typeof A<"u")for(let p of A)n.addPath(p);this.registrations.set(e,{specs:o,builder:n,index:u});for(let[p,{definition:h}]of o.entries())h(n,p);n.setContext({commandClass:e})}process(e,r){let{input:o,context:a,partial:n}=typeof e=="object"&&Array.isArray(e)?{input:e,context:r}:e,{contexts:u,process:A}=this.builder.compile(),p=A(o,{partial:n}),h={...t.defaultContext,...a};switch(p.selectedIndex){case Z0:{let E=JD.from(p,u);return E.context=h,E.tokens=p.tokens,E}default:{let{commandClass:E}=u[p.selectedIndex],I=this.registrations.get(E);if(typeof I>"u")throw new Error("Assertion failed: Expected the command class to have been registered.");let v=new E;v.context=h,v.tokens=p.tokens,v.path=p.path;try{for(let[x,{transformer:C}]of I.specs.entries())v[x]=C(I.builder,x,p,h);return v}catch(x){throw x[PV]=v,x}}break}}async run(e,r){var o,a;let n,u={...t.defaultContext,...r},A=(o=this.enableColors)!==null&&o!==void 0?o:u.colorDepth>1;if(!Array.isArray(e))n=e;else try{n=this.process(e,u)}catch(E){return u.stdout.write(this.error(E,{colored:A})),1}if(n.help)return u.stdout.write(this.usage(n,{colored:A,detailed:!0})),0;n.context=u,n.cli={binaryLabel:this.binaryLabel,binaryName:this.binaryName,binaryVersion:this.binaryVersion,enableCapture:this.enableCapture,enableColors:this.enableColors,definitions:()=>this.definitions(),definition:E=>this.definition(E),error:(E,I)=>this.error(E,I),format:E=>this.format(E),process:(E,I)=>this.process(E,{...u,...I}),run:(E,I)=>this.run(E,{...u,...I}),usage:(E,I)=>this.usage(E,I)};let p=this.enableCapture&&(a=BV(u))!==null&&a!==void 0?a:SV,h;try{h=await p(()=>n.validateAndExecute().catch(E=>n.catch(E).then(()=>0)))}catch(E){return u.stdout.write(this.error(E,{colored:A,command:n})),1}return h}async runExit(e,r){process.exitCode=await this.run(e,r)}definition(e,{colored:r=!1}={}){if(!e.usage)return null;let{usage:o}=this.getUsageByRegistration(e,{detailed:!1}),{usage:a,options:n}=this.getUsageByRegistration(e,{detailed:!0,inlineOptions:!1}),u=typeof e.usage.category<"u"?Do(e.usage.category,{format:this.format(r),paragraphs:!1}):void 0,A=typeof e.usage.description<"u"?Do(e.usage.description,{format:this.format(r),paragraphs:!1}):void 0,p=typeof e.usage.details<"u"?Do(e.usage.details,{format:this.format(r),paragraphs:!0}):void 0,h=typeof e.usage.examples<"u"?e.usage.examples.map(([E,I])=>[Do(E,{format:this.format(r),paragraphs:!1}),I.replace(/\$0/g,this.binaryName)]):void 0;return{path:o,usage:a,category:u,description:A,details:p,examples:h,options:n}}definitions({colored:e=!1}={}){let r=[];for(let o of this.registrations.keys()){let a=this.definition(o,{colored:e});a&&r.push(a)}return r}usage(e=null,{colored:r,detailed:o=!1,prefix:a="$ "}={}){var n;if(e===null){for(let p of this.registrations.keys()){let h=p.paths,E=typeof p.usage<"u";if(!h||h.length===0||h.length===1&&h[0].length===0||((n=h?.some(x=>x.length===0))!==null&&n!==void 0?n:!1))if(e){e=null;break}else e=p;else if(E){e=null;continue}}e&&(o=!0)}let u=e!==null&&e instanceof it?e.constructor:e,A="";if(u)if(o){let{description:p="",details:h="",examples:E=[]}=u.usage||{};p!==""&&(A+=Do(p,{format:this.format(r),paragraphs:!1}).replace(/^./,x=>x.toUpperCase()),A+=` +`),(h!==""||E.length>0)&&(A+=`${this.format(r).header("Usage")} +`,A+=` +`);let{usage:I,options:v}=this.getUsageByRegistration(u,{inlineOptions:!1});if(A+=`${this.format(r).bold(a)}${I} +`,v.length>0){A+=` +`,A+=`${this.format(r).header("Options")} +`;let x=v.reduce((C,R)=>Math.max(C,R.definition.length),0);A+=` +`;for(let{definition:C,description:R}of v)A+=` ${this.format(r).bold(C.padEnd(x))} ${Do(R,{format:this.format(r),paragraphs:!1})}`}if(h!==""&&(A+=` +`,A+=`${this.format(r).header("Details")} +`,A+=` +`,A+=Do(h,{format:this.format(r),paragraphs:!0})),E.length>0){A+=` +`,A+=`${this.format(r).header("Examples")} +`;for(let[x,C]of E)A+=` +`,A+=Do(x,{format:this.format(r),paragraphs:!1}),A+=`${C.replace(/^/m,` ${this.format(r).bold(a)}`).replace(/\$0/g,this.binaryName)} +`}}else{let{usage:p}=this.getUsageByRegistration(u);A+=`${this.format(r).bold(a)}${p} +`}else{let p=new Map;for(let[v,{index:x}]of this.registrations.entries()){if(typeof v.usage>"u")continue;let C=typeof v.usage.category<"u"?Do(v.usage.category,{format:this.format(r),paragraphs:!1}):null,R=p.get(C);typeof R>"u"&&p.set(C,R=[]);let{usage:L}=this.getUsageByIndex(x);R.push({commandClass:v,usage:L})}let h=Array.from(p.keys()).sort((v,x)=>v===null?-1:x===null?1:v.localeCompare(x,"en",{usage:"sort",caseFirst:"upper"})),E=typeof this.binaryLabel<"u",I=typeof this.binaryVersion<"u";E||I?(E&&I?A+=`${this.format(r).header(`${this.binaryLabel} - ${this.binaryVersion}`)} + +`:E?A+=`${this.format(r).header(`${this.binaryLabel}`)} +`:A+=`${this.format(r).header(`${this.binaryVersion}`)} +`,A+=` ${this.format(r).bold(a)}${this.binaryName} <command> +`):A+=`${this.format(r).bold(a)}${this.binaryName} <command> +`;for(let v of h){let x=p.get(v).slice().sort((R,L)=>R.usage.localeCompare(L.usage,"en",{usage:"sort",caseFirst:"upper"})),C=v!==null?v.trim():"General commands";A+=` +`,A+=`${this.format(r).header(`${C}`)} +`;for(let{commandClass:R,usage:L}of x){let U=R.usage.description||"undocumented";A+=` +`,A+=` ${this.format(r).bold(L)} +`,A+=` ${Do(U,{format:this.format(r),paragraphs:!1})}`}}A+=` +`,A+=Do("You can also print more details about any of these commands by calling them with the `-h,--help` flag right after the command name.",{format:this.format(r),paragraphs:!0})}return A}error(e,r){var o,{colored:a,command:n=(o=e[PV])!==null&&o!==void 0?o:null}=r===void 0?{}:r;(!e||typeof e!="object"||!("stack"in e))&&(e=new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(e)})`));let u="",A=e.name.replace(/([a-z])([A-Z])/g,"$1 $2");A==="Error"&&(A="Internal Error"),u+=`${this.format(a).error(A)}: ${e.message} +`;let p=e.clipanion;return typeof p<"u"?p.type==="usage"&&(u+=` +`,u+=this.usage(n)):e.stack&&(u+=`${e.stack.replace(/^.*\n/,"")} +`),u}format(e){var r;return((r=e??this.enableColors)!==null&&r!==void 0?r:t.defaultContext.colorDepth>1)?uV:AV}getUsageByRegistration(e,r){let o=this.registrations.get(e);if(typeof o>"u")throw new Error("Assertion failed: Unregistered command");return this.getUsageByIndex(o.index,r)}getUsageByIndex(e,r){return this.builder.getBuilderByIndex(e).usage(r)}};Jo.defaultContext={env:process.env,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr,colorDepth:IV()}});var Ww,FV=Et(()=>{Yp();Ww=class extends it{async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.definitions(),null,2)} +`)}};Ww.paths=[["--clipanion=definitions"]]});var Kw,RV=Et(()=>{Yp();Kw=class extends it{async execute(){this.context.stdout.write(this.cli.usage())}};Kw.paths=[["-h"],["--help"]]});function XD(t={}){return Ko({definition(e,r){var o;e.addProxy({name:(o=t.name)!==null&&o!==void 0?o:r,required:t.required})},transformer(e,r,o){return o.positionals.map(({value:a})=>a)}})}var xT=Et(()=>{yf()});var Vw,TV=Et(()=>{Yp();xT();Vw=class extends it{constructor(){super(...arguments),this.args=XD()}async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.process(this.args).tokens,null,2)} +`)}};Vw.paths=[["--clipanion=tokens"]]});var zw,NV=Et(()=>{Yp();zw=class extends it{async execute(){var e;this.context.stdout.write(`${(e=this.cli.binaryVersion)!==null&&e!==void 0?e:"<unknown>"} +`)}};zw.paths=[["-v"],["--version"]]});var kT={};Vt(kT,{DefinitionsCommand:()=>Ww,HelpCommand:()=>Kw,TokensCommand:()=>Vw,VersionCommand:()=>zw});var LV=Et(()=>{FV();RV();TV();NV()});function MV(t,e,r){let[o,a]=Gu(e,r??{}),{arity:n=1}=a,u=t.split(","),A=new Set(u);return Ko({definition(p){p.addOption({names:u,arity:n,hidden:a?.hidden,description:a?.description,required:a.required})},transformer(p,h,E){let I,v=typeof o<"u"?[...o]:void 0;for(let{name:x,value:C}of E.options)A.has(x)&&(I=x,v=v??[],v.push(C));return typeof v<"u"?$0(I??h,v,a.validator):v}})}var OV=Et(()=>{yf()});function UV(t,e,r){let[o,a]=Gu(e,r??{}),n=t.split(","),u=new Set(n);return Ko({definition(A){A.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(A,p,h){let E=o;for(let{name:I,value:v}of h.options)u.has(I)&&(E=v);return E}})}var _V=Et(()=>{yf()});function HV(t,e,r){let[o,a]=Gu(e,r??{}),n=t.split(","),u=new Set(n);return Ko({definition(A){A.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(A,p,h){let E=o;for(let{name:I,value:v}of h.options)u.has(I)&&(E??(E=0),v?E+=1:E=0);return E}})}var qV=Et(()=>{yf()});function jV(t={}){return Ko({definition(e,r){var o;e.addRest({name:(o=t.name)!==null&&o!==void 0?o:r,required:t.required})},transformer(e,r,o){let a=u=>{let A=o.positionals[u];return A.extra===rl||A.extra===!1&&u<e.arity.leading.length},n=0;for(;n<o.positionals.length&&a(n);)n+=1;return o.positionals.splice(0,n).map(({value:u})=>u)}})}var GV=Et(()=>{VD();yf()});function Jqe(t,e,r){let[o,a]=Gu(e,r??{}),{arity:n=1}=a,u=t.split(","),A=new Set(u);return Ko({definition(p){p.addOption({names:u,arity:a.tolerateBoolean?0:n,hidden:a.hidden,description:a.description,required:a.required})},transformer(p,h,E,I){let v,x=o;typeof a.env<"u"&&I.env[a.env]&&(v=a.env,x=I.env[a.env]);for(let{name:C,value:R}of E.options)A.has(C)&&(v=C,x=R);return typeof x=="string"?$0(v??h,x,a.validator):x}})}function Xqe(t={}){let{required:e=!0}=t;return Ko({definition(r,o){var a;r.addPositional({name:(a=t.name)!==null&&a!==void 0?a:o,required:t.required})},transformer(r,o,a){var n;for(let u=0;u<a.positionals.length;++u){if(a.positionals[u].extra===rl||e&&a.positionals[u].extra===!0||!e&&a.positionals[u].extra===!1)continue;let[A]=a.positionals.splice(u,1);return $0((n=t.name)!==null&&n!==void 0?n:o,A.value,t.validator)}}})}function YV(t,...e){return typeof t=="string"?Jqe(t,...e):Xqe(t)}var WV=Et(()=>{VD();yf()});var ge={};Vt(ge,{Array:()=>MV,Boolean:()=>UV,Counter:()=>HV,Proxy:()=>XD,Rest:()=>jV,String:()=>YV,applyValidator:()=>$0,cleanValidationError:()=>HD,formatError:()=>_w,isOptionSymbol:()=>Uw,makeCommandOption:()=>Ko,rerouteArguments:()=>Gu});var KV=Et(()=>{yf();xT();OV();_V();qV();GV();WV()});var Jw={};Vt(Jw,{Builtins:()=>kT,Cli:()=>Jo,Command:()=>it,Option:()=>ge,UsageError:()=>st,formatMarkdownish:()=>Do,run:()=>xV,runExit:()=>bV});var qt=Et(()=>{_D();yT();Yp();QV();LV();KV()});var VV=_((Rkt,Zqe)=>{Zqe.exports={name:"dotenv",version:"16.3.1",description:"Loads environment variables from .env file",main:"lib/main.js",types:"lib/main.d.ts",exports:{".":{types:"./lib/main.d.ts",require:"./lib/main.js",default:"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},scripts:{"dts-check":"tsc --project tests/types/tsconfig.json",lint:"standard","lint-readme":"standard-markdown",pretest:"npm run lint && npm run dts-check",test:"tap tests/*.js --100 -Rspec",prerelease:"npm test",release:"standard-version"},repository:{type:"git",url:"git://github.com/motdotla/dotenv.git"},funding:"https://github.com/motdotla/dotenv?sponsor=1",keywords:["dotenv","env",".env","environment","variables","config","settings"],readmeFilename:"README.md",license:"BSD-2-Clause",devDependencies:{"@definitelytyped/dtslint":"^0.0.133","@types/node":"^18.11.3",decache:"^4.6.1",sinon:"^14.0.1",standard:"^17.0.0","standard-markdown":"^7.1.0","standard-version":"^9.5.0",tap:"^16.3.0",tar:"^6.1.11",typescript:"^4.8.4"},engines:{node:">=12"},browser:{fs:!1}}});var ZV=_((Tkt,Ef)=>{var zV=ve("fs"),FT=ve("path"),$qe=ve("os"),eje=ve("crypto"),tje=VV(),RT=tje.version,rje=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;function nje(t){let e={},r=t.toString();r=r.replace(/\r\n?/mg,` +`);let o;for(;(o=rje.exec(r))!=null;){let a=o[1],n=o[2]||"";n=n.trim();let u=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/mg,"$2"),u==='"'&&(n=n.replace(/\\n/g,` +`),n=n.replace(/\\r/g,"\r")),e[a]=n}return e}function ije(t){let e=XV(t),r=ks.configDotenv({path:e});if(!r.parsed)throw new Error(`MISSING_DATA: Cannot parse ${e} for an unknown reason`);let o=JV(t).split(","),a=o.length,n;for(let u=0;u<a;u++)try{let A=o[u].trim(),p=aje(r,A);n=ks.decrypt(p.ciphertext,p.key);break}catch(A){if(u+1>=a)throw A}return ks.parse(n)}function sje(t){console.log(`[dotenv@${RT}][INFO] ${t}`)}function oje(t){console.log(`[dotenv@${RT}][WARN] ${t}`)}function QT(t){console.log(`[dotenv@${RT}][DEBUG] ${t}`)}function JV(t){return t&&t.DOTENV_KEY&&t.DOTENV_KEY.length>0?t.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function aje(t,e){let r;try{r=new URL(e)}catch(A){throw A.code==="ERR_INVALID_URL"?new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development"):A}let o=r.password;if(!o)throw new Error("INVALID_DOTENV_KEY: Missing key part");let a=r.searchParams.get("environment");if(!a)throw new Error("INVALID_DOTENV_KEY: Missing environment part");let n=`DOTENV_VAULT_${a.toUpperCase()}`,u=t.parsed[n];if(!u)throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);return{ciphertext:u,key:o}}function XV(t){let e=FT.resolve(process.cwd(),".env");return t&&t.path&&t.path.length>0&&(e=t.path),e.endsWith(".vault")?e:`${e}.vault`}function lje(t){return t[0]==="~"?FT.join($qe.homedir(),t.slice(1)):t}function cje(t){sje("Loading env from encrypted .env.vault");let e=ks._parseVault(t),r=process.env;return t&&t.processEnv!=null&&(r=t.processEnv),ks.populate(r,e,t),{parsed:e}}function uje(t){let e=FT.resolve(process.cwd(),".env"),r="utf8",o=!!(t&&t.debug);t&&(t.path!=null&&(e=lje(t.path)),t.encoding!=null&&(r=t.encoding));try{let a=ks.parse(zV.readFileSync(e,{encoding:r})),n=process.env;return t&&t.processEnv!=null&&(n=t.processEnv),ks.populate(n,a,t),{parsed:a}}catch(a){return o&&QT(`Failed to load ${e} ${a.message}`),{error:a}}}function Aje(t){let e=XV(t);return JV(t).length===0?ks.configDotenv(t):zV.existsSync(e)?ks._configVault(t):(oje(`You set DOTENV_KEY but you are missing a .env.vault file at ${e}. Did you forget to build it?`),ks.configDotenv(t))}function fje(t,e){let r=Buffer.from(e.slice(-64),"hex"),o=Buffer.from(t,"base64"),a=o.slice(0,12),n=o.slice(-16);o=o.slice(12,-16);try{let u=eje.createDecipheriv("aes-256-gcm",r,a);return u.setAuthTag(n),`${u.update(o)}${u.final()}`}catch(u){let A=u instanceof RangeError,p=u.message==="Invalid key length",h=u.message==="Unsupported state or unable to authenticate data";if(A||p){let E="INVALID_DOTENV_KEY: It must be 64 characters long (or more)";throw new Error(E)}else if(h){let E="DECRYPTION_FAILED: Please check your DOTENV_KEY";throw new Error(E)}else throw console.error("Error: ",u.code),console.error("Error: ",u.message),u}}function pje(t,e,r={}){let o=!!(r&&r.debug),a=!!(r&&r.override);if(typeof e!="object")throw new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");for(let n of Object.keys(e))Object.prototype.hasOwnProperty.call(t,n)?(a===!0&&(t[n]=e[n]),o&&QT(a===!0?`"${n}" is already defined and WAS overwritten`:`"${n}" is already defined and was NOT overwritten`)):t[n]=e[n]}var ks={configDotenv:uje,_configVault:cje,_parseVault:ije,config:Aje,decrypt:fje,parse:nje,populate:pje};Ef.exports.configDotenv=ks.configDotenv;Ef.exports._configVault=ks._configVault;Ef.exports._parseVault=ks._parseVault;Ef.exports.config=ks.config;Ef.exports.decrypt=ks.decrypt;Ef.exports.parse=ks.parse;Ef.exports.populate=ks.populate;Ef.exports=ks});var ez=_((Nkt,$V)=>{"use strict";$V.exports=(t,...e)=>new Promise(r=>{r(t(...e))})});var eg=_((Lkt,TT)=>{"use strict";var hje=ez(),tz=t=>{if(t<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let e=[],r=0,o=()=>{r--,e.length>0&&e.shift()()},a=(A,p,...h)=>{r++;let E=hje(A,...h);p(E),E.then(o,o)},n=(A,p,...h)=>{r<t?a(A,p,...h):e.push(a.bind(null,A,p,...h))},u=(A,...p)=>new Promise(h=>n(A,h,...p));return Object.defineProperties(u,{activeCount:{get:()=>r},pendingCount:{get:()=>e.length}}),u};TT.exports=tz;TT.exports.default=tz});function Ku(t){return`YN${t.toString(10).padStart(4,"0")}`}function ZD(t){let e=Number(t.slice(2));if(typeof wr[e]>"u")throw new Error(`Unknown message name: "${t}"`);return e}var wr,$D=Et(()=>{wr=(Me=>(Me[Me.UNNAMED=0]="UNNAMED",Me[Me.EXCEPTION=1]="EXCEPTION",Me[Me.MISSING_PEER_DEPENDENCY=2]="MISSING_PEER_DEPENDENCY",Me[Me.CYCLIC_DEPENDENCIES=3]="CYCLIC_DEPENDENCIES",Me[Me.DISABLED_BUILD_SCRIPTS=4]="DISABLED_BUILD_SCRIPTS",Me[Me.BUILD_DISABLED=5]="BUILD_DISABLED",Me[Me.SOFT_LINK_BUILD=6]="SOFT_LINK_BUILD",Me[Me.MUST_BUILD=7]="MUST_BUILD",Me[Me.MUST_REBUILD=8]="MUST_REBUILD",Me[Me.BUILD_FAILED=9]="BUILD_FAILED",Me[Me.RESOLVER_NOT_FOUND=10]="RESOLVER_NOT_FOUND",Me[Me.FETCHER_NOT_FOUND=11]="FETCHER_NOT_FOUND",Me[Me.LINKER_NOT_FOUND=12]="LINKER_NOT_FOUND",Me[Me.FETCH_NOT_CACHED=13]="FETCH_NOT_CACHED",Me[Me.YARN_IMPORT_FAILED=14]="YARN_IMPORT_FAILED",Me[Me.REMOTE_INVALID=15]="REMOTE_INVALID",Me[Me.REMOTE_NOT_FOUND=16]="REMOTE_NOT_FOUND",Me[Me.RESOLUTION_PACK=17]="RESOLUTION_PACK",Me[Me.CACHE_CHECKSUM_MISMATCH=18]="CACHE_CHECKSUM_MISMATCH",Me[Me.UNUSED_CACHE_ENTRY=19]="UNUSED_CACHE_ENTRY",Me[Me.MISSING_LOCKFILE_ENTRY=20]="MISSING_LOCKFILE_ENTRY",Me[Me.WORKSPACE_NOT_FOUND=21]="WORKSPACE_NOT_FOUND",Me[Me.TOO_MANY_MATCHING_WORKSPACES=22]="TOO_MANY_MATCHING_WORKSPACES",Me[Me.CONSTRAINTS_MISSING_DEPENDENCY=23]="CONSTRAINTS_MISSING_DEPENDENCY",Me[Me.CONSTRAINTS_INCOMPATIBLE_DEPENDENCY=24]="CONSTRAINTS_INCOMPATIBLE_DEPENDENCY",Me[Me.CONSTRAINTS_EXTRANEOUS_DEPENDENCY=25]="CONSTRAINTS_EXTRANEOUS_DEPENDENCY",Me[Me.CONSTRAINTS_INVALID_DEPENDENCY=26]="CONSTRAINTS_INVALID_DEPENDENCY",Me[Me.CANT_SUGGEST_RESOLUTIONS=27]="CANT_SUGGEST_RESOLUTIONS",Me[Me.FROZEN_LOCKFILE_EXCEPTION=28]="FROZEN_LOCKFILE_EXCEPTION",Me[Me.CROSS_DRIVE_VIRTUAL_LOCAL=29]="CROSS_DRIVE_VIRTUAL_LOCAL",Me[Me.FETCH_FAILED=30]="FETCH_FAILED",Me[Me.DANGEROUS_NODE_MODULES=31]="DANGEROUS_NODE_MODULES",Me[Me.NODE_GYP_INJECTED=32]="NODE_GYP_INJECTED",Me[Me.AUTHENTICATION_NOT_FOUND=33]="AUTHENTICATION_NOT_FOUND",Me[Me.INVALID_CONFIGURATION_KEY=34]="INVALID_CONFIGURATION_KEY",Me[Me.NETWORK_ERROR=35]="NETWORK_ERROR",Me[Me.LIFECYCLE_SCRIPT=36]="LIFECYCLE_SCRIPT",Me[Me.CONSTRAINTS_MISSING_FIELD=37]="CONSTRAINTS_MISSING_FIELD",Me[Me.CONSTRAINTS_INCOMPATIBLE_FIELD=38]="CONSTRAINTS_INCOMPATIBLE_FIELD",Me[Me.CONSTRAINTS_EXTRANEOUS_FIELD=39]="CONSTRAINTS_EXTRANEOUS_FIELD",Me[Me.CONSTRAINTS_INVALID_FIELD=40]="CONSTRAINTS_INVALID_FIELD",Me[Me.AUTHENTICATION_INVALID=41]="AUTHENTICATION_INVALID",Me[Me.PROLOG_UNKNOWN_ERROR=42]="PROLOG_UNKNOWN_ERROR",Me[Me.PROLOG_SYNTAX_ERROR=43]="PROLOG_SYNTAX_ERROR",Me[Me.PROLOG_EXISTENCE_ERROR=44]="PROLOG_EXISTENCE_ERROR",Me[Me.STACK_OVERFLOW_RESOLUTION=45]="STACK_OVERFLOW_RESOLUTION",Me[Me.AUTOMERGE_FAILED_TO_PARSE=46]="AUTOMERGE_FAILED_TO_PARSE",Me[Me.AUTOMERGE_IMMUTABLE=47]="AUTOMERGE_IMMUTABLE",Me[Me.AUTOMERGE_SUCCESS=48]="AUTOMERGE_SUCCESS",Me[Me.AUTOMERGE_REQUIRED=49]="AUTOMERGE_REQUIRED",Me[Me.DEPRECATED_CLI_SETTINGS=50]="DEPRECATED_CLI_SETTINGS",Me[Me.PLUGIN_NAME_NOT_FOUND=51]="PLUGIN_NAME_NOT_FOUND",Me[Me.INVALID_PLUGIN_REFERENCE=52]="INVALID_PLUGIN_REFERENCE",Me[Me.CONSTRAINTS_AMBIGUITY=53]="CONSTRAINTS_AMBIGUITY",Me[Me.CACHE_OUTSIDE_PROJECT=54]="CACHE_OUTSIDE_PROJECT",Me[Me.IMMUTABLE_INSTALL=55]="IMMUTABLE_INSTALL",Me[Me.IMMUTABLE_CACHE=56]="IMMUTABLE_CACHE",Me[Me.INVALID_MANIFEST=57]="INVALID_MANIFEST",Me[Me.PACKAGE_PREPARATION_FAILED=58]="PACKAGE_PREPARATION_FAILED",Me[Me.INVALID_RANGE_PEER_DEPENDENCY=59]="INVALID_RANGE_PEER_DEPENDENCY",Me[Me.INCOMPATIBLE_PEER_DEPENDENCY=60]="INCOMPATIBLE_PEER_DEPENDENCY",Me[Me.DEPRECATED_PACKAGE=61]="DEPRECATED_PACKAGE",Me[Me.INCOMPATIBLE_OS=62]="INCOMPATIBLE_OS",Me[Me.INCOMPATIBLE_CPU=63]="INCOMPATIBLE_CPU",Me[Me.FROZEN_ARTIFACT_EXCEPTION=64]="FROZEN_ARTIFACT_EXCEPTION",Me[Me.TELEMETRY_NOTICE=65]="TELEMETRY_NOTICE",Me[Me.PATCH_HUNK_FAILED=66]="PATCH_HUNK_FAILED",Me[Me.INVALID_CONFIGURATION_VALUE=67]="INVALID_CONFIGURATION_VALUE",Me[Me.UNUSED_PACKAGE_EXTENSION=68]="UNUSED_PACKAGE_EXTENSION",Me[Me.REDUNDANT_PACKAGE_EXTENSION=69]="REDUNDANT_PACKAGE_EXTENSION",Me[Me.AUTO_NM_SUCCESS=70]="AUTO_NM_SUCCESS",Me[Me.NM_CANT_INSTALL_EXTERNAL_SOFT_LINK=71]="NM_CANT_INSTALL_EXTERNAL_SOFT_LINK",Me[Me.NM_PRESERVE_SYMLINKS_REQUIRED=72]="NM_PRESERVE_SYMLINKS_REQUIRED",Me[Me.UPDATE_LOCKFILE_ONLY_SKIP_LINK=73]="UPDATE_LOCKFILE_ONLY_SKIP_LINK",Me[Me.NM_HARDLINKS_MODE_DOWNGRADED=74]="NM_HARDLINKS_MODE_DOWNGRADED",Me[Me.PROLOG_INSTANTIATION_ERROR=75]="PROLOG_INSTANTIATION_ERROR",Me[Me.INCOMPATIBLE_ARCHITECTURE=76]="INCOMPATIBLE_ARCHITECTURE",Me[Me.GHOST_ARCHITECTURE=77]="GHOST_ARCHITECTURE",Me[Me.RESOLUTION_MISMATCH=78]="RESOLUTION_MISMATCH",Me[Me.PROLOG_LIMIT_EXCEEDED=79]="PROLOG_LIMIT_EXCEEDED",Me[Me.NETWORK_DISABLED=80]="NETWORK_DISABLED",Me[Me.NETWORK_UNSAFE_HTTP=81]="NETWORK_UNSAFE_HTTP",Me[Me.RESOLUTION_FAILED=82]="RESOLUTION_FAILED",Me[Me.AUTOMERGE_GIT_ERROR=83]="AUTOMERGE_GIT_ERROR",Me[Me.CONSTRAINTS_CHECK_FAILED=84]="CONSTRAINTS_CHECK_FAILED",Me[Me.UPDATED_RESOLUTION_RECORD=85]="UPDATED_RESOLUTION_RECORD",Me[Me.EXPLAIN_PEER_DEPENDENCIES_CTA=86]="EXPLAIN_PEER_DEPENDENCIES_CTA",Me[Me.MIGRATION_SUCCESS=87]="MIGRATION_SUCCESS",Me[Me.VERSION_NOTICE=88]="VERSION_NOTICE",Me[Me.TIPS_NOTICE=89]="TIPS_NOTICE",Me[Me.OFFLINE_MODE_ENABLED=90]="OFFLINE_MODE_ENABLED",Me))(wr||{})});var Xw=_((Okt,rz)=>{var gje="2.0.0",dje=Number.MAX_SAFE_INTEGER||9007199254740991,mje=16,yje=250,Eje=["major","premajor","minor","preminor","patch","prepatch","prerelease"];rz.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:mje,MAX_SAFE_BUILD_LENGTH:yje,MAX_SAFE_INTEGER:dje,RELEASE_TYPES:Eje,SEMVER_SPEC_VERSION:gje,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}});var Zw=_((Ukt,nz)=>{var Cje=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...t)=>console.error("SEMVER",...t):()=>{};nz.exports=Cje});var lm=_((Cf,iz)=>{var{MAX_SAFE_COMPONENT_LENGTH:NT,MAX_SAFE_BUILD_LENGTH:wje,MAX_LENGTH:Ije}=Xw(),Bje=Zw();Cf=iz.exports={};var vje=Cf.re=[],Dje=Cf.safeRe=[],$t=Cf.src=[],er=Cf.t={},Pje=0,LT="[a-zA-Z0-9-]",Sje=[["\\s",1],["\\d",Ije],[LT,wje]],bje=t=>{for(let[e,r]of Sje)t=t.split(`${e}*`).join(`${e}{0,${r}}`).split(`${e}+`).join(`${e}{1,${r}}`);return t},jr=(t,e,r)=>{let o=bje(e),a=Pje++;Bje(t,a,e),er[t]=a,$t[a]=e,vje[a]=new RegExp(e,r?"g":void 0),Dje[a]=new RegExp(o,r?"g":void 0)};jr("NUMERICIDENTIFIER","0|[1-9]\\d*");jr("NUMERICIDENTIFIERLOOSE","\\d+");jr("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${LT}*`);jr("MAINVERSION",`(${$t[er.NUMERICIDENTIFIER]})\\.(${$t[er.NUMERICIDENTIFIER]})\\.(${$t[er.NUMERICIDENTIFIER]})`);jr("MAINVERSIONLOOSE",`(${$t[er.NUMERICIDENTIFIERLOOSE]})\\.(${$t[er.NUMERICIDENTIFIERLOOSE]})\\.(${$t[er.NUMERICIDENTIFIERLOOSE]})`);jr("PRERELEASEIDENTIFIER",`(?:${$t[er.NUMERICIDENTIFIER]}|${$t[er.NONNUMERICIDENTIFIER]})`);jr("PRERELEASEIDENTIFIERLOOSE",`(?:${$t[er.NUMERICIDENTIFIERLOOSE]}|${$t[er.NONNUMERICIDENTIFIER]})`);jr("PRERELEASE",`(?:-(${$t[er.PRERELEASEIDENTIFIER]}(?:\\.${$t[er.PRERELEASEIDENTIFIER]})*))`);jr("PRERELEASELOOSE",`(?:-?(${$t[er.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${$t[er.PRERELEASEIDENTIFIERLOOSE]})*))`);jr("BUILDIDENTIFIER",`${LT}+`);jr("BUILD",`(?:\\+(${$t[er.BUILDIDENTIFIER]}(?:\\.${$t[er.BUILDIDENTIFIER]})*))`);jr("FULLPLAIN",`v?${$t[er.MAINVERSION]}${$t[er.PRERELEASE]}?${$t[er.BUILD]}?`);jr("FULL",`^${$t[er.FULLPLAIN]}$`);jr("LOOSEPLAIN",`[v=\\s]*${$t[er.MAINVERSIONLOOSE]}${$t[er.PRERELEASELOOSE]}?${$t[er.BUILD]}?`);jr("LOOSE",`^${$t[er.LOOSEPLAIN]}$`);jr("GTLT","((?:<|>)?=?)");jr("XRANGEIDENTIFIERLOOSE",`${$t[er.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);jr("XRANGEIDENTIFIER",`${$t[er.NUMERICIDENTIFIER]}|x|X|\\*`);jr("XRANGEPLAIN",`[v=\\s]*(${$t[er.XRANGEIDENTIFIER]})(?:\\.(${$t[er.XRANGEIDENTIFIER]})(?:\\.(${$t[er.XRANGEIDENTIFIER]})(?:${$t[er.PRERELEASE]})?${$t[er.BUILD]}?)?)?`);jr("XRANGEPLAINLOOSE",`[v=\\s]*(${$t[er.XRANGEIDENTIFIERLOOSE]})(?:\\.(${$t[er.XRANGEIDENTIFIERLOOSE]})(?:\\.(${$t[er.XRANGEIDENTIFIERLOOSE]})(?:${$t[er.PRERELEASELOOSE]})?${$t[er.BUILD]}?)?)?`);jr("XRANGE",`^${$t[er.GTLT]}\\s*${$t[er.XRANGEPLAIN]}$`);jr("XRANGELOOSE",`^${$t[er.GTLT]}\\s*${$t[er.XRANGEPLAINLOOSE]}$`);jr("COERCEPLAIN",`(^|[^\\d])(\\d{1,${NT}})(?:\\.(\\d{1,${NT}}))?(?:\\.(\\d{1,${NT}}))?`);jr("COERCE",`${$t[er.COERCEPLAIN]}(?:$|[^\\d])`);jr("COERCEFULL",$t[er.COERCEPLAIN]+`(?:${$t[er.PRERELEASE]})?(?:${$t[er.BUILD]})?(?:$|[^\\d])`);jr("COERCERTL",$t[er.COERCE],!0);jr("COERCERTLFULL",$t[er.COERCEFULL],!0);jr("LONETILDE","(?:~>?)");jr("TILDETRIM",`(\\s*)${$t[er.LONETILDE]}\\s+`,!0);Cf.tildeTrimReplace="$1~";jr("TILDE",`^${$t[er.LONETILDE]}${$t[er.XRANGEPLAIN]}$`);jr("TILDELOOSE",`^${$t[er.LONETILDE]}${$t[er.XRANGEPLAINLOOSE]}$`);jr("LONECARET","(?:\\^)");jr("CARETTRIM",`(\\s*)${$t[er.LONECARET]}\\s+`,!0);Cf.caretTrimReplace="$1^";jr("CARET",`^${$t[er.LONECARET]}${$t[er.XRANGEPLAIN]}$`);jr("CARETLOOSE",`^${$t[er.LONECARET]}${$t[er.XRANGEPLAINLOOSE]}$`);jr("COMPARATORLOOSE",`^${$t[er.GTLT]}\\s*(${$t[er.LOOSEPLAIN]})$|^$`);jr("COMPARATOR",`^${$t[er.GTLT]}\\s*(${$t[er.FULLPLAIN]})$|^$`);jr("COMPARATORTRIM",`(\\s*)${$t[er.GTLT]}\\s*(${$t[er.LOOSEPLAIN]}|${$t[er.XRANGEPLAIN]})`,!0);Cf.comparatorTrimReplace="$1$2$3";jr("HYPHENRANGE",`^\\s*(${$t[er.XRANGEPLAIN]})\\s+-\\s+(${$t[er.XRANGEPLAIN]})\\s*$`);jr("HYPHENRANGELOOSE",`^\\s*(${$t[er.XRANGEPLAINLOOSE]})\\s+-\\s+(${$t[er.XRANGEPLAINLOOSE]})\\s*$`);jr("STAR","(<|>)?=?\\s*\\*");jr("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$");jr("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")});var eP=_((_kt,sz)=>{var xje=Object.freeze({loose:!0}),kje=Object.freeze({}),Qje=t=>t?typeof t!="object"?xje:t:kje;sz.exports=Qje});var MT=_((Hkt,lz)=>{var oz=/^[0-9]+$/,az=(t,e)=>{let r=oz.test(t),o=oz.test(e);return r&&o&&(t=+t,e=+e),t===e?0:r&&!o?-1:o&&!r?1:t<e?-1:1},Fje=(t,e)=>az(e,t);lz.exports={compareIdentifiers:az,rcompareIdentifiers:Fje}});var Po=_((qkt,fz)=>{var tP=Zw(),{MAX_LENGTH:cz,MAX_SAFE_INTEGER:rP}=Xw(),{safeRe:uz,t:Az}=lm(),Rje=eP(),{compareIdentifiers:cm}=MT(),OT=class t{constructor(e,r){if(r=Rje(r),e instanceof t){if(e.loose===!!r.loose&&e.includePrerelease===!!r.includePrerelease)return e;e=e.version}else if(typeof e!="string")throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>cz)throw new TypeError(`version is longer than ${cz} characters`);tP("SemVer",e,r),this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease;let o=e.trim().match(r.loose?uz[Az.LOOSE]:uz[Az.FULL]);if(!o)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+o[1],this.minor=+o[2],this.patch=+o[3],this.major>rP||this.major<0)throw new TypeError("Invalid major version");if(this.minor>rP||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>rP||this.patch<0)throw new TypeError("Invalid patch version");o[4]?this.prerelease=o[4].split(".").map(a=>{if(/^[0-9]+$/.test(a)){let n=+a;if(n>=0&&n<rP)return n}return a}):this.prerelease=[],this.build=o[5]?o[5].split("."):[],this.format()}format(){return this.version=`${this.major}.${this.minor}.${this.patch}`,this.prerelease.length&&(this.version+=`-${this.prerelease.join(".")}`),this.version}toString(){return this.version}compare(e){if(tP("SemVer.compare",this.version,this.options,e),!(e instanceof t)){if(typeof e=="string"&&e===this.version)return 0;e=new t(e,this.options)}return e.version===this.version?0:this.compareMain(e)||this.comparePre(e)}compareMain(e){return e instanceof t||(e=new t(e,this.options)),cm(this.major,e.major)||cm(this.minor,e.minor)||cm(this.patch,e.patch)}comparePre(e){if(e instanceof t||(e=new t(e,this.options)),this.prerelease.length&&!e.prerelease.length)return-1;if(!this.prerelease.length&&e.prerelease.length)return 1;if(!this.prerelease.length&&!e.prerelease.length)return 0;let r=0;do{let o=this.prerelease[r],a=e.prerelease[r];if(tP("prerelease compare",r,o,a),o===void 0&&a===void 0)return 0;if(a===void 0)return 1;if(o===void 0)return-1;if(o===a)continue;return cm(o,a)}while(++r)}compareBuild(e){e instanceof t||(e=new t(e,this.options));let r=0;do{let o=this.build[r],a=e.build[r];if(tP("prerelease compare",r,o,a),o===void 0&&a===void 0)return 0;if(a===void 0)return 1;if(o===void 0)return-1;if(o===a)continue;return cm(o,a)}while(++r)}inc(e,r,o){switch(e){case"premajor":this.prerelease.length=0,this.patch=0,this.minor=0,this.major++,this.inc("pre",r,o);break;case"preminor":this.prerelease.length=0,this.patch=0,this.minor++,this.inc("pre",r,o);break;case"prepatch":this.prerelease.length=0,this.inc("patch",r,o),this.inc("pre",r,o);break;case"prerelease":this.prerelease.length===0&&this.inc("patch",r,o),this.inc("pre",r,o);break;case"major":(this.minor!==0||this.patch!==0||this.prerelease.length===0)&&this.major++,this.minor=0,this.patch=0,this.prerelease=[];break;case"minor":(this.patch!==0||this.prerelease.length===0)&&this.minor++,this.patch=0,this.prerelease=[];break;case"patch":this.prerelease.length===0&&this.patch++,this.prerelease=[];break;case"pre":{let a=Number(o)?1:0;if(!r&&o===!1)throw new Error("invalid increment argument: identifier is empty");if(this.prerelease.length===0)this.prerelease=[a];else{let n=this.prerelease.length;for(;--n>=0;)typeof this.prerelease[n]=="number"&&(this.prerelease[n]++,n=-2);if(n===-1){if(r===this.prerelease.join(".")&&o===!1)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(a)}}if(r){let n=[r,a];o===!1&&(n=[r]),cm(this.prerelease[0],r)===0?isNaN(this.prerelease[1])&&(this.prerelease=n):this.prerelease=n}break}default:throw new Error(`invalid increment argument: ${e}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}};fz.exports=OT});var tg=_((jkt,hz)=>{var pz=Po(),Tje=(t,e,r=!1)=>{if(t instanceof pz)return t;try{return new pz(t,e)}catch(o){if(!r)return null;throw o}};hz.exports=Tje});var dz=_((Gkt,gz)=>{var Nje=tg(),Lje=(t,e)=>{let r=Nje(t,e);return r?r.version:null};gz.exports=Lje});var yz=_((Ykt,mz)=>{var Mje=tg(),Oje=(t,e)=>{let r=Mje(t.trim().replace(/^[=v]+/,""),e);return r?r.version:null};mz.exports=Oje});var wz=_((Wkt,Cz)=>{var Ez=Po(),Uje=(t,e,r,o,a)=>{typeof r=="string"&&(a=o,o=r,r=void 0);try{return new Ez(t instanceof Ez?t.version:t,r).inc(e,o,a).version}catch{return null}};Cz.exports=Uje});var vz=_((Kkt,Bz)=>{var Iz=tg(),_je=(t,e)=>{let r=Iz(t,null,!0),o=Iz(e,null,!0),a=r.compare(o);if(a===0)return null;let n=a>0,u=n?r:o,A=n?o:r,p=!!u.prerelease.length;if(!!A.prerelease.length&&!p)return!A.patch&&!A.minor?"major":u.patch?"patch":u.minor?"minor":"major";let E=p?"pre":"";return r.major!==o.major?E+"major":r.minor!==o.minor?E+"minor":r.patch!==o.patch?E+"patch":"prerelease"};Bz.exports=_je});var Pz=_((Vkt,Dz)=>{var Hje=Po(),qje=(t,e)=>new Hje(t,e).major;Dz.exports=qje});var bz=_((zkt,Sz)=>{var jje=Po(),Gje=(t,e)=>new jje(t,e).minor;Sz.exports=Gje});var kz=_((Jkt,xz)=>{var Yje=Po(),Wje=(t,e)=>new Yje(t,e).patch;xz.exports=Wje});var Fz=_((Xkt,Qz)=>{var Kje=tg(),Vje=(t,e)=>{let r=Kje(t,e);return r&&r.prerelease.length?r.prerelease:null};Qz.exports=Vje});var Ll=_((Zkt,Tz)=>{var Rz=Po(),zje=(t,e,r)=>new Rz(t,r).compare(new Rz(e,r));Tz.exports=zje});var Lz=_(($kt,Nz)=>{var Jje=Ll(),Xje=(t,e,r)=>Jje(e,t,r);Nz.exports=Xje});var Oz=_((eQt,Mz)=>{var Zje=Ll(),$je=(t,e)=>Zje(t,e,!0);Mz.exports=$je});var nP=_((tQt,_z)=>{var Uz=Po(),e5e=(t,e,r)=>{let o=new Uz(t,r),a=new Uz(e,r);return o.compare(a)||o.compareBuild(a)};_z.exports=e5e});var qz=_((rQt,Hz)=>{var t5e=nP(),r5e=(t,e)=>t.sort((r,o)=>t5e(r,o,e));Hz.exports=r5e});var Gz=_((nQt,jz)=>{var n5e=nP(),i5e=(t,e)=>t.sort((r,o)=>n5e(o,r,e));jz.exports=i5e});var $w=_((iQt,Yz)=>{var s5e=Ll(),o5e=(t,e,r)=>s5e(t,e,r)>0;Yz.exports=o5e});var iP=_((sQt,Wz)=>{var a5e=Ll(),l5e=(t,e,r)=>a5e(t,e,r)<0;Wz.exports=l5e});var UT=_((oQt,Kz)=>{var c5e=Ll(),u5e=(t,e,r)=>c5e(t,e,r)===0;Kz.exports=u5e});var _T=_((aQt,Vz)=>{var A5e=Ll(),f5e=(t,e,r)=>A5e(t,e,r)!==0;Vz.exports=f5e});var sP=_((lQt,zz)=>{var p5e=Ll(),h5e=(t,e,r)=>p5e(t,e,r)>=0;zz.exports=h5e});var oP=_((cQt,Jz)=>{var g5e=Ll(),d5e=(t,e,r)=>g5e(t,e,r)<=0;Jz.exports=d5e});var HT=_((uQt,Xz)=>{var m5e=UT(),y5e=_T(),E5e=$w(),C5e=sP(),w5e=iP(),I5e=oP(),B5e=(t,e,r,o)=>{switch(e){case"===":return typeof t=="object"&&(t=t.version),typeof r=="object"&&(r=r.version),t===r;case"!==":return typeof t=="object"&&(t=t.version),typeof r=="object"&&(r=r.version),t!==r;case"":case"=":case"==":return m5e(t,r,o);case"!=":return y5e(t,r,o);case">":return E5e(t,r,o);case">=":return C5e(t,r,o);case"<":return w5e(t,r,o);case"<=":return I5e(t,r,o);default:throw new TypeError(`Invalid operator: ${e}`)}};Xz.exports=B5e});var $z=_((AQt,Zz)=>{var v5e=Po(),D5e=tg(),{safeRe:aP,t:lP}=lm(),P5e=(t,e)=>{if(t instanceof v5e)return t;if(typeof t=="number"&&(t=String(t)),typeof t!="string")return null;e=e||{};let r=null;if(!e.rtl)r=t.match(e.includePrerelease?aP[lP.COERCEFULL]:aP[lP.COERCE]);else{let p=e.includePrerelease?aP[lP.COERCERTLFULL]:aP[lP.COERCERTL],h;for(;(h=p.exec(t))&&(!r||r.index+r[0].length!==t.length);)(!r||h.index+h[0].length!==r.index+r[0].length)&&(r=h),p.lastIndex=h.index+h[1].length+h[2].length;p.lastIndex=-1}if(r===null)return null;let o=r[2],a=r[3]||"0",n=r[4]||"0",u=e.includePrerelease&&r[5]?`-${r[5]}`:"",A=e.includePrerelease&&r[6]?`+${r[6]}`:"";return D5e(`${o}.${a}.${n}${u}${A}`,e)};Zz.exports=P5e});var tJ=_((fQt,eJ)=>{"use strict";eJ.exports=function(t){t.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var cP=_((pQt,rJ)=>{"use strict";rJ.exports=Cn;Cn.Node=rg;Cn.create=Cn;function Cn(t){var e=this;if(e instanceof Cn||(e=new Cn),e.tail=null,e.head=null,e.length=0,t&&typeof t.forEach=="function")t.forEach(function(a){e.push(a)});else if(arguments.length>0)for(var r=0,o=arguments.length;r<o;r++)e.push(arguments[r]);return e}Cn.prototype.removeNode=function(t){if(t.list!==this)throw new Error("removing node which does not belong to this list");var e=t.next,r=t.prev;return e&&(e.prev=r),r&&(r.next=e),t===this.head&&(this.head=e),t===this.tail&&(this.tail=r),t.list.length--,t.next=null,t.prev=null,t.list=null,e};Cn.prototype.unshiftNode=function(t){if(t!==this.head){t.list&&t.list.removeNode(t);var e=this.head;t.list=this,t.next=e,e&&(e.prev=t),this.head=t,this.tail||(this.tail=t),this.length++}};Cn.prototype.pushNode=function(t){if(t!==this.tail){t.list&&t.list.removeNode(t);var e=this.tail;t.list=this,t.prev=e,e&&(e.next=t),this.tail=t,this.head||(this.head=t),this.length++}};Cn.prototype.push=function(){for(var t=0,e=arguments.length;t<e;t++)b5e(this,arguments[t]);return this.length};Cn.prototype.unshift=function(){for(var t=0,e=arguments.length;t<e;t++)x5e(this,arguments[t]);return this.length};Cn.prototype.pop=function(){if(this.tail){var t=this.tail.value;return this.tail=this.tail.prev,this.tail?this.tail.next=null:this.head=null,this.length--,t}};Cn.prototype.shift=function(){if(this.head){var t=this.head.value;return this.head=this.head.next,this.head?this.head.prev=null:this.tail=null,this.length--,t}};Cn.prototype.forEach=function(t,e){e=e||this;for(var r=this.head,o=0;r!==null;o++)t.call(e,r.value,o,this),r=r.next};Cn.prototype.forEachReverse=function(t,e){e=e||this;for(var r=this.tail,o=this.length-1;r!==null;o--)t.call(e,r.value,o,this),r=r.prev};Cn.prototype.get=function(t){for(var e=0,r=this.head;r!==null&&e<t;e++)r=r.next;if(e===t&&r!==null)return r.value};Cn.prototype.getReverse=function(t){for(var e=0,r=this.tail;r!==null&&e<t;e++)r=r.prev;if(e===t&&r!==null)return r.value};Cn.prototype.map=function(t,e){e=e||this;for(var r=new Cn,o=this.head;o!==null;)r.push(t.call(e,o.value,this)),o=o.next;return r};Cn.prototype.mapReverse=function(t,e){e=e||this;for(var r=new Cn,o=this.tail;o!==null;)r.push(t.call(e,o.value,this)),o=o.prev;return r};Cn.prototype.reduce=function(t,e){var r,o=this.head;if(arguments.length>1)r=e;else if(this.head)o=this.head.next,r=this.head.value;else throw new TypeError("Reduce of empty list with no initial value");for(var a=0;o!==null;a++)r=t(r,o.value,a),o=o.next;return r};Cn.prototype.reduceReverse=function(t,e){var r,o=this.tail;if(arguments.length>1)r=e;else if(this.tail)o=this.tail.prev,r=this.tail.value;else throw new TypeError("Reduce of empty list with no initial value");for(var a=this.length-1;o!==null;a--)r=t(r,o.value,a),o=o.prev;return r};Cn.prototype.toArray=function(){for(var t=new Array(this.length),e=0,r=this.head;r!==null;e++)t[e]=r.value,r=r.next;return t};Cn.prototype.toArrayReverse=function(){for(var t=new Array(this.length),e=0,r=this.tail;r!==null;e++)t[e]=r.value,r=r.prev;return t};Cn.prototype.slice=function(t,e){e=e||this.length,e<0&&(e+=this.length),t=t||0,t<0&&(t+=this.length);var r=new Cn;if(e<t||e<0)return r;t<0&&(t=0),e>this.length&&(e=this.length);for(var o=0,a=this.head;a!==null&&o<t;o++)a=a.next;for(;a!==null&&o<e;o++,a=a.next)r.push(a.value);return r};Cn.prototype.sliceReverse=function(t,e){e=e||this.length,e<0&&(e+=this.length),t=t||0,t<0&&(t+=this.length);var r=new Cn;if(e<t||e<0)return r;t<0&&(t=0),e>this.length&&(e=this.length);for(var o=this.length,a=this.tail;a!==null&&o>e;o--)a=a.prev;for(;a!==null&&o>t;o--,a=a.prev)r.push(a.value);return r};Cn.prototype.splice=function(t,e,...r){t>this.length&&(t=this.length-1),t<0&&(t=this.length+t);for(var o=0,a=this.head;a!==null&&o<t;o++)a=a.next;for(var n=[],o=0;a&&o<e;o++)n.push(a.value),a=this.removeNode(a);a===null&&(a=this.tail),a!==this.head&&a!==this.tail&&(a=a.prev);for(var o=0;o<r.length;o++)a=S5e(this,a,r[o]);return n};Cn.prototype.reverse=function(){for(var t=this.head,e=this.tail,r=t;r!==null;r=r.prev){var o=r.prev;r.prev=r.next,r.next=o}return this.head=e,this.tail=t,this};function S5e(t,e,r){var o=e===t.head?new rg(r,null,e,t):new rg(r,e,e.next,t);return o.next===null&&(t.tail=o),o.prev===null&&(t.head=o),t.length++,o}function b5e(t,e){t.tail=new rg(e,t.tail,null,t),t.head||(t.head=t.tail),t.length++}function x5e(t,e){t.head=new rg(e,null,t.head,t),t.tail||(t.tail=t.head),t.length++}function rg(t,e,r,o){if(!(this instanceof rg))return new rg(t,e,r,o);this.list=o,this.value=t,e?(e.next=this,this.prev=e):this.prev=null,r?(r.prev=this,this.next=r):this.next=null}try{tJ()(Cn)}catch{}});var aJ=_((hQt,oJ)=>{"use strict";var k5e=cP(),ng=Symbol("max"),If=Symbol("length"),um=Symbol("lengthCalculator"),tI=Symbol("allowStale"),ig=Symbol("maxAge"),wf=Symbol("dispose"),nJ=Symbol("noDisposeOnSet"),Qs=Symbol("lruList"),Uc=Symbol("cache"),sJ=Symbol("updateAgeOnGet"),qT=()=>1,GT=class{constructor(e){if(typeof e=="number"&&(e={max:e}),e||(e={}),e.max&&(typeof e.max!="number"||e.max<0))throw new TypeError("max must be a non-negative number");let r=this[ng]=e.max||1/0,o=e.length||qT;if(this[um]=typeof o!="function"?qT:o,this[tI]=e.stale||!1,e.maxAge&&typeof e.maxAge!="number")throw new TypeError("maxAge must be a number");this[ig]=e.maxAge||0,this[wf]=e.dispose,this[nJ]=e.noDisposeOnSet||!1,this[sJ]=e.updateAgeOnGet||!1,this.reset()}set max(e){if(typeof e!="number"||e<0)throw new TypeError("max must be a non-negative number");this[ng]=e||1/0,eI(this)}get max(){return this[ng]}set allowStale(e){this[tI]=!!e}get allowStale(){return this[tI]}set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be a non-negative number");this[ig]=e,eI(this)}get maxAge(){return this[ig]}set lengthCalculator(e){typeof e!="function"&&(e=qT),e!==this[um]&&(this[um]=e,this[If]=0,this[Qs].forEach(r=>{r.length=this[um](r.value,r.key),this[If]+=r.length})),eI(this)}get lengthCalculator(){return this[um]}get length(){return this[If]}get itemCount(){return this[Qs].length}rforEach(e,r){r=r||this;for(let o=this[Qs].tail;o!==null;){let a=o.prev;iJ(this,e,o,r),o=a}}forEach(e,r){r=r||this;for(let o=this[Qs].head;o!==null;){let a=o.next;iJ(this,e,o,r),o=a}}keys(){return this[Qs].toArray().map(e=>e.key)}values(){return this[Qs].toArray().map(e=>e.value)}reset(){this[wf]&&this[Qs]&&this[Qs].length&&this[Qs].forEach(e=>this[wf](e.key,e.value)),this[Uc]=new Map,this[Qs]=new k5e,this[If]=0}dump(){return this[Qs].map(e=>uP(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[Qs]}set(e,r,o){if(o=o||this[ig],o&&typeof o!="number")throw new TypeError("maxAge must be a number");let a=o?Date.now():0,n=this[um](r,e);if(this[Uc].has(e)){if(n>this[ng])return Am(this,this[Uc].get(e)),!1;let p=this[Uc].get(e).value;return this[wf]&&(this[nJ]||this[wf](e,p.value)),p.now=a,p.maxAge=o,p.value=r,this[If]+=n-p.length,p.length=n,this.get(e),eI(this),!0}let u=new YT(e,r,n,a,o);return u.length>this[ng]?(this[wf]&&this[wf](e,r),!1):(this[If]+=u.length,this[Qs].unshift(u),this[Uc].set(e,this[Qs].head),eI(this),!0)}has(e){if(!this[Uc].has(e))return!1;let r=this[Uc].get(e).value;return!uP(this,r)}get(e){return jT(this,e,!0)}peek(e){return jT(this,e,!1)}pop(){let e=this[Qs].tail;return e?(Am(this,e),e.value):null}del(e){Am(this,this[Uc].get(e))}load(e){this.reset();let r=Date.now();for(let o=e.length-1;o>=0;o--){let a=e[o],n=a.e||0;if(n===0)this.set(a.k,a.v);else{let u=n-r;u>0&&this.set(a.k,a.v,u)}}}prune(){this[Uc].forEach((e,r)=>jT(this,r,!1))}},jT=(t,e,r)=>{let o=t[Uc].get(e);if(o){let a=o.value;if(uP(t,a)){if(Am(t,o),!t[tI])return}else r&&(t[sJ]&&(o.value.now=Date.now()),t[Qs].unshiftNode(o));return a.value}},uP=(t,e)=>{if(!e||!e.maxAge&&!t[ig])return!1;let r=Date.now()-e.now;return e.maxAge?r>e.maxAge:t[ig]&&r>t[ig]},eI=t=>{if(t[If]>t[ng])for(let e=t[Qs].tail;t[If]>t[ng]&&e!==null;){let r=e.prev;Am(t,e),e=r}},Am=(t,e)=>{if(e){let r=e.value;t[wf]&&t[wf](r.key,r.value),t[If]-=r.length,t[Uc].delete(r.key),t[Qs].removeNode(e)}},YT=class{constructor(e,r,o,a,n){this.key=e,this.value=r,this.length=o,this.now=a,this.maxAge=n||0}},iJ=(t,e,r,o)=>{let a=r.value;uP(t,a)&&(Am(t,r),t[tI]||(a=void 0)),a&&e.call(o,a.value,a.key,t)};oJ.exports=GT});var Ml=_((gQt,AJ)=>{var WT=class t{constructor(e,r){if(r=F5e(r),e instanceof t)return e.loose===!!r.loose&&e.includePrerelease===!!r.includePrerelease?e:new t(e.raw,r);if(e instanceof KT)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease,this.raw=e.trim().split(/\s+/).join(" "),this.set=this.raw.split("||").map(o=>this.parseRange(o.trim())).filter(o=>o.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){let o=this.set[0];if(this.set=this.set.filter(a=>!cJ(a[0])),this.set.length===0)this.set=[o];else if(this.set.length>1){for(let a of this.set)if(a.length===1&&U5e(a[0])){this.set=[a];break}}}this.format()}format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){let o=((this.options.includePrerelease&&M5e)|(this.options.loose&&O5e))+":"+e,a=lJ.get(o);if(a)return a;let n=this.options.loose,u=n?Sa[Xo.HYPHENRANGELOOSE]:Sa[Xo.HYPHENRANGE];e=e.replace(u,z5e(this.options.includePrerelease)),ci("hyphen replace",e),e=e.replace(Sa[Xo.COMPARATORTRIM],T5e),ci("comparator trim",e),e=e.replace(Sa[Xo.TILDETRIM],N5e),ci("tilde trim",e),e=e.replace(Sa[Xo.CARETTRIM],L5e),ci("caret trim",e);let A=e.split(" ").map(I=>_5e(I,this.options)).join(" ").split(/\s+/).map(I=>V5e(I,this.options));n&&(A=A.filter(I=>(ci("loose invalid filter",I,this.options),!!I.match(Sa[Xo.COMPARATORLOOSE])))),ci("range list",A);let p=new Map,h=A.map(I=>new KT(I,this.options));for(let I of h){if(cJ(I))return[I];p.set(I.value,I)}p.size>1&&p.has("")&&p.delete("");let E=[...p.values()];return lJ.set(o,E),E}intersects(e,r){if(!(e instanceof t))throw new TypeError("a Range is required");return this.set.some(o=>uJ(o,r)&&e.set.some(a=>uJ(a,r)&&o.every(n=>a.every(u=>n.intersects(u,r)))))}test(e){if(!e)return!1;if(typeof e=="string")try{e=new R5e(e,this.options)}catch{return!1}for(let r=0;r<this.set.length;r++)if(J5e(this.set[r],e,this.options))return!0;return!1}};AJ.exports=WT;var Q5e=aJ(),lJ=new Q5e({max:1e3}),F5e=eP(),KT=rI(),ci=Zw(),R5e=Po(),{safeRe:Sa,t:Xo,comparatorTrimReplace:T5e,tildeTrimReplace:N5e,caretTrimReplace:L5e}=lm(),{FLAG_INCLUDE_PRERELEASE:M5e,FLAG_LOOSE:O5e}=Xw(),cJ=t=>t.value==="<0.0.0-0",U5e=t=>t.value==="",uJ=(t,e)=>{let r=!0,o=t.slice(),a=o.pop();for(;r&&o.length;)r=o.every(n=>a.intersects(n,e)),a=o.pop();return r},_5e=(t,e)=>(ci("comp",t,e),t=j5e(t,e),ci("caret",t),t=H5e(t,e),ci("tildes",t),t=Y5e(t,e),ci("xrange",t),t=K5e(t,e),ci("stars",t),t),Zo=t=>!t||t.toLowerCase()==="x"||t==="*",H5e=(t,e)=>t.trim().split(/\s+/).map(r=>q5e(r,e)).join(" "),q5e=(t,e)=>{let r=e.loose?Sa[Xo.TILDELOOSE]:Sa[Xo.TILDE];return t.replace(r,(o,a,n,u,A)=>{ci("tilde",t,o,a,n,u,A);let p;return Zo(a)?p="":Zo(n)?p=`>=${a}.0.0 <${+a+1}.0.0-0`:Zo(u)?p=`>=${a}.${n}.0 <${a}.${+n+1}.0-0`:A?(ci("replaceTilde pr",A),p=`>=${a}.${n}.${u}-${A} <${a}.${+n+1}.0-0`):p=`>=${a}.${n}.${u} <${a}.${+n+1}.0-0`,ci("tilde return",p),p})},j5e=(t,e)=>t.trim().split(/\s+/).map(r=>G5e(r,e)).join(" "),G5e=(t,e)=>{ci("caret",t,e);let r=e.loose?Sa[Xo.CARETLOOSE]:Sa[Xo.CARET],o=e.includePrerelease?"-0":"";return t.replace(r,(a,n,u,A,p)=>{ci("caret",t,a,n,u,A,p);let h;return Zo(n)?h="":Zo(u)?h=`>=${n}.0.0${o} <${+n+1}.0.0-0`:Zo(A)?n==="0"?h=`>=${n}.${u}.0${o} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.0${o} <${+n+1}.0.0-0`:p?(ci("replaceCaret pr",p),n==="0"?u==="0"?h=`>=${n}.${u}.${A}-${p} <${n}.${u}.${+A+1}-0`:h=`>=${n}.${u}.${A}-${p} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.${A}-${p} <${+n+1}.0.0-0`):(ci("no pr"),n==="0"?u==="0"?h=`>=${n}.${u}.${A}${o} <${n}.${u}.${+A+1}-0`:h=`>=${n}.${u}.${A}${o} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.${A} <${+n+1}.0.0-0`),ci("caret return",h),h})},Y5e=(t,e)=>(ci("replaceXRanges",t,e),t.split(/\s+/).map(r=>W5e(r,e)).join(" ")),W5e=(t,e)=>{t=t.trim();let r=e.loose?Sa[Xo.XRANGELOOSE]:Sa[Xo.XRANGE];return t.replace(r,(o,a,n,u,A,p)=>{ci("xRange",t,o,a,n,u,A,p);let h=Zo(n),E=h||Zo(u),I=E||Zo(A),v=I;return a==="="&&v&&(a=""),p=e.includePrerelease?"-0":"",h?a===">"||a==="<"?o="<0.0.0-0":o="*":a&&v?(E&&(u=0),A=0,a===">"?(a=">=",E?(n=+n+1,u=0,A=0):(u=+u+1,A=0)):a==="<="&&(a="<",E?n=+n+1:u=+u+1),a==="<"&&(p="-0"),o=`${a+n}.${u}.${A}${p}`):E?o=`>=${n}.0.0${p} <${+n+1}.0.0-0`:I&&(o=`>=${n}.${u}.0${p} <${n}.${+u+1}.0-0`),ci("xRange return",o),o})},K5e=(t,e)=>(ci("replaceStars",t,e),t.trim().replace(Sa[Xo.STAR],"")),V5e=(t,e)=>(ci("replaceGTE0",t,e),t.trim().replace(Sa[e.includePrerelease?Xo.GTE0PRE:Xo.GTE0],"")),z5e=t=>(e,r,o,a,n,u,A,p,h,E,I,v,x)=>(Zo(o)?r="":Zo(a)?r=`>=${o}.0.0${t?"-0":""}`:Zo(n)?r=`>=${o}.${a}.0${t?"-0":""}`:u?r=`>=${r}`:r=`>=${r}${t?"-0":""}`,Zo(h)?p="":Zo(E)?p=`<${+h+1}.0.0-0`:Zo(I)?p=`<${h}.${+E+1}.0-0`:v?p=`<=${h}.${E}.${I}-${v}`:t?p=`<${h}.${E}.${+I+1}-0`:p=`<=${p}`,`${r} ${p}`.trim()),J5e=(t,e,r)=>{for(let o=0;o<t.length;o++)if(!t[o].test(e))return!1;if(e.prerelease.length&&!r.includePrerelease){for(let o=0;o<t.length;o++)if(ci(t[o].semver),t[o].semver!==KT.ANY&&t[o].semver.prerelease.length>0){let a=t[o].semver;if(a.major===e.major&&a.minor===e.minor&&a.patch===e.patch)return!0}return!1}return!0}});var rI=_((dQt,mJ)=>{var nI=Symbol("SemVer ANY"),JT=class t{static get ANY(){return nI}constructor(e,r){if(r=fJ(r),e instanceof t){if(e.loose===!!r.loose)return e;e=e.value}e=e.trim().split(/\s+/).join(" "),zT("comparator",e,r),this.options=r,this.loose=!!r.loose,this.parse(e),this.semver===nI?this.value="":this.value=this.operator+this.semver.version,zT("comp",this)}parse(e){let r=this.options.loose?pJ[hJ.COMPARATORLOOSE]:pJ[hJ.COMPARATOR],o=e.match(r);if(!o)throw new TypeError(`Invalid comparator: ${e}`);this.operator=o[1]!==void 0?o[1]:"",this.operator==="="&&(this.operator=""),o[2]?this.semver=new gJ(o[2],this.options.loose):this.semver=nI}toString(){return this.value}test(e){if(zT("Comparator.test",e,this.options.loose),this.semver===nI||e===nI)return!0;if(typeof e=="string")try{e=new gJ(e,this.options)}catch{return!1}return VT(e,this.operator,this.semver,this.options)}intersects(e,r){if(!(e instanceof t))throw new TypeError("a Comparator is required");return this.operator===""?this.value===""?!0:new dJ(e.value,r).test(this.value):e.operator===""?e.value===""?!0:new dJ(this.value,r).test(e.semver):(r=fJ(r),r.includePrerelease&&(this.value==="<0.0.0-0"||e.value==="<0.0.0-0")||!r.includePrerelease&&(this.value.startsWith("<0.0.0")||e.value.startsWith("<0.0.0"))?!1:!!(this.operator.startsWith(">")&&e.operator.startsWith(">")||this.operator.startsWith("<")&&e.operator.startsWith("<")||this.semver.version===e.semver.version&&this.operator.includes("=")&&e.operator.includes("=")||VT(this.semver,"<",e.semver,r)&&this.operator.startsWith(">")&&e.operator.startsWith("<")||VT(this.semver,">",e.semver,r)&&this.operator.startsWith("<")&&e.operator.startsWith(">")))}};mJ.exports=JT;var fJ=eP(),{safeRe:pJ,t:hJ}=lm(),VT=HT(),zT=Zw(),gJ=Po(),dJ=Ml()});var iI=_((mQt,yJ)=>{var X5e=Ml(),Z5e=(t,e,r)=>{try{e=new X5e(e,r)}catch{return!1}return e.test(t)};yJ.exports=Z5e});var CJ=_((yQt,EJ)=>{var $5e=Ml(),eGe=(t,e)=>new $5e(t,e).set.map(r=>r.map(o=>o.value).join(" ").trim().split(" "));EJ.exports=eGe});var IJ=_((EQt,wJ)=>{var tGe=Po(),rGe=Ml(),nGe=(t,e,r)=>{let o=null,a=null,n=null;try{n=new rGe(e,r)}catch{return null}return t.forEach(u=>{n.test(u)&&(!o||a.compare(u)===-1)&&(o=u,a=new tGe(o,r))}),o};wJ.exports=nGe});var vJ=_((CQt,BJ)=>{var iGe=Po(),sGe=Ml(),oGe=(t,e,r)=>{let o=null,a=null,n=null;try{n=new sGe(e,r)}catch{return null}return t.forEach(u=>{n.test(u)&&(!o||a.compare(u)===1)&&(o=u,a=new iGe(o,r))}),o};BJ.exports=oGe});var SJ=_((wQt,PJ)=>{var XT=Po(),aGe=Ml(),DJ=$w(),lGe=(t,e)=>{t=new aGe(t,e);let r=new XT("0.0.0");if(t.test(r)||(r=new XT("0.0.0-0"),t.test(r)))return r;r=null;for(let o=0;o<t.set.length;++o){let a=t.set[o],n=null;a.forEach(u=>{let A=new XT(u.semver.version);switch(u.operator){case">":A.prerelease.length===0?A.patch++:A.prerelease.push(0),A.raw=A.format();case"":case">=":(!n||DJ(A,n))&&(n=A);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${u.operator}`)}}),n&&(!r||DJ(r,n))&&(r=n)}return r&&t.test(r)?r:null};PJ.exports=lGe});var xJ=_((IQt,bJ)=>{var cGe=Ml(),uGe=(t,e)=>{try{return new cGe(t,e).range||"*"}catch{return null}};bJ.exports=uGe});var AP=_((BQt,RJ)=>{var AGe=Po(),FJ=rI(),{ANY:fGe}=FJ,pGe=Ml(),hGe=iI(),kJ=$w(),QJ=iP(),gGe=oP(),dGe=sP(),mGe=(t,e,r,o)=>{t=new AGe(t,o),e=new pGe(e,o);let a,n,u,A,p;switch(r){case">":a=kJ,n=gGe,u=QJ,A=">",p=">=";break;case"<":a=QJ,n=dGe,u=kJ,A="<",p="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(hGe(t,e,o))return!1;for(let h=0;h<e.set.length;++h){let E=e.set[h],I=null,v=null;if(E.forEach(x=>{x.semver===fGe&&(x=new FJ(">=0.0.0")),I=I||x,v=v||x,a(x.semver,I.semver,o)?I=x:u(x.semver,v.semver,o)&&(v=x)}),I.operator===A||I.operator===p||(!v.operator||v.operator===A)&&n(t,v.semver))return!1;if(v.operator===p&&u(t,v.semver))return!1}return!0};RJ.exports=mGe});var NJ=_((vQt,TJ)=>{var yGe=AP(),EGe=(t,e,r)=>yGe(t,e,">",r);TJ.exports=EGe});var MJ=_((DQt,LJ)=>{var CGe=AP(),wGe=(t,e,r)=>CGe(t,e,"<",r);LJ.exports=wGe});var _J=_((PQt,UJ)=>{var OJ=Ml(),IGe=(t,e,r)=>(t=new OJ(t,r),e=new OJ(e,r),t.intersects(e,r));UJ.exports=IGe});var qJ=_((SQt,HJ)=>{var BGe=iI(),vGe=Ll();HJ.exports=(t,e,r)=>{let o=[],a=null,n=null,u=t.sort((E,I)=>vGe(E,I,r));for(let E of u)BGe(E,e,r)?(n=E,a||(a=E)):(n&&o.push([a,n]),n=null,a=null);a&&o.push([a,null]);let A=[];for(let[E,I]of o)E===I?A.push(E):!I&&E===u[0]?A.push("*"):I?E===u[0]?A.push(`<=${I}`):A.push(`${E} - ${I}`):A.push(`>=${E}`);let p=A.join(" || "),h=typeof e.raw=="string"?e.raw:String(e);return p.length<h.length?p:e}});var VJ=_((bQt,KJ)=>{var jJ=Ml(),$T=rI(),{ANY:ZT}=$T,sI=iI(),eN=Ll(),DGe=(t,e,r={})=>{if(t===e)return!0;t=new jJ(t,r),e=new jJ(e,r);let o=!1;e:for(let a of t.set){for(let n of e.set){let u=SGe(a,n,r);if(o=o||u!==null,u)continue e}if(o)return!1}return!0},PGe=[new $T(">=0.0.0-0")],GJ=[new $T(">=0.0.0")],SGe=(t,e,r)=>{if(t===e)return!0;if(t.length===1&&t[0].semver===ZT){if(e.length===1&&e[0].semver===ZT)return!0;r.includePrerelease?t=PGe:t=GJ}if(e.length===1&&e[0].semver===ZT){if(r.includePrerelease)return!0;e=GJ}let o=new Set,a,n;for(let x of t)x.operator===">"||x.operator===">="?a=YJ(a,x,r):x.operator==="<"||x.operator==="<="?n=WJ(n,x,r):o.add(x.semver);if(o.size>1)return null;let u;if(a&&n){if(u=eN(a.semver,n.semver,r),u>0)return null;if(u===0&&(a.operator!==">="||n.operator!=="<="))return null}for(let x of o){if(a&&!sI(x,String(a),r)||n&&!sI(x,String(n),r))return null;for(let C of e)if(!sI(x,String(C),r))return!1;return!0}let A,p,h,E,I=n&&!r.includePrerelease&&n.semver.prerelease.length?n.semver:!1,v=a&&!r.includePrerelease&&a.semver.prerelease.length?a.semver:!1;I&&I.prerelease.length===1&&n.operator==="<"&&I.prerelease[0]===0&&(I=!1);for(let x of e){if(E=E||x.operator===">"||x.operator===">=",h=h||x.operator==="<"||x.operator==="<=",a){if(v&&x.semver.prerelease&&x.semver.prerelease.length&&x.semver.major===v.major&&x.semver.minor===v.minor&&x.semver.patch===v.patch&&(v=!1),x.operator===">"||x.operator===">="){if(A=YJ(a,x,r),A===x&&A!==a)return!1}else if(a.operator===">="&&!sI(a.semver,String(x),r))return!1}if(n){if(I&&x.semver.prerelease&&x.semver.prerelease.length&&x.semver.major===I.major&&x.semver.minor===I.minor&&x.semver.patch===I.patch&&(I=!1),x.operator==="<"||x.operator==="<="){if(p=WJ(n,x,r),p===x&&p!==n)return!1}else if(n.operator==="<="&&!sI(n.semver,String(x),r))return!1}if(!x.operator&&(n||a)&&u!==0)return!1}return!(a&&h&&!n&&u!==0||n&&E&&!a&&u!==0||v||I)},YJ=(t,e,r)=>{if(!t)return e;let o=eN(t.semver,e.semver,r);return o>0?t:o<0||e.operator===">"&&t.operator===">="?e:t},WJ=(t,e,r)=>{if(!t)return e;let o=eN(t.semver,e.semver,r);return o<0?t:o>0||e.operator==="<"&&t.operator==="<="?e:t};KJ.exports=DGe});var Jn=_((xQt,XJ)=>{var tN=lm(),zJ=Xw(),bGe=Po(),JJ=MT(),xGe=tg(),kGe=dz(),QGe=yz(),FGe=wz(),RGe=vz(),TGe=Pz(),NGe=bz(),LGe=kz(),MGe=Fz(),OGe=Ll(),UGe=Lz(),_Ge=Oz(),HGe=nP(),qGe=qz(),jGe=Gz(),GGe=$w(),YGe=iP(),WGe=UT(),KGe=_T(),VGe=sP(),zGe=oP(),JGe=HT(),XGe=$z(),ZGe=rI(),$Ge=Ml(),e9e=iI(),t9e=CJ(),r9e=IJ(),n9e=vJ(),i9e=SJ(),s9e=xJ(),o9e=AP(),a9e=NJ(),l9e=MJ(),c9e=_J(),u9e=qJ(),A9e=VJ();XJ.exports={parse:xGe,valid:kGe,clean:QGe,inc:FGe,diff:RGe,major:TGe,minor:NGe,patch:LGe,prerelease:MGe,compare:OGe,rcompare:UGe,compareLoose:_Ge,compareBuild:HGe,sort:qGe,rsort:jGe,gt:GGe,lt:YGe,eq:WGe,neq:KGe,gte:VGe,lte:zGe,cmp:JGe,coerce:XGe,Comparator:ZGe,Range:$Ge,satisfies:e9e,toComparators:t9e,maxSatisfying:r9e,minSatisfying:n9e,minVersion:i9e,validRange:s9e,outside:o9e,gtr:a9e,ltr:l9e,intersects:c9e,simplifyRange:u9e,subset:A9e,SemVer:bGe,re:tN.re,src:tN.src,tokens:tN.t,SEMVER_SPEC_VERSION:zJ.SEMVER_SPEC_VERSION,RELEASE_TYPES:zJ.RELEASE_TYPES,compareIdentifiers:JJ.compareIdentifiers,rcompareIdentifiers:JJ.rcompareIdentifiers}});var $J=_((kQt,ZJ)=>{"use strict";function f9e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function sg(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,sg)}f9e(sg,Error);sg.buildMessage=function(t,e){var r={literal:function(h){return'"'+a(h.text)+'"'},class:function(h){var E="",I;for(I=0;I<h.parts.length;I++)E+=h.parts[I]instanceof Array?n(h.parts[I][0])+"-"+n(h.parts[I][1]):n(h.parts[I]);return"["+(h.inverted?"^":"")+E+"]"},any:function(h){return"any character"},end:function(h){return"end of input"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(E){return"\\x0"+o(E)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(E){return"\\x"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),I,v;for(I=0;I<h.length;I++)E[I]=u(h[I]);if(E.sort(),E.length>0){for(I=1,v=1;I<E.length;I++)E[I-1]!==E[I]&&(E[v]=E[I],v++);E.length=v}switch(E.length){case 1:return E[0];case 2:return E[0]+" or "+E[1];default:return E.slice(0,-1).join(", ")+", or "+E[E.length-1]}}function p(h){return h?'"'+a(h)+'"':"end of input"}return"Expected "+A(t)+" but "+p(e)+" found."};function p9e(t,e){e=e!==void 0?e:{};var r={},o={Expression:y},a=y,n="|",u=Te("|",!1),A="&",p=Te("&",!1),h="^",E=Te("^",!1),I=function($,ie){return!!ie.reduce((be,Re)=>{switch(Re[1]){case"|":return be|Re[3];case"&":return be&Re[3];case"^":return be^Re[3]}},$)},v="!",x=Te("!",!1),C=function($){return!$},R="(",L=Te("(",!1),U=")",z=Te(")",!1),te=function($){return $},ae=/^[^ \t\n\r()!|&\^]/,le=Fe([" "," ",` +`,"\r","(",")","!","|","&","^"],!0,!1),ce=function($){return e.queryPattern.test($)},Ce=function($){return e.checkFn($)},de=Se("whitespace"),Be=/^[ \t\n\r]/,Ee=Fe([" "," ",` +`,"\r"],!1,!1),g=0,me=0,we=[{line:1,column:1}],Ae=0,ne=[],Z=0,xe;if("startRule"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=o[e.startRule]}function Ne(){return t.substring(me,g)}function ht(){return Ue(me,g)}function H($,ie){throw ie=ie!==void 0?ie:Ue(me,g),S([Se($)],t.substring(me,g),ie)}function rt($,ie){throw ie=ie!==void 0?ie:Ue(me,g),w($,ie)}function Te($,ie){return{type:"literal",text:$,ignoreCase:ie}}function Fe($,ie,be){return{type:"class",parts:$,inverted:ie,ignoreCase:be}}function ke(){return{type:"any"}}function Ye(){return{type:"end"}}function Se($){return{type:"other",description:$}}function et($){var ie=we[$],be;if(ie)return ie;for(be=$-1;!we[be];)be--;for(ie=we[be],ie={line:ie.line,column:ie.column};be<$;)t.charCodeAt(be)===10?(ie.line++,ie.column=1):ie.column++,be++;return we[$]=ie,ie}function Ue($,ie){var be=et($),Re=et(ie);return{start:{offset:$,line:be.line,column:be.column},end:{offset:ie,line:Re.line,column:Re.column}}}function b($){g<Ae||(g>Ae&&(Ae=g,ne=[]),ne.push($))}function w($,ie){return new sg($,null,null,ie)}function S($,ie,be){return new sg(sg.buildMessage($,ie),$,ie,be)}function y(){var $,ie,be,Re,at,dt,jt,tr;if($=g,ie=F(),ie!==r){for(be=[],Re=g,at=X(),at!==r?(t.charCodeAt(g)===124?(dt=n,g++):(dt=r,Z===0&&b(u)),dt===r&&(t.charCodeAt(g)===38?(dt=A,g++):(dt=r,Z===0&&b(p)),dt===r&&(t.charCodeAt(g)===94?(dt=h,g++):(dt=r,Z===0&&b(E)))),dt!==r?(jt=X(),jt!==r?(tr=F(),tr!==r?(at=[at,dt,jt,tr],Re=at):(g=Re,Re=r)):(g=Re,Re=r)):(g=Re,Re=r)):(g=Re,Re=r);Re!==r;)be.push(Re),Re=g,at=X(),at!==r?(t.charCodeAt(g)===124?(dt=n,g++):(dt=r,Z===0&&b(u)),dt===r&&(t.charCodeAt(g)===38?(dt=A,g++):(dt=r,Z===0&&b(p)),dt===r&&(t.charCodeAt(g)===94?(dt=h,g++):(dt=r,Z===0&&b(E)))),dt!==r?(jt=X(),jt!==r?(tr=F(),tr!==r?(at=[at,dt,jt,tr],Re=at):(g=Re,Re=r)):(g=Re,Re=r)):(g=Re,Re=r)):(g=Re,Re=r);be!==r?(me=$,ie=I(ie,be),$=ie):(g=$,$=r)}else g=$,$=r;return $}function F(){var $,ie,be,Re,at,dt;return $=g,t.charCodeAt(g)===33?(ie=v,g++):(ie=r,Z===0&&b(x)),ie!==r?(be=F(),be!==r?(me=$,ie=C(be),$=ie):(g=$,$=r)):(g=$,$=r),$===r&&($=g,t.charCodeAt(g)===40?(ie=R,g++):(ie=r,Z===0&&b(L)),ie!==r?(be=X(),be!==r?(Re=y(),Re!==r?(at=X(),at!==r?(t.charCodeAt(g)===41?(dt=U,g++):(dt=r,Z===0&&b(z)),dt!==r?(me=$,ie=te(Re),$=ie):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r),$===r&&($=J())),$}function J(){var $,ie,be,Re,at;if($=g,ie=X(),ie!==r){if(be=g,Re=[],ae.test(t.charAt(g))?(at=t.charAt(g),g++):(at=r,Z===0&&b(le)),at!==r)for(;at!==r;)Re.push(at),ae.test(t.charAt(g))?(at=t.charAt(g),g++):(at=r,Z===0&&b(le));else Re=r;Re!==r?be=t.substring(be,g):be=Re,be!==r?(me=g,Re=ce(be),Re?Re=void 0:Re=r,Re!==r?(me=$,ie=Ce(be),$=ie):(g=$,$=r)):(g=$,$=r)}else g=$,$=r;return $}function X(){var $,ie;for(Z++,$=[],Be.test(t.charAt(g))?(ie=t.charAt(g),g++):(ie=r,Z===0&&b(Ee));ie!==r;)$.push(ie),Be.test(t.charAt(g))?(ie=t.charAt(g),g++):(ie=r,Z===0&&b(Ee));return Z--,$===r&&(ie=r,Z===0&&b(de)),$}if(xe=a(),xe!==r&&g===t.length)return xe;throw xe!==r&&g<t.length&&b(Ye()),S(ne,Ae<t.length?t.charAt(Ae):null,Ae<t.length?Ue(Ae,Ae+1):Ue(Ae,Ae))}ZJ.exports={SyntaxError:sg,parse:p9e}});var eX=_(fP=>{var{parse:h9e}=$J();fP.makeParser=(t=/[a-z]+/)=>(e,r)=>h9e(e,{queryPattern:t,checkFn:r});fP.parse=fP.makeParser()});var rX=_((FQt,tX)=>{"use strict";tX.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var rN=_((RQt,iX)=>{var oI=rX(),nX={};for(let t of Object.keys(oI))nX[oI[t]]=t;var Ar={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};iX.exports=Ar;for(let t of Object.keys(Ar)){if(!("channels"in Ar[t]))throw new Error("missing channels property: "+t);if(!("labels"in Ar[t]))throw new Error("missing channel labels property: "+t);if(Ar[t].labels.length!==Ar[t].channels)throw new Error("channel and label counts mismatch: "+t);let{channels:e,labels:r}=Ar[t];delete Ar[t].channels,delete Ar[t].labels,Object.defineProperty(Ar[t],"channels",{value:e}),Object.defineProperty(Ar[t],"labels",{value:r})}Ar.rgb.hsl=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(e,r,o),n=Math.max(e,r,o),u=n-a,A,p;n===a?A=0:e===n?A=(r-o)/u:r===n?A=2+(o-e)/u:o===n&&(A=4+(e-r)/u),A=Math.min(A*60,360),A<0&&(A+=360);let h=(a+n)/2;return n===a?p=0:h<=.5?p=u/(n+a):p=u/(2-n-a),[A,p*100,h*100]};Ar.rgb.hsv=function(t){let e,r,o,a,n,u=t[0]/255,A=t[1]/255,p=t[2]/255,h=Math.max(u,A,p),E=h-Math.min(u,A,p),I=function(v){return(h-v)/6/E+1/2};return E===0?(a=0,n=0):(n=E/h,e=I(u),r=I(A),o=I(p),u===h?a=o-r:A===h?a=1/3+e-o:p===h&&(a=2/3+r-e),a<0?a+=1:a>1&&(a-=1)),[a*360,n*100,h*100]};Ar.rgb.hwb=function(t){let e=t[0],r=t[1],o=t[2],a=Ar.rgb.hsl(t)[0],n=1/255*Math.min(e,Math.min(r,o));return o=1-1/255*Math.max(e,Math.max(r,o)),[a,n*100,o*100]};Ar.rgb.cmyk=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(1-e,1-r,1-o),n=(1-e-a)/(1-a)||0,u=(1-r-a)/(1-a)||0,A=(1-o-a)/(1-a)||0;return[n*100,u*100,A*100,a*100]};function g9e(t,e){return(t[0]-e[0])**2+(t[1]-e[1])**2+(t[2]-e[2])**2}Ar.rgb.keyword=function(t){let e=nX[t];if(e)return e;let r=1/0,o;for(let a of Object.keys(oI)){let n=oI[a],u=g9e(t,n);u<r&&(r=u,o=a)}return o};Ar.keyword.rgb=function(t){return oI[t]};Ar.rgb.xyz=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255;e=e>.04045?((e+.055)/1.055)**2.4:e/12.92,r=r>.04045?((r+.055)/1.055)**2.4:r/12.92,o=o>.04045?((o+.055)/1.055)**2.4:o/12.92;let a=e*.4124+r*.3576+o*.1805,n=e*.2126+r*.7152+o*.0722,u=e*.0193+r*.1192+o*.9505;return[a*100,n*100,u*100]};Ar.rgb.lab=function(t){let e=Ar.rgb.xyz(t),r=e[0],o=e[1],a=e[2];r/=95.047,o/=100,a/=108.883,r=r>.008856?r**(1/3):7.787*r+16/116,o=o>.008856?o**(1/3):7.787*o+16/116,a=a>.008856?a**(1/3):7.787*a+16/116;let n=116*o-16,u=500*(r-o),A=200*(o-a);return[n,u,A]};Ar.hsl.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100,a,n,u;if(r===0)return u=o*255,[u,u,u];o<.5?a=o*(1+r):a=o+r-o*r;let A=2*o-a,p=[0,0,0];for(let h=0;h<3;h++)n=e+1/3*-(h-1),n<0&&n++,n>1&&n--,6*n<1?u=A+(a-A)*6*n:2*n<1?u=a:3*n<2?u=A+(a-A)*(2/3-n)*6:u=A,p[h]=u*255;return p};Ar.hsl.hsv=function(t){let e=t[0],r=t[1]/100,o=t[2]/100,a=r,n=Math.max(o,.01);o*=2,r*=o<=1?o:2-o,a*=n<=1?n:2-n;let u=(o+r)/2,A=o===0?2*a/(n+a):2*r/(o+r);return[e,A*100,u*100]};Ar.hsv.rgb=function(t){let e=t[0]/60,r=t[1]/100,o=t[2]/100,a=Math.floor(e)%6,n=e-Math.floor(e),u=255*o*(1-r),A=255*o*(1-r*n),p=255*o*(1-r*(1-n));switch(o*=255,a){case 0:return[o,p,u];case 1:return[A,o,u];case 2:return[u,o,p];case 3:return[u,A,o];case 4:return[p,u,o];case 5:return[o,u,A]}};Ar.hsv.hsl=function(t){let e=t[0],r=t[1]/100,o=t[2]/100,a=Math.max(o,.01),n,u;u=(2-r)*o;let A=(2-r)*a;return n=r*a,n/=A<=1?A:2-A,n=n||0,u/=2,[e,n*100,u*100]};Ar.hwb.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100,a=r+o,n;a>1&&(r/=a,o/=a);let u=Math.floor(6*e),A=1-o;n=6*e-u,u&1&&(n=1-n);let p=r+n*(A-r),h,E,I;switch(u){default:case 6:case 0:h=A,E=p,I=r;break;case 1:h=p,E=A,I=r;break;case 2:h=r,E=A,I=p;break;case 3:h=r,E=p,I=A;break;case 4:h=p,E=r,I=A;break;case 5:h=A,E=r,I=p;break}return[h*255,E*255,I*255]};Ar.cmyk.rgb=function(t){let e=t[0]/100,r=t[1]/100,o=t[2]/100,a=t[3]/100,n=1-Math.min(1,e*(1-a)+a),u=1-Math.min(1,r*(1-a)+a),A=1-Math.min(1,o*(1-a)+a);return[n*255,u*255,A*255]};Ar.xyz.rgb=function(t){let e=t[0]/100,r=t[1]/100,o=t[2]/100,a,n,u;return a=e*3.2406+r*-1.5372+o*-.4986,n=e*-.9689+r*1.8758+o*.0415,u=e*.0557+r*-.204+o*1.057,a=a>.0031308?1.055*a**(1/2.4)-.055:a*12.92,n=n>.0031308?1.055*n**(1/2.4)-.055:n*12.92,u=u>.0031308?1.055*u**(1/2.4)-.055:u*12.92,a=Math.min(Math.max(0,a),1),n=Math.min(Math.max(0,n),1),u=Math.min(Math.max(0,u),1),[a*255,n*255,u*255]};Ar.xyz.lab=function(t){let e=t[0],r=t[1],o=t[2];e/=95.047,r/=100,o/=108.883,e=e>.008856?e**(1/3):7.787*e+16/116,r=r>.008856?r**(1/3):7.787*r+16/116,o=o>.008856?o**(1/3):7.787*o+16/116;let a=116*r-16,n=500*(e-r),u=200*(r-o);return[a,n,u]};Ar.lab.xyz=function(t){let e=t[0],r=t[1],o=t[2],a,n,u;n=(e+16)/116,a=r/500+n,u=n-o/200;let A=n**3,p=a**3,h=u**3;return n=A>.008856?A:(n-16/116)/7.787,a=p>.008856?p:(a-16/116)/7.787,u=h>.008856?h:(u-16/116)/7.787,a*=95.047,n*=100,u*=108.883,[a,n,u]};Ar.lab.lch=function(t){let e=t[0],r=t[1],o=t[2],a;a=Math.atan2(o,r)*360/2/Math.PI,a<0&&(a+=360);let u=Math.sqrt(r*r+o*o);return[e,u,a]};Ar.lch.lab=function(t){let e=t[0],r=t[1],a=t[2]/360*2*Math.PI,n=r*Math.cos(a),u=r*Math.sin(a);return[e,n,u]};Ar.rgb.ansi16=function(t,e=null){let[r,o,a]=t,n=e===null?Ar.rgb.hsv(t)[2]:e;if(n=Math.round(n/50),n===0)return 30;let u=30+(Math.round(a/255)<<2|Math.round(o/255)<<1|Math.round(r/255));return n===2&&(u+=60),u};Ar.hsv.ansi16=function(t){return Ar.rgb.ansi16(Ar.hsv.rgb(t),t[2])};Ar.rgb.ansi256=function(t){let e=t[0],r=t[1],o=t[2];return e===r&&r===o?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(r/255*5)+Math.round(o/255*5)};Ar.ansi16.rgb=function(t){let e=t%10;if(e===0||e===7)return t>50&&(e+=3.5),e=e/10.5*255,[e,e,e];let r=(~~(t>50)+1)*.5,o=(e&1)*r*255,a=(e>>1&1)*r*255,n=(e>>2&1)*r*255;return[o,a,n]};Ar.ansi256.rgb=function(t){if(t>=232){let n=(t-232)*10+8;return[n,n,n]}t-=16;let e,r=Math.floor(t/36)/5*255,o=Math.floor((e=t%36)/6)/5*255,a=e%6/5*255;return[r,o,a]};Ar.rgb.hex=function(t){let r=(((Math.round(t[0])&255)<<16)+((Math.round(t[1])&255)<<8)+(Math.round(t[2])&255)).toString(16).toUpperCase();return"000000".substring(r.length)+r};Ar.hex.rgb=function(t){let e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];let r=e[0];e[0].length===3&&(r=r.split("").map(A=>A+A).join(""));let o=parseInt(r,16),a=o>>16&255,n=o>>8&255,u=o&255;return[a,n,u]};Ar.rgb.hcg=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.max(Math.max(e,r),o),n=Math.min(Math.min(e,r),o),u=a-n,A,p;return u<1?A=n/(1-u):A=0,u<=0?p=0:a===e?p=(r-o)/u%6:a===r?p=2+(o-e)/u:p=4+(e-r)/u,p/=6,p%=1,[p*360,u*100,A*100]};Ar.hsl.hcg=function(t){let e=t[1]/100,r=t[2]/100,o=r<.5?2*e*r:2*e*(1-r),a=0;return o<1&&(a=(r-.5*o)/(1-o)),[t[0],o*100,a*100]};Ar.hsv.hcg=function(t){let e=t[1]/100,r=t[2]/100,o=e*r,a=0;return o<1&&(a=(r-o)/(1-o)),[t[0],o*100,a*100]};Ar.hcg.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100;if(r===0)return[o*255,o*255,o*255];let a=[0,0,0],n=e%1*6,u=n%1,A=1-u,p=0;switch(Math.floor(n)){case 0:a[0]=1,a[1]=u,a[2]=0;break;case 1:a[0]=A,a[1]=1,a[2]=0;break;case 2:a[0]=0,a[1]=1,a[2]=u;break;case 3:a[0]=0,a[1]=A,a[2]=1;break;case 4:a[0]=u,a[1]=0,a[2]=1;break;default:a[0]=1,a[1]=0,a[2]=A}return p=(1-r)*o,[(r*a[0]+p)*255,(r*a[1]+p)*255,(r*a[2]+p)*255]};Ar.hcg.hsv=function(t){let e=t[1]/100,r=t[2]/100,o=e+r*(1-e),a=0;return o>0&&(a=e/o),[t[0],a*100,o*100]};Ar.hcg.hsl=function(t){let e=t[1]/100,o=t[2]/100*(1-e)+.5*e,a=0;return o>0&&o<.5?a=e/(2*o):o>=.5&&o<1&&(a=e/(2*(1-o))),[t[0],a*100,o*100]};Ar.hcg.hwb=function(t){let e=t[1]/100,r=t[2]/100,o=e+r*(1-e);return[t[0],(o-e)*100,(1-o)*100]};Ar.hwb.hcg=function(t){let e=t[1]/100,o=1-t[2]/100,a=o-e,n=0;return a<1&&(n=(o-a)/(1-a)),[t[0],a*100,n*100]};Ar.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]};Ar.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]};Ar.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]};Ar.gray.hsl=function(t){return[0,0,t[0]]};Ar.gray.hsv=Ar.gray.hsl;Ar.gray.hwb=function(t){return[0,100,t[0]]};Ar.gray.cmyk=function(t){return[0,0,0,t[0]]};Ar.gray.lab=function(t){return[t[0],0,0]};Ar.gray.hex=function(t){let e=Math.round(t[0]/100*255)&255,o=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(o.length)+o};Ar.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}});var oX=_((TQt,sX)=>{var pP=rN();function d9e(){let t={},e=Object.keys(pP);for(let r=e.length,o=0;o<r;o++)t[e[o]]={distance:-1,parent:null};return t}function m9e(t){let e=d9e(),r=[t];for(e[t].distance=0;r.length;){let o=r.pop(),a=Object.keys(pP[o]);for(let n=a.length,u=0;u<n;u++){let A=a[u],p=e[A];p.distance===-1&&(p.distance=e[o].distance+1,p.parent=o,r.unshift(A))}}return e}function y9e(t,e){return function(r){return e(t(r))}}function E9e(t,e){let r=[e[t].parent,t],o=pP[e[t].parent][t],a=e[t].parent;for(;e[a].parent;)r.unshift(e[a].parent),o=y9e(pP[e[a].parent][a],o),a=e[a].parent;return o.conversion=r,o}sX.exports=function(t){let e=m9e(t),r={},o=Object.keys(e);for(let a=o.length,n=0;n<a;n++){let u=o[n];e[u].parent!==null&&(r[u]=E9e(u,e))}return r}});var lX=_((NQt,aX)=>{var nN=rN(),C9e=oX(),fm={},w9e=Object.keys(nN);function I9e(t){let e=function(...r){let o=r[0];return o==null?o:(o.length>1&&(r=o),t(r))};return"conversion"in t&&(e.conversion=t.conversion),e}function B9e(t){let e=function(...r){let o=r[0];if(o==null)return o;o.length>1&&(r=o);let a=t(r);if(typeof a=="object")for(let n=a.length,u=0;u<n;u++)a[u]=Math.round(a[u]);return a};return"conversion"in t&&(e.conversion=t.conversion),e}w9e.forEach(t=>{fm[t]={},Object.defineProperty(fm[t],"channels",{value:nN[t].channels}),Object.defineProperty(fm[t],"labels",{value:nN[t].labels});let e=C9e(t);Object.keys(e).forEach(o=>{let a=e[o];fm[t][o]=B9e(a),fm[t][o].raw=I9e(a)})});aX.exports=fm});var aI=_((LQt,pX)=>{"use strict";var cX=(t,e)=>(...r)=>`\x1B[${t(...r)+e}m`,uX=(t,e)=>(...r)=>{let o=t(...r);return`\x1B[${38+e};5;${o}m`},AX=(t,e)=>(...r)=>{let o=t(...r);return`\x1B[${38+e};2;${o[0]};${o[1]};${o[2]}m`},hP=t=>t,fX=(t,e,r)=>[t,e,r],pm=(t,e,r)=>{Object.defineProperty(t,e,{get:()=>{let o=r();return Object.defineProperty(t,e,{value:o,enumerable:!0,configurable:!0}),o},enumerable:!0,configurable:!0})},iN,hm=(t,e,r,o)=>{iN===void 0&&(iN=lX());let a=o?10:0,n={};for(let[u,A]of Object.entries(iN)){let p=u==="ansi16"?"ansi":u;u===e?n[p]=t(r,a):typeof A=="object"&&(n[p]=t(A[e],a))}return n};function v9e(){let t=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};e.color.gray=e.color.blackBright,e.bgColor.bgGray=e.bgColor.bgBlackBright,e.color.grey=e.color.blackBright,e.bgColor.bgGrey=e.bgColor.bgBlackBright;for(let[r,o]of Object.entries(e)){for(let[a,n]of Object.entries(o))e[a]={open:`\x1B[${n[0]}m`,close:`\x1B[${n[1]}m`},o[a]=e[a],t.set(n[0],n[1]);Object.defineProperty(e,r,{value:o,enumerable:!1})}return Object.defineProperty(e,"codes",{value:t,enumerable:!1}),e.color.close="\x1B[39m",e.bgColor.close="\x1B[49m",pm(e.color,"ansi",()=>hm(cX,"ansi16",hP,!1)),pm(e.color,"ansi256",()=>hm(uX,"ansi256",hP,!1)),pm(e.color,"ansi16m",()=>hm(AX,"rgb",fX,!1)),pm(e.bgColor,"ansi",()=>hm(cX,"ansi16",hP,!0)),pm(e.bgColor,"ansi256",()=>hm(uX,"ansi256",hP,!0)),pm(e.bgColor,"ansi16m",()=>hm(AX,"rgb",fX,!0)),e}Object.defineProperty(pX,"exports",{enumerable:!0,get:v9e})});var gX=_((MQt,hX)=>{"use strict";hX.exports=(t,e=process.argv)=>{let r=t.startsWith("-")?"":t.length===1?"-":"--",o=e.indexOf(r+t),a=e.indexOf("--");return o!==-1&&(a===-1||o<a)}});var aN=_((OQt,mX)=>{"use strict";var D9e=ve("os"),dX=ve("tty"),Ol=gX(),{env:us}=process,Wp;Ol("no-color")||Ol("no-colors")||Ol("color=false")||Ol("color=never")?Wp=0:(Ol("color")||Ol("colors")||Ol("color=true")||Ol("color=always"))&&(Wp=1);"FORCE_COLOR"in us&&(us.FORCE_COLOR==="true"?Wp=1:us.FORCE_COLOR==="false"?Wp=0:Wp=us.FORCE_COLOR.length===0?1:Math.min(parseInt(us.FORCE_COLOR,10),3));function sN(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}function oN(t,e){if(Wp===0)return 0;if(Ol("color=16m")||Ol("color=full")||Ol("color=truecolor"))return 3;if(Ol("color=256"))return 2;if(t&&!e&&Wp===void 0)return 0;let r=Wp||0;if(us.TERM==="dumb")return r;if(process.platform==="win32"){let o=D9e.release().split(".");return Number(o[0])>=10&&Number(o[2])>=10586?Number(o[2])>=14931?3:2:1}if("CI"in us)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(o=>o in us)||us.CI_NAME==="codeship"?1:r;if("TEAMCITY_VERSION"in us)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(us.TEAMCITY_VERSION)?1:0;if("GITHUB_ACTIONS"in us)return 1;if(us.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in us){let o=parseInt((us.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(us.TERM_PROGRAM){case"iTerm.app":return o>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(us.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(us.TERM)||"COLORTERM"in us?1:r}function P9e(t){let e=oN(t,t&&t.isTTY);return sN(e)}mX.exports={supportsColor:P9e,stdout:sN(oN(!0,dX.isatty(1))),stderr:sN(oN(!0,dX.isatty(2)))}});var EX=_((UQt,yX)=>{"use strict";var S9e=(t,e,r)=>{let o=t.indexOf(e);if(o===-1)return t;let a=e.length,n=0,u="";do u+=t.substr(n,o-n)+e+r,n=o+a,o=t.indexOf(e,n);while(o!==-1);return u+=t.substr(n),u},b9e=(t,e,r,o)=>{let a=0,n="";do{let u=t[o-1]==="\r";n+=t.substr(a,(u?o-1:o)-a)+e+(u?`\r +`:` +`)+r,a=o+1,o=t.indexOf(` +`,a)}while(o!==-1);return n+=t.substr(a),n};yX.exports={stringReplaceAll:S9e,stringEncaseCRLFWithFirstIndex:b9e}});var vX=_((_Qt,BX)=>{"use strict";var x9e=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,CX=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,k9e=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,Q9e=/\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.)|([^\\])/gi,F9e=new Map([["n",` +`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function IX(t){let e=t[0]==="u",r=t[1]==="{";return e&&!r&&t.length===5||t[0]==="x"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):F9e.get(t)||t}function R9e(t,e){let r=[],o=e.trim().split(/\s*,\s*/g),a;for(let n of o){let u=Number(n);if(!Number.isNaN(u))r.push(u);else if(a=n.match(k9e))r.push(a[2].replace(Q9e,(A,p,h)=>p?IX(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function T9e(t){CX.lastIndex=0;let e=[],r;for(;(r=CX.exec(t))!==null;){let o=r[1];if(r[2]){let a=R9e(o,r[2]);e.push([o].concat(a))}else e.push([o])}return e}function wX(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let o=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in o))throw new Error(`Unknown Chalk style: ${a}`);o=n.length>0?o[a](...n):o[a]}return o}BX.exports=(t,e)=>{let r=[],o=[],a=[];if(e.replace(x9e,(n,u,A,p,h,E)=>{if(u)a.push(IX(u));else if(p){let I=a.join("");a=[],o.push(r.length===0?I:wX(t,r)(I)),r.push({inverse:A,styles:T9e(p)})}else if(h){if(r.length===0)throw new Error("Found extraneous } in Chalk template literal");o.push(wX(t,r)(a.join(""))),a=[],r.pop()}else a.push(E)}),o.push(a.join("")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?"":"s"} (\`}\`)`;throw new Error(n)}return o.join("")}});var pN=_((HQt,bX)=>{"use strict";var lI=aI(),{stdout:cN,stderr:uN}=aN(),{stringReplaceAll:N9e,stringEncaseCRLFWithFirstIndex:L9e}=EX(),DX=["ansi","ansi","ansi256","ansi16m"],gm=Object.create(null),M9e=(t,e={})=>{if(e.level>3||e.level<0)throw new Error("The `level` option should be an integer from 0 to 3");let r=cN?cN.level:0;t.level=e.level===void 0?r:e.level},AN=class{constructor(e){return PX(e)}},PX=t=>{let e={};return M9e(e,t),e.template=(...r)=>_9e(e.template,...r),Object.setPrototypeOf(e,gP.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},e.template.Instance=AN,e.template};function gP(t){return PX(t)}for(let[t,e]of Object.entries(lI))gm[t]={get(){let r=dP(this,fN(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};gm.visible={get(){let t=dP(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:t}),t}};var SX=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let t of SX)gm[t]={get(){let{level:e}=this;return function(...r){let o=fN(lI.color[DX[e]][t](...r),lI.color.close,this._styler);return dP(this,o,this._isEmpty)}}};for(let t of SX){let e="bg"+t[0].toUpperCase()+t.slice(1);gm[e]={get(){let{level:r}=this;return function(...o){let a=fN(lI.bgColor[DX[r]][t](...o),lI.bgColor.close,this._styler);return dP(this,a,this._isEmpty)}}}}var O9e=Object.defineProperties(()=>{},{...gm,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),fN=(t,e,r)=>{let o,a;return r===void 0?(o=t,a=e):(o=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:a,parent:r}},dP=(t,e,r)=>{let o=(...a)=>U9e(o,a.length===1?""+a[0]:a.join(" "));return o.__proto__=O9e,o._generator=t,o._styler=e,o._isEmpty=r,o},U9e=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?"":e;let r=t._styler;if(r===void 0)return e;let{openAll:o,closeAll:a}=r;if(e.indexOf("\x1B")!==-1)for(;r!==void 0;)e=N9e(e,r.close,r.open),r=r.parent;let n=e.indexOf(` +`);return n!==-1&&(e=L9e(e,a,o,n)),o+e+a},lN,_9e=(t,...e)=>{let[r]=e;if(!Array.isArray(r))return e.join(" ");let o=e.slice(1),a=[r.raw[0]];for(let n=1;n<r.length;n++)a.push(String(o[n-1]).replace(/[{}\\]/g,"\\$&"),String(r.raw[n]));return lN===void 0&&(lN=vX()),lN(t,a.join(""))};Object.defineProperties(gP.prototype,gm);var cI=gP();cI.supportsColor=cN;cI.stderr=gP({level:uN?uN.level:0});cI.stderr.supportsColor=uN;cI.Level={None:0,Basic:1,Ansi256:2,TrueColor:3,0:"None",1:"Basic",2:"Ansi256",3:"TrueColor"};bX.exports=cI});var mP=_(Ul=>{"use strict";Ul.isInteger=t=>typeof t=="number"?Number.isInteger(t):typeof t=="string"&&t.trim()!==""?Number.isInteger(Number(t)):!1;Ul.find=(t,e)=>t.nodes.find(r=>r.type===e);Ul.exceedsLimit=(t,e,r=1,o)=>o===!1||!Ul.isInteger(t)||!Ul.isInteger(e)?!1:(Number(e)-Number(t))/Number(r)>=o;Ul.escapeNode=(t,e=0,r)=>{let o=t.nodes[e];o&&(r&&o.type===r||o.type==="open"||o.type==="close")&&o.escaped!==!0&&(o.value="\\"+o.value,o.escaped=!0)};Ul.encloseBrace=t=>t.type!=="brace"||t.commas>>0+t.ranges>>0?!1:(t.invalid=!0,!0);Ul.isInvalidBrace=t=>t.type!=="brace"?!1:t.invalid===!0||t.dollar?!0:!(t.commas>>0+t.ranges>>0)||t.open!==!0||t.close!==!0?(t.invalid=!0,!0):!1;Ul.isOpenOrClose=t=>t.type==="open"||t.type==="close"?!0:t.open===!0||t.close===!0;Ul.reduce=t=>t.reduce((e,r)=>(r.type==="text"&&e.push(r.value),r.type==="range"&&(r.type="text"),e),[]);Ul.flatten=(...t)=>{let e=[],r=o=>{for(let a=0;a<o.length;a++){let n=o[a];Array.isArray(n)?r(n,e):n!==void 0&&e.push(n)}return e};return r(t),e}});var yP=_((jQt,kX)=>{"use strict";var xX=mP();kX.exports=(t,e={})=>{let r=(o,a={})=>{let n=e.escapeInvalid&&xX.isInvalidBrace(a),u=o.invalid===!0&&e.escapeInvalid===!0,A="";if(o.value)return(n||u)&&xX.isOpenOrClose(o)?"\\"+o.value:o.value;if(o.value)return o.value;if(o.nodes)for(let p of o.nodes)A+=r(p);return A};return r(t)}});var FX=_((GQt,QX)=>{"use strict";QX.exports=function(t){return typeof t=="number"?t-t===0:typeof t=="string"&&t.trim()!==""?Number.isFinite?Number.isFinite(+t):isFinite(+t):!1}});var HX=_((YQt,_X)=>{"use strict";var RX=FX(),og=(t,e,r)=>{if(RX(t)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(e===void 0||t===e)return String(t);if(RX(e)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let o={relaxZeros:!0,...r};typeof o.strictZeros=="boolean"&&(o.relaxZeros=o.strictZeros===!1);let a=String(o.relaxZeros),n=String(o.shorthand),u=String(o.capture),A=String(o.wrap),p=t+":"+e+"="+a+n+u+A;if(og.cache.hasOwnProperty(p))return og.cache[p].result;let h=Math.min(t,e),E=Math.max(t,e);if(Math.abs(h-E)===1){let R=t+"|"+e;return o.capture?`(${R})`:o.wrap===!1?R:`(?:${R})`}let I=UX(t)||UX(e),v={min:t,max:e,a:h,b:E},x=[],C=[];if(I&&(v.isPadded=I,v.maxLen=String(v.max).length),h<0){let R=E<0?Math.abs(E):1;C=TX(R,Math.abs(h),v,o),h=v.a=0}return E>=0&&(x=TX(h,E,v,o)),v.negatives=C,v.positives=x,v.result=H9e(C,x,o),o.capture===!0?v.result=`(${v.result})`:o.wrap!==!1&&x.length+C.length>1&&(v.result=`(?:${v.result})`),og.cache[p]=v,v.result};function H9e(t,e,r){let o=hN(t,e,"-",!1,r)||[],a=hN(e,t,"",!1,r)||[],n=hN(t,e,"-?",!0,r)||[];return o.concat(n).concat(a).join("|")}function q9e(t,e){let r=1,o=1,a=LX(t,r),n=new Set([e]);for(;t<=a&&a<=e;)n.add(a),r+=1,a=LX(t,r);for(a=MX(e+1,o)-1;t<a&&a<=e;)n.add(a),o+=1,a=MX(e+1,o)-1;return n=[...n],n.sort(Y9e),n}function j9e(t,e,r){if(t===e)return{pattern:t,count:[],digits:0};let o=G9e(t,e),a=o.length,n="",u=0;for(let A=0;A<a;A++){let[p,h]=o[A];p===h?n+=p:p!=="0"||h!=="9"?n+=W9e(p,h,r):u++}return u&&(n+=r.shorthand===!0?"\\d":"[0-9]"),{pattern:n,count:[u],digits:a}}function TX(t,e,r,o){let a=q9e(t,e),n=[],u=t,A;for(let p=0;p<a.length;p++){let h=a[p],E=j9e(String(u),String(h),o),I="";if(!r.isPadded&&A&&A.pattern===E.pattern){A.count.length>1&&A.count.pop(),A.count.push(E.count[0]),A.string=A.pattern+OX(A.count),u=h+1;continue}r.isPadded&&(I=K9e(h,r,o)),E.string=I+E.pattern+OX(E.count),n.push(E),u=h+1,A=E}return n}function hN(t,e,r,o,a){let n=[];for(let u of t){let{string:A}=u;!o&&!NX(e,"string",A)&&n.push(r+A),o&&NX(e,"string",A)&&n.push(r+A)}return n}function G9e(t,e){let r=[];for(let o=0;o<t.length;o++)r.push([t[o],e[o]]);return r}function Y9e(t,e){return t>e?1:e>t?-1:0}function NX(t,e,r){return t.some(o=>o[e]===r)}function LX(t,e){return Number(String(t).slice(0,-e)+"9".repeat(e))}function MX(t,e){return t-t%Math.pow(10,e)}function OX(t){let[e=0,r=""]=t;return r||e>1?`{${e+(r?","+r:"")}}`:""}function W9e(t,e,r){return`[${t}${e-t===1?"":"-"}${e}]`}function UX(t){return/^-?(0+)\d/.test(t)}function K9e(t,e,r){if(!e.isPadded)return t;let o=Math.abs(e.maxLen-String(t).length),a=r.relaxZeros!==!1;switch(o){case 0:return"";case 1:return a?"0?":"0";case 2:return a?"0{0,2}":"00";default:return a?`0{0,${o}}`:`0{${o}}`}}og.cache={};og.clearCache=()=>og.cache={};_X.exports=og});var mN=_((WQt,zX)=>{"use strict";var V9e=ve("util"),GX=HX(),qX=t=>t!==null&&typeof t=="object"&&!Array.isArray(t),z9e=t=>e=>t===!0?Number(e):String(e),gN=t=>typeof t=="number"||typeof t=="string"&&t!=="",uI=t=>Number.isInteger(+t),dN=t=>{let e=`${t}`,r=-1;if(e[0]==="-"&&(e=e.slice(1)),e==="0")return!1;for(;e[++r]==="0";);return r>0},J9e=(t,e,r)=>typeof t=="string"||typeof e=="string"?!0:r.stringify===!0,X9e=(t,e,r)=>{if(e>0){let o=t[0]==="-"?"-":"";o&&(t=t.slice(1)),t=o+t.padStart(o?e-1:e,"0")}return r===!1?String(t):t},jX=(t,e)=>{let r=t[0]==="-"?"-":"";for(r&&(t=t.slice(1),e--);t.length<e;)t="0"+t;return r?"-"+t:t},Z9e=(t,e)=>{t.negatives.sort((u,A)=>u<A?-1:u>A?1:0),t.positives.sort((u,A)=>u<A?-1:u>A?1:0);let r=e.capture?"":"?:",o="",a="",n;return t.positives.length&&(o=t.positives.join("|")),t.negatives.length&&(a=`-(${r}${t.negatives.join("|")})`),o&&a?n=`${o}|${a}`:n=o||a,e.wrap?`(${r}${n})`:n},YX=(t,e,r,o)=>{if(r)return GX(t,e,{wrap:!1,...o});let a=String.fromCharCode(t);if(t===e)return a;let n=String.fromCharCode(e);return`[${a}-${n}]`},WX=(t,e,r)=>{if(Array.isArray(t)){let o=r.wrap===!0,a=r.capture?"":"?:";return o?`(${a}${t.join("|")})`:t.join("|")}return GX(t,e,r)},KX=(...t)=>new RangeError("Invalid range arguments: "+V9e.inspect(...t)),VX=(t,e,r)=>{if(r.strictRanges===!0)throw KX([t,e]);return[]},$9e=(t,e)=>{if(e.strictRanges===!0)throw new TypeError(`Expected step "${t}" to be a number`);return[]},e7e=(t,e,r=1,o={})=>{let a=Number(t),n=Number(e);if(!Number.isInteger(a)||!Number.isInteger(n)){if(o.strictRanges===!0)throw KX([t,e]);return[]}a===0&&(a=0),n===0&&(n=0);let u=a>n,A=String(t),p=String(e),h=String(r);r=Math.max(Math.abs(r),1);let E=dN(A)||dN(p)||dN(h),I=E?Math.max(A.length,p.length,h.length):0,v=E===!1&&J9e(t,e,o)===!1,x=o.transform||z9e(v);if(o.toRegex&&r===1)return YX(jX(t,I),jX(e,I),!0,o);let C={negatives:[],positives:[]},R=z=>C[z<0?"negatives":"positives"].push(Math.abs(z)),L=[],U=0;for(;u?a>=n:a<=n;)o.toRegex===!0&&r>1?R(a):L.push(X9e(x(a,U),I,v)),a=u?a-r:a+r,U++;return o.toRegex===!0?r>1?Z9e(C,o):WX(L,null,{wrap:!1,...o}):L},t7e=(t,e,r=1,o={})=>{if(!uI(t)&&t.length>1||!uI(e)&&e.length>1)return VX(t,e,o);let a=o.transform||(v=>String.fromCharCode(v)),n=`${t}`.charCodeAt(0),u=`${e}`.charCodeAt(0),A=n>u,p=Math.min(n,u),h=Math.max(n,u);if(o.toRegex&&r===1)return YX(p,h,!1,o);let E=[],I=0;for(;A?n>=u:n<=u;)E.push(a(n,I)),n=A?n-r:n+r,I++;return o.toRegex===!0?WX(E,null,{wrap:!1,options:o}):E},EP=(t,e,r,o={})=>{if(e==null&&gN(t))return[t];if(!gN(t)||!gN(e))return VX(t,e,o);if(typeof r=="function")return EP(t,e,1,{transform:r});if(qX(r))return EP(t,e,0,r);let a={...o};return a.capture===!0&&(a.wrap=!0),r=r||a.step||1,uI(r)?uI(t)&&uI(e)?e7e(t,e,r,a):t7e(t,e,Math.max(Math.abs(r),1),a):r!=null&&!qX(r)?$9e(r,a):EP(t,e,1,r)};zX.exports=EP});var ZX=_((KQt,XX)=>{"use strict";var r7e=mN(),JX=mP(),n7e=(t,e={})=>{let r=(o,a={})=>{let n=JX.isInvalidBrace(a),u=o.invalid===!0&&e.escapeInvalid===!0,A=n===!0||u===!0,p=e.escapeInvalid===!0?"\\":"",h="";if(o.isOpen===!0||o.isClose===!0)return p+o.value;if(o.type==="open")return A?p+o.value:"(";if(o.type==="close")return A?p+o.value:")";if(o.type==="comma")return o.prev.type==="comma"?"":A?o.value:"|";if(o.value)return o.value;if(o.nodes&&o.ranges>0){let E=JX.reduce(o.nodes),I=r7e(...E,{...e,wrap:!1,toRegex:!0});if(I.length!==0)return E.length>1&&I.length>1?`(${I})`:I}if(o.nodes)for(let E of o.nodes)h+=r(E,o);return h};return r(t)};XX.exports=n7e});var tZ=_((VQt,eZ)=>{"use strict";var i7e=mN(),$X=yP(),dm=mP(),ag=(t="",e="",r=!1)=>{let o=[];if(t=[].concat(t),e=[].concat(e),!e.length)return t;if(!t.length)return r?dm.flatten(e).map(a=>`{${a}}`):e;for(let a of t)if(Array.isArray(a))for(let n of a)o.push(ag(n,e,r));else for(let n of e)r===!0&&typeof n=="string"&&(n=`{${n}}`),o.push(Array.isArray(n)?ag(a,n,r):a+n);return dm.flatten(o)},s7e=(t,e={})=>{let r=e.rangeLimit===void 0?1e3:e.rangeLimit,o=(a,n={})=>{a.queue=[];let u=n,A=n.queue;for(;u.type!=="brace"&&u.type!=="root"&&u.parent;)u=u.parent,A=u.queue;if(a.invalid||a.dollar){A.push(ag(A.pop(),$X(a,e)));return}if(a.type==="brace"&&a.invalid!==!0&&a.nodes.length===2){A.push(ag(A.pop(),["{}"]));return}if(a.nodes&&a.ranges>0){let I=dm.reduce(a.nodes);if(dm.exceedsLimit(...I,e.step,r))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let v=i7e(...I,e);v.length===0&&(v=$X(a,e)),A.push(ag(A.pop(),v)),a.nodes=[];return}let p=dm.encloseBrace(a),h=a.queue,E=a;for(;E.type!=="brace"&&E.type!=="root"&&E.parent;)E=E.parent,h=E.queue;for(let I=0;I<a.nodes.length;I++){let v=a.nodes[I];if(v.type==="comma"&&a.type==="brace"){I===1&&h.push(""),h.push("");continue}if(v.type==="close"){A.push(ag(A.pop(),h,p));continue}if(v.value&&v.type!=="open"){h.push(ag(h.pop(),v.value));continue}v.nodes&&o(v,a)}return h};return dm.flatten(o(t))};eZ.exports=s7e});var nZ=_((zQt,rZ)=>{"use strict";rZ.exports={MAX_LENGTH:1024*64,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:` +`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var lZ=_((JQt,aZ)=>{"use strict";var o7e=yP(),{MAX_LENGTH:iZ,CHAR_BACKSLASH:yN,CHAR_BACKTICK:a7e,CHAR_COMMA:l7e,CHAR_DOT:c7e,CHAR_LEFT_PARENTHESES:u7e,CHAR_RIGHT_PARENTHESES:A7e,CHAR_LEFT_CURLY_BRACE:f7e,CHAR_RIGHT_CURLY_BRACE:p7e,CHAR_LEFT_SQUARE_BRACKET:sZ,CHAR_RIGHT_SQUARE_BRACKET:oZ,CHAR_DOUBLE_QUOTE:h7e,CHAR_SINGLE_QUOTE:g7e,CHAR_NO_BREAK_SPACE:d7e,CHAR_ZERO_WIDTH_NOBREAK_SPACE:m7e}=nZ(),y7e=(t,e={})=>{if(typeof t!="string")throw new TypeError("Expected a string");let r=e||{},o=typeof r.maxLength=="number"?Math.min(iZ,r.maxLength):iZ;if(t.length>o)throw new SyntaxError(`Input length (${t.length}), exceeds max characters (${o})`);let a={type:"root",input:t,nodes:[]},n=[a],u=a,A=a,p=0,h=t.length,E=0,I=0,v,x={},C=()=>t[E++],R=L=>{if(L.type==="text"&&A.type==="dot"&&(A.type="text"),A&&A.type==="text"&&L.type==="text"){A.value+=L.value;return}return u.nodes.push(L),L.parent=u,L.prev=A,A=L,L};for(R({type:"bos"});E<h;)if(u=n[n.length-1],v=C(),!(v===m7e||v===d7e)){if(v===yN){R({type:"text",value:(e.keepEscaping?v:"")+C()});continue}if(v===oZ){R({type:"text",value:"\\"+v});continue}if(v===sZ){p++;let L=!0,U;for(;E<h&&(U=C());){if(v+=U,U===sZ){p++;continue}if(U===yN){v+=C();continue}if(U===oZ&&(p--,p===0))break}R({type:"text",value:v});continue}if(v===u7e){u=R({type:"paren",nodes:[]}),n.push(u),R({type:"text",value:v});continue}if(v===A7e){if(u.type!=="paren"){R({type:"text",value:v});continue}u=n.pop(),R({type:"text",value:v}),u=n[n.length-1];continue}if(v===h7e||v===g7e||v===a7e){let L=v,U;for(e.keepQuotes!==!0&&(v="");E<h&&(U=C());){if(U===yN){v+=U+C();continue}if(U===L){e.keepQuotes===!0&&(v+=U);break}v+=U}R({type:"text",value:v});continue}if(v===f7e){I++;let U={type:"brace",open:!0,close:!1,dollar:A.value&&A.value.slice(-1)==="$"||u.dollar===!0,depth:I,commas:0,ranges:0,nodes:[]};u=R(U),n.push(u),R({type:"open",value:v});continue}if(v===p7e){if(u.type!=="brace"){R({type:"text",value:v});continue}let L="close";u=n.pop(),u.close=!0,R({type:L,value:v}),I--,u=n[n.length-1];continue}if(v===l7e&&I>0){if(u.ranges>0){u.ranges=0;let L=u.nodes.shift();u.nodes=[L,{type:"text",value:o7e(u)}]}R({type:"comma",value:v}),u.commas++;continue}if(v===c7e&&I>0&&u.commas===0){let L=u.nodes;if(I===0||L.length===0){R({type:"text",value:v});continue}if(A.type==="dot"){if(u.range=[],A.value+=v,A.type="range",u.nodes.length!==3&&u.nodes.length!==5){u.invalid=!0,u.ranges=0,A.type="text";continue}u.ranges++,u.args=[];continue}if(A.type==="range"){L.pop();let U=L[L.length-1];U.value+=A.value+v,A=U,u.ranges--;continue}R({type:"dot",value:v});continue}R({type:"text",value:v})}do if(u=n.pop(),u.type!=="root"){u.nodes.forEach(z=>{z.nodes||(z.type==="open"&&(z.isOpen=!0),z.type==="close"&&(z.isClose=!0),z.nodes||(z.type="text"),z.invalid=!0)});let L=n[n.length-1],U=L.nodes.indexOf(u);L.nodes.splice(U,1,...u.nodes)}while(n.length>0);return R({type:"eos"}),a};aZ.exports=y7e});var AZ=_((XQt,uZ)=>{"use strict";var cZ=yP(),E7e=ZX(),C7e=tZ(),w7e=lZ(),nl=(t,e={})=>{let r=[];if(Array.isArray(t))for(let o of t){let a=nl.create(o,e);Array.isArray(a)?r.push(...a):r.push(a)}else r=[].concat(nl.create(t,e));return e&&e.expand===!0&&e.nodupes===!0&&(r=[...new Set(r)]),r};nl.parse=(t,e={})=>w7e(t,e);nl.stringify=(t,e={})=>cZ(typeof t=="string"?nl.parse(t,e):t,e);nl.compile=(t,e={})=>(typeof t=="string"&&(t=nl.parse(t,e)),E7e(t,e));nl.expand=(t,e={})=>{typeof t=="string"&&(t=nl.parse(t,e));let r=C7e(t,e);return e.noempty===!0&&(r=r.filter(Boolean)),e.nodupes===!0&&(r=[...new Set(r)]),r};nl.create=(t,e={})=>t===""||t.length<3?[t]:e.expand!==!0?nl.compile(t,e):nl.expand(t,e);uZ.exports=nl});var AI=_((ZQt,dZ)=>{"use strict";var I7e=ve("path"),Vu="\\\\/",fZ=`[^${Vu}]`,Bf="\\.",B7e="\\+",v7e="\\?",CP="\\/",D7e="(?=.)",pZ="[^/]",EN=`(?:${CP}|$)`,hZ=`(?:^|${CP})`,CN=`${Bf}{1,2}${EN}`,P7e=`(?!${Bf})`,S7e=`(?!${hZ}${CN})`,b7e=`(?!${Bf}{0,1}${EN})`,x7e=`(?!${CN})`,k7e=`[^.${CP}]`,Q7e=`${pZ}*?`,gZ={DOT_LITERAL:Bf,PLUS_LITERAL:B7e,QMARK_LITERAL:v7e,SLASH_LITERAL:CP,ONE_CHAR:D7e,QMARK:pZ,END_ANCHOR:EN,DOTS_SLASH:CN,NO_DOT:P7e,NO_DOTS:S7e,NO_DOT_SLASH:b7e,NO_DOTS_SLASH:x7e,QMARK_NO_DOT:k7e,STAR:Q7e,START_ANCHOR:hZ},F7e={...gZ,SLASH_LITERAL:`[${Vu}]`,QMARK:fZ,STAR:`${fZ}*?`,DOTS_SLASH:`${Bf}{1,2}(?:[${Vu}]|$)`,NO_DOT:`(?!${Bf})`,NO_DOTS:`(?!(?:^|[${Vu}])${Bf}{1,2}(?:[${Vu}]|$))`,NO_DOT_SLASH:`(?!${Bf}{0,1}(?:[${Vu}]|$))`,NO_DOTS_SLASH:`(?!${Bf}{1,2}(?:[${Vu}]|$))`,QMARK_NO_DOT:`[^.${Vu}]`,START_ANCHOR:`(?:^|[${Vu}])`,END_ANCHOR:`(?:[${Vu}]|$)`},R7e={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};dZ.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:R7e,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:I7e.sep,extglobChars(t){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${t.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(t){return t===!0?F7e:gZ}}});var fI=_(ba=>{"use strict";var T7e=ve("path"),N7e=process.platform==="win32",{REGEX_BACKSLASH:L7e,REGEX_REMOVE_BACKSLASH:M7e,REGEX_SPECIAL_CHARS:O7e,REGEX_SPECIAL_CHARS_GLOBAL:U7e}=AI();ba.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);ba.hasRegexChars=t=>O7e.test(t);ba.isRegexChar=t=>t.length===1&&ba.hasRegexChars(t);ba.escapeRegex=t=>t.replace(U7e,"\\$1");ba.toPosixSlashes=t=>t.replace(L7e,"/");ba.removeBackslashes=t=>t.replace(M7e,e=>e==="\\"?"":e);ba.supportsLookbehinds=()=>{let t=process.version.slice(1).split(".").map(Number);return t.length===3&&t[0]>=9||t[0]===8&&t[1]>=10};ba.isWindows=t=>t&&typeof t.windows=="boolean"?t.windows:N7e===!0||T7e.sep==="\\";ba.escapeLast=(t,e,r)=>{let o=t.lastIndexOf(e,r);return o===-1?t:t[o-1]==="\\"?ba.escapeLast(t,e,o-1):`${t.slice(0,o)}\\${t.slice(o)}`};ba.removePrefix=(t,e={})=>{let r=t;return r.startsWith("./")&&(r=r.slice(2),e.prefix="./"),r};ba.wrapOutput=(t,e={},r={})=>{let o=r.contains?"":"^",a=r.contains?"":"$",n=`${o}(?:${t})${a}`;return e.negated===!0&&(n=`(?:^(?!${n}).*$)`),n}});var vZ=_((eFt,BZ)=>{"use strict";var mZ=fI(),{CHAR_ASTERISK:wN,CHAR_AT:_7e,CHAR_BACKWARD_SLASH:pI,CHAR_COMMA:H7e,CHAR_DOT:IN,CHAR_EXCLAMATION_MARK:BN,CHAR_FORWARD_SLASH:IZ,CHAR_LEFT_CURLY_BRACE:vN,CHAR_LEFT_PARENTHESES:DN,CHAR_LEFT_SQUARE_BRACKET:q7e,CHAR_PLUS:j7e,CHAR_QUESTION_MARK:yZ,CHAR_RIGHT_CURLY_BRACE:G7e,CHAR_RIGHT_PARENTHESES:EZ,CHAR_RIGHT_SQUARE_BRACKET:Y7e}=AI(),CZ=t=>t===IZ||t===pI,wZ=t=>{t.isPrefix!==!0&&(t.depth=t.isGlobstar?1/0:1)},W7e=(t,e)=>{let r=e||{},o=t.length-1,a=r.parts===!0||r.scanToEnd===!0,n=[],u=[],A=[],p=t,h=-1,E=0,I=0,v=!1,x=!1,C=!1,R=!1,L=!1,U=!1,z=!1,te=!1,ae=!1,le=!1,ce=0,Ce,de,Be={value:"",depth:0,isGlob:!1},Ee=()=>h>=o,g=()=>p.charCodeAt(h+1),me=()=>(Ce=de,p.charCodeAt(++h));for(;h<o;){de=me();let xe;if(de===pI){z=Be.backslashes=!0,de=me(),de===vN&&(U=!0);continue}if(U===!0||de===vN){for(ce++;Ee()!==!0&&(de=me());){if(de===pI){z=Be.backslashes=!0,me();continue}if(de===vN){ce++;continue}if(U!==!0&&de===IN&&(de=me())===IN){if(v=Be.isBrace=!0,C=Be.isGlob=!0,le=!0,a===!0)continue;break}if(U!==!0&&de===H7e){if(v=Be.isBrace=!0,C=Be.isGlob=!0,le=!0,a===!0)continue;break}if(de===G7e&&(ce--,ce===0)){U=!1,v=Be.isBrace=!0,le=!0;break}}if(a===!0)continue;break}if(de===IZ){if(n.push(h),u.push(Be),Be={value:"",depth:0,isGlob:!1},le===!0)continue;if(Ce===IN&&h===E+1){E+=2;continue}I=h+1;continue}if(r.noext!==!0&&(de===j7e||de===_7e||de===wN||de===yZ||de===BN)===!0&&g()===DN){if(C=Be.isGlob=!0,R=Be.isExtglob=!0,le=!0,de===BN&&h===E&&(ae=!0),a===!0){for(;Ee()!==!0&&(de=me());){if(de===pI){z=Be.backslashes=!0,de=me();continue}if(de===EZ){C=Be.isGlob=!0,le=!0;break}}continue}break}if(de===wN){if(Ce===wN&&(L=Be.isGlobstar=!0),C=Be.isGlob=!0,le=!0,a===!0)continue;break}if(de===yZ){if(C=Be.isGlob=!0,le=!0,a===!0)continue;break}if(de===q7e){for(;Ee()!==!0&&(xe=me());){if(xe===pI){z=Be.backslashes=!0,me();continue}if(xe===Y7e){x=Be.isBracket=!0,C=Be.isGlob=!0,le=!0;break}}if(a===!0)continue;break}if(r.nonegate!==!0&&de===BN&&h===E){te=Be.negated=!0,E++;continue}if(r.noparen!==!0&&de===DN){if(C=Be.isGlob=!0,a===!0){for(;Ee()!==!0&&(de=me());){if(de===DN){z=Be.backslashes=!0,de=me();continue}if(de===EZ){le=!0;break}}continue}break}if(C===!0){if(le=!0,a===!0)continue;break}}r.noext===!0&&(R=!1,C=!1);let we=p,Ae="",ne="";E>0&&(Ae=p.slice(0,E),p=p.slice(E),I-=E),we&&C===!0&&I>0?(we=p.slice(0,I),ne=p.slice(I)):C===!0?(we="",ne=p):we=p,we&&we!==""&&we!=="/"&&we!==p&&CZ(we.charCodeAt(we.length-1))&&(we=we.slice(0,-1)),r.unescape===!0&&(ne&&(ne=mZ.removeBackslashes(ne)),we&&z===!0&&(we=mZ.removeBackslashes(we)));let Z={prefix:Ae,input:t,start:E,base:we,glob:ne,isBrace:v,isBracket:x,isGlob:C,isExtglob:R,isGlobstar:L,negated:te,negatedExtglob:ae};if(r.tokens===!0&&(Z.maxDepth=0,CZ(de)||u.push(Be),Z.tokens=u),r.parts===!0||r.tokens===!0){let xe;for(let Ne=0;Ne<n.length;Ne++){let ht=xe?xe+1:E,H=n[Ne],rt=t.slice(ht,H);r.tokens&&(Ne===0&&E!==0?(u[Ne].isPrefix=!0,u[Ne].value=Ae):u[Ne].value=rt,wZ(u[Ne]),Z.maxDepth+=u[Ne].depth),(Ne!==0||rt!=="")&&A.push(rt),xe=H}if(xe&&xe+1<t.length){let Ne=t.slice(xe+1);A.push(Ne),r.tokens&&(u[u.length-1].value=Ne,wZ(u[u.length-1]),Z.maxDepth+=u[u.length-1].depth)}Z.slashes=n,Z.parts=A}return Z};BZ.exports=W7e});var SZ=_((tFt,PZ)=>{"use strict";var wP=AI(),il=fI(),{MAX_LENGTH:IP,POSIX_REGEX_SOURCE:K7e,REGEX_NON_SPECIAL_CHARS:V7e,REGEX_SPECIAL_CHARS_BACKREF:z7e,REPLACEMENTS:DZ}=wP,J7e=(t,e)=>{if(typeof e.expandRange=="function")return e.expandRange(...t,e);t.sort();let r=`[${t.join("-")}]`;try{new RegExp(r)}catch{return t.map(a=>il.escapeRegex(a)).join("..")}return r},mm=(t,e)=>`Missing ${t}: "${e}" - use "\\\\${e}" to match literal characters`,PN=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");t=DZ[t]||t;let r={...e},o=typeof r.maxLength=="number"?Math.min(IP,r.maxLength):IP,a=t.length;if(a>o)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${o}`);let n={type:"bos",value:"",output:r.prepend||""},u=[n],A=r.capture?"":"?:",p=il.isWindows(e),h=wP.globChars(p),E=wP.extglobChars(h),{DOT_LITERAL:I,PLUS_LITERAL:v,SLASH_LITERAL:x,ONE_CHAR:C,DOTS_SLASH:R,NO_DOT:L,NO_DOT_SLASH:U,NO_DOTS_SLASH:z,QMARK:te,QMARK_NO_DOT:ae,STAR:le,START_ANCHOR:ce}=h,Ce=b=>`(${A}(?:(?!${ce}${b.dot?R:I}).)*?)`,de=r.dot?"":L,Be=r.dot?te:ae,Ee=r.bash===!0?Ce(r):le;r.capture&&(Ee=`(${Ee})`),typeof r.noext=="boolean"&&(r.noextglob=r.noext);let g={input:t,index:-1,start:0,dot:r.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:u};t=il.removePrefix(t,g),a=t.length;let me=[],we=[],Ae=[],ne=n,Z,xe=()=>g.index===a-1,Ne=g.peek=(b=1)=>t[g.index+b],ht=g.advance=()=>t[++g.index]||"",H=()=>t.slice(g.index+1),rt=(b="",w=0)=>{g.consumed+=b,g.index+=w},Te=b=>{g.output+=b.output!=null?b.output:b.value,rt(b.value)},Fe=()=>{let b=1;for(;Ne()==="!"&&(Ne(2)!=="("||Ne(3)==="?");)ht(),g.start++,b++;return b%2===0?!1:(g.negated=!0,g.start++,!0)},ke=b=>{g[b]++,Ae.push(b)},Ye=b=>{g[b]--,Ae.pop()},Se=b=>{if(ne.type==="globstar"){let w=g.braces>0&&(b.type==="comma"||b.type==="brace"),S=b.extglob===!0||me.length&&(b.type==="pipe"||b.type==="paren");b.type!=="slash"&&b.type!=="paren"&&!w&&!S&&(g.output=g.output.slice(0,-ne.output.length),ne.type="star",ne.value="*",ne.output=Ee,g.output+=ne.output)}if(me.length&&b.type!=="paren"&&(me[me.length-1].inner+=b.value),(b.value||b.output)&&Te(b),ne&&ne.type==="text"&&b.type==="text"){ne.value+=b.value,ne.output=(ne.output||"")+b.value;return}b.prev=ne,u.push(b),ne=b},et=(b,w)=>{let S={...E[w],conditions:1,inner:""};S.prev=ne,S.parens=g.parens,S.output=g.output;let y=(r.capture?"(":"")+S.open;ke("parens"),Se({type:b,value:w,output:g.output?"":C}),Se({type:"paren",extglob:!0,value:ht(),output:y}),me.push(S)},Ue=b=>{let w=b.close+(r.capture?")":""),S;if(b.type==="negate"){let y=Ee;if(b.inner&&b.inner.length>1&&b.inner.includes("/")&&(y=Ce(r)),(y!==Ee||xe()||/^\)+$/.test(H()))&&(w=b.close=`)$))${y}`),b.inner.includes("*")&&(S=H())&&/^\.[^\\/.]+$/.test(S)){let F=PN(S,{...e,fastpaths:!1}).output;w=b.close=`)${F})${y})`}b.prev.type==="bos"&&(g.negatedExtglob=!0)}Se({type:"paren",extglob:!0,value:Z,output:w}),Ye("parens")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(t)){let b=!1,w=t.replace(z7e,(S,y,F,J,X,$)=>J==="\\"?(b=!0,S):J==="?"?y?y+J+(X?te.repeat(X.length):""):$===0?Be+(X?te.repeat(X.length):""):te.repeat(F.length):J==="."?I.repeat(F.length):J==="*"?y?y+J+(X?Ee:""):Ee:y?S:`\\${S}`);return b===!0&&(r.unescape===!0?w=w.replace(/\\/g,""):w=w.replace(/\\+/g,S=>S.length%2===0?"\\\\":S?"\\":"")),w===t&&r.contains===!0?(g.output=t,g):(g.output=il.wrapOutput(w,g,e),g)}for(;!xe();){if(Z=ht(),Z==="\0")continue;if(Z==="\\"){let S=Ne();if(S==="/"&&r.bash!==!0||S==="."||S===";")continue;if(!S){Z+="\\",Se({type:"text",value:Z});continue}let y=/^\\+/.exec(H()),F=0;if(y&&y[0].length>2&&(F=y[0].length,g.index+=F,F%2!==0&&(Z+="\\")),r.unescape===!0?Z=ht():Z+=ht(),g.brackets===0){Se({type:"text",value:Z});continue}}if(g.brackets>0&&(Z!=="]"||ne.value==="["||ne.value==="[^")){if(r.posix!==!1&&Z===":"){let S=ne.value.slice(1);if(S.includes("[")&&(ne.posix=!0,S.includes(":"))){let y=ne.value.lastIndexOf("["),F=ne.value.slice(0,y),J=ne.value.slice(y+2),X=K7e[J];if(X){ne.value=F+X,g.backtrack=!0,ht(),!n.output&&u.indexOf(ne)===1&&(n.output=C);continue}}}(Z==="["&&Ne()!==":"||Z==="-"&&Ne()==="]")&&(Z=`\\${Z}`),Z==="]"&&(ne.value==="["||ne.value==="[^")&&(Z=`\\${Z}`),r.posix===!0&&Z==="!"&&ne.value==="["&&(Z="^"),ne.value+=Z,Te({value:Z});continue}if(g.quotes===1&&Z!=='"'){Z=il.escapeRegex(Z),ne.value+=Z,Te({value:Z});continue}if(Z==='"'){g.quotes=g.quotes===1?0:1,r.keepQuotes===!0&&Se({type:"text",value:Z});continue}if(Z==="("){ke("parens"),Se({type:"paren",value:Z});continue}if(Z===")"){if(g.parens===0&&r.strictBrackets===!0)throw new SyntaxError(mm("opening","("));let S=me[me.length-1];if(S&&g.parens===S.parens+1){Ue(me.pop());continue}Se({type:"paren",value:Z,output:g.parens?")":"\\)"}),Ye("parens");continue}if(Z==="["){if(r.nobracket===!0||!H().includes("]")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(mm("closing","]"));Z=`\\${Z}`}else ke("brackets");Se({type:"bracket",value:Z});continue}if(Z==="]"){if(r.nobracket===!0||ne&&ne.type==="bracket"&&ne.value.length===1){Se({type:"text",value:Z,output:`\\${Z}`});continue}if(g.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(mm("opening","["));Se({type:"text",value:Z,output:`\\${Z}`});continue}Ye("brackets");let S=ne.value.slice(1);if(ne.posix!==!0&&S[0]==="^"&&!S.includes("/")&&(Z=`/${Z}`),ne.value+=Z,Te({value:Z}),r.literalBrackets===!1||il.hasRegexChars(S))continue;let y=il.escapeRegex(ne.value);if(g.output=g.output.slice(0,-ne.value.length),r.literalBrackets===!0){g.output+=y,ne.value=y;continue}ne.value=`(${A}${y}|${ne.value})`,g.output+=ne.value;continue}if(Z==="{"&&r.nobrace!==!0){ke("braces");let S={type:"brace",value:Z,output:"(",outputIndex:g.output.length,tokensIndex:g.tokens.length};we.push(S),Se(S);continue}if(Z==="}"){let S=we[we.length-1];if(r.nobrace===!0||!S){Se({type:"text",value:Z,output:Z});continue}let y=")";if(S.dots===!0){let F=u.slice(),J=[];for(let X=F.length-1;X>=0&&(u.pop(),F[X].type!=="brace");X--)F[X].type!=="dots"&&J.unshift(F[X].value);y=J7e(J,r),g.backtrack=!0}if(S.comma!==!0&&S.dots!==!0){let F=g.output.slice(0,S.outputIndex),J=g.tokens.slice(S.tokensIndex);S.value=S.output="\\{",Z=y="\\}",g.output=F;for(let X of J)g.output+=X.output||X.value}Se({type:"brace",value:Z,output:y}),Ye("braces"),we.pop();continue}if(Z==="|"){me.length>0&&me[me.length-1].conditions++,Se({type:"text",value:Z});continue}if(Z===","){let S=Z,y=we[we.length-1];y&&Ae[Ae.length-1]==="braces"&&(y.comma=!0,S="|"),Se({type:"comma",value:Z,output:S});continue}if(Z==="/"){if(ne.type==="dot"&&g.index===g.start+1){g.start=g.index+1,g.consumed="",g.output="",u.pop(),ne=n;continue}Se({type:"slash",value:Z,output:x});continue}if(Z==="."){if(g.braces>0&&ne.type==="dot"){ne.value==="."&&(ne.output=I);let S=we[we.length-1];ne.type="dots",ne.output+=Z,ne.value+=Z,S.dots=!0;continue}if(g.braces+g.parens===0&&ne.type!=="bos"&&ne.type!=="slash"){Se({type:"text",value:Z,output:I});continue}Se({type:"dot",value:Z,output:I});continue}if(Z==="?"){if(!(ne&&ne.value==="(")&&r.noextglob!==!0&&Ne()==="("&&Ne(2)!=="?"){et("qmark",Z);continue}if(ne&&ne.type==="paren"){let y=Ne(),F=Z;if(y==="<"&&!il.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(ne.value==="("&&!/[!=<:]/.test(y)||y==="<"&&!/<([!=]|\w+>)/.test(H()))&&(F=`\\${Z}`),Se({type:"text",value:Z,output:F});continue}if(r.dot!==!0&&(ne.type==="slash"||ne.type==="bos")){Se({type:"qmark",value:Z,output:ae});continue}Se({type:"qmark",value:Z,output:te});continue}if(Z==="!"){if(r.noextglob!==!0&&Ne()==="("&&(Ne(2)!=="?"||!/[!=<:]/.test(Ne(3)))){et("negate",Z);continue}if(r.nonegate!==!0&&g.index===0){Fe();continue}}if(Z==="+"){if(r.noextglob!==!0&&Ne()==="("&&Ne(2)!=="?"){et("plus",Z);continue}if(ne&&ne.value==="("||r.regex===!1){Se({type:"plus",value:Z,output:v});continue}if(ne&&(ne.type==="bracket"||ne.type==="paren"||ne.type==="brace")||g.parens>0){Se({type:"plus",value:Z});continue}Se({type:"plus",value:v});continue}if(Z==="@"){if(r.noextglob!==!0&&Ne()==="("&&Ne(2)!=="?"){Se({type:"at",extglob:!0,value:Z,output:""});continue}Se({type:"text",value:Z});continue}if(Z!=="*"){(Z==="$"||Z==="^")&&(Z=`\\${Z}`);let S=V7e.exec(H());S&&(Z+=S[0],g.index+=S[0].length),Se({type:"text",value:Z});continue}if(ne&&(ne.type==="globstar"||ne.star===!0)){ne.type="star",ne.star=!0,ne.value+=Z,ne.output=Ee,g.backtrack=!0,g.globstar=!0,rt(Z);continue}let b=H();if(r.noextglob!==!0&&/^\([^?]/.test(b)){et("star",Z);continue}if(ne.type==="star"){if(r.noglobstar===!0){rt(Z);continue}let S=ne.prev,y=S.prev,F=S.type==="slash"||S.type==="bos",J=y&&(y.type==="star"||y.type==="globstar");if(r.bash===!0&&(!F||b[0]&&b[0]!=="/")){Se({type:"star",value:Z,output:""});continue}let X=g.braces>0&&(S.type==="comma"||S.type==="brace"),$=me.length&&(S.type==="pipe"||S.type==="paren");if(!F&&S.type!=="paren"&&!X&&!$){Se({type:"star",value:Z,output:""});continue}for(;b.slice(0,3)==="/**";){let ie=t[g.index+4];if(ie&&ie!=="/")break;b=b.slice(3),rt("/**",3)}if(S.type==="bos"&&xe()){ne.type="globstar",ne.value+=Z,ne.output=Ce(r),g.output=ne.output,g.globstar=!0,rt(Z);continue}if(S.type==="slash"&&S.prev.type!=="bos"&&!J&&xe()){g.output=g.output.slice(0,-(S.output+ne.output).length),S.output=`(?:${S.output}`,ne.type="globstar",ne.output=Ce(r)+(r.strictSlashes?")":"|$)"),ne.value+=Z,g.globstar=!0,g.output+=S.output+ne.output,rt(Z);continue}if(S.type==="slash"&&S.prev.type!=="bos"&&b[0]==="/"){let ie=b[1]!==void 0?"|$":"";g.output=g.output.slice(0,-(S.output+ne.output).length),S.output=`(?:${S.output}`,ne.type="globstar",ne.output=`${Ce(r)}${x}|${x}${ie})`,ne.value+=Z,g.output+=S.output+ne.output,g.globstar=!0,rt(Z+ht()),Se({type:"slash",value:"/",output:""});continue}if(S.type==="bos"&&b[0]==="/"){ne.type="globstar",ne.value+=Z,ne.output=`(?:^|${x}|${Ce(r)}${x})`,g.output=ne.output,g.globstar=!0,rt(Z+ht()),Se({type:"slash",value:"/",output:""});continue}g.output=g.output.slice(0,-ne.output.length),ne.type="globstar",ne.output=Ce(r),ne.value+=Z,g.output+=ne.output,g.globstar=!0,rt(Z);continue}let w={type:"star",value:Z,output:Ee};if(r.bash===!0){w.output=".*?",(ne.type==="bos"||ne.type==="slash")&&(w.output=de+w.output),Se(w);continue}if(ne&&(ne.type==="bracket"||ne.type==="paren")&&r.regex===!0){w.output=Z,Se(w);continue}(g.index===g.start||ne.type==="slash"||ne.type==="dot")&&(ne.type==="dot"?(g.output+=U,ne.output+=U):r.dot===!0?(g.output+=z,ne.output+=z):(g.output+=de,ne.output+=de),Ne()!=="*"&&(g.output+=C,ne.output+=C)),Se(w)}for(;g.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(mm("closing","]"));g.output=il.escapeLast(g.output,"["),Ye("brackets")}for(;g.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(mm("closing",")"));g.output=il.escapeLast(g.output,"("),Ye("parens")}for(;g.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(mm("closing","}"));g.output=il.escapeLast(g.output,"{"),Ye("braces")}if(r.strictSlashes!==!0&&(ne.type==="star"||ne.type==="bracket")&&Se({type:"maybe_slash",value:"",output:`${x}?`}),g.backtrack===!0){g.output="";for(let b of g.tokens)g.output+=b.output!=null?b.output:b.value,b.suffix&&(g.output+=b.suffix)}return g};PN.fastpaths=(t,e)=>{let r={...e},o=typeof r.maxLength=="number"?Math.min(IP,r.maxLength):IP,a=t.length;if(a>o)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${o}`);t=DZ[t]||t;let n=il.isWindows(e),{DOT_LITERAL:u,SLASH_LITERAL:A,ONE_CHAR:p,DOTS_SLASH:h,NO_DOT:E,NO_DOTS:I,NO_DOTS_SLASH:v,STAR:x,START_ANCHOR:C}=wP.globChars(n),R=r.dot?I:E,L=r.dot?v:E,U=r.capture?"":"?:",z={negated:!1,prefix:""},te=r.bash===!0?".*?":x;r.capture&&(te=`(${te})`);let ae=de=>de.noglobstar===!0?te:`(${U}(?:(?!${C}${de.dot?h:u}).)*?)`,le=de=>{switch(de){case"*":return`${R}${p}${te}`;case".*":return`${u}${p}${te}`;case"*.*":return`${R}${te}${u}${p}${te}`;case"*/*":return`${R}${te}${A}${p}${L}${te}`;case"**":return R+ae(r);case"**/*":return`(?:${R}${ae(r)}${A})?${L}${p}${te}`;case"**/*.*":return`(?:${R}${ae(r)}${A})?${L}${te}${u}${p}${te}`;case"**/.*":return`(?:${R}${ae(r)}${A})?${u}${p}${te}`;default:{let Be=/^(.*?)\.(\w+)$/.exec(de);if(!Be)return;let Ee=le(Be[1]);return Ee?Ee+u+Be[2]:void 0}}},ce=il.removePrefix(t,z),Ce=le(ce);return Ce&&r.strictSlashes!==!0&&(Ce+=`${A}?`),Ce};PZ.exports=PN});var xZ=_((rFt,bZ)=>{"use strict";var X7e=ve("path"),Z7e=vZ(),SN=SZ(),bN=fI(),$7e=AI(),eYe=t=>t&&typeof t=="object"&&!Array.isArray(t),Mi=(t,e,r=!1)=>{if(Array.isArray(t)){let E=t.map(v=>Mi(v,e,r));return v=>{for(let x of E){let C=x(v);if(C)return C}return!1}}let o=eYe(t)&&t.tokens&&t.input;if(t===""||typeof t!="string"&&!o)throw new TypeError("Expected pattern to be a non-empty string");let a=e||{},n=bN.isWindows(e),u=o?Mi.compileRe(t,e):Mi.makeRe(t,e,!1,!0),A=u.state;delete u.state;let p=()=>!1;if(a.ignore){let E={...e,ignore:null,onMatch:null,onResult:null};p=Mi(a.ignore,E,r)}let h=(E,I=!1)=>{let{isMatch:v,match:x,output:C}=Mi.test(E,u,e,{glob:t,posix:n}),R={glob:t,state:A,regex:u,posix:n,input:E,output:C,match:x,isMatch:v};return typeof a.onResult=="function"&&a.onResult(R),v===!1?(R.isMatch=!1,I?R:!1):p(E)?(typeof a.onIgnore=="function"&&a.onIgnore(R),R.isMatch=!1,I?R:!1):(typeof a.onMatch=="function"&&a.onMatch(R),I?R:!0)};return r&&(h.state=A),h};Mi.test=(t,e,r,{glob:o,posix:a}={})=>{if(typeof t!="string")throw new TypeError("Expected input to be a string");if(t==="")return{isMatch:!1,output:""};let n=r||{},u=n.format||(a?bN.toPosixSlashes:null),A=t===o,p=A&&u?u(t):t;return A===!1&&(p=u?u(t):t,A=p===o),(A===!1||n.capture===!0)&&(n.matchBase===!0||n.basename===!0?A=Mi.matchBase(t,e,r,a):A=e.exec(p)),{isMatch:!!A,match:A,output:p}};Mi.matchBase=(t,e,r,o=bN.isWindows(r))=>(e instanceof RegExp?e:Mi.makeRe(e,r)).test(X7e.basename(t));Mi.isMatch=(t,e,r)=>Mi(e,r)(t);Mi.parse=(t,e)=>Array.isArray(t)?t.map(r=>Mi.parse(r,e)):SN(t,{...e,fastpaths:!1});Mi.scan=(t,e)=>Z7e(t,e);Mi.compileRe=(t,e,r=!1,o=!1)=>{if(r===!0)return t.output;let a=e||{},n=a.contains?"":"^",u=a.contains?"":"$",A=`${n}(?:${t.output})${u}`;t&&t.negated===!0&&(A=`^(?!${A}).*$`);let p=Mi.toRegex(A,e);return o===!0&&(p.state=t),p};Mi.makeRe=(t,e={},r=!1,o=!1)=>{if(!t||typeof t!="string")throw new TypeError("Expected a non-empty string");let a={negated:!1,fastpaths:!0};return e.fastpaths!==!1&&(t[0]==="."||t[0]==="*")&&(a.output=SN.fastpaths(t,e)),a.output||(a=SN(t,e)),Mi.compileRe(a,e,r,o)};Mi.toRegex=(t,e)=>{try{let r=e||{};return new RegExp(t,r.flags||(r.nocase?"i":""))}catch(r){if(e&&e.debug===!0)throw r;return/$^/}};Mi.constants=$7e;bZ.exports=Mi});var QZ=_((nFt,kZ)=>{"use strict";kZ.exports=xZ()});var $o=_((iFt,NZ)=>{"use strict";var RZ=ve("util"),TZ=AZ(),zu=QZ(),xN=fI(),FZ=t=>t===""||t==="./",mi=(t,e,r)=>{e=[].concat(e),t=[].concat(t);let o=new Set,a=new Set,n=new Set,u=0,A=E=>{n.add(E.output),r&&r.onResult&&r.onResult(E)};for(let E=0;E<e.length;E++){let I=zu(String(e[E]),{...r,onResult:A},!0),v=I.state.negated||I.state.negatedExtglob;v&&u++;for(let x of t){let C=I(x,!0);(v?!C.isMatch:C.isMatch)&&(v?o.add(C.output):(o.delete(C.output),a.add(C.output)))}}let h=(u===e.length?[...n]:[...a]).filter(E=>!o.has(E));if(r&&h.length===0){if(r.failglob===!0)throw new Error(`No matches found for "${e.join(", ")}"`);if(r.nonull===!0||r.nullglob===!0)return r.unescape?e.map(E=>E.replace(/\\/g,"")):e}return h};mi.match=mi;mi.matcher=(t,e)=>zu(t,e);mi.isMatch=(t,e,r)=>zu(e,r)(t);mi.any=mi.isMatch;mi.not=(t,e,r={})=>{e=[].concat(e).map(String);let o=new Set,a=[],n=A=>{r.onResult&&r.onResult(A),a.push(A.output)},u=new Set(mi(t,e,{...r,onResult:n}));for(let A of a)u.has(A)||o.add(A);return[...o]};mi.contains=(t,e,r)=>{if(typeof t!="string")throw new TypeError(`Expected a string: "${RZ.inspect(t)}"`);if(Array.isArray(e))return e.some(o=>mi.contains(t,o,r));if(typeof e=="string"){if(FZ(t)||FZ(e))return!1;if(t.includes(e)||t.startsWith("./")&&t.slice(2).includes(e))return!0}return mi.isMatch(t,e,{...r,contains:!0})};mi.matchKeys=(t,e,r)=>{if(!xN.isObject(t))throw new TypeError("Expected the first argument to be an object");let o=mi(Object.keys(t),e,r),a={};for(let n of o)a[n]=t[n];return a};mi.some=(t,e,r)=>{let o=[].concat(t);for(let a of[].concat(e)){let n=zu(String(a),r);if(o.some(u=>n(u)))return!0}return!1};mi.every=(t,e,r)=>{let o=[].concat(t);for(let a of[].concat(e)){let n=zu(String(a),r);if(!o.every(u=>n(u)))return!1}return!0};mi.all=(t,e,r)=>{if(typeof t!="string")throw new TypeError(`Expected a string: "${RZ.inspect(t)}"`);return[].concat(e).every(o=>zu(o,r)(t))};mi.capture=(t,e,r)=>{let o=xN.isWindows(r),n=zu.makeRe(String(t),{...r,capture:!0}).exec(o?xN.toPosixSlashes(e):e);if(n)return n.slice(1).map(u=>u===void 0?"":u)};mi.makeRe=(...t)=>zu.makeRe(...t);mi.scan=(...t)=>zu.scan(...t);mi.parse=(t,e)=>{let r=[];for(let o of[].concat(t||[]))for(let a of TZ(String(o),e))r.push(zu.parse(a,e));return r};mi.braces=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");return e&&e.nobrace===!0||!/\{.*\}/.test(t)?[t]:TZ(t,e)};mi.braceExpand=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");return mi.braces(t,{...e,expand:!0})};NZ.exports=mi});var MZ=_((sFt,LZ)=>{"use strict";LZ.exports=({onlyFirst:t=!1}={})=>{let e=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(e,t?void 0:"g")}});var BP=_((oFt,OZ)=>{"use strict";var tYe=MZ();OZ.exports=t=>typeof t=="string"?t.replace(tYe(),""):t});var _Z=_((aFt,UZ)=>{function rYe(){this.__data__=[],this.size=0}UZ.exports=rYe});var ym=_((lFt,HZ)=>{function nYe(t,e){return t===e||t!==t&&e!==e}HZ.exports=nYe});var hI=_((cFt,qZ)=>{var iYe=ym();function sYe(t,e){for(var r=t.length;r--;)if(iYe(t[r][0],e))return r;return-1}qZ.exports=sYe});var GZ=_((uFt,jZ)=>{var oYe=hI(),aYe=Array.prototype,lYe=aYe.splice;function cYe(t){var e=this.__data__,r=oYe(e,t);if(r<0)return!1;var o=e.length-1;return r==o?e.pop():lYe.call(e,r,1),--this.size,!0}jZ.exports=cYe});var WZ=_((AFt,YZ)=>{var uYe=hI();function AYe(t){var e=this.__data__,r=uYe(e,t);return r<0?void 0:e[r][1]}YZ.exports=AYe});var VZ=_((fFt,KZ)=>{var fYe=hI();function pYe(t){return fYe(this.__data__,t)>-1}KZ.exports=pYe});var JZ=_((pFt,zZ)=>{var hYe=hI();function gYe(t,e){var r=this.__data__,o=hYe(r,t);return o<0?(++this.size,r.push([t,e])):r[o][1]=e,this}zZ.exports=gYe});var gI=_((hFt,XZ)=>{var dYe=_Z(),mYe=GZ(),yYe=WZ(),EYe=VZ(),CYe=JZ();function Em(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var o=t[e];this.set(o[0],o[1])}}Em.prototype.clear=dYe;Em.prototype.delete=mYe;Em.prototype.get=yYe;Em.prototype.has=EYe;Em.prototype.set=CYe;XZ.exports=Em});var $Z=_((gFt,ZZ)=>{var wYe=gI();function IYe(){this.__data__=new wYe,this.size=0}ZZ.exports=IYe});var t$=_((dFt,e$)=>{function BYe(t){var e=this.__data__,r=e.delete(t);return this.size=e.size,r}e$.exports=BYe});var n$=_((mFt,r$)=>{function vYe(t){return this.__data__.get(t)}r$.exports=vYe});var s$=_((yFt,i$)=>{function DYe(t){return this.__data__.has(t)}i$.exports=DYe});var kN=_((EFt,o$)=>{var PYe=typeof global=="object"&&global&&global.Object===Object&&global;o$.exports=PYe});var _l=_((CFt,a$)=>{var SYe=kN(),bYe=typeof self=="object"&&self&&self.Object===Object&&self,xYe=SYe||bYe||Function("return this")();a$.exports=xYe});var lg=_((wFt,l$)=>{var kYe=_l(),QYe=kYe.Symbol;l$.exports=QYe});var f$=_((IFt,A$)=>{var c$=lg(),u$=Object.prototype,FYe=u$.hasOwnProperty,RYe=u$.toString,dI=c$?c$.toStringTag:void 0;function TYe(t){var e=FYe.call(t,dI),r=t[dI];try{t[dI]=void 0;var o=!0}catch{}var a=RYe.call(t);return o&&(e?t[dI]=r:delete t[dI]),a}A$.exports=TYe});var h$=_((BFt,p$)=>{var NYe=Object.prototype,LYe=NYe.toString;function MYe(t){return LYe.call(t)}p$.exports=MYe});var cg=_((vFt,m$)=>{var g$=lg(),OYe=f$(),UYe=h$(),_Ye="[object Null]",HYe="[object Undefined]",d$=g$?g$.toStringTag:void 0;function qYe(t){return t==null?t===void 0?HYe:_Ye:d$&&d$ in Object(t)?OYe(t):UYe(t)}m$.exports=qYe});var sl=_((DFt,y$)=>{function jYe(t){var e=typeof t;return t!=null&&(e=="object"||e=="function")}y$.exports=jYe});var vP=_((PFt,E$)=>{var GYe=cg(),YYe=sl(),WYe="[object AsyncFunction]",KYe="[object Function]",VYe="[object GeneratorFunction]",zYe="[object Proxy]";function JYe(t){if(!YYe(t))return!1;var e=GYe(t);return e==KYe||e==VYe||e==WYe||e==zYe}E$.exports=JYe});var w$=_((SFt,C$)=>{var XYe=_l(),ZYe=XYe["__core-js_shared__"];C$.exports=ZYe});var v$=_((bFt,B$)=>{var QN=w$(),I$=function(){var t=/[^.]+$/.exec(QN&&QN.keys&&QN.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}();function $Ye(t){return!!I$&&I$ in t}B$.exports=$Ye});var FN=_((xFt,D$)=>{var eWe=Function.prototype,tWe=eWe.toString;function rWe(t){if(t!=null){try{return tWe.call(t)}catch{}try{return t+""}catch{}}return""}D$.exports=rWe});var S$=_((kFt,P$)=>{var nWe=vP(),iWe=v$(),sWe=sl(),oWe=FN(),aWe=/[\\^$.*+?()[\]{}|]/g,lWe=/^\[object .+?Constructor\]$/,cWe=Function.prototype,uWe=Object.prototype,AWe=cWe.toString,fWe=uWe.hasOwnProperty,pWe=RegExp("^"+AWe.call(fWe).replace(aWe,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function hWe(t){if(!sWe(t)||iWe(t))return!1;var e=nWe(t)?pWe:lWe;return e.test(oWe(t))}P$.exports=hWe});var x$=_((QFt,b$)=>{function gWe(t,e){return t?.[e]}b$.exports=gWe});var Kp=_((FFt,k$)=>{var dWe=S$(),mWe=x$();function yWe(t,e){var r=mWe(t,e);return dWe(r)?r:void 0}k$.exports=yWe});var DP=_((RFt,Q$)=>{var EWe=Kp(),CWe=_l(),wWe=EWe(CWe,"Map");Q$.exports=wWe});var mI=_((TFt,F$)=>{var IWe=Kp(),BWe=IWe(Object,"create");F$.exports=BWe});var N$=_((NFt,T$)=>{var R$=mI();function vWe(){this.__data__=R$?R$(null):{},this.size=0}T$.exports=vWe});var M$=_((LFt,L$)=>{function DWe(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}L$.exports=DWe});var U$=_((MFt,O$)=>{var PWe=mI(),SWe="__lodash_hash_undefined__",bWe=Object.prototype,xWe=bWe.hasOwnProperty;function kWe(t){var e=this.__data__;if(PWe){var r=e[t];return r===SWe?void 0:r}return xWe.call(e,t)?e[t]:void 0}O$.exports=kWe});var H$=_((OFt,_$)=>{var QWe=mI(),FWe=Object.prototype,RWe=FWe.hasOwnProperty;function TWe(t){var e=this.__data__;return QWe?e[t]!==void 0:RWe.call(e,t)}_$.exports=TWe});var j$=_((UFt,q$)=>{var NWe=mI(),LWe="__lodash_hash_undefined__";function MWe(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=NWe&&e===void 0?LWe:e,this}q$.exports=MWe});var Y$=_((_Ft,G$)=>{var OWe=N$(),UWe=M$(),_We=U$(),HWe=H$(),qWe=j$();function Cm(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var o=t[e];this.set(o[0],o[1])}}Cm.prototype.clear=OWe;Cm.prototype.delete=UWe;Cm.prototype.get=_We;Cm.prototype.has=HWe;Cm.prototype.set=qWe;G$.exports=Cm});var V$=_((HFt,K$)=>{var W$=Y$(),jWe=gI(),GWe=DP();function YWe(){this.size=0,this.__data__={hash:new W$,map:new(GWe||jWe),string:new W$}}K$.exports=YWe});var J$=_((qFt,z$)=>{function WWe(t){var e=typeof t;return e=="string"||e=="number"||e=="symbol"||e=="boolean"?t!=="__proto__":t===null}z$.exports=WWe});var yI=_((jFt,X$)=>{var KWe=J$();function VWe(t,e){var r=t.__data__;return KWe(e)?r[typeof e=="string"?"string":"hash"]:r.map}X$.exports=VWe});var $$=_((GFt,Z$)=>{var zWe=yI();function JWe(t){var e=zWe(this,t).delete(t);return this.size-=e?1:0,e}Z$.exports=JWe});var tee=_((YFt,eee)=>{var XWe=yI();function ZWe(t){return XWe(this,t).get(t)}eee.exports=ZWe});var nee=_((WFt,ree)=>{var $We=yI();function eKe(t){return $We(this,t).has(t)}ree.exports=eKe});var see=_((KFt,iee)=>{var tKe=yI();function rKe(t,e){var r=tKe(this,t),o=r.size;return r.set(t,e),this.size+=r.size==o?0:1,this}iee.exports=rKe});var PP=_((VFt,oee)=>{var nKe=V$(),iKe=$$(),sKe=tee(),oKe=nee(),aKe=see();function wm(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var o=t[e];this.set(o[0],o[1])}}wm.prototype.clear=nKe;wm.prototype.delete=iKe;wm.prototype.get=sKe;wm.prototype.has=oKe;wm.prototype.set=aKe;oee.exports=wm});var lee=_((zFt,aee)=>{var lKe=gI(),cKe=DP(),uKe=PP(),AKe=200;function fKe(t,e){var r=this.__data__;if(r instanceof lKe){var o=r.__data__;if(!cKe||o.length<AKe-1)return o.push([t,e]),this.size=++r.size,this;r=this.__data__=new uKe(o)}return r.set(t,e),this.size=r.size,this}aee.exports=fKe});var SP=_((JFt,cee)=>{var pKe=gI(),hKe=$Z(),gKe=t$(),dKe=n$(),mKe=s$(),yKe=lee();function Im(t){var e=this.__data__=new pKe(t);this.size=e.size}Im.prototype.clear=hKe;Im.prototype.delete=gKe;Im.prototype.get=dKe;Im.prototype.has=mKe;Im.prototype.set=yKe;cee.exports=Im});var Aee=_((XFt,uee)=>{var EKe="__lodash_hash_undefined__";function CKe(t){return this.__data__.set(t,EKe),this}uee.exports=CKe});var pee=_((ZFt,fee)=>{function wKe(t){return this.__data__.has(t)}fee.exports=wKe});var gee=_(($Ft,hee)=>{var IKe=PP(),BKe=Aee(),vKe=pee();function bP(t){var e=-1,r=t==null?0:t.length;for(this.__data__=new IKe;++e<r;)this.add(t[e])}bP.prototype.add=bP.prototype.push=BKe;bP.prototype.has=vKe;hee.exports=bP});var mee=_((eRt,dee)=>{function DKe(t,e){for(var r=-1,o=t==null?0:t.length;++r<o;)if(e(t[r],r,t))return!0;return!1}dee.exports=DKe});var Eee=_((tRt,yee)=>{function PKe(t,e){return t.has(e)}yee.exports=PKe});var RN=_((rRt,Cee)=>{var SKe=gee(),bKe=mee(),xKe=Eee(),kKe=1,QKe=2;function FKe(t,e,r,o,a,n){var u=r&kKe,A=t.length,p=e.length;if(A!=p&&!(u&&p>A))return!1;var h=n.get(t),E=n.get(e);if(h&&E)return h==e&&E==t;var I=-1,v=!0,x=r&QKe?new SKe:void 0;for(n.set(t,e),n.set(e,t);++I<A;){var C=t[I],R=e[I];if(o)var L=u?o(R,C,I,e,t,n):o(C,R,I,t,e,n);if(L!==void 0){if(L)continue;v=!1;break}if(x){if(!bKe(e,function(U,z){if(!xKe(x,z)&&(C===U||a(C,U,r,o,n)))return x.push(z)})){v=!1;break}}else if(!(C===R||a(C,R,r,o,n))){v=!1;break}}return n.delete(t),n.delete(e),v}Cee.exports=FKe});var TN=_((nRt,wee)=>{var RKe=_l(),TKe=RKe.Uint8Array;wee.exports=TKe});var Bee=_((iRt,Iee)=>{function NKe(t){var e=-1,r=Array(t.size);return t.forEach(function(o,a){r[++e]=[a,o]}),r}Iee.exports=NKe});var Dee=_((sRt,vee)=>{function LKe(t){var e=-1,r=Array(t.size);return t.forEach(function(o){r[++e]=o}),r}vee.exports=LKe});var kee=_((oRt,xee)=>{var Pee=lg(),See=TN(),MKe=ym(),OKe=RN(),UKe=Bee(),_Ke=Dee(),HKe=1,qKe=2,jKe="[object Boolean]",GKe="[object Date]",YKe="[object Error]",WKe="[object Map]",KKe="[object Number]",VKe="[object RegExp]",zKe="[object Set]",JKe="[object String]",XKe="[object Symbol]",ZKe="[object ArrayBuffer]",$Ke="[object DataView]",bee=Pee?Pee.prototype:void 0,NN=bee?bee.valueOf:void 0;function eVe(t,e,r,o,a,n,u){switch(r){case $Ke:if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)return!1;t=t.buffer,e=e.buffer;case ZKe:return!(t.byteLength!=e.byteLength||!n(new See(t),new See(e)));case jKe:case GKe:case KKe:return MKe(+t,+e);case YKe:return t.name==e.name&&t.message==e.message;case VKe:case JKe:return t==e+"";case WKe:var A=UKe;case zKe:var p=o&HKe;if(A||(A=_Ke),t.size!=e.size&&!p)return!1;var h=u.get(t);if(h)return h==e;o|=qKe,u.set(t,e);var E=OKe(A(t),A(e),o,a,n,u);return u.delete(t),E;case XKe:if(NN)return NN.call(t)==NN.call(e)}return!1}xee.exports=eVe});var xP=_((aRt,Qee)=>{function tVe(t,e){for(var r=-1,o=e.length,a=t.length;++r<o;)t[a+r]=e[r];return t}Qee.exports=tVe});var Hl=_((lRt,Fee)=>{var rVe=Array.isArray;Fee.exports=rVe});var LN=_((cRt,Ree)=>{var nVe=xP(),iVe=Hl();function sVe(t,e,r){var o=e(t);return iVe(t)?o:nVe(o,r(t))}Ree.exports=sVe});var Nee=_((uRt,Tee)=>{function oVe(t,e){for(var r=-1,o=t==null?0:t.length,a=0,n=[];++r<o;){var u=t[r];e(u,r,t)&&(n[a++]=u)}return n}Tee.exports=oVe});var MN=_((ARt,Lee)=>{function aVe(){return[]}Lee.exports=aVe});var kP=_((fRt,Oee)=>{var lVe=Nee(),cVe=MN(),uVe=Object.prototype,AVe=uVe.propertyIsEnumerable,Mee=Object.getOwnPropertySymbols,fVe=Mee?function(t){return t==null?[]:(t=Object(t),lVe(Mee(t),function(e){return AVe.call(t,e)}))}:cVe;Oee.exports=fVe});var _ee=_((pRt,Uee)=>{function pVe(t,e){for(var r=-1,o=Array(t);++r<t;)o[r]=e(r);return o}Uee.exports=pVe});var Ju=_((hRt,Hee)=>{function hVe(t){return t!=null&&typeof t=="object"}Hee.exports=hVe});var jee=_((gRt,qee)=>{var gVe=cg(),dVe=Ju(),mVe="[object Arguments]";function yVe(t){return dVe(t)&&gVe(t)==mVe}qee.exports=yVe});var EI=_((dRt,Wee)=>{var Gee=jee(),EVe=Ju(),Yee=Object.prototype,CVe=Yee.hasOwnProperty,wVe=Yee.propertyIsEnumerable,IVe=Gee(function(){return arguments}())?Gee:function(t){return EVe(t)&&CVe.call(t,"callee")&&!wVe.call(t,"callee")};Wee.exports=IVe});var Vee=_((mRt,Kee)=>{function BVe(){return!1}Kee.exports=BVe});var wI=_((CI,Bm)=>{var vVe=_l(),DVe=Vee(),Xee=typeof CI=="object"&&CI&&!CI.nodeType&&CI,zee=Xee&&typeof Bm=="object"&&Bm&&!Bm.nodeType&&Bm,PVe=zee&&zee.exports===Xee,Jee=PVe?vVe.Buffer:void 0,SVe=Jee?Jee.isBuffer:void 0,bVe=SVe||DVe;Bm.exports=bVe});var II=_((yRt,Zee)=>{var xVe=9007199254740991,kVe=/^(?:0|[1-9]\d*)$/;function QVe(t,e){var r=typeof t;return e=e??xVe,!!e&&(r=="number"||r!="symbol"&&kVe.test(t))&&t>-1&&t%1==0&&t<e}Zee.exports=QVe});var QP=_((ERt,$ee)=>{var FVe=9007199254740991;function RVe(t){return typeof t=="number"&&t>-1&&t%1==0&&t<=FVe}$ee.exports=RVe});var tte=_((CRt,ete)=>{var TVe=cg(),NVe=QP(),LVe=Ju(),MVe="[object Arguments]",OVe="[object Array]",UVe="[object Boolean]",_Ve="[object Date]",HVe="[object Error]",qVe="[object Function]",jVe="[object Map]",GVe="[object Number]",YVe="[object Object]",WVe="[object RegExp]",KVe="[object Set]",VVe="[object String]",zVe="[object WeakMap]",JVe="[object ArrayBuffer]",XVe="[object DataView]",ZVe="[object Float32Array]",$Ve="[object Float64Array]",eze="[object Int8Array]",tze="[object Int16Array]",rze="[object Int32Array]",nze="[object Uint8Array]",ize="[object Uint8ClampedArray]",sze="[object Uint16Array]",oze="[object Uint32Array]",ui={};ui[ZVe]=ui[$Ve]=ui[eze]=ui[tze]=ui[rze]=ui[nze]=ui[ize]=ui[sze]=ui[oze]=!0;ui[MVe]=ui[OVe]=ui[JVe]=ui[UVe]=ui[XVe]=ui[_Ve]=ui[HVe]=ui[qVe]=ui[jVe]=ui[GVe]=ui[YVe]=ui[WVe]=ui[KVe]=ui[VVe]=ui[zVe]=!1;function aze(t){return LVe(t)&&NVe(t.length)&&!!ui[TVe(t)]}ete.exports=aze});var FP=_((wRt,rte)=>{function lze(t){return function(e){return t(e)}}rte.exports=lze});var RP=_((BI,vm)=>{var cze=kN(),nte=typeof BI=="object"&&BI&&!BI.nodeType&&BI,vI=nte&&typeof vm=="object"&&vm&&!vm.nodeType&&vm,uze=vI&&vI.exports===nte,ON=uze&&cze.process,Aze=function(){try{var t=vI&&vI.require&&vI.require("util").types;return t||ON&&ON.binding&&ON.binding("util")}catch{}}();vm.exports=Aze});var TP=_((IRt,ote)=>{var fze=tte(),pze=FP(),ite=RP(),ste=ite&&ite.isTypedArray,hze=ste?pze(ste):fze;ote.exports=hze});var UN=_((BRt,ate)=>{var gze=_ee(),dze=EI(),mze=Hl(),yze=wI(),Eze=II(),Cze=TP(),wze=Object.prototype,Ize=wze.hasOwnProperty;function Bze(t,e){var r=mze(t),o=!r&&dze(t),a=!r&&!o&&yze(t),n=!r&&!o&&!a&&Cze(t),u=r||o||a||n,A=u?gze(t.length,String):[],p=A.length;for(var h in t)(e||Ize.call(t,h))&&!(u&&(h=="length"||a&&(h=="offset"||h=="parent")||n&&(h=="buffer"||h=="byteLength"||h=="byteOffset")||Eze(h,p)))&&A.push(h);return A}ate.exports=Bze});var NP=_((vRt,lte)=>{var vze=Object.prototype;function Dze(t){var e=t&&t.constructor,r=typeof e=="function"&&e.prototype||vze;return t===r}lte.exports=Dze});var _N=_((DRt,cte)=>{function Pze(t,e){return function(r){return t(e(r))}}cte.exports=Pze});var Ate=_((PRt,ute)=>{var Sze=_N(),bze=Sze(Object.keys,Object);ute.exports=bze});var pte=_((SRt,fte)=>{var xze=NP(),kze=Ate(),Qze=Object.prototype,Fze=Qze.hasOwnProperty;function Rze(t){if(!xze(t))return kze(t);var e=[];for(var r in Object(t))Fze.call(t,r)&&r!="constructor"&&e.push(r);return e}fte.exports=Rze});var DI=_((bRt,hte)=>{var Tze=vP(),Nze=QP();function Lze(t){return t!=null&&Nze(t.length)&&!Tze(t)}hte.exports=Lze});var LP=_((xRt,gte)=>{var Mze=UN(),Oze=pte(),Uze=DI();function _ze(t){return Uze(t)?Mze(t):Oze(t)}gte.exports=_ze});var HN=_((kRt,dte)=>{var Hze=LN(),qze=kP(),jze=LP();function Gze(t){return Hze(t,jze,qze)}dte.exports=Gze});var Ete=_((QRt,yte)=>{var mte=HN(),Yze=1,Wze=Object.prototype,Kze=Wze.hasOwnProperty;function Vze(t,e,r,o,a,n){var u=r&Yze,A=mte(t),p=A.length,h=mte(e),E=h.length;if(p!=E&&!u)return!1;for(var I=p;I--;){var v=A[I];if(!(u?v in e:Kze.call(e,v)))return!1}var x=n.get(t),C=n.get(e);if(x&&C)return x==e&&C==t;var R=!0;n.set(t,e),n.set(e,t);for(var L=u;++I<p;){v=A[I];var U=t[v],z=e[v];if(o)var te=u?o(z,U,v,e,t,n):o(U,z,v,t,e,n);if(!(te===void 0?U===z||a(U,z,r,o,n):te)){R=!1;break}L||(L=v=="constructor")}if(R&&!L){var ae=t.constructor,le=e.constructor;ae!=le&&"constructor"in t&&"constructor"in e&&!(typeof ae=="function"&&ae instanceof ae&&typeof le=="function"&&le instanceof le)&&(R=!1)}return n.delete(t),n.delete(e),R}yte.exports=Vze});var wte=_((FRt,Cte)=>{var zze=Kp(),Jze=_l(),Xze=zze(Jze,"DataView");Cte.exports=Xze});var Bte=_((RRt,Ite)=>{var Zze=Kp(),$ze=_l(),eJe=Zze($ze,"Promise");Ite.exports=eJe});var Dte=_((TRt,vte)=>{var tJe=Kp(),rJe=_l(),nJe=tJe(rJe,"Set");vte.exports=nJe});var Ste=_((NRt,Pte)=>{var iJe=Kp(),sJe=_l(),oJe=iJe(sJe,"WeakMap");Pte.exports=oJe});var PI=_((LRt,Tte)=>{var qN=wte(),jN=DP(),GN=Bte(),YN=Dte(),WN=Ste(),Rte=cg(),Dm=FN(),bte="[object Map]",aJe="[object Object]",xte="[object Promise]",kte="[object Set]",Qte="[object WeakMap]",Fte="[object DataView]",lJe=Dm(qN),cJe=Dm(jN),uJe=Dm(GN),AJe=Dm(YN),fJe=Dm(WN),ug=Rte;(qN&&ug(new qN(new ArrayBuffer(1)))!=Fte||jN&&ug(new jN)!=bte||GN&&ug(GN.resolve())!=xte||YN&&ug(new YN)!=kte||WN&&ug(new WN)!=Qte)&&(ug=function(t){var e=Rte(t),r=e==aJe?t.constructor:void 0,o=r?Dm(r):"";if(o)switch(o){case lJe:return Fte;case cJe:return bte;case uJe:return xte;case AJe:return kte;case fJe:return Qte}return e});Tte.exports=ug});var qte=_((MRt,Hte)=>{var KN=SP(),pJe=RN(),hJe=kee(),gJe=Ete(),Nte=PI(),Lte=Hl(),Mte=wI(),dJe=TP(),mJe=1,Ote="[object Arguments]",Ute="[object Array]",MP="[object Object]",yJe=Object.prototype,_te=yJe.hasOwnProperty;function EJe(t,e,r,o,a,n){var u=Lte(t),A=Lte(e),p=u?Ute:Nte(t),h=A?Ute:Nte(e);p=p==Ote?MP:p,h=h==Ote?MP:h;var E=p==MP,I=h==MP,v=p==h;if(v&&Mte(t)){if(!Mte(e))return!1;u=!0,E=!1}if(v&&!E)return n||(n=new KN),u||dJe(t)?pJe(t,e,r,o,a,n):hJe(t,e,p,r,o,a,n);if(!(r&mJe)){var x=E&&_te.call(t,"__wrapped__"),C=I&&_te.call(e,"__wrapped__");if(x||C){var R=x?t.value():t,L=C?e.value():e;return n||(n=new KN),a(R,L,r,o,n)}}return v?(n||(n=new KN),gJe(t,e,r,o,a,n)):!1}Hte.exports=EJe});var Wte=_((ORt,Yte)=>{var CJe=qte(),jte=Ju();function Gte(t,e,r,o,a){return t===e?!0:t==null||e==null||!jte(t)&&!jte(e)?t!==t&&e!==e:CJe(t,e,r,o,Gte,a)}Yte.exports=Gte});var Vte=_((URt,Kte)=>{var wJe=Wte();function IJe(t,e){return wJe(t,e)}Kte.exports=IJe});var VN=_((_Rt,zte)=>{var BJe=Kp(),vJe=function(){try{var t=BJe(Object,"defineProperty");return t({},"",{}),t}catch{}}();zte.exports=vJe});var OP=_((HRt,Xte)=>{var Jte=VN();function DJe(t,e,r){e=="__proto__"&&Jte?Jte(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}Xte.exports=DJe});var zN=_((qRt,Zte)=>{var PJe=OP(),SJe=ym();function bJe(t,e,r){(r!==void 0&&!SJe(t[e],r)||r===void 0&&!(e in t))&&PJe(t,e,r)}Zte.exports=bJe});var ere=_((jRt,$te)=>{function xJe(t){return function(e,r,o){for(var a=-1,n=Object(e),u=o(e),A=u.length;A--;){var p=u[t?A:++a];if(r(n[p],p,n)===!1)break}return e}}$te.exports=xJe});var rre=_((GRt,tre)=>{var kJe=ere(),QJe=kJe();tre.exports=QJe});var JN=_((SI,Pm)=>{var FJe=_l(),ore=typeof SI=="object"&&SI&&!SI.nodeType&&SI,nre=ore&&typeof Pm=="object"&&Pm&&!Pm.nodeType&&Pm,RJe=nre&&nre.exports===ore,ire=RJe?FJe.Buffer:void 0,sre=ire?ire.allocUnsafe:void 0;function TJe(t,e){if(e)return t.slice();var r=t.length,o=sre?sre(r):new t.constructor(r);return t.copy(o),o}Pm.exports=TJe});var UP=_((YRt,lre)=>{var are=TN();function NJe(t){var e=new t.constructor(t.byteLength);return new are(e).set(new are(t)),e}lre.exports=NJe});var XN=_((WRt,cre)=>{var LJe=UP();function MJe(t,e){var r=e?LJe(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.length)}cre.exports=MJe});var _P=_((KRt,ure)=>{function OJe(t,e){var r=-1,o=t.length;for(e||(e=Array(o));++r<o;)e[r]=t[r];return e}ure.exports=OJe});var pre=_((VRt,fre)=>{var UJe=sl(),Are=Object.create,_Je=function(){function t(){}return function(e){if(!UJe(e))return{};if(Are)return Are(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();fre.exports=_Je});var HP=_((zRt,hre)=>{var HJe=_N(),qJe=HJe(Object.getPrototypeOf,Object);hre.exports=qJe});var ZN=_((JRt,gre)=>{var jJe=pre(),GJe=HP(),YJe=NP();function WJe(t){return typeof t.constructor=="function"&&!YJe(t)?jJe(GJe(t)):{}}gre.exports=WJe});var mre=_((XRt,dre)=>{var KJe=DI(),VJe=Ju();function zJe(t){return VJe(t)&&KJe(t)}dre.exports=zJe});var $N=_((ZRt,Ere)=>{var JJe=cg(),XJe=HP(),ZJe=Ju(),$Je="[object Object]",eXe=Function.prototype,tXe=Object.prototype,yre=eXe.toString,rXe=tXe.hasOwnProperty,nXe=yre.call(Object);function iXe(t){if(!ZJe(t)||JJe(t)!=$Je)return!1;var e=XJe(t);if(e===null)return!0;var r=rXe.call(e,"constructor")&&e.constructor;return typeof r=="function"&&r instanceof r&&yre.call(r)==nXe}Ere.exports=iXe});var eL=_(($Rt,Cre)=>{function sXe(t,e){if(!(e==="constructor"&&typeof t[e]=="function")&&e!="__proto__")return t[e]}Cre.exports=sXe});var qP=_((eTt,wre)=>{var oXe=OP(),aXe=ym(),lXe=Object.prototype,cXe=lXe.hasOwnProperty;function uXe(t,e,r){var o=t[e];(!(cXe.call(t,e)&&aXe(o,r))||r===void 0&&!(e in t))&&oXe(t,e,r)}wre.exports=uXe});var Ag=_((tTt,Ire)=>{var AXe=qP(),fXe=OP();function pXe(t,e,r,o){var a=!r;r||(r={});for(var n=-1,u=e.length;++n<u;){var A=e[n],p=o?o(r[A],t[A],A,r,t):void 0;p===void 0&&(p=t[A]),a?fXe(r,A,p):AXe(r,A,p)}return r}Ire.exports=pXe});var vre=_((rTt,Bre)=>{function hXe(t){var e=[];if(t!=null)for(var r in Object(t))e.push(r);return e}Bre.exports=hXe});var Pre=_((nTt,Dre)=>{var gXe=sl(),dXe=NP(),mXe=vre(),yXe=Object.prototype,EXe=yXe.hasOwnProperty;function CXe(t){if(!gXe(t))return mXe(t);var e=dXe(t),r=[];for(var o in t)o=="constructor"&&(e||!EXe.call(t,o))||r.push(o);return r}Dre.exports=CXe});var Sm=_((iTt,Sre)=>{var wXe=UN(),IXe=Pre(),BXe=DI();function vXe(t){return BXe(t)?wXe(t,!0):IXe(t)}Sre.exports=vXe});var xre=_((sTt,bre)=>{var DXe=Ag(),PXe=Sm();function SXe(t){return DXe(t,PXe(t))}bre.exports=SXe});var Nre=_((oTt,Tre)=>{var kre=zN(),bXe=JN(),xXe=XN(),kXe=_P(),QXe=ZN(),Qre=EI(),Fre=Hl(),FXe=mre(),RXe=wI(),TXe=vP(),NXe=sl(),LXe=$N(),MXe=TP(),Rre=eL(),OXe=xre();function UXe(t,e,r,o,a,n,u){var A=Rre(t,r),p=Rre(e,r),h=u.get(p);if(h){kre(t,r,h);return}var E=n?n(A,p,r+"",t,e,u):void 0,I=E===void 0;if(I){var v=Fre(p),x=!v&&RXe(p),C=!v&&!x&&MXe(p);E=p,v||x||C?Fre(A)?E=A:FXe(A)?E=kXe(A):x?(I=!1,E=bXe(p,!0)):C?(I=!1,E=xXe(p,!0)):E=[]:LXe(p)||Qre(p)?(E=A,Qre(A)?E=OXe(A):(!NXe(A)||TXe(A))&&(E=QXe(p))):I=!1}I&&(u.set(p,E),a(E,p,o,n,u),u.delete(p)),kre(t,r,E)}Tre.exports=UXe});var Ore=_((aTt,Mre)=>{var _Xe=SP(),HXe=zN(),qXe=rre(),jXe=Nre(),GXe=sl(),YXe=Sm(),WXe=eL();function Lre(t,e,r,o,a){t!==e&&qXe(e,function(n,u){if(a||(a=new _Xe),GXe(n))jXe(t,e,u,r,Lre,o,a);else{var A=o?o(WXe(t,u),n,u+"",t,e,a):void 0;A===void 0&&(A=n),HXe(t,u,A)}},YXe)}Mre.exports=Lre});var tL=_((lTt,Ure)=>{function KXe(t){return t}Ure.exports=KXe});var Hre=_((cTt,_re)=>{function VXe(t,e,r){switch(r.length){case 0:return t.call(e);case 1:return t.call(e,r[0]);case 2:return t.call(e,r[0],r[1]);case 3:return t.call(e,r[0],r[1],r[2])}return t.apply(e,r)}_re.exports=VXe});var rL=_((uTt,jre)=>{var zXe=Hre(),qre=Math.max;function JXe(t,e,r){return e=qre(e===void 0?t.length-1:e,0),function(){for(var o=arguments,a=-1,n=qre(o.length-e,0),u=Array(n);++a<n;)u[a]=o[e+a];a=-1;for(var A=Array(e+1);++a<e;)A[a]=o[a];return A[e]=r(u),zXe(t,this,A)}}jre.exports=JXe});var Yre=_((ATt,Gre)=>{function XXe(t){return function(){return t}}Gre.exports=XXe});var Vre=_((fTt,Kre)=>{var ZXe=Yre(),Wre=VN(),$Xe=tL(),eZe=Wre?function(t,e){return Wre(t,"toString",{configurable:!0,enumerable:!1,value:ZXe(e),writable:!0})}:$Xe;Kre.exports=eZe});var Jre=_((pTt,zre)=>{var tZe=800,rZe=16,nZe=Date.now;function iZe(t){var e=0,r=0;return function(){var o=nZe(),a=rZe-(o-r);if(r=o,a>0){if(++e>=tZe)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}zre.exports=iZe});var nL=_((hTt,Xre)=>{var sZe=Vre(),oZe=Jre(),aZe=oZe(sZe);Xre.exports=aZe});var $re=_((gTt,Zre)=>{var lZe=tL(),cZe=rL(),uZe=nL();function AZe(t,e){return uZe(cZe(t,e,lZe),t+"")}Zre.exports=AZe});var tne=_((dTt,ene)=>{var fZe=ym(),pZe=DI(),hZe=II(),gZe=sl();function dZe(t,e,r){if(!gZe(r))return!1;var o=typeof e;return(o=="number"?pZe(r)&&hZe(e,r.length):o=="string"&&e in r)?fZe(r[e],t):!1}ene.exports=dZe});var nne=_((mTt,rne)=>{var mZe=$re(),yZe=tne();function EZe(t){return mZe(function(e,r){var o=-1,a=r.length,n=a>1?r[a-1]:void 0,u=a>2?r[2]:void 0;for(n=t.length>3&&typeof n=="function"?(a--,n):void 0,u&&yZe(r[0],r[1],u)&&(n=a<3?void 0:n,a=1),e=Object(e);++o<a;){var A=r[o];A&&t(e,A,o,n)}return e})}rne.exports=EZe});var sne=_((yTt,ine)=>{var CZe=Ore(),wZe=nne(),IZe=wZe(function(t,e,r,o){CZe(t,e,r,o)});ine.exports=IZe});var He={};Vt(He,{AsyncActions:()=>oL,BufferStream:()=>sL,CachingStrategy:()=>mne,DefaultStream:()=>aL,allSettledSafe:()=>_c,assertNever:()=>cL,bufferStream:()=>km,buildIgnorePattern:()=>xZe,convertMapsToIndexableObjects:()=>GP,dynamicRequire:()=>vf,escapeRegExp:()=>vZe,getArrayWithDefault:()=>xI,getFactoryWithDefault:()=>al,getMapWithDefault:()=>kI,getSetWithDefault:()=>bm,groupBy:()=>FZe,isIndexableObject:()=>iL,isPathLike:()=>kZe,isTaggedYarnVersion:()=>BZe,makeDeferred:()=>hne,mapAndFilter:()=>ol,mapAndFind:()=>Vp,mergeIntoTarget:()=>Ene,overrideType:()=>DZe,parseBoolean:()=>QI,parseInt:()=>Qm,parseOptionalBoolean:()=>yne,plural:()=>jP,prettifyAsyncErrors:()=>xm,prettifySyncErrors:()=>uL,releaseAfterUseAsync:()=>SZe,replaceEnvVariables:()=>YP,sortMap:()=>Fs,toMerged:()=>QZe,tryParseOptionalBoolean:()=>AL,validateEnum:()=>PZe});function BZe(t){return!!(Ane.default.valid(t)&&t.match(/^[^-]+(-rc\.[0-9]+)?$/))}function jP(t,{one:e,more:r,zero:o=r}){return t===0?o:t===1?e:r}function vZe(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function DZe(t){}function cL(t){throw new Error(`Assertion failed: Unexpected object '${t}'`)}function PZe(t,e){let r=Object.values(t);if(!r.includes(e))throw new st(`Invalid value for enumeration: ${JSON.stringify(e)} (expected one of ${r.map(o=>JSON.stringify(o)).join(", ")})`);return e}function ol(t,e){let r=[];for(let o of t){let a=e(o);a!==fne&&r.push(a)}return r}function Vp(t,e){for(let r of t){let o=e(r);if(o!==pne)return o}}function iL(t){return typeof t=="object"&&t!==null}async function _c(t){let e=await Promise.allSettled(t),r=[];for(let o of e){if(o.status==="rejected")throw o.reason;r.push(o.value)}return r}function GP(t){if(t instanceof Map&&(t=Object.fromEntries(t)),iL(t))for(let e of Object.keys(t)){let r=t[e];iL(r)&&(t[e]=GP(r))}return t}function al(t,e,r){let o=t.get(e);return typeof o>"u"&&t.set(e,o=r()),o}function xI(t,e){let r=t.get(e);return typeof r>"u"&&t.set(e,r=[]),r}function bm(t,e){let r=t.get(e);return typeof r>"u"&&t.set(e,r=new Set),r}function kI(t,e){let r=t.get(e);return typeof r>"u"&&t.set(e,r=new Map),r}async function SZe(t,e){if(e==null)return await t();try{return await t()}finally{await e()}}async function xm(t,e){try{return await t()}catch(r){throw r.message=e(r.message),r}}function uL(t,e){try{return t()}catch(r){throw r.message=e(r.message),r}}async function km(t){return await new Promise((e,r)=>{let o=[];t.on("error",a=>{r(a)}),t.on("data",a=>{o.push(a)}),t.on("end",()=>{e(Buffer.concat(o))})})}function hne(){let t,e;return{promise:new Promise((o,a)=>{t=o,e=a}),resolve:t,reject:e}}function gne(t){return bI(ue.fromPortablePath(t))}function dne(path){let physicalPath=ue.fromPortablePath(path),currentCacheEntry=bI.cache[physicalPath];delete bI.cache[physicalPath];let result;try{result=gne(physicalPath);let freshCacheEntry=bI.cache[physicalPath],dynamicModule=eval("module"),freshCacheIndex=dynamicModule.children.indexOf(freshCacheEntry);freshCacheIndex!==-1&&dynamicModule.children.splice(freshCacheIndex,1)}finally{bI.cache[physicalPath]=currentCacheEntry}return result}function bZe(t){let e=one.get(t),r=oe.statSync(t);if(e?.mtime===r.mtimeMs)return e.instance;let o=dne(t);return one.set(t,{mtime:r.mtimeMs,instance:o}),o}function vf(t,{cachingStrategy:e=2}={}){switch(e){case 0:return dne(t);case 1:return bZe(t);case 2:return gne(t);default:throw new Error("Unsupported caching strategy")}}function Fs(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let o=[];for(let n of e)o.push(r.map(u=>n(u)));let a=r.map((n,u)=>u);return a.sort((n,u)=>{for(let A of o){let p=A[n]<A[u]?-1:A[n]>A[u]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function xZe(t){return t.length===0?null:t.map(e=>`(${cne.default.makeRe(e,{windows:!1,dot:!0}).source})`).join("|")}function YP(t,{env:e}){let r=/\${(?<variableName>[\d\w_]+)(?<colon>:)?(?:-(?<fallback>[^}]*))?}/g;return t.replace(r,(...o)=>{let{variableName:a,colon:n,fallback:u}=o[o.length-1],A=Object.hasOwn(e,a),p=e[a];if(p||A&&!n)return p;if(u!=null)return u;throw new st(`Environment variable not found (${a})`)})}function QI(t){switch(t){case"true":case"1":case 1:case!0:return!0;case"false":case"0":case 0:case!1:return!1;default:throw new Error(`Couldn't parse "${t}" as a boolean`)}}function yne(t){return typeof t>"u"?t:QI(t)}function AL(t){try{return yne(t)}catch{return null}}function kZe(t){return!!(ue.isAbsolute(t)||t.match(/^(\.{1,2}|~)\//))}function Ene(t,...e){let r=u=>({value:u}),o=r(t),a=e.map(u=>r(u)),{value:n}=(0,lne.default)(o,...a,(u,A)=>{if(Array.isArray(u)&&Array.isArray(A)){for(let p of A)u.find(h=>(0,ane.default)(h,p))||u.push(p);return u}});return n}function QZe(...t){return Ene({},...t)}function FZe(t,e){let r=Object.create(null);for(let o of t){let a=o[e];r[a]??=[],r[a].push(o)}return r}function Qm(t){return typeof t=="string"?Number.parseInt(t,10):t}var ane,lne,cne,une,Ane,lL,fne,pne,sL,oL,aL,bI,one,mne,ql=Et(()=>{Pt();qt();ane=Ze(Vte()),lne=Ze(sne()),cne=Ze($o()),une=Ze(eg()),Ane=Ze(Jn()),lL=ve("stream");fne=Symbol();ol.skip=fne;pne=Symbol();Vp.skip=pne;sL=class extends lL.Transform{constructor(){super(...arguments);this.chunks=[]}_transform(r,o,a){if(o!=="buffer"||!Buffer.isBuffer(r))throw new Error("Assertion failed: BufferStream only accept buffers");this.chunks.push(r),a(null,null)}_flush(r){r(null,Buffer.concat(this.chunks))}};oL=class{constructor(e){this.deferred=new Map;this.promises=new Map;this.limit=(0,une.default)(e)}set(e,r){let o=this.deferred.get(e);typeof o>"u"&&this.deferred.set(e,o=hne());let a=this.limit(()=>r());return this.promises.set(e,a),a.then(()=>{this.promises.get(e)===a&&o.resolve()},n=>{this.promises.get(e)===a&&o.reject(n)}),o.promise}reduce(e,r){let o=this.promises.get(e)??Promise.resolve();this.set(e,()=>r(o))}async wait(){await Promise.all(this.promises.values())}},aL=class extends lL.Transform{constructor(r=Buffer.alloc(0)){super();this.active=!0;this.ifEmpty=r}_transform(r,o,a){if(o!=="buffer"||!Buffer.isBuffer(r))throw new Error("Assertion failed: DefaultStream only accept buffers");this.active=!1,a(null,r)}_flush(r){this.active&&this.ifEmpty.length>0?r(null,this.ifEmpty):r(null)}},bI=eval("require");one=new Map;mne=(o=>(o[o.NoCache=0]="NoCache",o[o.FsTime=1]="FsTime",o[o.Node=2]="Node",o))(mne||{})});var Fm,fL,pL,Cne=Et(()=>{Fm=(r=>(r.HARD="HARD",r.SOFT="SOFT",r))(Fm||{}),fL=(o=>(o.Dependency="Dependency",o.PeerDependency="PeerDependency",o.PeerDependencyMeta="PeerDependencyMeta",o))(fL||{}),pL=(o=>(o.Inactive="inactive",o.Redundant="redundant",o.Active="active",o))(pL||{})});var pe={};Vt(pe,{LogLevel:()=>JP,Style:()=>KP,Type:()=>yt,addLogFilterSupport:()=>TI,applyColor:()=>Xs,applyHyperlink:()=>Tm,applyStyle:()=>fg,json:()=>pg,jsonOrPretty:()=>NZe,mark:()=>yL,pretty:()=>Ot,prettyField:()=>Xu,prettyList:()=>mL,prettyTruncatedLocatorList:()=>zP,stripAnsi:()=>Rm.default,supportsColor:()=>VP,supportsHyperlinks:()=>dL,tuple:()=>Hc});function wne(t){let e=["KiB","MiB","GiB","TiB"],r=e.length;for(;r>1&&t<1024**r;)r-=1;let o=1024**r;return`${Math.floor(t*100/o)/100} ${e[r-1]}`}function Hc(t,e){return[e,t]}function fg(t,e,r){return t.get("enableColors")&&r&2&&(e=RI.default.bold(e)),e}function Xs(t,e,r){if(!t.get("enableColors"))return e;let o=RZe.get(r);if(o===null)return e;let a=typeof o>"u"?r:gL.level>=3?o[0]:o[1],n=typeof a=="number"?hL.ansi256(a):a.startsWith("#")?hL.hex(a):hL[a];if(typeof n!="function")throw new Error(`Invalid format type ${a}`);return n(e)}function Tm(t,e,r){return t.get("enableHyperlinks")?TZe?`\x1B]8;;${r}\x1B\\${e}\x1B]8;;\x1B\\`:`\x1B]8;;${r}\x07${e}\x1B]8;;\x07`:e}function Ot(t,e,r){if(e===null)return Xs(t,"null",yt.NULL);if(Object.hasOwn(WP,r))return WP[r].pretty(t,e);if(typeof e!="string")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof e}`);return Xs(t,e,r)}function mL(t,e,r,{separator:o=", "}={}){return[...e].map(a=>Ot(t,a,r)).join(o)}function pg(t,e){if(t===null)return null;if(Object.hasOwn(WP,e))return WP[e].json(t);if(typeof t!="string")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof t}`);return t}function NZe(t,e,[r,o]){return t?pg(r,o):Ot(e,r,o)}function yL(t){return{Check:Xs(t,"\u2713","green"),Cross:Xs(t,"\u2718","red"),Question:Xs(t,"?","cyan")}}function Xu(t,{label:e,value:[r,o]}){return`${Ot(t,e,yt.CODE)}: ${Ot(t,r,o)}`}function zP(t,e,r){let o=[],a=[...e],n=r;for(;a.length>0;){let h=a[0],E=`${qr(t,h)}, `,I=EL(h).length+2;if(o.length>0&&n<I)break;o.push([E,I]),n-=I,a.shift()}if(a.length===0)return o.map(([h])=>h).join("").slice(0,-2);let u="X".repeat(a.length.toString().length),A=`and ${u} more.`,p=a.length;for(;o.length>1&&n<A.length;)n+=o[o.length-1][1],p+=1,o.pop();return[o.map(([h])=>h).join(""),A.replace(u,Ot(t,p,yt.NUMBER))].join("")}function TI(t,{configuration:e}){let r=e.get("logFilters"),o=new Map,a=new Map,n=[];for(let I of r){let v=I.get("level");if(typeof v>"u")continue;let x=I.get("code");typeof x<"u"&&o.set(x,v);let C=I.get("text");typeof C<"u"&&a.set(C,v);let R=I.get("pattern");typeof R<"u"&&n.push([Ine.default.matcher(R,{contains:!0}),v])}n.reverse();let u=(I,v,x)=>{if(I===null||I===0)return x;let C=a.size>0||n.length>0?(0,Rm.default)(v):v;if(a.size>0){let R=a.get(C);if(typeof R<"u")return R??x}if(n.length>0){for(let[R,L]of n)if(R(C))return L??x}if(o.size>0){let R=o.get(Ku(I));if(typeof R<"u")return R??x}return x},A=t.reportInfo,p=t.reportWarning,h=t.reportError,E=function(I,v,x,C){switch(u(v,x,C)){case"info":A.call(I,v,x);break;case"warning":p.call(I,v??0,x);break;case"error":h.call(I,v??0,x);break}};t.reportInfo=function(...I){return E(this,...I,"info")},t.reportWarning=function(...I){return E(this,...I,"warning")},t.reportError=function(...I){return E(this,...I,"error")}}var RI,FI,Ine,Rm,Bne,yt,KP,gL,VP,dL,hL,RZe,So,WP,TZe,JP,jl=Et(()=>{Pt();RI=Ze(pN()),FI=Ze(X0());qt();Ine=Ze($o()),Rm=Ze(BP()),Bne=ve("util");$D();bo();yt={NO_HINT:"NO_HINT",ID:"ID",NULL:"NULL",SCOPE:"SCOPE",NAME:"NAME",RANGE:"RANGE",REFERENCE:"REFERENCE",NUMBER:"NUMBER",PATH:"PATH",URL:"URL",ADDED:"ADDED",REMOVED:"REMOVED",CODE:"CODE",INSPECT:"INSPECT",DURATION:"DURATION",SIZE:"SIZE",SIZE_DIFF:"SIZE_DIFF",IDENT:"IDENT",DESCRIPTOR:"DESCRIPTOR",LOCATOR:"LOCATOR",RESOLUTION:"RESOLUTION",DEPENDENT:"DEPENDENT",PACKAGE_EXTENSION:"PACKAGE_EXTENSION",SETTING:"SETTING",MARKDOWN:"MARKDOWN",MARKDOWN_INLINE:"MARKDOWN_INLINE"},KP=(e=>(e[e.BOLD=2]="BOLD",e))(KP||{}),gL=FI.default.GITHUB_ACTIONS?{level:2}:RI.default.supportsColor?{level:RI.default.supportsColor.level}:{level:0},VP=gL.level!==0,dL=VP&&!FI.default.GITHUB_ACTIONS&&!FI.default.CIRCLE&&!FI.default.GITLAB,hL=new RI.default.Instance(gL),RZe=new Map([[yt.NO_HINT,null],[yt.NULL,["#a853b5",129]],[yt.SCOPE,["#d75f00",166]],[yt.NAME,["#d7875f",173]],[yt.RANGE,["#00afaf",37]],[yt.REFERENCE,["#87afff",111]],[yt.NUMBER,["#ffd700",220]],[yt.PATH,["#d75fd7",170]],[yt.URL,["#d75fd7",170]],[yt.ADDED,["#5faf00",70]],[yt.REMOVED,["#ff3131",160]],[yt.CODE,["#87afff",111]],[yt.SIZE,["#ffd700",220]]]),So=t=>t;WP={[yt.ID]:So({pretty:(t,e)=>typeof e=="number"?Xs(t,`${e}`,yt.NUMBER):Xs(t,e,yt.CODE),json:t=>t}),[yt.INSPECT]:So({pretty:(t,e)=>(0,Bne.inspect)(e,{depth:1/0,colors:t.get("enableColors"),compact:!0,breakLength:1/0}),json:t=>t}),[yt.NUMBER]:So({pretty:(t,e)=>Xs(t,`${e}`,yt.NUMBER),json:t=>t}),[yt.IDENT]:So({pretty:(t,e)=>Oi(t,e),json:t=>rn(t)}),[yt.LOCATOR]:So({pretty:(t,e)=>qr(t,e),json:t=>ka(t)}),[yt.DESCRIPTOR]:So({pretty:(t,e)=>jn(t,e),json:t=>xa(t)}),[yt.RESOLUTION]:So({pretty:(t,{descriptor:e,locator:r})=>NI(t,e,r),json:({descriptor:t,locator:e})=>({descriptor:xa(t),locator:e!==null?ka(e):null})}),[yt.DEPENDENT]:So({pretty:(t,{locator:e,descriptor:r})=>CL(t,e,r),json:({locator:t,descriptor:e})=>({locator:ka(t),descriptor:xa(e)})}),[yt.PACKAGE_EXTENSION]:So({pretty:(t,e)=>{switch(e.type){case"Dependency":return`${Oi(t,e.parentDescriptor)} \u27A4 ${Xs(t,"dependencies",yt.CODE)} \u27A4 ${Oi(t,e.descriptor)}`;case"PeerDependency":return`${Oi(t,e.parentDescriptor)} \u27A4 ${Xs(t,"peerDependencies",yt.CODE)} \u27A4 ${Oi(t,e.descriptor)}`;case"PeerDependencyMeta":return`${Oi(t,e.parentDescriptor)} \u27A4 ${Xs(t,"peerDependenciesMeta",yt.CODE)} \u27A4 ${Oi(t,ea(e.selector))} \u27A4 ${Xs(t,e.key,yt.CODE)}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${e.type}`)}},json:t=>{switch(t.type){case"Dependency":return`${rn(t.parentDescriptor)} > ${rn(t.descriptor)}`;case"PeerDependency":return`${rn(t.parentDescriptor)} >> ${rn(t.descriptor)}`;case"PeerDependencyMeta":return`${rn(t.parentDescriptor)} >> ${t.selector} / ${t.key}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${t.type}`)}}}),[yt.SETTING]:So({pretty:(t,e)=>(t.get(e),Tm(t,Xs(t,e,yt.CODE),`https://yarnpkg.com/configuration/yarnrc#${e}`)),json:t=>t}),[yt.DURATION]:So({pretty:(t,e)=>{if(e>1e3*60){let r=Math.floor(e/1e3/60),o=Math.ceil((e-r*60*1e3)/1e3);return o===0?`${r}m`:`${r}m ${o}s`}else{let r=Math.floor(e/1e3),o=e-r*1e3;return o===0?`${r}s`:`${r}s ${o}ms`}},json:t=>t}),[yt.SIZE]:So({pretty:(t,e)=>Xs(t,wne(e),yt.NUMBER),json:t=>t}),[yt.SIZE_DIFF]:So({pretty:(t,e)=>{let r=e>=0?"+":"-",o=r==="+"?yt.REMOVED:yt.ADDED;return Xs(t,`${r} ${wne(Math.max(Math.abs(e),1))}`,o)},json:t=>t}),[yt.PATH]:So({pretty:(t,e)=>Xs(t,ue.fromPortablePath(e),yt.PATH),json:t=>ue.fromPortablePath(t)}),[yt.MARKDOWN]:So({pretty:(t,{text:e,format:r,paragraphs:o})=>Do(e,{format:r,paragraphs:o}),json:({text:t})=>t}),[yt.MARKDOWN_INLINE]:So({pretty:(t,e)=>(e=e.replace(/(`+)((?:.|[\n])*?)\1/g,(r,o,a)=>Ot(t,o+a+o,yt.CODE)),e=e.replace(/(\*\*)((?:.|[\n])*?)\1/g,(r,o,a)=>fg(t,a,2)),e),json:t=>t})};TZe=!!process.env.KONSOLE_VERSION;JP=(a=>(a.Error="error",a.Warning="warning",a.Info="info",a.Discard="discard",a))(JP||{})});var vne=_(Nm=>{"use strict";Object.defineProperty(Nm,"__esModule",{value:!0});Nm.splitWhen=Nm.flatten=void 0;function LZe(t){return t.reduce((e,r)=>[].concat(e,r),[])}Nm.flatten=LZe;function MZe(t,e){let r=[[]],o=0;for(let a of t)e(a)?(o++,r[o]=[]):r[o].push(a);return r}Nm.splitWhen=MZe});var Dne=_(XP=>{"use strict";Object.defineProperty(XP,"__esModule",{value:!0});XP.isEnoentCodeError=void 0;function OZe(t){return t.code==="ENOENT"}XP.isEnoentCodeError=OZe});var Pne=_(ZP=>{"use strict";Object.defineProperty(ZP,"__esModule",{value:!0});ZP.createDirentFromStats=void 0;var wL=class{constructor(e,r){this.name=e,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function UZe(t,e){return new wL(t,e)}ZP.createDirentFromStats=UZe});var kne=_(Vi=>{"use strict";Object.defineProperty(Vi,"__esModule",{value:!0});Vi.convertPosixPathToPattern=Vi.convertWindowsPathToPattern=Vi.convertPathToPattern=Vi.escapePosixPath=Vi.escapeWindowsPath=Vi.escape=Vi.removeLeadingDotSegment=Vi.makeAbsolute=Vi.unixify=void 0;var _Ze=ve("os"),HZe=ve("path"),Sne=_Ze.platform()==="win32",qZe=2,jZe=/(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g,GZe=/(\\?)([()[\]{}]|^!|[!+@](?=\())/g,YZe=/^\\\\([.?])/,WZe=/\\(?![!()+@[\]{}])/g;function KZe(t){return t.replace(/\\/g,"/")}Vi.unixify=KZe;function VZe(t,e){return HZe.resolve(t,e)}Vi.makeAbsolute=VZe;function zZe(t){if(t.charAt(0)==="."){let e=t.charAt(1);if(e==="/"||e==="\\")return t.slice(qZe)}return t}Vi.removeLeadingDotSegment=zZe;Vi.escape=Sne?IL:BL;function IL(t){return t.replace(GZe,"\\$2")}Vi.escapeWindowsPath=IL;function BL(t){return t.replace(jZe,"\\$2")}Vi.escapePosixPath=BL;Vi.convertPathToPattern=Sne?bne:xne;function bne(t){return IL(t).replace(YZe,"//$1").replace(WZe,"/")}Vi.convertWindowsPathToPattern=bne;function xne(t){return BL(t)}Vi.convertPosixPathToPattern=xne});var Fne=_((RTt,Qne)=>{Qne.exports=function(e){if(typeof e!="string"||e==="")return!1;for(var r;r=/(\\).|([@?!+*]\(.*\))/g.exec(e);){if(r[2])return!0;e=e.slice(r.index+r[0].length)}return!1}});var Nne=_((TTt,Tne)=>{var JZe=Fne(),Rne={"{":"}","(":")","[":"]"},XZe=function(t){if(t[0]==="!")return!0;for(var e=0,r=-2,o=-2,a=-2,n=-2,u=-2;e<t.length;){if(t[e]==="*"||t[e+1]==="?"&&/[\].+)]/.test(t[e])||o!==-1&&t[e]==="["&&t[e+1]!=="]"&&(o<e&&(o=t.indexOf("]",e)),o>e&&(u===-1||u>o||(u=t.indexOf("\\",e),u===-1||u>o)))||a!==-1&&t[e]==="{"&&t[e+1]!=="}"&&(a=t.indexOf("}",e),a>e&&(u=t.indexOf("\\",e),u===-1||u>a))||n!==-1&&t[e]==="("&&t[e+1]==="?"&&/[:!=]/.test(t[e+2])&&t[e+3]!==")"&&(n=t.indexOf(")",e),n>e&&(u=t.indexOf("\\",e),u===-1||u>n))||r!==-1&&t[e]==="("&&t[e+1]!=="|"&&(r<e&&(r=t.indexOf("|",e)),r!==-1&&t[r+1]!==")"&&(n=t.indexOf(")",r),n>r&&(u=t.indexOf("\\",r),u===-1||u>n))))return!0;if(t[e]==="\\"){var A=t[e+1];e+=2;var p=Rne[A];if(p){var h=t.indexOf(p,e);h!==-1&&(e=h+1)}if(t[e]==="!")return!0}else e++}return!1},ZZe=function(t){if(t[0]==="!")return!0;for(var e=0;e<t.length;){if(/[*?{}()[\]]/.test(t[e]))return!0;if(t[e]==="\\"){var r=t[e+1];e+=2;var o=Rne[r];if(o){var a=t.indexOf(o,e);a!==-1&&(e=a+1)}if(t[e]==="!")return!0}else e++}return!1};Tne.exports=function(e,r){if(typeof e!="string"||e==="")return!1;if(JZe(e))return!0;var o=XZe;return r&&r.strict===!1&&(o=ZZe),o(e)}});var Mne=_((NTt,Lne)=>{"use strict";var $Ze=Nne(),e$e=ve("path").posix.dirname,t$e=ve("os").platform()==="win32",vL="/",r$e=/\\/g,n$e=/[\{\[].*[\}\]]$/,i$e=/(^|[^\\])([\{\[]|\([^\)]+$)/,s$e=/\\([\!\*\?\|\[\]\(\)\{\}])/g;Lne.exports=function(e,r){var o=Object.assign({flipBackslashes:!0},r);o.flipBackslashes&&t$e&&e.indexOf(vL)<0&&(e=e.replace(r$e,vL)),n$e.test(e)&&(e+=vL),e+="a";do e=e$e(e);while($Ze(e)||i$e.test(e));return e.replace(s$e,"$1")}});var Yne=_(Nr=>{"use strict";Object.defineProperty(Nr,"__esModule",{value:!0});Nr.removeDuplicateSlashes=Nr.matchAny=Nr.convertPatternsToRe=Nr.makeRe=Nr.getPatternParts=Nr.expandBraceExpansion=Nr.expandPatternsWithBraceExpansion=Nr.isAffectDepthOfReadingPattern=Nr.endsWithSlashGlobStar=Nr.hasGlobStar=Nr.getBaseDirectory=Nr.isPatternRelatedToParentDirectory=Nr.getPatternsOutsideCurrentDirectory=Nr.getPatternsInsideCurrentDirectory=Nr.getPositivePatterns=Nr.getNegativePatterns=Nr.isPositivePattern=Nr.isNegativePattern=Nr.convertToNegativePattern=Nr.convertToPositivePattern=Nr.isDynamicPattern=Nr.isStaticPattern=void 0;var o$e=ve("path"),a$e=Mne(),DL=$o(),One="**",l$e="\\",c$e=/[*?]|^!/,u$e=/\[[^[]*]/,A$e=/(?:^|[^!*+?@])\([^(]*\|[^|]*\)/,f$e=/[!*+?@]\([^(]*\)/,p$e=/,|\.\./,h$e=/(?!^)\/{2,}/g;function Une(t,e={}){return!_ne(t,e)}Nr.isStaticPattern=Une;function _ne(t,e={}){return t===""?!1:!!(e.caseSensitiveMatch===!1||t.includes(l$e)||c$e.test(t)||u$e.test(t)||A$e.test(t)||e.extglob!==!1&&f$e.test(t)||e.braceExpansion!==!1&&g$e(t))}Nr.isDynamicPattern=_ne;function g$e(t){let e=t.indexOf("{");if(e===-1)return!1;let r=t.indexOf("}",e+1);if(r===-1)return!1;let o=t.slice(e,r);return p$e.test(o)}function d$e(t){return $P(t)?t.slice(1):t}Nr.convertToPositivePattern=d$e;function m$e(t){return"!"+t}Nr.convertToNegativePattern=m$e;function $P(t){return t.startsWith("!")&&t[1]!=="("}Nr.isNegativePattern=$P;function Hne(t){return!$P(t)}Nr.isPositivePattern=Hne;function y$e(t){return t.filter($P)}Nr.getNegativePatterns=y$e;function E$e(t){return t.filter(Hne)}Nr.getPositivePatterns=E$e;function C$e(t){return t.filter(e=>!PL(e))}Nr.getPatternsInsideCurrentDirectory=C$e;function w$e(t){return t.filter(PL)}Nr.getPatternsOutsideCurrentDirectory=w$e;function PL(t){return t.startsWith("..")||t.startsWith("./..")}Nr.isPatternRelatedToParentDirectory=PL;function I$e(t){return a$e(t,{flipBackslashes:!1})}Nr.getBaseDirectory=I$e;function B$e(t){return t.includes(One)}Nr.hasGlobStar=B$e;function qne(t){return t.endsWith("/"+One)}Nr.endsWithSlashGlobStar=qne;function v$e(t){let e=o$e.basename(t);return qne(t)||Une(e)}Nr.isAffectDepthOfReadingPattern=v$e;function D$e(t){return t.reduce((e,r)=>e.concat(jne(r)),[])}Nr.expandPatternsWithBraceExpansion=D$e;function jne(t){let e=DL.braces(t,{expand:!0,nodupes:!0,keepEscaping:!0});return e.sort((r,o)=>r.length-o.length),e.filter(r=>r!=="")}Nr.expandBraceExpansion=jne;function P$e(t,e){let{parts:r}=DL.scan(t,Object.assign(Object.assign({},e),{parts:!0}));return r.length===0&&(r=[t]),r[0].startsWith("/")&&(r[0]=r[0].slice(1),r.unshift("")),r}Nr.getPatternParts=P$e;function Gne(t,e){return DL.makeRe(t,e)}Nr.makeRe=Gne;function S$e(t,e){return t.map(r=>Gne(r,e))}Nr.convertPatternsToRe=S$e;function b$e(t,e){return e.some(r=>r.test(t))}Nr.matchAny=b$e;function x$e(t){return t.replace(h$e,"/")}Nr.removeDuplicateSlashes=x$e});var zne=_((MTt,Vne)=>{"use strict";var k$e=ve("stream"),Wne=k$e.PassThrough,Q$e=Array.prototype.slice;Vne.exports=F$e;function F$e(){let t=[],e=Q$e.call(arguments),r=!1,o=e[e.length-1];o&&!Array.isArray(o)&&o.pipe==null?e.pop():o={};let a=o.end!==!1,n=o.pipeError===!0;o.objectMode==null&&(o.objectMode=!0),o.highWaterMark==null&&(o.highWaterMark=64*1024);let u=Wne(o);function A(){for(let E=0,I=arguments.length;E<I;E++)t.push(Kne(arguments[E],o));return p(),this}function p(){if(r)return;r=!0;let E=t.shift();if(!E){process.nextTick(h);return}Array.isArray(E)||(E=[E]);let I=E.length+1;function v(){--I>0||(r=!1,p())}function x(C){function R(){C.removeListener("merge2UnpipeEnd",R),C.removeListener("end",R),n&&C.removeListener("error",L),v()}function L(U){u.emit("error",U)}if(C._readableState.endEmitted)return v();C.on("merge2UnpipeEnd",R),C.on("end",R),n&&C.on("error",L),C.pipe(u,{end:!1}),C.resume()}for(let C=0;C<E.length;C++)x(E[C]);v()}function h(){r=!1,u.emit("queueDrain"),a&&u.end()}return u.setMaxListeners(0),u.add=A,u.on("unpipe",function(E){E.emit("merge2UnpipeEnd")}),e.length&&A.apply(null,e),u}function Kne(t,e){if(Array.isArray(t))for(let r=0,o=t.length;r<o;r++)t[r]=Kne(t[r],e);else{if(!t._readableState&&t.pipe&&(t=t.pipe(Wne(e))),!t._readableState||!t.pause||!t.pipe)throw new Error("Only readable stream can be merged.");t.pause()}return t}});var Xne=_(eS=>{"use strict";Object.defineProperty(eS,"__esModule",{value:!0});eS.merge=void 0;var R$e=zne();function T$e(t){let e=R$e(t);return t.forEach(r=>{r.once("error",o=>e.emit("error",o))}),e.once("close",()=>Jne(t)),e.once("end",()=>Jne(t)),e}eS.merge=T$e;function Jne(t){t.forEach(e=>e.emit("close"))}});var Zne=_(Lm=>{"use strict";Object.defineProperty(Lm,"__esModule",{value:!0});Lm.isEmpty=Lm.isString=void 0;function N$e(t){return typeof t=="string"}Lm.isString=N$e;function L$e(t){return t===""}Lm.isEmpty=L$e});var Df=_(xo=>{"use strict";Object.defineProperty(xo,"__esModule",{value:!0});xo.string=xo.stream=xo.pattern=xo.path=xo.fs=xo.errno=xo.array=void 0;var M$e=vne();xo.array=M$e;var O$e=Dne();xo.errno=O$e;var U$e=Pne();xo.fs=U$e;var _$e=kne();xo.path=_$e;var H$e=Yne();xo.pattern=H$e;var q$e=Xne();xo.stream=q$e;var j$e=Zne();xo.string=j$e});var rie=_(ko=>{"use strict";Object.defineProperty(ko,"__esModule",{value:!0});ko.convertPatternGroupToTask=ko.convertPatternGroupsToTasks=ko.groupPatternsByBaseDirectory=ko.getNegativePatternsAsPositive=ko.getPositivePatterns=ko.convertPatternsToTasks=ko.generate=void 0;var qc=Df();function G$e(t,e){let r=$ne(t,e),o=$ne(e.ignore,e),a=eie(r),n=tie(r,o),u=a.filter(E=>qc.pattern.isStaticPattern(E,e)),A=a.filter(E=>qc.pattern.isDynamicPattern(E,e)),p=SL(u,n,!1),h=SL(A,n,!0);return p.concat(h)}ko.generate=G$e;function $ne(t,e){let r=t;return e.braceExpansion&&(r=qc.pattern.expandPatternsWithBraceExpansion(r)),e.baseNameMatch&&(r=r.map(o=>o.includes("/")?o:`**/${o}`)),r.map(o=>qc.pattern.removeDuplicateSlashes(o))}function SL(t,e,r){let o=[],a=qc.pattern.getPatternsOutsideCurrentDirectory(t),n=qc.pattern.getPatternsInsideCurrentDirectory(t),u=bL(a),A=bL(n);return o.push(...xL(u,e,r)),"."in A?o.push(kL(".",n,e,r)):o.push(...xL(A,e,r)),o}ko.convertPatternsToTasks=SL;function eie(t){return qc.pattern.getPositivePatterns(t)}ko.getPositivePatterns=eie;function tie(t,e){return qc.pattern.getNegativePatterns(t).concat(e).map(qc.pattern.convertToPositivePattern)}ko.getNegativePatternsAsPositive=tie;function bL(t){let e={};return t.reduce((r,o)=>{let a=qc.pattern.getBaseDirectory(o);return a in r?r[a].push(o):r[a]=[o],r},e)}ko.groupPatternsByBaseDirectory=bL;function xL(t,e,r){return Object.keys(t).map(o=>kL(o,t[o],e,r))}ko.convertPatternGroupsToTasks=xL;function kL(t,e,r,o){return{dynamic:o,positive:e,negative:r,base:t,patterns:[].concat(e,r.map(qc.pattern.convertToNegativePattern))}}ko.convertPatternGroupToTask=kL});var iie=_(tS=>{"use strict";Object.defineProperty(tS,"__esModule",{value:!0});tS.read=void 0;function Y$e(t,e,r){e.fs.lstat(t,(o,a)=>{if(o!==null){nie(r,o);return}if(!a.isSymbolicLink()||!e.followSymbolicLink){QL(r,a);return}e.fs.stat(t,(n,u)=>{if(n!==null){if(e.throwErrorOnBrokenSymbolicLink){nie(r,n);return}QL(r,a);return}e.markSymbolicLink&&(u.isSymbolicLink=()=>!0),QL(r,u)})})}tS.read=Y$e;function nie(t,e){t(e)}function QL(t,e){t(null,e)}});var sie=_(rS=>{"use strict";Object.defineProperty(rS,"__esModule",{value:!0});rS.read=void 0;function W$e(t,e){let r=e.fs.lstatSync(t);if(!r.isSymbolicLink()||!e.followSymbolicLink)return r;try{let o=e.fs.statSync(t);return e.markSymbolicLink&&(o.isSymbolicLink=()=>!0),o}catch(o){if(!e.throwErrorOnBrokenSymbolicLink)return r;throw o}}rS.read=W$e});var oie=_(zp=>{"use strict";Object.defineProperty(zp,"__esModule",{value:!0});zp.createFileSystemAdapter=zp.FILE_SYSTEM_ADAPTER=void 0;var nS=ve("fs");zp.FILE_SYSTEM_ADAPTER={lstat:nS.lstat,stat:nS.stat,lstatSync:nS.lstatSync,statSync:nS.statSync};function K$e(t){return t===void 0?zp.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},zp.FILE_SYSTEM_ADAPTER),t)}zp.createFileSystemAdapter=K$e});var aie=_(RL=>{"use strict";Object.defineProperty(RL,"__esModule",{value:!0});var V$e=oie(),FL=class{constructor(e={}){this._options=e,this.followSymbolicLink=this._getValue(this._options.followSymbolicLink,!0),this.fs=V$e.createFileSystemAdapter(this._options.fs),this.markSymbolicLink=this._getValue(this._options.markSymbolicLink,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0)}_getValue(e,r){return e??r}};RL.default=FL});var hg=_(Jp=>{"use strict";Object.defineProperty(Jp,"__esModule",{value:!0});Jp.statSync=Jp.stat=Jp.Settings=void 0;var lie=iie(),z$e=sie(),TL=aie();Jp.Settings=TL.default;function J$e(t,e,r){if(typeof e=="function"){lie.read(t,NL(),e);return}lie.read(t,NL(e),r)}Jp.stat=J$e;function X$e(t,e){let r=NL(e);return z$e.read(t,r)}Jp.statSync=X$e;function NL(t={}){return t instanceof TL.default?t:new TL.default(t)}});var Aie=_((KTt,uie)=>{var cie;uie.exports=typeof queueMicrotask=="function"?queueMicrotask.bind(typeof window<"u"?window:global):t=>(cie||(cie=Promise.resolve())).then(t).catch(e=>setTimeout(()=>{throw e},0))});var pie=_((VTt,fie)=>{fie.exports=$$e;var Z$e=Aie();function $$e(t,e){let r,o,a,n=!0;Array.isArray(t)?(r=[],o=t.length):(a=Object.keys(t),r={},o=a.length);function u(p){function h(){e&&e(p,r),e=null}n?Z$e(h):h()}function A(p,h,E){r[p]=E,(--o===0||h)&&u(h)}o?a?a.forEach(function(p){t[p](function(h,E){A(p,h,E)})}):t.forEach(function(p,h){p(function(E,I){A(h,E,I)})}):u(null),n=!1}});var LL=_(sS=>{"use strict";Object.defineProperty(sS,"__esModule",{value:!0});sS.IS_SUPPORT_READDIR_WITH_FILE_TYPES=void 0;var iS=process.versions.node.split(".");if(iS[0]===void 0||iS[1]===void 0)throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);var hie=Number.parseInt(iS[0],10),eet=Number.parseInt(iS[1],10),gie=10,tet=10,ret=hie>gie,net=hie===gie&&eet>=tet;sS.IS_SUPPORT_READDIR_WITH_FILE_TYPES=ret||net});var die=_(oS=>{"use strict";Object.defineProperty(oS,"__esModule",{value:!0});oS.createDirentFromStats=void 0;var ML=class{constructor(e,r){this.name=e,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function iet(t,e){return new ML(t,e)}oS.createDirentFromStats=iet});var OL=_(aS=>{"use strict";Object.defineProperty(aS,"__esModule",{value:!0});aS.fs=void 0;var set=die();aS.fs=set});var UL=_(lS=>{"use strict";Object.defineProperty(lS,"__esModule",{value:!0});lS.joinPathSegments=void 0;function oet(t,e,r){return t.endsWith(r)?t+e:t+r+e}lS.joinPathSegments=oet});var Iie=_(Xp=>{"use strict";Object.defineProperty(Xp,"__esModule",{value:!0});Xp.readdir=Xp.readdirWithFileTypes=Xp.read=void 0;var aet=hg(),mie=pie(),cet=LL(),yie=OL(),Eie=UL();function uet(t,e,r){if(!e.stats&&cet.IS_SUPPORT_READDIR_WITH_FILE_TYPES){Cie(t,e,r);return}wie(t,e,r)}Xp.read=uet;function Cie(t,e,r){e.fs.readdir(t,{withFileTypes:!0},(o,a)=>{if(o!==null){cS(r,o);return}let n=a.map(A=>({dirent:A,name:A.name,path:Eie.joinPathSegments(t,A.name,e.pathSegmentSeparator)}));if(!e.followSymbolicLinks){_L(r,n);return}let u=n.map(A=>Aet(A,e));mie(u,(A,p)=>{if(A!==null){cS(r,A);return}_L(r,p)})})}Xp.readdirWithFileTypes=Cie;function Aet(t,e){return r=>{if(!t.dirent.isSymbolicLink()){r(null,t);return}e.fs.stat(t.path,(o,a)=>{if(o!==null){if(e.throwErrorOnBrokenSymbolicLink){r(o);return}r(null,t);return}t.dirent=yie.fs.createDirentFromStats(t.name,a),r(null,t)})}}function wie(t,e,r){e.fs.readdir(t,(o,a)=>{if(o!==null){cS(r,o);return}let n=a.map(u=>{let A=Eie.joinPathSegments(t,u,e.pathSegmentSeparator);return p=>{aet.stat(A,e.fsStatSettings,(h,E)=>{if(h!==null){p(h);return}let I={name:u,path:A,dirent:yie.fs.createDirentFromStats(u,E)};e.stats&&(I.stats=E),p(null,I)})}});mie(n,(u,A)=>{if(u!==null){cS(r,u);return}_L(r,A)})})}Xp.readdir=wie;function cS(t,e){t(e)}function _L(t,e){t(null,e)}});var Sie=_(Zp=>{"use strict";Object.defineProperty(Zp,"__esModule",{value:!0});Zp.readdir=Zp.readdirWithFileTypes=Zp.read=void 0;var fet=hg(),pet=LL(),Bie=OL(),vie=UL();function het(t,e){return!e.stats&&pet.IS_SUPPORT_READDIR_WITH_FILE_TYPES?Die(t,e):Pie(t,e)}Zp.read=het;function Die(t,e){return e.fs.readdirSync(t,{withFileTypes:!0}).map(o=>{let a={dirent:o,name:o.name,path:vie.joinPathSegments(t,o.name,e.pathSegmentSeparator)};if(a.dirent.isSymbolicLink()&&e.followSymbolicLinks)try{let n=e.fs.statSync(a.path);a.dirent=Bie.fs.createDirentFromStats(a.name,n)}catch(n){if(e.throwErrorOnBrokenSymbolicLink)throw n}return a})}Zp.readdirWithFileTypes=Die;function Pie(t,e){return e.fs.readdirSync(t).map(o=>{let a=vie.joinPathSegments(t,o,e.pathSegmentSeparator),n=fet.statSync(a,e.fsStatSettings),u={name:o,path:a,dirent:Bie.fs.createDirentFromStats(o,n)};return e.stats&&(u.stats=n),u})}Zp.readdir=Pie});var bie=_($p=>{"use strict";Object.defineProperty($p,"__esModule",{value:!0});$p.createFileSystemAdapter=$p.FILE_SYSTEM_ADAPTER=void 0;var Mm=ve("fs");$p.FILE_SYSTEM_ADAPTER={lstat:Mm.lstat,stat:Mm.stat,lstatSync:Mm.lstatSync,statSync:Mm.statSync,readdir:Mm.readdir,readdirSync:Mm.readdirSync};function get(t){return t===void 0?$p.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},$p.FILE_SYSTEM_ADAPTER),t)}$p.createFileSystemAdapter=get});var xie=_(qL=>{"use strict";Object.defineProperty(qL,"__esModule",{value:!0});var det=ve("path"),met=hg(),yet=bie(),HL=class{constructor(e={}){this._options=e,this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!1),this.fs=yet.createFileSystemAdapter(this._options.fs),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,det.sep),this.stats=this._getValue(this._options.stats,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0),this.fsStatSettings=new met.Settings({followSymbolicLink:this.followSymbolicLinks,fs:this.fs,throwErrorOnBrokenSymbolicLink:this.throwErrorOnBrokenSymbolicLink})}_getValue(e,r){return e??r}};qL.default=HL});var uS=_(eh=>{"use strict";Object.defineProperty(eh,"__esModule",{value:!0});eh.Settings=eh.scandirSync=eh.scandir=void 0;var kie=Iie(),Eet=Sie(),jL=xie();eh.Settings=jL.default;function Cet(t,e,r){if(typeof e=="function"){kie.read(t,YL(),e);return}kie.read(t,YL(e),r)}eh.scandir=Cet;function wet(t,e){let r=YL(e);return Eet.read(t,r)}eh.scandirSync=wet;function YL(t={}){return t instanceof jL.default?t:new jL.default(t)}});var Fie=_((iNt,Qie)=>{"use strict";function Iet(t){var e=new t,r=e;function o(){var n=e;return n.next?e=n.next:(e=new t,r=e),n.next=null,n}function a(n){r.next=n,r=n}return{get:o,release:a}}Qie.exports=Iet});var Tie=_((sNt,WL)=>{"use strict";var Bet=Fie();function Rie(t,e,r){if(typeof t=="function"&&(r=e,e=t,t=null),!(r>=1))throw new Error("fastqueue concurrency must be equal to or greater than 1");var o=Bet(vet),a=null,n=null,u=0,A=null,p={push:R,drain:Gl,saturated:Gl,pause:E,paused:!1,get concurrency(){return r},set concurrency(le){if(!(le>=1))throw new Error("fastqueue concurrency must be equal to or greater than 1");if(r=le,!p.paused)for(;a&&u<r;)u++,U()},running:h,resume:x,idle:C,length:I,getQueue:v,unshift:L,empty:Gl,kill:z,killAndDrain:te,error:ae};return p;function h(){return u}function E(){p.paused=!0}function I(){for(var le=a,ce=0;le;)le=le.next,ce++;return ce}function v(){for(var le=a,ce=[];le;)ce.push(le.value),le=le.next;return ce}function x(){if(p.paused){if(p.paused=!1,a===null){u++,U();return}for(;a&&u<r;)u++,U()}}function C(){return u===0&&p.length()===0}function R(le,ce){var Ce=o.get();Ce.context=t,Ce.release=U,Ce.value=le,Ce.callback=ce||Gl,Ce.errorHandler=A,u>=r||p.paused?n?(n.next=Ce,n=Ce):(a=Ce,n=Ce,p.saturated()):(u++,e.call(t,Ce.value,Ce.worked))}function L(le,ce){var Ce=o.get();Ce.context=t,Ce.release=U,Ce.value=le,Ce.callback=ce||Gl,Ce.errorHandler=A,u>=r||p.paused?a?(Ce.next=a,a=Ce):(a=Ce,n=Ce,p.saturated()):(u++,e.call(t,Ce.value,Ce.worked))}function U(le){le&&o.release(le);var ce=a;ce&&u<=r?p.paused?u--:(n===a&&(n=null),a=ce.next,ce.next=null,e.call(t,ce.value,ce.worked),n===null&&p.empty()):--u===0&&p.drain()}function z(){a=null,n=null,p.drain=Gl}function te(){a=null,n=null,p.drain(),p.drain=Gl}function ae(le){A=le}}function Gl(){}function vet(){this.value=null,this.callback=Gl,this.next=null,this.release=Gl,this.context=null,this.errorHandler=null;var t=this;this.worked=function(r,o){var a=t.callback,n=t.errorHandler,u=t.value;t.value=null,t.callback=Gl,t.errorHandler&&n(r,u),a.call(t.context,r,o),t.release(t)}}function Det(t,e,r){typeof t=="function"&&(r=e,e=t,t=null);function o(E,I){e.call(this,E).then(function(v){I(null,v)},I)}var a=Rie(t,o,r),n=a.push,u=a.unshift;return a.push=A,a.unshift=p,a.drained=h,a;function A(E){var I=new Promise(function(v,x){n(E,function(C,R){if(C){x(C);return}v(R)})});return I.catch(Gl),I}function p(E){var I=new Promise(function(v,x){u(E,function(C,R){if(C){x(C);return}v(R)})});return I.catch(Gl),I}function h(){if(a.idle())return new Promise(function(v){v()});var E=a.drain,I=new Promise(function(v){a.drain=function(){E(),v()}});return I}}WL.exports=Rie;WL.exports.promise=Det});var AS=_(Zu=>{"use strict";Object.defineProperty(Zu,"__esModule",{value:!0});Zu.joinPathSegments=Zu.replacePathSegmentSeparator=Zu.isAppliedFilter=Zu.isFatalError=void 0;function Pet(t,e){return t.errorFilter===null?!0:!t.errorFilter(e)}Zu.isFatalError=Pet;function bet(t,e){return t===null||t(e)}Zu.isAppliedFilter=bet;function xet(t,e){return t.split(/[/\\]/).join(e)}Zu.replacePathSegmentSeparator=xet;function ket(t,e,r){return t===""?e:t.endsWith(r)?t+e:t+r+e}Zu.joinPathSegments=ket});var zL=_(VL=>{"use strict";Object.defineProperty(VL,"__esModule",{value:!0});var Qet=AS(),KL=class{constructor(e,r){this._root=e,this._settings=r,this._root=Qet.replacePathSegmentSeparator(e,r.pathSegmentSeparator)}};VL.default=KL});var ZL=_(XL=>{"use strict";Object.defineProperty(XL,"__esModule",{value:!0});var Fet=ve("events"),Ret=uS(),Tet=Tie(),fS=AS(),Net=zL(),JL=class extends Net.default{constructor(e,r){super(e,r),this._settings=r,this._scandir=Ret.scandir,this._emitter=new Fet.EventEmitter,this._queue=Tet(this._worker.bind(this),this._settings.concurrency),this._isFatalError=!1,this._isDestroyed=!1,this._queue.drain=()=>{this._isFatalError||this._emitter.emit("end")}}read(){return this._isFatalError=!1,this._isDestroyed=!1,setImmediate(()=>{this._pushToQueue(this._root,this._settings.basePath)}),this._emitter}get isDestroyed(){return this._isDestroyed}destroy(){if(this._isDestroyed)throw new Error("The reader is already destroyed");this._isDestroyed=!0,this._queue.killAndDrain()}onEntry(e){this._emitter.on("entry",e)}onError(e){this._emitter.once("error",e)}onEnd(e){this._emitter.once("end",e)}_pushToQueue(e,r){let o={directory:e,base:r};this._queue.push(o,a=>{a!==null&&this._handleError(a)})}_worker(e,r){this._scandir(e.directory,this._settings.fsScandirSettings,(o,a)=>{if(o!==null){r(o,void 0);return}for(let n of a)this._handleEntry(n,e.base);r(null,void 0)})}_handleError(e){this._isDestroyed||!fS.isFatalError(this._settings,e)||(this._isFatalError=!0,this._isDestroyed=!0,this._emitter.emit("error",e))}_handleEntry(e,r){if(this._isDestroyed||this._isFatalError)return;let o=e.path;r!==void 0&&(e.path=fS.joinPathSegments(r,e.name,this._settings.pathSegmentSeparator)),fS.isAppliedFilter(this._settings.entryFilter,e)&&this._emitEntry(e),e.dirent.isDirectory()&&fS.isAppliedFilter(this._settings.deepFilter,e)&&this._pushToQueue(o,r===void 0?void 0:e.path)}_emitEntry(e){this._emitter.emit("entry",e)}};XL.default=JL});var Nie=_(eM=>{"use strict";Object.defineProperty(eM,"__esModule",{value:!0});var Let=ZL(),$L=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new Let.default(this._root,this._settings),this._storage=[]}read(e){this._reader.onError(r=>{Met(e,r)}),this._reader.onEntry(r=>{this._storage.push(r)}),this._reader.onEnd(()=>{Oet(e,this._storage)}),this._reader.read()}};eM.default=$L;function Met(t,e){t(e)}function Oet(t,e){t(null,e)}});var Lie=_(rM=>{"use strict";Object.defineProperty(rM,"__esModule",{value:!0});var Uet=ve("stream"),_et=ZL(),tM=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new _et.default(this._root,this._settings),this._stream=new Uet.Readable({objectMode:!0,read:()=>{},destroy:()=>{this._reader.isDestroyed||this._reader.destroy()}})}read(){return this._reader.onError(e=>{this._stream.emit("error",e)}),this._reader.onEntry(e=>{this._stream.push(e)}),this._reader.onEnd(()=>{this._stream.push(null)}),this._reader.read(),this._stream}};rM.default=tM});var Mie=_(iM=>{"use strict";Object.defineProperty(iM,"__esModule",{value:!0});var Het=uS(),pS=AS(),qet=zL(),nM=class extends qet.default{constructor(){super(...arguments),this._scandir=Het.scandirSync,this._storage=[],this._queue=new Set}read(){return this._pushToQueue(this._root,this._settings.basePath),this._handleQueue(),this._storage}_pushToQueue(e,r){this._queue.add({directory:e,base:r})}_handleQueue(){for(let e of this._queue.values())this._handleDirectory(e.directory,e.base)}_handleDirectory(e,r){try{let o=this._scandir(e,this._settings.fsScandirSettings);for(let a of o)this._handleEntry(a,r)}catch(o){this._handleError(o)}}_handleError(e){if(pS.isFatalError(this._settings,e))throw e}_handleEntry(e,r){let o=e.path;r!==void 0&&(e.path=pS.joinPathSegments(r,e.name,this._settings.pathSegmentSeparator)),pS.isAppliedFilter(this._settings.entryFilter,e)&&this._pushToStorage(e),e.dirent.isDirectory()&&pS.isAppliedFilter(this._settings.deepFilter,e)&&this._pushToQueue(o,r===void 0?void 0:e.path)}_pushToStorage(e){this._storage.push(e)}};iM.default=nM});var Oie=_(oM=>{"use strict";Object.defineProperty(oM,"__esModule",{value:!0});var jet=Mie(),sM=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new jet.default(this._root,this._settings)}read(){return this._reader.read()}};oM.default=sM});var Uie=_(lM=>{"use strict";Object.defineProperty(lM,"__esModule",{value:!0});var Get=ve("path"),Yet=uS(),aM=class{constructor(e={}){this._options=e,this.basePath=this._getValue(this._options.basePath,void 0),this.concurrency=this._getValue(this._options.concurrency,Number.POSITIVE_INFINITY),this.deepFilter=this._getValue(this._options.deepFilter,null),this.entryFilter=this._getValue(this._options.entryFilter,null),this.errorFilter=this._getValue(this._options.errorFilter,null),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,Get.sep),this.fsScandirSettings=new Yet.Settings({followSymbolicLinks:this._options.followSymbolicLinks,fs:this._options.fs,pathSegmentSeparator:this._options.pathSegmentSeparator,stats:this._options.stats,throwErrorOnBrokenSymbolicLink:this._options.throwErrorOnBrokenSymbolicLink})}_getValue(e,r){return e??r}};lM.default=aM});var gS=_($u=>{"use strict";Object.defineProperty($u,"__esModule",{value:!0});$u.Settings=$u.walkStream=$u.walkSync=$u.walk=void 0;var _ie=Nie(),Wet=Lie(),Ket=Oie(),cM=Uie();$u.Settings=cM.default;function Vet(t,e,r){if(typeof e=="function"){new _ie.default(t,hS()).read(e);return}new _ie.default(t,hS(e)).read(r)}$u.walk=Vet;function zet(t,e){let r=hS(e);return new Ket.default(t,r).read()}$u.walkSync=zet;function Jet(t,e){let r=hS(e);return new Wet.default(t,r).read()}$u.walkStream=Jet;function hS(t={}){return t instanceof cM.default?t:new cM.default(t)}});var dS=_(AM=>{"use strict";Object.defineProperty(AM,"__esModule",{value:!0});var Xet=ve("path"),Zet=hg(),Hie=Df(),uM=class{constructor(e){this._settings=e,this._fsStatSettings=new Zet.Settings({followSymbolicLink:this._settings.followSymbolicLinks,fs:this._settings.fs,throwErrorOnBrokenSymbolicLink:this._settings.followSymbolicLinks})}_getFullEntryPath(e){return Xet.resolve(this._settings.cwd,e)}_makeEntry(e,r){let o={name:r,path:r,dirent:Hie.fs.createDirentFromStats(r,e)};return this._settings.stats&&(o.stats=e),o}_isFatalError(e){return!Hie.errno.isEnoentCodeError(e)&&!this._settings.suppressErrors}};AM.default=uM});var hM=_(pM=>{"use strict";Object.defineProperty(pM,"__esModule",{value:!0});var $et=ve("stream"),ett=hg(),ttt=gS(),rtt=dS(),fM=class extends rtt.default{constructor(){super(...arguments),this._walkStream=ttt.walkStream,this._stat=ett.stat}dynamic(e,r){return this._walkStream(e,r)}static(e,r){let o=e.map(this._getFullEntryPath,this),a=new $et.PassThrough({objectMode:!0});a._write=(n,u,A)=>this._getEntry(o[n],e[n],r).then(p=>{p!==null&&r.entryFilter(p)&&a.push(p),n===o.length-1&&a.end(),A()}).catch(A);for(let n=0;n<o.length;n++)a.write(n);return a}_getEntry(e,r,o){return this._getStat(e).then(a=>this._makeEntry(a,r)).catch(a=>{if(o.errorFilter(a))return null;throw a})}_getStat(e){return new Promise((r,o)=>{this._stat(e,this._fsStatSettings,(a,n)=>a===null?r(n):o(a))})}};pM.default=fM});var qie=_(dM=>{"use strict";Object.defineProperty(dM,"__esModule",{value:!0});var ntt=gS(),itt=dS(),stt=hM(),gM=class extends itt.default{constructor(){super(...arguments),this._walkAsync=ntt.walk,this._readerStream=new stt.default(this._settings)}dynamic(e,r){return new Promise((o,a)=>{this._walkAsync(e,r,(n,u)=>{n===null?o(u):a(n)})})}async static(e,r){let o=[],a=this._readerStream.static(e,r);return new Promise((n,u)=>{a.once("error",u),a.on("data",A=>o.push(A)),a.once("end",()=>n(o))})}};dM.default=gM});var jie=_(yM=>{"use strict";Object.defineProperty(yM,"__esModule",{value:!0});var LI=Df(),mM=class{constructor(e,r,o){this._patterns=e,this._settings=r,this._micromatchOptions=o,this._storage=[],this._fillStorage()}_fillStorage(){for(let e of this._patterns){let r=this._getPatternSegments(e),o=this._splitSegmentsIntoSections(r);this._storage.push({complete:o.length<=1,pattern:e,segments:r,sections:o})}}_getPatternSegments(e){return LI.pattern.getPatternParts(e,this._micromatchOptions).map(o=>LI.pattern.isDynamicPattern(o,this._settings)?{dynamic:!0,pattern:o,patternRe:LI.pattern.makeRe(o,this._micromatchOptions)}:{dynamic:!1,pattern:o})}_splitSegmentsIntoSections(e){return LI.array.splitWhen(e,r=>r.dynamic&&LI.pattern.hasGlobStar(r.pattern))}};yM.default=mM});var Gie=_(CM=>{"use strict";Object.defineProperty(CM,"__esModule",{value:!0});var ott=jie(),EM=class extends ott.default{match(e){let r=e.split("/"),o=r.length,a=this._storage.filter(n=>!n.complete||n.segments.length>o);for(let n of a){let u=n.sections[0];if(!n.complete&&o>u.length||r.every((p,h)=>{let E=n.segments[h];return!!(E.dynamic&&E.patternRe.test(p)||!E.dynamic&&E.pattern===p)}))return!0}return!1}};CM.default=EM});var Yie=_(IM=>{"use strict";Object.defineProperty(IM,"__esModule",{value:!0});var mS=Df(),att=Gie(),wM=class{constructor(e,r){this._settings=e,this._micromatchOptions=r}getFilter(e,r,o){let a=this._getMatcher(r),n=this._getNegativePatternsRe(o);return u=>this._filter(e,u,a,n)}_getMatcher(e){return new att.default(e,this._settings,this._micromatchOptions)}_getNegativePatternsRe(e){let r=e.filter(mS.pattern.isAffectDepthOfReadingPattern);return mS.pattern.convertPatternsToRe(r,this._micromatchOptions)}_filter(e,r,o,a){if(this._isSkippedByDeep(e,r.path)||this._isSkippedSymbolicLink(r))return!1;let n=mS.path.removeLeadingDotSegment(r.path);return this._isSkippedByPositivePatterns(n,o)?!1:this._isSkippedByNegativePatterns(n,a)}_isSkippedByDeep(e,r){return this._settings.deep===1/0?!1:this._getEntryLevel(e,r)>=this._settings.deep}_getEntryLevel(e,r){let o=r.split("/").length;if(e==="")return o;let a=e.split("/").length;return o-a}_isSkippedSymbolicLink(e){return!this._settings.followSymbolicLinks&&e.dirent.isSymbolicLink()}_isSkippedByPositivePatterns(e,r){return!this._settings.baseNameMatch&&!r.match(e)}_isSkippedByNegativePatterns(e,r){return!mS.pattern.matchAny(e,r)}};IM.default=wM});var Wie=_(vM=>{"use strict";Object.defineProperty(vM,"__esModule",{value:!0});var gg=Df(),BM=class{constructor(e,r){this._settings=e,this._micromatchOptions=r,this.index=new Map}getFilter(e,r){let o=gg.pattern.convertPatternsToRe(e,this._micromatchOptions),a=gg.pattern.convertPatternsToRe(r,Object.assign(Object.assign({},this._micromatchOptions),{dot:!0}));return n=>this._filter(n,o,a)}_filter(e,r,o){let a=gg.path.removeLeadingDotSegment(e.path);if(this._settings.unique&&this._isDuplicateEntry(a)||this._onlyFileFilter(e)||this._onlyDirectoryFilter(e)||this._isSkippedByAbsoluteNegativePatterns(a,o))return!1;let n=e.dirent.isDirectory(),u=this._isMatchToPatterns(a,r,n)&&!this._isMatchToPatterns(a,o,n);return this._settings.unique&&u&&this._createIndexRecord(a),u}_isDuplicateEntry(e){return this.index.has(e)}_createIndexRecord(e){this.index.set(e,void 0)}_onlyFileFilter(e){return this._settings.onlyFiles&&!e.dirent.isFile()}_onlyDirectoryFilter(e){return this._settings.onlyDirectories&&!e.dirent.isDirectory()}_isSkippedByAbsoluteNegativePatterns(e,r){if(!this._settings.absolute)return!1;let o=gg.path.makeAbsolute(this._settings.cwd,e);return gg.pattern.matchAny(o,r)}_isMatchToPatterns(e,r,o){let a=gg.pattern.matchAny(e,r);return!a&&o?gg.pattern.matchAny(e+"/",r):a}};vM.default=BM});var Kie=_(PM=>{"use strict";Object.defineProperty(PM,"__esModule",{value:!0});var ltt=Df(),DM=class{constructor(e){this._settings=e}getFilter(){return e=>this._isNonFatalError(e)}_isNonFatalError(e){return ltt.errno.isEnoentCodeError(e)||this._settings.suppressErrors}};PM.default=DM});var zie=_(bM=>{"use strict";Object.defineProperty(bM,"__esModule",{value:!0});var Vie=Df(),SM=class{constructor(e){this._settings=e}getTransformer(){return e=>this._transform(e)}_transform(e){let r=e.path;return this._settings.absolute&&(r=Vie.path.makeAbsolute(this._settings.cwd,r),r=Vie.path.unixify(r)),this._settings.markDirectories&&e.dirent.isDirectory()&&(r+="/"),this._settings.objectMode?Object.assign(Object.assign({},e),{path:r}):r}};bM.default=SM});var yS=_(kM=>{"use strict";Object.defineProperty(kM,"__esModule",{value:!0});var ctt=ve("path"),utt=Yie(),Att=Wie(),ftt=Kie(),ptt=zie(),xM=class{constructor(e){this._settings=e,this.errorFilter=new ftt.default(this._settings),this.entryFilter=new Att.default(this._settings,this._getMicromatchOptions()),this.deepFilter=new utt.default(this._settings,this._getMicromatchOptions()),this.entryTransformer=new ptt.default(this._settings)}_getRootDirectory(e){return ctt.resolve(this._settings.cwd,e.base)}_getReaderOptions(e){let r=e.base==="."?"":e.base;return{basePath:r,pathSegmentSeparator:"/",concurrency:this._settings.concurrency,deepFilter:this.deepFilter.getFilter(r,e.positive,e.negative),entryFilter:this.entryFilter.getFilter(e.positive,e.negative),errorFilter:this.errorFilter.getFilter(),followSymbolicLinks:this._settings.followSymbolicLinks,fs:this._settings.fs,stats:this._settings.stats,throwErrorOnBrokenSymbolicLink:this._settings.throwErrorOnBrokenSymbolicLink,transform:this.entryTransformer.getTransformer()}}_getMicromatchOptions(){return{dot:this._settings.dot,matchBase:this._settings.baseNameMatch,nobrace:!this._settings.braceExpansion,nocase:!this._settings.caseSensitiveMatch,noext:!this._settings.extglob,noglobstar:!this._settings.globstar,posix:!0,strictSlashes:!1}}};kM.default=xM});var Jie=_(FM=>{"use strict";Object.defineProperty(FM,"__esModule",{value:!0});var htt=qie(),gtt=yS(),QM=class extends gtt.default{constructor(){super(...arguments),this._reader=new htt.default(this._settings)}async read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e);return(await this.api(r,e,o)).map(n=>o.transform(n))}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};FM.default=QM});var Xie=_(TM=>{"use strict";Object.defineProperty(TM,"__esModule",{value:!0});var dtt=ve("stream"),mtt=hM(),ytt=yS(),RM=class extends ytt.default{constructor(){super(...arguments),this._reader=new mtt.default(this._settings)}read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e),a=this.api(r,e,o),n=new dtt.Readable({objectMode:!0,read:()=>{}});return a.once("error",u=>n.emit("error",u)).on("data",u=>n.emit("data",o.transform(u))).once("end",()=>n.emit("end")),n.once("close",()=>a.destroy()),n}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};TM.default=RM});var Zie=_(LM=>{"use strict";Object.defineProperty(LM,"__esModule",{value:!0});var Ett=hg(),Ctt=gS(),wtt=dS(),NM=class extends wtt.default{constructor(){super(...arguments),this._walkSync=Ctt.walkSync,this._statSync=Ett.statSync}dynamic(e,r){return this._walkSync(e,r)}static(e,r){let o=[];for(let a of e){let n=this._getFullEntryPath(a),u=this._getEntry(n,a,r);u===null||!r.entryFilter(u)||o.push(u)}return o}_getEntry(e,r,o){try{let a=this._getStat(e);return this._makeEntry(a,r)}catch(a){if(o.errorFilter(a))return null;throw a}}_getStat(e){return this._statSync(e,this._fsStatSettings)}};LM.default=NM});var $ie=_(OM=>{"use strict";Object.defineProperty(OM,"__esModule",{value:!0});var Itt=Zie(),Btt=yS(),MM=class extends Btt.default{constructor(){super(...arguments),this._reader=new Itt.default(this._settings)}read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e);return this.api(r,e,o).map(o.transform)}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};OM.default=MM});var ese=_(Um=>{"use strict";Object.defineProperty(Um,"__esModule",{value:!0});Um.DEFAULT_FILE_SYSTEM_ADAPTER=void 0;var Om=ve("fs"),vtt=ve("os"),Dtt=Math.max(vtt.cpus().length,1);Um.DEFAULT_FILE_SYSTEM_ADAPTER={lstat:Om.lstat,lstatSync:Om.lstatSync,stat:Om.stat,statSync:Om.statSync,readdir:Om.readdir,readdirSync:Om.readdirSync};var UM=class{constructor(e={}){this._options=e,this.absolute=this._getValue(this._options.absolute,!1),this.baseNameMatch=this._getValue(this._options.baseNameMatch,!1),this.braceExpansion=this._getValue(this._options.braceExpansion,!0),this.caseSensitiveMatch=this._getValue(this._options.caseSensitiveMatch,!0),this.concurrency=this._getValue(this._options.concurrency,Dtt),this.cwd=this._getValue(this._options.cwd,process.cwd()),this.deep=this._getValue(this._options.deep,1/0),this.dot=this._getValue(this._options.dot,!1),this.extglob=this._getValue(this._options.extglob,!0),this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!0),this.fs=this._getFileSystemMethods(this._options.fs),this.globstar=this._getValue(this._options.globstar,!0),this.ignore=this._getValue(this._options.ignore,[]),this.markDirectories=this._getValue(this._options.markDirectories,!1),this.objectMode=this._getValue(this._options.objectMode,!1),this.onlyDirectories=this._getValue(this._options.onlyDirectories,!1),this.onlyFiles=this._getValue(this._options.onlyFiles,!0),this.stats=this._getValue(this._options.stats,!1),this.suppressErrors=this._getValue(this._options.suppressErrors,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!1),this.unique=this._getValue(this._options.unique,!0),this.onlyDirectories&&(this.onlyFiles=!1),this.stats&&(this.objectMode=!0),this.ignore=[].concat(this.ignore)}_getValue(e,r){return e===void 0?r:e}_getFileSystemMethods(e={}){return Object.assign(Object.assign({},Um.DEFAULT_FILE_SYSTEM_ADAPTER),e)}};Um.default=UM});var ES=_((kNt,rse)=>{"use strict";var tse=rie(),Ptt=Jie(),Stt=Xie(),btt=$ie(),_M=ese(),Yl=Df();async function HM(t,e){jc(t);let r=qM(t,Ptt.default,e),o=await Promise.all(r);return Yl.array.flatten(o)}(function(t){t.glob=t,t.globSync=e,t.globStream=r,t.async=t;function e(h,E){jc(h);let I=qM(h,btt.default,E);return Yl.array.flatten(I)}t.sync=e;function r(h,E){jc(h);let I=qM(h,Stt.default,E);return Yl.stream.merge(I)}t.stream=r;function o(h,E){jc(h);let I=[].concat(h),v=new _M.default(E);return tse.generate(I,v)}t.generateTasks=o;function a(h,E){jc(h);let I=new _M.default(E);return Yl.pattern.isDynamicPattern(h,I)}t.isDynamicPattern=a;function n(h){return jc(h),Yl.path.escape(h)}t.escapePath=n;function u(h){return jc(h),Yl.path.convertPathToPattern(h)}t.convertPathToPattern=u;let A;(function(h){function E(v){return jc(v),Yl.path.escapePosixPath(v)}h.escapePath=E;function I(v){return jc(v),Yl.path.convertPosixPathToPattern(v)}h.convertPathToPattern=I})(A=t.posix||(t.posix={}));let p;(function(h){function E(v){return jc(v),Yl.path.escapeWindowsPath(v)}h.escapePath=E;function I(v){return jc(v),Yl.path.convertWindowsPathToPattern(v)}h.convertPathToPattern=I})(p=t.win32||(t.win32={}))})(HM||(HM={}));function qM(t,e,r){let o=[].concat(t),a=new _M.default(r),n=tse.generate(o,a),u=new e(a);return n.map(u.read,u)}function jc(t){if(![].concat(t).every(o=>Yl.string.isString(o)&&!Yl.string.isEmpty(o)))throw new TypeError("Patterns must be a string (non empty) or an array of strings")}rse.exports=HM});var wn={};Vt(wn,{checksumFile:()=>wS,checksumPattern:()=>IS,makeHash:()=>zi});function zi(...t){let e=(0,CS.createHash)("sha512"),r="";for(let o of t)typeof o=="string"?r+=o:o&&(r&&(e.update(r),r=""),e.update(o));return r&&e.update(r),e.digest("hex")}async function wS(t,{baseFs:e,algorithm:r}={baseFs:oe,algorithm:"sha512"}){let o=await e.openPromise(t,"r");try{let n=Buffer.allocUnsafeSlow(65536),u=(0,CS.createHash)(r),A=0;for(;(A=await e.readPromise(o,n,0,65536))!==0;)u.update(A===65536?n:n.slice(0,A));return u.digest("hex")}finally{await e.closePromise(o)}}async function IS(t,{cwd:e}){let o=(await(0,jM.default)(t,{cwd:ue.fromPortablePath(e),onlyDirectories:!0})).map(A=>`${A}/**/*`),a=await(0,jM.default)([t,...o],{cwd:ue.fromPortablePath(e),onlyFiles:!1});a.sort();let n=await Promise.all(a.map(async A=>{let p=[Buffer.from(A)],h=K.join(e,ue.toPortablePath(A)),E=await oe.lstatPromise(h);return E.isSymbolicLink()?p.push(Buffer.from(await oe.readlinkPromise(h))):E.isFile()&&p.push(await oe.readFilePromise(h)),p.join("\0")})),u=(0,CS.createHash)("sha512");for(let A of n)u.update(A);return u.digest("hex")}var CS,jM,th=Et(()=>{Pt();CS=ve("crypto"),jM=Ze(ES())});var G={};Vt(G,{allPeerRequests:()=>WI,areDescriptorsEqual:()=>ase,areIdentsEqual:()=>HI,areLocatorsEqual:()=>qI,areVirtualPackagesEquivalent:()=>Mtt,bindDescriptor:()=>Ntt,bindLocator:()=>Ltt,convertDescriptorToLocator:()=>BS,convertLocatorToDescriptor:()=>YM,convertPackageToLocator:()=>Ftt,convertToIdent:()=>Qtt,convertToManifestRange:()=>Ktt,copyPackage:()=>OI,devirtualizeDescriptor:()=>UI,devirtualizeLocator:()=>_I,ensureDevirtualizedDescriptor:()=>Rtt,ensureDevirtualizedLocator:()=>Ttt,getIdentVendorPath:()=>zM,isPackageCompatible:()=>bS,isVirtualDescriptor:()=>Pf,isVirtualLocator:()=>Gc,makeDescriptor:()=>In,makeIdent:()=>eA,makeLocator:()=>Rs,makeRange:()=>PS,parseDescriptor:()=>rh,parseFileStyleRange:()=>Ytt,parseIdent:()=>ea,parseLocator:()=>Sf,parseRange:()=>dg,prettyDependent:()=>CL,prettyDescriptor:()=>jn,prettyIdent:()=>Oi,prettyLocator:()=>qr,prettyLocatorNoColors:()=>EL,prettyRange:()=>qm,prettyReference:()=>GI,prettyResolution:()=>NI,prettyWorkspace:()=>YI,renamePackage:()=>WM,slugifyIdent:()=>GM,slugifyLocator:()=>Hm,sortDescriptors:()=>jm,stringifyDescriptor:()=>xa,stringifyIdent:()=>rn,stringifyLocator:()=>ka,tryParseDescriptor:()=>jI,tryParseIdent:()=>lse,tryParseLocator:()=>DS,tryParseRange:()=>Gtt,virtualizeDescriptor:()=>KM,virtualizePackage:()=>VM});function eA(t,e){if(t?.startsWith("@"))throw new Error("Invalid scope: don't prefix it with '@'");return{identHash:zi(t,e),scope:t,name:e}}function In(t,e){return{identHash:t.identHash,scope:t.scope,name:t.name,descriptorHash:zi(t.identHash,e),range:e}}function Rs(t,e){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:zi(t.identHash,e),reference:e}}function Qtt(t){return{identHash:t.identHash,scope:t.scope,name:t.name}}function BS(t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.descriptorHash,reference:t.range}}function YM(t){return{identHash:t.identHash,scope:t.scope,name:t.name,descriptorHash:t.locatorHash,range:t.reference}}function Ftt(t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.locatorHash,reference:t.reference}}function WM(t,e){return{identHash:e.identHash,scope:e.scope,name:e.name,locatorHash:e.locatorHash,reference:e.reference,version:t.version,languageName:t.languageName,linkType:t.linkType,conditions:t.conditions,dependencies:new Map(t.dependencies),peerDependencies:new Map(t.peerDependencies),dependenciesMeta:new Map(t.dependenciesMeta),peerDependenciesMeta:new Map(t.peerDependenciesMeta),bin:new Map(t.bin)}}function OI(t){return WM(t,t)}function KM(t,e){if(e.includes("#"))throw new Error("Invalid entropy");return In(t,`virtual:${e}#${t.range}`)}function VM(t,e){if(e.includes("#"))throw new Error("Invalid entropy");return WM(t,Rs(t,`virtual:${e}#${t.reference}`))}function Pf(t){return t.range.startsWith(MI)}function Gc(t){return t.reference.startsWith(MI)}function UI(t){if(!Pf(t))throw new Error("Not a virtual descriptor");return In(t,t.range.replace(vS,""))}function _I(t){if(!Gc(t))throw new Error("Not a virtual descriptor");return Rs(t,t.reference.replace(vS,""))}function Rtt(t){return Pf(t)?In(t,t.range.replace(vS,"")):t}function Ttt(t){return Gc(t)?Rs(t,t.reference.replace(vS,"")):t}function Ntt(t,e){return t.range.includes("::")?t:In(t,`${t.range}::${_m.default.stringify(e)}`)}function Ltt(t,e){return t.reference.includes("::")?t:Rs(t,`${t.reference}::${_m.default.stringify(e)}`)}function HI(t,e){return t.identHash===e.identHash}function ase(t,e){return t.descriptorHash===e.descriptorHash}function qI(t,e){return t.locatorHash===e.locatorHash}function Mtt(t,e){if(!Gc(t))throw new Error("Invalid package type");if(!Gc(e))throw new Error("Invalid package type");if(!HI(t,e)||t.dependencies.size!==e.dependencies.size)return!1;for(let r of t.dependencies.values()){let o=e.dependencies.get(r.identHash);if(!o||!ase(r,o))return!1}return!0}function ea(t){let e=lse(t);if(!e)throw new Error(`Invalid ident (${t})`);return e}function lse(t){let e=t.match(Ott);if(!e)return null;let[,r,o]=e;return eA(typeof r<"u"?r:null,o)}function rh(t,e=!1){let r=jI(t,e);if(!r)throw new Error(`Invalid descriptor (${t})`);return r}function jI(t,e=!1){let r=e?t.match(Utt):t.match(_tt);if(!r)return null;let[,o,a,n]=r;if(n==="unknown")throw new Error(`Invalid range (${t})`);let u=typeof o<"u"?o:null,A=typeof n<"u"?n:"unknown";return In(eA(u,a),A)}function Sf(t,e=!1){let r=DS(t,e);if(!r)throw new Error(`Invalid locator (${t})`);return r}function DS(t,e=!1){let r=e?t.match(Htt):t.match(qtt);if(!r)return null;let[,o,a,n]=r;if(n==="unknown")throw new Error(`Invalid reference (${t})`);let u=typeof o<"u"?o:null,A=typeof n<"u"?n:"unknown";return Rs(eA(u,a),A)}function dg(t,e){let r=t.match(jtt);if(r===null)throw new Error(`Invalid range (${t})`);let o=typeof r[1]<"u"?r[1]:null;if(typeof e?.requireProtocol=="string"&&o!==e.requireProtocol)throw new Error(`Invalid protocol (${o})`);if(e?.requireProtocol&&o===null)throw new Error(`Missing protocol (${o})`);let a=typeof r[3]<"u"?decodeURIComponent(r[2]):null;if(e?.requireSource&&a===null)throw new Error(`Missing source (${t})`);let n=typeof r[3]<"u"?decodeURIComponent(r[3]):decodeURIComponent(r[2]),u=e?.parseSelector?_m.default.parse(n):n,A=typeof r[4]<"u"?_m.default.parse(r[4]):null;return{protocol:o,source:a,selector:u,params:A}}function Gtt(t,e){try{return dg(t,e)}catch{return null}}function Ytt(t,{protocol:e}){let{selector:r,params:o}=dg(t,{requireProtocol:e,requireBindings:!0});if(typeof o.locator!="string")throw new Error(`Assertion failed: Invalid bindings for ${t}`);return{parentLocator:Sf(o.locator,!0),path:r}}function nse(t){return t=t.replaceAll("%","%25"),t=t.replaceAll(":","%3A"),t=t.replaceAll("#","%23"),t}function Wtt(t){return t===null?!1:Object.entries(t).length>0}function PS({protocol:t,source:e,selector:r,params:o}){let a="";return t!==null&&(a+=`${t}`),e!==null&&(a+=`${nse(e)}#`),a+=nse(r),Wtt(o)&&(a+=`::${_m.default.stringify(o)}`),a}function Ktt(t){let{params:e,protocol:r,source:o,selector:a}=dg(t);for(let n in e)n.startsWith("__")&&delete e[n];return PS({protocol:r,source:o,params:e,selector:a})}function rn(t){return t.scope?`@${t.scope}/${t.name}`:`${t.name}`}function xa(t){return t.scope?`@${t.scope}/${t.name}@${t.range}`:`${t.name}@${t.range}`}function ka(t){return t.scope?`@${t.scope}/${t.name}@${t.reference}`:`${t.name}@${t.reference}`}function GM(t){return t.scope!==null?`@${t.scope}-${t.name}`:t.name}function Hm(t){let{protocol:e,selector:r}=dg(t.reference),o=e!==null?e.replace(Vtt,""):"exotic",a=ise.default.valid(r),n=a!==null?`${o}-${a}`:`${o}`,u=10;return t.scope?`${GM(t)}-${n}-${t.locatorHash.slice(0,u)}`:`${GM(t)}-${n}-${t.locatorHash.slice(0,u)}`}function Oi(t,e){return e.scope?`${Ot(t,`@${e.scope}/`,yt.SCOPE)}${Ot(t,e.name,yt.NAME)}`:`${Ot(t,e.name,yt.NAME)}`}function SS(t){if(t.startsWith(MI)){let e=SS(t.substring(t.indexOf("#")+1)),r=t.substring(MI.length,MI.length+xtt);return`${e} [${r}]`}else return t.replace(ztt,"?[...]")}function qm(t,e){return`${Ot(t,SS(e),yt.RANGE)}`}function jn(t,e){return`${Oi(t,e)}${Ot(t,"@",yt.RANGE)}${qm(t,e.range)}`}function GI(t,e){return`${Ot(t,SS(e),yt.REFERENCE)}`}function qr(t,e){return`${Oi(t,e)}${Ot(t,"@",yt.REFERENCE)}${GI(t,e.reference)}`}function EL(t){return`${rn(t)}@${SS(t.reference)}`}function jm(t){return Fs(t,[e=>rn(e),e=>e.range])}function YI(t,e){return Oi(t,e.anchoredLocator)}function NI(t,e,r){let o=Pf(e)?UI(e):e;return r===null?`${jn(t,o)} \u2192 ${yL(t).Cross}`:o.identHash===r.identHash?`${jn(t,o)} \u2192 ${GI(t,r.reference)}`:`${jn(t,o)} \u2192 ${qr(t,r)}`}function CL(t,e,r){return r===null?`${qr(t,e)}`:`${qr(t,e)} (via ${qm(t,r.range)})`}function zM(t){return`node_modules/${rn(t)}`}function bS(t,e){return t.conditions?ktt(t.conditions,r=>{let[,o,a]=r.match(ose),n=e[o];return n?n.includes(a):!0}):!0}function WI(t){let e=new Set;if("children"in t)e.add(t);else for(let r of t.requests.values())e.add(r);for(let r of e)for(let o of r.children.values())e.add(o);return e}var _m,ise,sse,MI,xtt,ose,ktt,vS,Ott,Utt,_tt,Htt,qtt,jtt,Vtt,ztt,bo=Et(()=>{_m=Ze(ve("querystring")),ise=Ze(Jn()),sse=Ze(eX());jl();th();ql();bo();MI="virtual:",xtt=5,ose=/(os|cpu|libc)=([a-z0-9_-]+)/,ktt=(0,sse.makeParser)(ose);vS=/^[^#]*#/;Ott=/^(?:@([^/]+?)\/)?([^@/]+)$/;Utt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))$/,_tt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))?$/;Htt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))$/,qtt=/^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))?$/;jtt=/^([^#:]*:)?((?:(?!::)[^#])*)(?:#((?:(?!::).)*))?(?:::(.*))?$/;Vtt=/:$/;ztt=/\?.*/});var cse,use=Et(()=>{bo();cse={hooks:{reduceDependency:(t,e,r,o,{resolver:a,resolveOptions:n})=>{for(let{pattern:u,reference:A}of e.topLevelWorkspace.manifest.resolutions){if(u.from&&(u.from.fullName!==rn(r)||e.configuration.normalizeLocator(Rs(ea(u.from.fullName),u.from.description??r.reference)).locatorHash!==r.locatorHash)||u.descriptor.fullName!==rn(t)||e.configuration.normalizeDependency(In(Sf(u.descriptor.fullName),u.descriptor.description??t.range)).descriptorHash!==t.descriptorHash)continue;return a.bindDescriptor(e.configuration.normalizeDependency(In(t,A)),e.topLevelWorkspace.anchoredLocator,n)}return t},validateProject:async(t,e)=>{for(let r of t.workspaces){let o=YI(t.configuration,r);await t.configuration.triggerHook(a=>a.validateWorkspace,r,{reportWarning:(a,n)=>e.reportWarning(a,`${o}: ${n}`),reportError:(a,n)=>e.reportError(a,`${o}: ${n}`)})}},validateWorkspace:async(t,e)=>{let{manifest:r}=t;r.resolutions.length&&t.cwd!==t.project.cwd&&r.errors.push(new Error("Resolutions field will be ignored"));for(let o of r.errors)e.reportWarning(57,o.message)}}}});var ei,mg=Et(()=>{ei=class t{static{this.protocol="workspace:"}supportsDescriptor(e,r){return!!(e.range.startsWith(t.protocol)||r.project.tryWorkspaceByDescriptor(e)!==null)}supportsLocator(e,r){return!!e.reference.startsWith(t.protocol)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){return[o.project.getWorkspaceByDescriptor(e).anchoredLocator]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let o=r.project.getWorkspaceByCwd(e.reference.slice(t.protocol.length));return{...e,version:o.manifest.version||"0.0.0",languageName:"unknown",linkType:"SOFT",conditions:null,dependencies:r.project.configuration.normalizeDependencyMap(new Map([...o.manifest.dependencies,...o.manifest.devDependencies])),peerDependencies:new Map([...o.manifest.peerDependencies]),dependenciesMeta:o.manifest.dependenciesMeta,peerDependenciesMeta:o.manifest.peerDependenciesMeta,bin:o.manifest.bin}}}});var Lr={};Vt(Lr,{SemVer:()=>gse.SemVer,clean:()=>Xtt,getComparator:()=>pse,mergeComparators:()=>JM,satisfiesWithPrereleases:()=>tA,simplifyRanges:()=>XM,stringifyComparator:()=>hse,validRange:()=>Qa});function tA(t,e,r=!1){if(!t)return!1;let o=`${e}${r}`,a=Ase.get(o);if(typeof a>"u")try{a=new nh.default.Range(e,{includePrerelease:!0,loose:r})}catch{return!1}finally{Ase.set(o,a||null)}else if(a===null)return!1;let n;try{n=new nh.default.SemVer(t,a)}catch{return!1}return a.test(n)?!0:(n.prerelease&&(n.prerelease=[]),a.set.some(u=>{for(let A of u)A.semver.prerelease&&(A.semver.prerelease=[]);return u.every(A=>A.test(n))}))}function Qa(t){if(t.indexOf(":")!==-1)return null;let e=fse.get(t);if(typeof e<"u")return e;try{e=new nh.default.Range(t)}catch{e=null}return fse.set(t,e),e}function Xtt(t){let e=Jtt.exec(t);return e?e[1]:null}function pse(t){if(t.semver===nh.default.Comparator.ANY)return{gt:null,lt:null};switch(t.operator){case"":return{gt:[">=",t.semver],lt:["<=",t.semver]};case">":case">=":return{gt:[t.operator,t.semver],lt:null};case"<":case"<=":return{gt:null,lt:[t.operator,t.semver]};default:throw new Error(`Assertion failed: Unexpected comparator operator (${t.operator})`)}}function JM(t){if(t.length===0)return null;let e=null,r=null;for(let o of t){if(o.gt){let a=e!==null?nh.default.compare(o.gt[1],e[1]):null;(a===null||a>0||a===0&&o.gt[0]===">")&&(e=o.gt)}if(o.lt){let a=r!==null?nh.default.compare(o.lt[1],r[1]):null;(a===null||a<0||a===0&&o.lt[0]==="<")&&(r=o.lt)}}if(e&&r){let o=nh.default.compare(e[1],r[1]);if(o===0&&(e[0]===">"||r[0]==="<")||o>0)return null}return{gt:e,lt:r}}function hse(t){if(t.gt&&t.lt){if(t.gt[0]===">="&&t.lt[0]==="<="&&t.gt[1].version===t.lt[1].version)return t.gt[1].version;if(t.gt[0]===">="&&t.lt[0]==="<"){if(t.lt[1].version===`${t.gt[1].major+1}.0.0-0`)return`^${t.gt[1].version}`;if(t.lt[1].version===`${t.gt[1].major}.${t.gt[1].minor+1}.0-0`)return`~${t.gt[1].version}`}}let e=[];return t.gt&&e.push(t.gt[0]+t.gt[1].version),t.lt&&e.push(t.lt[0]+t.lt[1].version),e.length?e.join(" "):"*"}function XM(t){let e=t.map(o=>Qa(o).set.map(a=>a.map(n=>pse(n)))),r=e.shift().map(o=>JM(o)).filter(o=>o!==null);for(let o of e){let a=[];for(let n of r)for(let u of o){let A=JM([n,...u]);A!==null&&a.push(A)}r=a}return r.length===0?null:r.map(o=>hse(o)).join(" || ")}var nh,gse,Ase,fse,Jtt,bf=Et(()=>{nh=Ze(Jn()),gse=Ze(Jn()),Ase=new Map;fse=new Map;Jtt=/^(?:[\sv=]*?)((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\s*)$/});function dse(t){let e=t.match(/^[ \t]+/m);return e?e[0]:" "}function mse(t){return t.charCodeAt(0)===65279?t.slice(1):t}function ta(t){return t.replace(/\\/g,"/")}function xS(t,{yamlCompatibilityMode:e}){return e?AL(t):typeof t>"u"||typeof t=="boolean"?t:null}function yse(t,e){let r=e.search(/[^!]/);if(r===-1)return"invalid";let o=r%2===0?"":"!",a=e.slice(r);return`${o}${t}=${a}`}function ZM(t,e){return e.length===1?yse(t,e[0]):`(${e.map(r=>yse(t,r)).join(" | ")})`}var Ese,Ut,Gm=Et(()=>{Pt();Nl();Ese=Ze(Jn());mg();ql();bf();bo();Ut=class t{constructor(){this.indent=" ";this.name=null;this.version=null;this.os=null;this.cpu=null;this.libc=null;this.type=null;this.packageManager=null;this.private=!1;this.license=null;this.main=null;this.module=null;this.browser=null;this.languageName=null;this.bin=new Map;this.scripts=new Map;this.dependencies=new Map;this.devDependencies=new Map;this.peerDependencies=new Map;this.workspaceDefinitions=[];this.dependenciesMeta=new Map;this.peerDependenciesMeta=new Map;this.resolutions=[];this.files=null;this.publishConfig=null;this.installConfig=null;this.preferUnplugged=null;this.raw={};this.errors=[]}static{this.fileName="package.json"}static{this.allDependencies=["dependencies","devDependencies","peerDependencies"]}static{this.hardDependencies=["dependencies","devDependencies"]}static async tryFind(e,{baseFs:r=new Tn}={}){let o=K.join(e,"package.json");try{return await t.fromFile(o,{baseFs:r})}catch(a){if(a.code==="ENOENT")return null;throw a}}static async find(e,{baseFs:r}={}){let o=await t.tryFind(e,{baseFs:r});if(o===null)throw new Error("Manifest not found");return o}static async fromFile(e,{baseFs:r=new Tn}={}){let o=new t;return await o.loadFile(e,{baseFs:r}),o}static fromText(e){let r=new t;return r.loadFromText(e),r}loadFromText(e){let r;try{r=JSON.parse(mse(e)||"{}")}catch(o){throw o.message+=` (when parsing ${e})`,o}this.load(r),this.indent=dse(e)}async loadFile(e,{baseFs:r=new Tn}){let o=await r.readFilePromise(e,"utf8"),a;try{a=JSON.parse(mse(o)||"{}")}catch(n){throw n.message+=` (when parsing ${e})`,n}this.load(a),this.indent=dse(o)}load(e,{yamlCompatibilityMode:r=!1}={}){if(typeof e!="object"||e===null)throw new Error(`Utterly invalid manifest data (${e})`);this.raw=e;let o=[];if(this.name=null,typeof e.name=="string")try{this.name=ea(e.name)}catch{o.push(new Error("Parsing failed for the 'name' field"))}if(typeof e.version=="string"?this.version=e.version:this.version=null,Array.isArray(e.os)){let n=[];this.os=n;for(let u of e.os)typeof u!="string"?o.push(new Error("Parsing failed for the 'os' field")):n.push(u)}else this.os=null;if(Array.isArray(e.cpu)){let n=[];this.cpu=n;for(let u of e.cpu)typeof u!="string"?o.push(new Error("Parsing failed for the 'cpu' field")):n.push(u)}else this.cpu=null;if(Array.isArray(e.libc)){let n=[];this.libc=n;for(let u of e.libc)typeof u!="string"?o.push(new Error("Parsing failed for the 'libc' field")):n.push(u)}else this.libc=null;if(typeof e.type=="string"?this.type=e.type:this.type=null,typeof e.packageManager=="string"?this.packageManager=e.packageManager:this.packageManager=null,typeof e.private=="boolean"?this.private=e.private:this.private=!1,typeof e.license=="string"?this.license=e.license:this.license=null,typeof e.languageName=="string"?this.languageName=e.languageName:this.languageName=null,typeof e.main=="string"?this.main=ta(e.main):this.main=null,typeof e.module=="string"?this.module=ta(e.module):this.module=null,e.browser!=null)if(typeof e.browser=="string")this.browser=ta(e.browser);else{this.browser=new Map;for(let[n,u]of Object.entries(e.browser))this.browser.set(ta(n),typeof u=="string"?ta(u):u)}else this.browser=null;if(this.bin=new Map,typeof e.bin=="string")e.bin.trim()===""?o.push(new Error("Invalid bin field")):this.name!==null?this.bin.set(this.name.name,ta(e.bin)):o.push(new Error("String bin field, but no attached package name"));else if(typeof e.bin=="object"&&e.bin!==null)for(let[n,u]of Object.entries(e.bin)){if(typeof u!="string"||u.trim()===""){o.push(new Error(`Invalid bin definition for '${n}'`));continue}let A=ea(n);this.bin.set(A.name,ta(u))}if(this.scripts=new Map,typeof e.scripts=="object"&&e.scripts!==null)for(let[n,u]of Object.entries(e.scripts)){if(typeof u!="string"){o.push(new Error(`Invalid script definition for '${n}'`));continue}this.scripts.set(n,u)}if(this.dependencies=new Map,typeof e.dependencies=="object"&&e.dependencies!==null)for(let[n,u]of Object.entries(e.dependencies)){if(typeof u!="string"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=ea(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=In(A,u);this.dependencies.set(p.identHash,p)}if(this.devDependencies=new Map,typeof e.devDependencies=="object"&&e.devDependencies!==null)for(let[n,u]of Object.entries(e.devDependencies)){if(typeof u!="string"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=ea(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=In(A,u);this.devDependencies.set(p.identHash,p)}if(this.peerDependencies=new Map,typeof e.peerDependencies=="object"&&e.peerDependencies!==null)for(let[n,u]of Object.entries(e.peerDependencies)){let A;try{A=ea(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}(typeof u!="string"||!u.startsWith(ei.protocol)&&!Qa(u))&&(o.push(new Error(`Invalid dependency range for '${n}'`)),u="*");let p=In(A,u);this.peerDependencies.set(p.identHash,p)}typeof e.workspaces=="object"&&e.workspaces!==null&&e.workspaces.nohoist&&o.push(new Error("'nohoist' is deprecated, please use 'installConfig.hoistingLimits' instead"));let a=Array.isArray(e.workspaces)?e.workspaces:typeof e.workspaces=="object"&&e.workspaces!==null&&Array.isArray(e.workspaces.packages)?e.workspaces.packages:[];this.workspaceDefinitions=[];for(let n of a){if(typeof n!="string"){o.push(new Error(`Invalid workspace definition for '${n}'`));continue}this.workspaceDefinitions.push({pattern:n})}if(this.dependenciesMeta=new Map,typeof e.dependenciesMeta=="object"&&e.dependenciesMeta!==null)for(let[n,u]of Object.entries(e.dependenciesMeta)){if(typeof u!="object"||u===null){o.push(new Error(`Invalid meta field for '${n}`));continue}let A=rh(n),p=this.ensureDependencyMeta(A),h=xS(u.built,{yamlCompatibilityMode:r});if(h===null){o.push(new Error(`Invalid built meta field for '${n}'`));continue}let E=xS(u.optional,{yamlCompatibilityMode:r});if(E===null){o.push(new Error(`Invalid optional meta field for '${n}'`));continue}let I=xS(u.unplugged,{yamlCompatibilityMode:r});if(I===null){o.push(new Error(`Invalid unplugged meta field for '${n}'`));continue}Object.assign(p,{built:h,optional:E,unplugged:I})}if(this.peerDependenciesMeta=new Map,typeof e.peerDependenciesMeta=="object"&&e.peerDependenciesMeta!==null)for(let[n,u]of Object.entries(e.peerDependenciesMeta)){if(typeof u!="object"||u===null){o.push(new Error(`Invalid meta field for '${n}'`));continue}let A=rh(n),p=this.ensurePeerDependencyMeta(A),h=xS(u.optional,{yamlCompatibilityMode:r});if(h===null){o.push(new Error(`Invalid optional meta field for '${n}'`));continue}Object.assign(p,{optional:h})}if(this.resolutions=[],typeof e.resolutions=="object"&&e.resolutions!==null)for(let[n,u]of Object.entries(e.resolutions)){if(typeof u!="string"){o.push(new Error(`Invalid resolution entry for '${n}'`));continue}try{this.resolutions.push({pattern:BD(n),reference:u})}catch(A){o.push(A);continue}}if(Array.isArray(e.files)){this.files=new Set;for(let n of e.files){if(typeof n!="string"){o.push(new Error(`Invalid files entry for '${n}'`));continue}this.files.add(n)}}else this.files=null;if(typeof e.publishConfig=="object"&&e.publishConfig!==null){if(this.publishConfig={},typeof e.publishConfig.access=="string"&&(this.publishConfig.access=e.publishConfig.access),typeof e.publishConfig.main=="string"&&(this.publishConfig.main=ta(e.publishConfig.main)),typeof e.publishConfig.module=="string"&&(this.publishConfig.module=ta(e.publishConfig.module)),e.publishConfig.browser!=null)if(typeof e.publishConfig.browser=="string")this.publishConfig.browser=ta(e.publishConfig.browser);else{this.publishConfig.browser=new Map;for(let[n,u]of Object.entries(e.publishConfig.browser))this.publishConfig.browser.set(ta(n),typeof u=="string"?ta(u):u)}if(typeof e.publishConfig.registry=="string"&&(this.publishConfig.registry=e.publishConfig.registry),typeof e.publishConfig.bin=="string")this.name!==null?this.publishConfig.bin=new Map([[this.name.name,ta(e.publishConfig.bin)]]):o.push(new Error("String bin field, but no attached package name"));else if(typeof e.publishConfig.bin=="object"&&e.publishConfig.bin!==null){this.publishConfig.bin=new Map;for(let[n,u]of Object.entries(e.publishConfig.bin)){if(typeof u!="string"){o.push(new Error(`Invalid bin definition for '${n}'`));continue}this.publishConfig.bin.set(n,ta(u))}}if(Array.isArray(e.publishConfig.executableFiles)){this.publishConfig.executableFiles=new Set;for(let n of e.publishConfig.executableFiles){if(typeof n!="string"){o.push(new Error("Invalid executable file definition"));continue}this.publishConfig.executableFiles.add(ta(n))}}}else this.publishConfig=null;if(typeof e.installConfig=="object"&&e.installConfig!==null){this.installConfig={};for(let n of Object.keys(e.installConfig))n==="hoistingLimits"?typeof e.installConfig.hoistingLimits=="string"?this.installConfig.hoistingLimits=e.installConfig.hoistingLimits:o.push(new Error("Invalid hoisting limits definition")):n=="selfReferences"?typeof e.installConfig.selfReferences=="boolean"?this.installConfig.selfReferences=e.installConfig.selfReferences:o.push(new Error("Invalid selfReferences definition, must be a boolean value")):o.push(new Error(`Unrecognized installConfig key: ${n}`))}else this.installConfig=null;if(typeof e.optionalDependencies=="object"&&e.optionalDependencies!==null)for(let[n,u]of Object.entries(e.optionalDependencies)){if(typeof u!="string"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=ea(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=In(A,u);this.dependencies.set(p.identHash,p);let h=In(A,"unknown"),E=this.ensureDependencyMeta(h);Object.assign(E,{optional:!0})}typeof e.preferUnplugged=="boolean"?this.preferUnplugged=e.preferUnplugged:this.preferUnplugged=null,this.errors=o}getForScope(e){switch(e){case"dependencies":return this.dependencies;case"devDependencies":return this.devDependencies;case"peerDependencies":return this.peerDependencies;default:throw new Error(`Unsupported value ("${e}")`)}}hasConsumerDependency(e){return!!(this.dependencies.has(e.identHash)||this.peerDependencies.has(e.identHash))}hasHardDependency(e){return!!(this.dependencies.has(e.identHash)||this.devDependencies.has(e.identHash))}hasSoftDependency(e){return!!this.peerDependencies.has(e.identHash)}hasDependency(e){return!!(this.hasHardDependency(e)||this.hasSoftDependency(e))}getConditions(){let e=[];return this.os&&this.os.length>0&&e.push(ZM("os",this.os)),this.cpu&&this.cpu.length>0&&e.push(ZM("cpu",this.cpu)),this.libc&&this.libc.length>0&&e.push(ZM("libc",this.libc)),e.length>0?e.join(" & "):null}ensureDependencyMeta(e){if(e.range!=="unknown"&&!Ese.default.valid(e.range))throw new Error(`Invalid meta field range for '${xa(e)}'`);let r=rn(e),o=e.range!=="unknown"?e.range:null,a=this.dependenciesMeta.get(r);a||this.dependenciesMeta.set(r,a=new Map);let n=a.get(o);return n||a.set(o,n={}),n}ensurePeerDependencyMeta(e){if(e.range!=="unknown")throw new Error(`Invalid meta field range for '${xa(e)}'`);let r=rn(e),o=this.peerDependenciesMeta.get(r);return o||this.peerDependenciesMeta.set(r,o={}),o}setRawField(e,r,{after:o=[]}={}){let a=new Set(o.filter(n=>Object.hasOwn(this.raw,n)));if(a.size===0||Object.hasOwn(this.raw,e))this.raw[e]=r;else{let n=this.raw,u=this.raw={},A=!1;for(let p of Object.keys(n))u[p]=n[p],A||(a.delete(p),a.size===0&&(u[e]=r,A=!0))}}exportTo(e,{compatibilityMode:r=!0}={}){if(Object.assign(e,this.raw),this.name!==null?e.name=rn(this.name):delete e.name,this.version!==null?e.version=this.version:delete e.version,this.os!==null?e.os=this.os:delete e.os,this.cpu!==null?e.cpu=this.cpu:delete e.cpu,this.type!==null?e.type=this.type:delete e.type,this.packageManager!==null?e.packageManager=this.packageManager:delete e.packageManager,this.private?e.private=!0:delete e.private,this.license!==null?e.license=this.license:delete e.license,this.languageName!==null?e.languageName=this.languageName:delete e.languageName,this.main!==null?e.main=this.main:delete e.main,this.module!==null?e.module=this.module:delete e.module,this.browser!==null){let n=this.browser;typeof n=="string"?e.browser=n:n instanceof Map&&(e.browser=Object.assign({},...Array.from(n.keys()).sort().map(u=>({[u]:n.get(u)}))))}else delete e.browser;this.bin.size===1&&this.name!==null&&this.bin.has(this.name.name)?e.bin=this.bin.get(this.name.name):this.bin.size>0?e.bin=Object.assign({},...Array.from(this.bin.keys()).sort().map(n=>({[n]:this.bin.get(n)}))):delete e.bin,this.workspaceDefinitions.length>0?this.raw.workspaces&&!Array.isArray(this.raw.workspaces)?e.workspaces={...this.raw.workspaces,packages:this.workspaceDefinitions.map(({pattern:n})=>n)}:e.workspaces=this.workspaceDefinitions.map(({pattern:n})=>n):this.raw.workspaces&&!Array.isArray(this.raw.workspaces)&&Object.keys(this.raw.workspaces).length>0?e.workspaces=this.raw.workspaces:delete e.workspaces;let o=[],a=[];for(let n of this.dependencies.values()){let u=this.dependenciesMeta.get(rn(n)),A=!1;if(r&&u){let p=u.get(null);p&&p.optional&&(A=!0)}A?a.push(n):o.push(n)}o.length>0?e.dependencies=Object.assign({},...jm(o).map(n=>({[rn(n)]:n.range}))):delete e.dependencies,a.length>0?e.optionalDependencies=Object.assign({},...jm(a).map(n=>({[rn(n)]:n.range}))):delete e.optionalDependencies,this.devDependencies.size>0?e.devDependencies=Object.assign({},...jm(this.devDependencies.values()).map(n=>({[rn(n)]:n.range}))):delete e.devDependencies,this.peerDependencies.size>0?e.peerDependencies=Object.assign({},...jm(this.peerDependencies.values()).map(n=>({[rn(n)]:n.range}))):delete e.peerDependencies,e.dependenciesMeta={};for(let[n,u]of Fs(this.dependenciesMeta.entries(),([A,p])=>A))for(let[A,p]of Fs(u.entries(),([h,E])=>h!==null?`0${h}`:"1")){let h=A!==null?xa(In(ea(n),A)):n,E={...p};r&&A===null&&delete E.optional,Object.keys(E).length!==0&&(e.dependenciesMeta[h]=E)}if(Object.keys(e.dependenciesMeta).length===0&&delete e.dependenciesMeta,this.peerDependenciesMeta.size>0?e.peerDependenciesMeta=Object.assign({},...Fs(this.peerDependenciesMeta.entries(),([n,u])=>n).map(([n,u])=>({[n]:u}))):delete e.peerDependenciesMeta,this.resolutions.length>0?e.resolutions=Object.assign({},...this.resolutions.map(({pattern:n,reference:u})=>({[vD(n)]:u}))):delete e.resolutions,this.files!==null?e.files=Array.from(this.files):delete e.files,this.preferUnplugged!==null?e.preferUnplugged=this.preferUnplugged:delete e.preferUnplugged,this.scripts!==null&&this.scripts.size>0){e.scripts??={};for(let n of Object.keys(e.scripts))this.scripts.has(n)||delete e.scripts[n];for(let[n,u]of this.scripts.entries())e.scripts[n]=u}else delete e.scripts;return e}}});var wse=_((YNt,Cse)=>{var Ztt=_l(),$tt=function(){return Ztt.Date.now()};Cse.exports=$tt});var Bse=_((WNt,Ise)=>{var ert=/\s/;function trt(t){for(var e=t.length;e--&&ert.test(t.charAt(e)););return e}Ise.exports=trt});var Dse=_((KNt,vse)=>{var rrt=Bse(),nrt=/^\s+/;function irt(t){return t&&t.slice(0,rrt(t)+1).replace(nrt,"")}vse.exports=irt});var Ym=_((VNt,Pse)=>{var srt=cg(),ort=Ju(),art="[object Symbol]";function lrt(t){return typeof t=="symbol"||ort(t)&&srt(t)==art}Pse.exports=lrt});var kse=_((zNt,xse)=>{var crt=Dse(),Sse=sl(),urt=Ym(),bse=NaN,Art=/^[-+]0x[0-9a-f]+$/i,frt=/^0b[01]+$/i,prt=/^0o[0-7]+$/i,hrt=parseInt;function grt(t){if(typeof t=="number")return t;if(urt(t))return bse;if(Sse(t)){var e=typeof t.valueOf=="function"?t.valueOf():t;t=Sse(e)?e+"":e}if(typeof t!="string")return t===0?t:+t;t=crt(t);var r=frt.test(t);return r||prt.test(t)?hrt(t.slice(2),r?2:8):Art.test(t)?bse:+t}xse.exports=grt});var Rse=_((JNt,Fse)=>{var drt=sl(),$M=wse(),Qse=kse(),mrt="Expected a function",yrt=Math.max,Ert=Math.min;function Crt(t,e,r){var o,a,n,u,A,p,h=0,E=!1,I=!1,v=!0;if(typeof t!="function")throw new TypeError(mrt);e=Qse(e)||0,drt(r)&&(E=!!r.leading,I="maxWait"in r,n=I?yrt(Qse(r.maxWait)||0,e):n,v="trailing"in r?!!r.trailing:v);function x(ce){var Ce=o,de=a;return o=a=void 0,h=ce,u=t.apply(de,Ce),u}function C(ce){return h=ce,A=setTimeout(U,e),E?x(ce):u}function R(ce){var Ce=ce-p,de=ce-h,Be=e-Ce;return I?Ert(Be,n-de):Be}function L(ce){var Ce=ce-p,de=ce-h;return p===void 0||Ce>=e||Ce<0||I&&de>=n}function U(){var ce=$M();if(L(ce))return z(ce);A=setTimeout(U,R(ce))}function z(ce){return A=void 0,v&&o?x(ce):(o=a=void 0,u)}function te(){A!==void 0&&clearTimeout(A),h=0,o=p=a=A=void 0}function ae(){return A===void 0?u:z($M())}function le(){var ce=$M(),Ce=L(ce);if(o=arguments,a=this,p=ce,Ce){if(A===void 0)return C(p);if(I)return clearTimeout(A),A=setTimeout(U,e),x(p)}return A===void 0&&(A=setTimeout(U,e)),u}return le.cancel=te,le.flush=ae,le}Fse.exports=Crt});var eO=_((XNt,Tse)=>{var wrt=Rse(),Irt=sl(),Brt="Expected a function";function vrt(t,e,r){var o=!0,a=!0;if(typeof t!="function")throw new TypeError(Brt);return Irt(r)&&(o="leading"in r?!!r.leading:o,a="trailing"in r?!!r.trailing:a),wrt(t,e,{leading:o,maxWait:e,trailing:a})}Tse.exports=vrt});function Prt(t){return typeof t.reportCode<"u"}var Nse,Lse,Mse,Drt,Jt,Zs,Wl=Et(()=>{Nse=Ze(eO()),Lse=ve("stream"),Mse=ve("string_decoder"),Drt=15,Jt=class extends Error{constructor(r,o,a){super(o);this.reportExtra=a;this.reportCode=r}};Zs=class{constructor(){this.cacheHits=new Set;this.cacheMisses=new Set;this.reportedInfos=new Set;this.reportedWarnings=new Set;this.reportedErrors=new Set}getRecommendedLength(){return 180}reportCacheHit(e){this.cacheHits.add(e.locatorHash)}reportCacheMiss(e,r){this.cacheMisses.add(e.locatorHash)}static progressViaCounter(e){let r=0,o,a=new Promise(p=>{o=p}),n=p=>{let h=o;a=new Promise(E=>{o=E}),r=p,h()},u=(p=0)=>{n(r+1)},A=async function*(){for(;r<e;)await a,yield{progress:r/e}}();return{[Symbol.asyncIterator](){return A},hasProgress:!0,hasTitle:!1,set:n,tick:u}}static progressViaTitle(){let e,r,o=new Promise(u=>{r=u}),a=(0,Nse.default)(u=>{let A=r;o=new Promise(p=>{r=p}),e=u,A()},1e3/Drt),n=async function*(){for(;;)await o,yield{title:e}}();return{[Symbol.asyncIterator](){return n},hasProgress:!1,hasTitle:!0,setTitle:a}}async startProgressPromise(e,r){let o=this.reportProgress(e);try{return await r(e)}finally{o.stop()}}startProgressSync(e,r){let o=this.reportProgress(e);try{return r(e)}finally{o.stop()}}reportInfoOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedInfos.has(a)||(this.reportedInfos.add(a),this.reportInfo(e,r),o?.reportExtra?.(this))}reportWarningOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedWarnings.has(a)||(this.reportedWarnings.add(a),this.reportWarning(e,r),o?.reportExtra?.(this))}reportErrorOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedErrors.has(a)||(this.reportedErrors.add(a),this.reportError(e,r),o?.reportExtra?.(this))}reportExceptionOnce(e){Prt(e)?this.reportErrorOnce(e.reportCode,e.message,{key:e,reportExtra:e.reportExtra}):this.reportErrorOnce(1,e.stack||e.message,{key:e})}createStreamReporter(e=null){let r=new Lse.PassThrough,o=new Mse.StringDecoder,a="";return r.on("data",n=>{let u=o.write(n),A;do if(A=u.indexOf(` +`),A!==-1){let p=a+u.substring(0,A);u=u.substring(A+1),a="",e!==null?this.reportInfo(null,`${e} ${p}`):this.reportInfo(null,p)}while(A!==-1);a+=u}),r.on("end",()=>{let n=o.end();n!==""&&(e!==null?this.reportInfo(null,`${e} ${n}`):this.reportInfo(null,n))}),r}}});var Wm,tO=Et(()=>{Wl();bo();Wm=class{constructor(e){this.fetchers=e}supports(e,r){return!!this.tryFetcher(e,r)}getLocalPath(e,r){return this.getFetcher(e,r).getLocalPath(e,r)}async fetch(e,r){return await this.getFetcher(e,r).fetch(e,r)}tryFetcher(e,r){let o=this.fetchers.find(a=>a.supports(e,r));return o||null}getFetcher(e,r){let o=this.fetchers.find(a=>a.supports(e,r));if(!o)throw new Jt(11,`${qr(r.project.configuration,e)} isn't supported by any available fetcher`);return o}}});var yg,rO=Et(()=>{bo();yg=class{constructor(e){this.resolvers=e.filter(r=>r)}supportsDescriptor(e,r){return!!this.tryResolverByDescriptor(e,r)}supportsLocator(e,r){return!!this.tryResolverByLocator(e,r)}shouldPersistResolution(e,r){return this.getResolverByLocator(e,r).shouldPersistResolution(e,r)}bindDescriptor(e,r,o){return this.getResolverByDescriptor(e,o).bindDescriptor(e,r,o)}getResolutionDependencies(e,r){return this.getResolverByDescriptor(e,r).getResolutionDependencies(e,r)}async getCandidates(e,r,o){return await this.getResolverByDescriptor(e,o).getCandidates(e,r,o)}async getSatisfying(e,r,o,a){return this.getResolverByDescriptor(e,a).getSatisfying(e,r,o,a)}async resolve(e,r){return await this.getResolverByLocator(e,r).resolve(e,r)}tryResolverByDescriptor(e,r){let o=this.resolvers.find(a=>a.supportsDescriptor(e,r));return o||null}getResolverByDescriptor(e,r){let o=this.resolvers.find(a=>a.supportsDescriptor(e,r));if(!o)throw new Error(`${jn(r.project.configuration,e)} isn't supported by any available resolver`);return o}tryResolverByLocator(e,r){let o=this.resolvers.find(a=>a.supportsLocator(e,r));return o||null}getResolverByLocator(e,r){let o=this.resolvers.find(a=>a.supportsLocator(e,r));if(!o)throw new Error(`${qr(r.project.configuration,e)} isn't supported by any available resolver`);return o}}});var Km,nO=Et(()=>{Pt();bo();Km=class{supports(e){return!!e.reference.startsWith("virtual:")}getLocalPath(e,r){let o=e.reference.indexOf("#");if(o===-1)throw new Error("Invalid virtual package reference");let a=e.reference.slice(o+1),n=Rs(e,a);return r.fetcher.getLocalPath(n,r)}async fetch(e,r){let o=e.reference.indexOf("#");if(o===-1)throw new Error("Invalid virtual package reference");let a=e.reference.slice(o+1),n=Rs(e,a),u=await r.fetcher.fetch(n,r);return await this.ensureVirtualLink(e,u,r)}getLocatorFilename(e){return Hm(e)}async ensureVirtualLink(e,r,o){let a=r.packageFs.getRealPath(),n=o.project.configuration.get("virtualFolder"),u=this.getLocatorFilename(e),A=zs.makeVirtualPath(n,u,a),p=new Hu(A,{baseFs:r.packageFs,pathUtils:K});return{...r,packageFs:p}}}});var kS,Ose=Et(()=>{kS=class t{static{this.protocol="virtual:"}static isVirtualDescriptor(e){return!!e.range.startsWith(t.protocol)}static isVirtualLocator(e){return!!e.reference.startsWith(t.protocol)}supportsDescriptor(e,r){return t.isVirtualDescriptor(e)}supportsLocator(e,r){return t.isVirtualLocator(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){throw new Error('Assertion failed: calling "bindDescriptor" on a virtual descriptor is unsupported')}getResolutionDependencies(e,r){throw new Error('Assertion failed: calling "getResolutionDependencies" on a virtual descriptor is unsupported')}async getCandidates(e,r,o){throw new Error('Assertion failed: calling "getCandidates" on a virtual descriptor is unsupported')}async getSatisfying(e,r,o,a){throw new Error('Assertion failed: calling "getSatisfying" on a virtual descriptor is unsupported')}async resolve(e,r){throw new Error('Assertion failed: calling "resolve" on a virtual locator is unsupported')}}});var Vm,iO=Et(()=>{Pt();mg();Vm=class{supports(e){return!!e.reference.startsWith(ei.protocol)}getLocalPath(e,r){return this.getWorkspace(e,r).cwd}async fetch(e,r){let o=this.getWorkspace(e,r).cwd;return{packageFs:new gn(o),prefixPath:It.dot,localPath:o}}getWorkspace(e,r){return r.project.getWorkspaceByCwd(e.reference.slice(ei.protocol.length))}}});function KI(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Use(t){return typeof t>"u"?3:KI(t)?0:Array.isArray(t)?1:2}function aO(t,e){return Object.hasOwn(t,e)}function brt(t){return KI(t)&&aO(t,"onConflict")&&typeof t.onConflict=="string"}function xrt(t){if(typeof t>"u")return{onConflict:"default",value:t};if(!brt(t))return{onConflict:"default",value:t};if(aO(t,"value"))return t;let{onConflict:e,...r}=t;return{onConflict:e,value:r}}function _se(t,e){let r=KI(t)&&aO(t,e)?t[e]:void 0;return xrt(r)}function zm(t,e){return[t,e,Hse]}function lO(t){return Array.isArray(t)?t[2]===Hse:!1}function sO(t,e){if(KI(t)){let r={};for(let o of Object.keys(t))r[o]=sO(t[o],e);return zm(e,r)}return Array.isArray(t)?zm(e,t.map(r=>sO(r,e))):zm(e,t)}function oO(t,e,r,o,a){let n,u=[],A=a,p=0;for(let E=a-1;E>=o;--E){let[I,v]=t[E],{onConflict:x,value:C}=_se(v,r),R=Use(C);if(R!==3){if(n??=R,R!==n||x==="hardReset"){p=A;break}if(R===2)return zm(I,C);if(u.unshift([I,C]),x==="reset"){p=E;break}x==="extend"&&E===o&&(o=0),A=E}}if(typeof n>"u")return null;let h=u.map(([E])=>E).join(", ");switch(n){case 1:return zm(h,new Array().concat(...u.map(([E,I])=>I.map(v=>sO(v,E)))));case 0:{let E=Object.assign({},...u.map(([,R])=>R)),I=Object.keys(E),v={},x=t.map(([R,L])=>[R,_se(L,r).value]),C=Srt(x,([R,L])=>{let U=Use(L);return U!==0&&U!==3});if(C!==-1){let R=x.slice(C+1);for(let L of I)v[L]=oO(R,e,L,0,R.length)}else for(let R of I)v[R]=oO(x,e,R,p,x.length);return zm(h,v)}default:throw new Error("Assertion failed: Non-extendable value type")}}function qse(t){return oO(t.map(([e,r])=>[e,{".":r}]),[],".",0,t.length)}function VI(t){return lO(t)?t[1]:t}function QS(t){let e=lO(t)?t[1]:t;if(Array.isArray(e))return e.map(r=>QS(r));if(KI(e)){let r={};for(let[o,a]of Object.entries(e))r[o]=QS(a);return r}return e}function cO(t){return lO(t)?t[0]:null}var Srt,Hse,jse=Et(()=>{Srt=(t,e,r)=>{let o=[...t];return o.reverse(),o.findIndex(e,r)};Hse=Symbol()});var RS={};Vt(RS,{getDefaultGlobalFolder:()=>AO,getHomeFolder:()=>Jm,isFolderInside:()=>fO});function AO(){if(process.platform==="win32"){let t=ue.toPortablePath(process.env.LOCALAPPDATA||ue.join((0,uO.homedir)(),"AppData","Local"));return K.resolve(t,"Yarn/Berry")}if(process.env.XDG_DATA_HOME){let t=ue.toPortablePath(process.env.XDG_DATA_HOME);return K.resolve(t,"yarn/berry")}return K.resolve(Jm(),".yarn/berry")}function Jm(){return ue.toPortablePath((0,uO.homedir)()||"/usr/local/share")}function fO(t,e){let r=K.relative(e,t);return r&&!r.startsWith("..")&&!K.isAbsolute(r)}var uO,TS=Et(()=>{Pt();uO=ve("os")});var Kse=_(Xm=>{"use strict";var uLt=ve("net"),Qrt=ve("tls"),pO=ve("http"),Gse=ve("https"),Frt=ve("events"),ALt=ve("assert"),Rrt=ve("util");Xm.httpOverHttp=Trt;Xm.httpsOverHttp=Nrt;Xm.httpOverHttps=Lrt;Xm.httpsOverHttps=Mrt;function Trt(t){var e=new xf(t);return e.request=pO.request,e}function Nrt(t){var e=new xf(t);return e.request=pO.request,e.createSocket=Yse,e.defaultPort=443,e}function Lrt(t){var e=new xf(t);return e.request=Gse.request,e}function Mrt(t){var e=new xf(t);return e.request=Gse.request,e.createSocket=Yse,e.defaultPort=443,e}function xf(t){var e=this;e.options=t||{},e.proxyOptions=e.options.proxy||{},e.maxSockets=e.options.maxSockets||pO.Agent.defaultMaxSockets,e.requests=[],e.sockets=[],e.on("free",function(o,a,n,u){for(var A=Wse(a,n,u),p=0,h=e.requests.length;p<h;++p){var E=e.requests[p];if(E.host===A.host&&E.port===A.port){e.requests.splice(p,1),E.request.onSocket(o);return}}o.destroy(),e.removeSocket(o)})}Rrt.inherits(xf,Frt.EventEmitter);xf.prototype.addRequest=function(e,r,o,a){var n=this,u=hO({request:e},n.options,Wse(r,o,a));if(n.sockets.length>=this.maxSockets){n.requests.push(u);return}n.createSocket(u,function(A){A.on("free",p),A.on("close",h),A.on("agentRemove",h),e.onSocket(A);function p(){n.emit("free",A,u)}function h(E){n.removeSocket(A),A.removeListener("free",p),A.removeListener("close",h),A.removeListener("agentRemove",h)}})};xf.prototype.createSocket=function(e,r){var o=this,a={};o.sockets.push(a);var n=hO({},o.proxyOptions,{method:"CONNECT",path:e.host+":"+e.port,agent:!1,headers:{host:e.host+":"+e.port}});e.localAddress&&(n.localAddress=e.localAddress),n.proxyAuth&&(n.headers=n.headers||{},n.headers["Proxy-Authorization"]="Basic "+new Buffer(n.proxyAuth).toString("base64")),ih("making CONNECT request");var u=o.request(n);u.useChunkedEncodingByDefault=!1,u.once("response",A),u.once("upgrade",p),u.once("connect",h),u.once("error",E),u.end();function A(I){I.upgrade=!0}function p(I,v,x){process.nextTick(function(){h(I,v,x)})}function h(I,v,x){if(u.removeAllListeners(),v.removeAllListeners(),I.statusCode!==200){ih("tunneling socket could not be established, statusCode=%d",I.statusCode),v.destroy();var C=new Error("tunneling socket could not be established, statusCode="+I.statusCode);C.code="ECONNRESET",e.request.emit("error",C),o.removeSocket(a);return}if(x.length>0){ih("got illegal response body from proxy"),v.destroy();var C=new Error("got illegal response body from proxy");C.code="ECONNRESET",e.request.emit("error",C),o.removeSocket(a);return}return ih("tunneling connection has established"),o.sockets[o.sockets.indexOf(a)]=v,r(v)}function E(I){u.removeAllListeners(),ih(`tunneling socket could not be established, cause=%s +`,I.message,I.stack);var v=new Error("tunneling socket could not be established, cause="+I.message);v.code="ECONNRESET",e.request.emit("error",v),o.removeSocket(a)}};xf.prototype.removeSocket=function(e){var r=this.sockets.indexOf(e);if(r!==-1){this.sockets.splice(r,1);var o=this.requests.shift();o&&this.createSocket(o,function(a){o.request.onSocket(a)})}};function Yse(t,e){var r=this;xf.prototype.createSocket.call(r,t,function(o){var a=t.request.getHeader("host"),n=hO({},r.options,{socket:o,servername:a?a.replace(/:.*$/,""):t.host}),u=Qrt.connect(0,n);r.sockets[r.sockets.indexOf(o)]=u,e(u)})}function Wse(t,e,r){return typeof t=="string"?{host:t,port:e,localAddress:r}:t}function hO(t){for(var e=1,r=arguments.length;e<r;++e){var o=arguments[e];if(typeof o=="object")for(var a=Object.keys(o),n=0,u=a.length;n<u;++n){var A=a[n];o[A]!==void 0&&(t[A]=o[A])}}return t}var ih;process.env.NODE_DEBUG&&/\btunnel\b/.test(process.env.NODE_DEBUG)?ih=function(){var t=Array.prototype.slice.call(arguments);typeof t[0]=="string"?t[0]="TUNNEL: "+t[0]:t.unshift("TUNNEL:"),console.error.apply(console,t)}:ih=function(){};Xm.debug=ih});var zse=_((pLt,Vse)=>{Vse.exports=Kse()});var Qf=_((kf,NS)=>{"use strict";Object.defineProperty(kf,"__esModule",{value:!0});var Jse=["Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","Float32Array","Float64Array","BigInt64Array","BigUint64Array"];function Ort(t){return Jse.includes(t)}var Urt=["Function","Generator","AsyncGenerator","GeneratorFunction","AsyncGeneratorFunction","AsyncFunction","Observable","Array","Buffer","Blob","Object","RegExp","Date","Error","Map","Set","WeakMap","WeakSet","ArrayBuffer","SharedArrayBuffer","DataView","Promise","URL","FormData","URLSearchParams","HTMLElement",...Jse];function _rt(t){return Urt.includes(t)}var Hrt=["null","undefined","string","number","bigint","boolean","symbol"];function qrt(t){return Hrt.includes(t)}function Zm(t){return e=>typeof e===t}var{toString:Xse}=Object.prototype,zI=t=>{let e=Xse.call(t).slice(8,-1);if(/HTML\w+Element/.test(e)&&Pe.domElement(t))return"HTMLElement";if(_rt(e))return e},Xn=t=>e=>zI(e)===t;function Pe(t){if(t===null)return"null";switch(typeof t){case"undefined":return"undefined";case"string":return"string";case"number":return"number";case"boolean":return"boolean";case"function":return"Function";case"bigint":return"bigint";case"symbol":return"symbol";default:}if(Pe.observable(t))return"Observable";if(Pe.array(t))return"Array";if(Pe.buffer(t))return"Buffer";let e=zI(t);if(e)return e;if(t instanceof String||t instanceof Boolean||t instanceof Number)throw new TypeError("Please don't use object wrappers for primitive types");return"Object"}Pe.undefined=Zm("undefined");Pe.string=Zm("string");var jrt=Zm("number");Pe.number=t=>jrt(t)&&!Pe.nan(t);Pe.bigint=Zm("bigint");Pe.function_=Zm("function");Pe.null_=t=>t===null;Pe.class_=t=>Pe.function_(t)&&t.toString().startsWith("class ");Pe.boolean=t=>t===!0||t===!1;Pe.symbol=Zm("symbol");Pe.numericString=t=>Pe.string(t)&&!Pe.emptyStringOrWhitespace(t)&&!Number.isNaN(Number(t));Pe.array=(t,e)=>Array.isArray(t)?Pe.function_(e)?t.every(e):!0:!1;Pe.buffer=t=>{var e,r,o,a;return(a=(o=(r=(e=t)===null||e===void 0?void 0:e.constructor)===null||r===void 0?void 0:r.isBuffer)===null||o===void 0?void 0:o.call(r,t))!==null&&a!==void 0?a:!1};Pe.blob=t=>Xn("Blob")(t);Pe.nullOrUndefined=t=>Pe.null_(t)||Pe.undefined(t);Pe.object=t=>!Pe.null_(t)&&(typeof t=="object"||Pe.function_(t));Pe.iterable=t=>{var e;return Pe.function_((e=t)===null||e===void 0?void 0:e[Symbol.iterator])};Pe.asyncIterable=t=>{var e;return Pe.function_((e=t)===null||e===void 0?void 0:e[Symbol.asyncIterator])};Pe.generator=t=>{var e,r;return Pe.iterable(t)&&Pe.function_((e=t)===null||e===void 0?void 0:e.next)&&Pe.function_((r=t)===null||r===void 0?void 0:r.throw)};Pe.asyncGenerator=t=>Pe.asyncIterable(t)&&Pe.function_(t.next)&&Pe.function_(t.throw);Pe.nativePromise=t=>Xn("Promise")(t);var Grt=t=>{var e,r;return Pe.function_((e=t)===null||e===void 0?void 0:e.then)&&Pe.function_((r=t)===null||r===void 0?void 0:r.catch)};Pe.promise=t=>Pe.nativePromise(t)||Grt(t);Pe.generatorFunction=Xn("GeneratorFunction");Pe.asyncGeneratorFunction=t=>zI(t)==="AsyncGeneratorFunction";Pe.asyncFunction=t=>zI(t)==="AsyncFunction";Pe.boundFunction=t=>Pe.function_(t)&&!t.hasOwnProperty("prototype");Pe.regExp=Xn("RegExp");Pe.date=Xn("Date");Pe.error=Xn("Error");Pe.map=t=>Xn("Map")(t);Pe.set=t=>Xn("Set")(t);Pe.weakMap=t=>Xn("WeakMap")(t);Pe.weakSet=t=>Xn("WeakSet")(t);Pe.int8Array=Xn("Int8Array");Pe.uint8Array=Xn("Uint8Array");Pe.uint8ClampedArray=Xn("Uint8ClampedArray");Pe.int16Array=Xn("Int16Array");Pe.uint16Array=Xn("Uint16Array");Pe.int32Array=Xn("Int32Array");Pe.uint32Array=Xn("Uint32Array");Pe.float32Array=Xn("Float32Array");Pe.float64Array=Xn("Float64Array");Pe.bigInt64Array=Xn("BigInt64Array");Pe.bigUint64Array=Xn("BigUint64Array");Pe.arrayBuffer=Xn("ArrayBuffer");Pe.sharedArrayBuffer=Xn("SharedArrayBuffer");Pe.dataView=Xn("DataView");Pe.enumCase=(t,e)=>Object.values(e).includes(t);Pe.directInstanceOf=(t,e)=>Object.getPrototypeOf(t)===e.prototype;Pe.urlInstance=t=>Xn("URL")(t);Pe.urlString=t=>{if(!Pe.string(t))return!1;try{return new URL(t),!0}catch{return!1}};Pe.truthy=t=>!!t;Pe.falsy=t=>!t;Pe.nan=t=>Number.isNaN(t);Pe.primitive=t=>Pe.null_(t)||qrt(typeof t);Pe.integer=t=>Number.isInteger(t);Pe.safeInteger=t=>Number.isSafeInteger(t);Pe.plainObject=t=>{if(Xse.call(t)!=="[object Object]")return!1;let e=Object.getPrototypeOf(t);return e===null||e===Object.getPrototypeOf({})};Pe.typedArray=t=>Ort(zI(t));var Yrt=t=>Pe.safeInteger(t)&&t>=0;Pe.arrayLike=t=>!Pe.nullOrUndefined(t)&&!Pe.function_(t)&&Yrt(t.length);Pe.inRange=(t,e)=>{if(Pe.number(e))return t>=Math.min(0,e)&&t<=Math.max(e,0);if(Pe.array(e)&&e.length===2)return t>=Math.min(...e)&&t<=Math.max(...e);throw new TypeError(`Invalid range: ${JSON.stringify(e)}`)};var Wrt=1,Krt=["innerHTML","ownerDocument","style","attributes","nodeValue"];Pe.domElement=t=>Pe.object(t)&&t.nodeType===Wrt&&Pe.string(t.nodeName)&&!Pe.plainObject(t)&&Krt.every(e=>e in t);Pe.observable=t=>{var e,r,o,a;return t?t===((r=(e=t)[Symbol.observable])===null||r===void 0?void 0:r.call(e))||t===((a=(o=t)["@@observable"])===null||a===void 0?void 0:a.call(o)):!1};Pe.nodeStream=t=>Pe.object(t)&&Pe.function_(t.pipe)&&!Pe.observable(t);Pe.infinite=t=>t===1/0||t===-1/0;var Zse=t=>e=>Pe.integer(e)&&Math.abs(e%2)===t;Pe.evenInteger=Zse(0);Pe.oddInteger=Zse(1);Pe.emptyArray=t=>Pe.array(t)&&t.length===0;Pe.nonEmptyArray=t=>Pe.array(t)&&t.length>0;Pe.emptyString=t=>Pe.string(t)&&t.length===0;var Vrt=t=>Pe.string(t)&&!/\S/.test(t);Pe.emptyStringOrWhitespace=t=>Pe.emptyString(t)||Vrt(t);Pe.nonEmptyString=t=>Pe.string(t)&&t.length>0;Pe.nonEmptyStringAndNotWhitespace=t=>Pe.string(t)&&!Pe.emptyStringOrWhitespace(t);Pe.emptyObject=t=>Pe.object(t)&&!Pe.map(t)&&!Pe.set(t)&&Object.keys(t).length===0;Pe.nonEmptyObject=t=>Pe.object(t)&&!Pe.map(t)&&!Pe.set(t)&&Object.keys(t).length>0;Pe.emptySet=t=>Pe.set(t)&&t.size===0;Pe.nonEmptySet=t=>Pe.set(t)&&t.size>0;Pe.emptyMap=t=>Pe.map(t)&&t.size===0;Pe.nonEmptyMap=t=>Pe.map(t)&&t.size>0;Pe.propertyKey=t=>Pe.any([Pe.string,Pe.number,Pe.symbol],t);Pe.formData=t=>Xn("FormData")(t);Pe.urlSearchParams=t=>Xn("URLSearchParams")(t);var $se=(t,e,r)=>{if(!Pe.function_(e))throw new TypeError(`Invalid predicate: ${JSON.stringify(e)}`);if(r.length===0)throw new TypeError("Invalid number of values");return t.call(r,e)};Pe.any=(t,...e)=>(Pe.array(t)?t:[t]).some(o=>$se(Array.prototype.some,o,e));Pe.all=(t,...e)=>$se(Array.prototype.every,t,e);var Mt=(t,e,r,o={})=>{if(!t){let{multipleValues:a}=o,n=a?`received values of types ${[...new Set(r.map(u=>`\`${Pe(u)}\``))].join(", ")}`:`received value of type \`${Pe(r)}\``;throw new TypeError(`Expected value which is \`${e}\`, ${n}.`)}};kf.assert={undefined:t=>Mt(Pe.undefined(t),"undefined",t),string:t=>Mt(Pe.string(t),"string",t),number:t=>Mt(Pe.number(t),"number",t),bigint:t=>Mt(Pe.bigint(t),"bigint",t),function_:t=>Mt(Pe.function_(t),"Function",t),null_:t=>Mt(Pe.null_(t),"null",t),class_:t=>Mt(Pe.class_(t),"Class",t),boolean:t=>Mt(Pe.boolean(t),"boolean",t),symbol:t=>Mt(Pe.symbol(t),"symbol",t),numericString:t=>Mt(Pe.numericString(t),"string with a number",t),array:(t,e)=>{Mt(Pe.array(t),"Array",t),e&&t.forEach(e)},buffer:t=>Mt(Pe.buffer(t),"Buffer",t),blob:t=>Mt(Pe.blob(t),"Blob",t),nullOrUndefined:t=>Mt(Pe.nullOrUndefined(t),"null or undefined",t),object:t=>Mt(Pe.object(t),"Object",t),iterable:t=>Mt(Pe.iterable(t),"Iterable",t),asyncIterable:t=>Mt(Pe.asyncIterable(t),"AsyncIterable",t),generator:t=>Mt(Pe.generator(t),"Generator",t),asyncGenerator:t=>Mt(Pe.asyncGenerator(t),"AsyncGenerator",t),nativePromise:t=>Mt(Pe.nativePromise(t),"native Promise",t),promise:t=>Mt(Pe.promise(t),"Promise",t),generatorFunction:t=>Mt(Pe.generatorFunction(t),"GeneratorFunction",t),asyncGeneratorFunction:t=>Mt(Pe.asyncGeneratorFunction(t),"AsyncGeneratorFunction",t),asyncFunction:t=>Mt(Pe.asyncFunction(t),"AsyncFunction",t),boundFunction:t=>Mt(Pe.boundFunction(t),"Function",t),regExp:t=>Mt(Pe.regExp(t),"RegExp",t),date:t=>Mt(Pe.date(t),"Date",t),error:t=>Mt(Pe.error(t),"Error",t),map:t=>Mt(Pe.map(t),"Map",t),set:t=>Mt(Pe.set(t),"Set",t),weakMap:t=>Mt(Pe.weakMap(t),"WeakMap",t),weakSet:t=>Mt(Pe.weakSet(t),"WeakSet",t),int8Array:t=>Mt(Pe.int8Array(t),"Int8Array",t),uint8Array:t=>Mt(Pe.uint8Array(t),"Uint8Array",t),uint8ClampedArray:t=>Mt(Pe.uint8ClampedArray(t),"Uint8ClampedArray",t),int16Array:t=>Mt(Pe.int16Array(t),"Int16Array",t),uint16Array:t=>Mt(Pe.uint16Array(t),"Uint16Array",t),int32Array:t=>Mt(Pe.int32Array(t),"Int32Array",t),uint32Array:t=>Mt(Pe.uint32Array(t),"Uint32Array",t),float32Array:t=>Mt(Pe.float32Array(t),"Float32Array",t),float64Array:t=>Mt(Pe.float64Array(t),"Float64Array",t),bigInt64Array:t=>Mt(Pe.bigInt64Array(t),"BigInt64Array",t),bigUint64Array:t=>Mt(Pe.bigUint64Array(t),"BigUint64Array",t),arrayBuffer:t=>Mt(Pe.arrayBuffer(t),"ArrayBuffer",t),sharedArrayBuffer:t=>Mt(Pe.sharedArrayBuffer(t),"SharedArrayBuffer",t),dataView:t=>Mt(Pe.dataView(t),"DataView",t),enumCase:(t,e)=>Mt(Pe.enumCase(t,e),"EnumCase",t),urlInstance:t=>Mt(Pe.urlInstance(t),"URL",t),urlString:t=>Mt(Pe.urlString(t),"string with a URL",t),truthy:t=>Mt(Pe.truthy(t),"truthy",t),falsy:t=>Mt(Pe.falsy(t),"falsy",t),nan:t=>Mt(Pe.nan(t),"NaN",t),primitive:t=>Mt(Pe.primitive(t),"primitive",t),integer:t=>Mt(Pe.integer(t),"integer",t),safeInteger:t=>Mt(Pe.safeInteger(t),"integer",t),plainObject:t=>Mt(Pe.plainObject(t),"plain object",t),typedArray:t=>Mt(Pe.typedArray(t),"TypedArray",t),arrayLike:t=>Mt(Pe.arrayLike(t),"array-like",t),domElement:t=>Mt(Pe.domElement(t),"HTMLElement",t),observable:t=>Mt(Pe.observable(t),"Observable",t),nodeStream:t=>Mt(Pe.nodeStream(t),"Node.js Stream",t),infinite:t=>Mt(Pe.infinite(t),"infinite number",t),emptyArray:t=>Mt(Pe.emptyArray(t),"empty array",t),nonEmptyArray:t=>Mt(Pe.nonEmptyArray(t),"non-empty array",t),emptyString:t=>Mt(Pe.emptyString(t),"empty string",t),emptyStringOrWhitespace:t=>Mt(Pe.emptyStringOrWhitespace(t),"empty string or whitespace",t),nonEmptyString:t=>Mt(Pe.nonEmptyString(t),"non-empty string",t),nonEmptyStringAndNotWhitespace:t=>Mt(Pe.nonEmptyStringAndNotWhitespace(t),"non-empty string and not whitespace",t),emptyObject:t=>Mt(Pe.emptyObject(t),"empty object",t),nonEmptyObject:t=>Mt(Pe.nonEmptyObject(t),"non-empty object",t),emptySet:t=>Mt(Pe.emptySet(t),"empty set",t),nonEmptySet:t=>Mt(Pe.nonEmptySet(t),"non-empty set",t),emptyMap:t=>Mt(Pe.emptyMap(t),"empty map",t),nonEmptyMap:t=>Mt(Pe.nonEmptyMap(t),"non-empty map",t),propertyKey:t=>Mt(Pe.propertyKey(t),"PropertyKey",t),formData:t=>Mt(Pe.formData(t),"FormData",t),urlSearchParams:t=>Mt(Pe.urlSearchParams(t),"URLSearchParams",t),evenInteger:t=>Mt(Pe.evenInteger(t),"even integer",t),oddInteger:t=>Mt(Pe.oddInteger(t),"odd integer",t),directInstanceOf:(t,e)=>Mt(Pe.directInstanceOf(t,e),"T",t),inRange:(t,e)=>Mt(Pe.inRange(t,e),"in range",t),any:(t,...e)=>Mt(Pe.any(t,...e),"predicate returns truthy for any value",e,{multipleValues:!0}),all:(t,...e)=>Mt(Pe.all(t,...e),"predicate returns truthy for all values",e,{multipleValues:!0})};Object.defineProperties(Pe,{class:{value:Pe.class_},function:{value:Pe.function_},null:{value:Pe.null_}});Object.defineProperties(kf.assert,{class:{value:kf.assert.class_},function:{value:kf.assert.function_},null:{value:kf.assert.null_}});kf.default=Pe;NS.exports=Pe;NS.exports.default=Pe;NS.exports.assert=kf.assert});var eoe=_((hLt,gO)=>{"use strict";var LS=class extends Error{constructor(e){super(e||"Promise was canceled"),this.name="CancelError"}get isCanceled(){return!0}},MS=class t{static fn(e){return(...r)=>new t((o,a,n)=>{r.push(n),e(...r).then(o,a)})}constructor(e){this._cancelHandlers=[],this._isPending=!0,this._isCanceled=!1,this._rejectOnCancel=!0,this._promise=new Promise((r,o)=>{this._reject=o;let a=A=>{this._isPending=!1,r(A)},n=A=>{this._isPending=!1,o(A)},u=A=>{if(!this._isPending)throw new Error("The `onCancel` handler was attached after the promise settled.");this._cancelHandlers.push(A)};return Object.defineProperties(u,{shouldReject:{get:()=>this._rejectOnCancel,set:A=>{this._rejectOnCancel=A}}}),e(a,n,u)})}then(e,r){return this._promise.then(e,r)}catch(e){return this._promise.catch(e)}finally(e){return this._promise.finally(e)}cancel(e){if(!(!this._isPending||this._isCanceled)){if(this._cancelHandlers.length>0)try{for(let r of this._cancelHandlers)r()}catch(r){this._reject(r)}this._isCanceled=!0,this._rejectOnCancel&&this._reject(new LS(e))}}get isCanceled(){return this._isCanceled}};Object.setPrototypeOf(MS.prototype,Promise.prototype);gO.exports=MS;gO.exports.CancelError=LS});var toe=_((mO,yO)=>{"use strict";Object.defineProperty(mO,"__esModule",{value:!0});function zrt(t){return t.encrypted}var dO=(t,e)=>{let r;typeof e=="function"?r={connect:e}:r=e;let o=typeof r.connect=="function",a=typeof r.secureConnect=="function",n=typeof r.close=="function",u=()=>{o&&r.connect(),zrt(t)&&a&&(t.authorized?r.secureConnect():t.authorizationError||t.once("secureConnect",r.secureConnect)),n&&t.once("close",r.close)};t.writable&&!t.connecting?u():t.connecting?t.once("connect",u):t.destroyed&&n&&r.close(t._hadError)};mO.default=dO;yO.exports=dO;yO.exports.default=dO});var roe=_((CO,wO)=>{"use strict";Object.defineProperty(CO,"__esModule",{value:!0});var Jrt=toe(),Xrt=Number(process.versions.node.split(".")[0]),EO=t=>{let e={start:Date.now(),socket:void 0,lookup:void 0,connect:void 0,secureConnect:void 0,upload:void 0,response:void 0,end:void 0,error:void 0,abort:void 0,phases:{wait:void 0,dns:void 0,tcp:void 0,tls:void 0,request:void 0,firstByte:void 0,download:void 0,total:void 0}};t.timings=e;let r=u=>{let A=u.emit.bind(u);u.emit=(p,...h)=>(p==="error"&&(e.error=Date.now(),e.phases.total=e.error-e.start,u.emit=A),A(p,...h))};r(t),t.prependOnceListener("abort",()=>{e.abort=Date.now(),(!e.response||Xrt>=13)&&(e.phases.total=Date.now()-e.start)});let o=u=>{e.socket=Date.now(),e.phases.wait=e.socket-e.start;let A=()=>{e.lookup=Date.now(),e.phases.dns=e.lookup-e.socket};u.prependOnceListener("lookup",A),Jrt.default(u,{connect:()=>{e.connect=Date.now(),e.lookup===void 0&&(u.removeListener("lookup",A),e.lookup=e.connect,e.phases.dns=e.lookup-e.socket),e.phases.tcp=e.connect-e.lookup},secureConnect:()=>{e.secureConnect=Date.now(),e.phases.tls=e.secureConnect-e.connect}})};t.socket?o(t.socket):t.prependOnceListener("socket",o);let a=()=>{var u;e.upload=Date.now(),e.phases.request=e.upload-(u=e.secureConnect,u??e.connect)};return(typeof t.writableFinished=="boolean"?t.writableFinished:t.finished&&t.outputSize===0&&(!t.socket||t.socket.writableLength===0))?a():t.prependOnceListener("finish",a),t.prependOnceListener("response",u=>{e.response=Date.now(),e.phases.firstByte=e.response-e.upload,u.timings=e,r(u),u.prependOnceListener("end",()=>{e.end=Date.now(),e.phases.download=e.end-e.response,e.phases.total=e.end-e.start})}),e};CO.default=EO;wO.exports=EO;wO.exports.default=EO});var coe=_((gLt,vO)=>{"use strict";var{V4MAPPED:Zrt,ADDRCONFIG:$rt,ALL:loe,promises:{Resolver:noe},lookup:ent}=ve("dns"),{promisify:IO}=ve("util"),tnt=ve("os"),$m=Symbol("cacheableLookupCreateConnection"),BO=Symbol("cacheableLookupInstance"),ioe=Symbol("expires"),rnt=typeof loe=="number",soe=t=>{if(!(t&&typeof t.createConnection=="function"))throw new Error("Expected an Agent instance as the first argument")},nnt=t=>{for(let e of t)e.family!==6&&(e.address=`::ffff:${e.address}`,e.family=6)},ooe=()=>{let t=!1,e=!1;for(let r of Object.values(tnt.networkInterfaces()))for(let o of r)if(!o.internal&&(o.family==="IPv6"?e=!0:t=!0,t&&e))return{has4:t,has6:e};return{has4:t,has6:e}},int=t=>Symbol.iterator in t,aoe={ttl:!0},snt={all:!0},OS=class{constructor({cache:e=new Map,maxTtl:r=1/0,fallbackDuration:o=3600,errorTtl:a=.15,resolver:n=new noe,lookup:u=ent}={}){if(this.maxTtl=r,this.errorTtl=a,this._cache=e,this._resolver=n,this._dnsLookup=IO(u),this._resolver instanceof noe?(this._resolve4=this._resolver.resolve4.bind(this._resolver),this._resolve6=this._resolver.resolve6.bind(this._resolver)):(this._resolve4=IO(this._resolver.resolve4.bind(this._resolver)),this._resolve6=IO(this._resolver.resolve6.bind(this._resolver))),this._iface=ooe(),this._pending={},this._nextRemovalTime=!1,this._hostnamesToFallback=new Set,o<1)this._fallback=!1;else{this._fallback=!0;let A=setInterval(()=>{this._hostnamesToFallback.clear()},o*1e3);A.unref&&A.unref()}this.lookup=this.lookup.bind(this),this.lookupAsync=this.lookupAsync.bind(this)}set servers(e){this.clear(),this._resolver.setServers(e)}get servers(){return this._resolver.getServers()}lookup(e,r,o){if(typeof r=="function"?(o=r,r={}):typeof r=="number"&&(r={family:r}),!o)throw new Error("Callback must be a function.");this.lookupAsync(e,r).then(a=>{r.all?o(null,a):o(null,a.address,a.family,a.expires,a.ttl)},o)}async lookupAsync(e,r={}){typeof r=="number"&&(r={family:r});let o=await this.query(e);if(r.family===6){let a=o.filter(n=>n.family===6);r.hints&Zrt&&(rnt&&r.hints&loe||a.length===0)?nnt(o):o=a}else r.family===4&&(o=o.filter(a=>a.family===4));if(r.hints&$rt){let{_iface:a}=this;o=o.filter(n=>n.family===6?a.has6:a.has4)}if(o.length===0){let a=new Error(`cacheableLookup ENOTFOUND ${e}`);throw a.code="ENOTFOUND",a.hostname=e,a}return r.all?o:o[0]}async query(e){let r=await this._cache.get(e);if(!r){let o=this._pending[e];if(o)r=await o;else{let a=this.queryAndCache(e);this._pending[e]=a,r=await a}}return r=r.map(o=>({...o})),r}async _resolve(e){let r=async h=>{try{return await h}catch(E){if(E.code==="ENODATA"||E.code==="ENOTFOUND")return[];throw E}},[o,a]=await Promise.all([this._resolve4(e,aoe),this._resolve6(e,aoe)].map(h=>r(h))),n=0,u=0,A=0,p=Date.now();for(let h of o)h.family=4,h.expires=p+h.ttl*1e3,n=Math.max(n,h.ttl);for(let h of a)h.family=6,h.expires=p+h.ttl*1e3,u=Math.max(u,h.ttl);return o.length>0?a.length>0?A=Math.min(n,u):A=n:A=u,{entries:[...o,...a],cacheTtl:A}}async _lookup(e){try{return{entries:await this._dnsLookup(e,{all:!0}),cacheTtl:0}}catch{return{entries:[],cacheTtl:0}}}async _set(e,r,o){if(this.maxTtl>0&&o>0){o=Math.min(o,this.maxTtl)*1e3,r[ioe]=Date.now()+o;try{await this._cache.set(e,r,o)}catch(a){this.lookupAsync=async()=>{let n=new Error("Cache Error. Please recreate the CacheableLookup instance.");throw n.cause=a,n}}int(this._cache)&&this._tick(o)}}async queryAndCache(e){if(this._hostnamesToFallback.has(e))return this._dnsLookup(e,snt);try{let r=await this._resolve(e);r.entries.length===0&&this._fallback&&(r=await this._lookup(e),r.entries.length!==0&&this._hostnamesToFallback.add(e));let o=r.entries.length===0?this.errorTtl:r.cacheTtl;return await this._set(e,r.entries,o),delete this._pending[e],r.entries}catch(r){throw delete this._pending[e],r}}_tick(e){let r=this._nextRemovalTime;(!r||e<r)&&(clearTimeout(this._removalTimeout),this._nextRemovalTime=e,this._removalTimeout=setTimeout(()=>{this._nextRemovalTime=!1;let o=1/0,a=Date.now();for(let[n,u]of this._cache){let A=u[ioe];a>=A?this._cache.delete(n):A<o&&(o=A)}o!==1/0&&this._tick(o-a)},e),this._removalTimeout.unref&&this._removalTimeout.unref())}install(e){if(soe(e),$m in e)throw new Error("CacheableLookup has been already installed");e[$m]=e.createConnection,e[BO]=this,e.createConnection=(r,o)=>("lookup"in r||(r.lookup=this.lookup),e[$m](r,o))}uninstall(e){if(soe(e),e[$m]){if(e[BO]!==this)throw new Error("The agent is not owned by this CacheableLookup instance");e.createConnection=e[$m],delete e[$m],delete e[BO]}}updateInterfaceInfo(){let{_iface:e}=this;this._iface=ooe(),(e.has4&&!this._iface.has4||e.has6&&!this._iface.has6)&&this._cache.clear()}clear(e){if(e){this._cache.delete(e);return}this._cache.clear()}};vO.exports=OS;vO.exports.default=OS});var foe=_((dLt,DO)=>{"use strict";var ont=typeof URL>"u"?ve("url").URL:URL,ant="text/plain",lnt="us-ascii",uoe=(t,e)=>e.some(r=>r instanceof RegExp?r.test(t):r===t),cnt=(t,{stripHash:e})=>{let r=t.match(/^data:([^,]*?),([^#]*?)(?:#(.*))?$/);if(!r)throw new Error(`Invalid URL: ${t}`);let o=r[1].split(";"),a=r[2],n=e?"":r[3],u=!1;o[o.length-1]==="base64"&&(o.pop(),u=!0);let A=(o.shift()||"").toLowerCase(),h=[...o.map(E=>{let[I,v=""]=E.split("=").map(x=>x.trim());return I==="charset"&&(v=v.toLowerCase(),v===lnt)?"":`${I}${v?`=${v}`:""}`}).filter(Boolean)];return u&&h.push("base64"),(h.length!==0||A&&A!==ant)&&h.unshift(A),`data:${h.join(";")},${u?a.trim():a}${n?`#${n}`:""}`},Aoe=(t,e)=>{if(e={defaultProtocol:"http:",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripWWW:!0,removeQueryParameters:[/^utm_\w+/i],removeTrailingSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...e},Reflect.has(e,"normalizeHttps"))throw new Error("options.normalizeHttps is renamed to options.forceHttp");if(Reflect.has(e,"normalizeHttp"))throw new Error("options.normalizeHttp is renamed to options.forceHttps");if(Reflect.has(e,"stripFragment"))throw new Error("options.stripFragment is renamed to options.stripHash");if(t=t.trim(),/^data:/i.test(t))return cnt(t,e);let r=t.startsWith("//");!r&&/^\.*\//.test(t)||(t=t.replace(/^(?!(?:\w+:)?\/\/)|^\/\//,e.defaultProtocol));let a=new ont(t);if(e.forceHttp&&e.forceHttps)throw new Error("The `forceHttp` and `forceHttps` options cannot be used together");if(e.forceHttp&&a.protocol==="https:"&&(a.protocol="http:"),e.forceHttps&&a.protocol==="http:"&&(a.protocol="https:"),e.stripAuthentication&&(a.username="",a.password=""),e.stripHash&&(a.hash=""),a.pathname&&(a.pathname=a.pathname.replace(/((?!:).|^)\/{2,}/g,(n,u)=>/^(?!\/)/g.test(u)?`${u}/`:"/")),a.pathname&&(a.pathname=decodeURI(a.pathname)),e.removeDirectoryIndex===!0&&(e.removeDirectoryIndex=[/^index\.[a-z]+$/]),Array.isArray(e.removeDirectoryIndex)&&e.removeDirectoryIndex.length>0){let n=a.pathname.split("/"),u=n[n.length-1];uoe(u,e.removeDirectoryIndex)&&(n=n.slice(0,n.length-1),a.pathname=n.slice(1).join("/")+"/")}if(a.hostname&&(a.hostname=a.hostname.replace(/\.$/,""),e.stripWWW&&/^www\.([a-z\-\d]{2,63})\.([a-z.]{2,5})$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\./,""))),Array.isArray(e.removeQueryParameters))for(let n of[...a.searchParams.keys()])uoe(n,e.removeQueryParameters)&&a.searchParams.delete(n);return e.sortQueryParameters&&a.searchParams.sort(),e.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\/$/,"")),t=a.toString(),(e.removeTrailingSlash||a.pathname==="/")&&a.hash===""&&(t=t.replace(/\/$/,"")),r&&!e.normalizeProtocol&&(t=t.replace(/^http:\/\//,"//")),e.stripProtocol&&(t=t.replace(/^(?:https?:)?\/\//,"")),t};DO.exports=Aoe;DO.exports.default=Aoe});var goe=_((mLt,hoe)=>{hoe.exports=poe;function poe(t,e){if(t&&e)return poe(t)(e);if(typeof t!="function")throw new TypeError("need wrapper function");return Object.keys(t).forEach(function(o){r[o]=t[o]}),r;function r(){for(var o=new Array(arguments.length),a=0;a<o.length;a++)o[a]=arguments[a];var n=t.apply(this,o),u=o[o.length-1];return typeof n=="function"&&n!==u&&Object.keys(u).forEach(function(A){n[A]=u[A]}),n}}});var SO=_((yLt,PO)=>{var doe=goe();PO.exports=doe(US);PO.exports.strict=doe(moe);US.proto=US(function(){Object.defineProperty(Function.prototype,"once",{value:function(){return US(this)},configurable:!0}),Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return moe(this)},configurable:!0})});function US(t){var e=function(){return e.called?e.value:(e.called=!0,e.value=t.apply(this,arguments))};return e.called=!1,e}function moe(t){var e=function(){if(e.called)throw new Error(e.onceError);return e.called=!0,e.value=t.apply(this,arguments)},r=t.name||"Function wrapped with `once`";return e.onceError=r+" shouldn't be called more than once",e.called=!1,e}});var bO=_((ELt,Eoe)=>{var unt=SO(),Ant=function(){},fnt=function(t){return t.setHeader&&typeof t.abort=="function"},pnt=function(t){return t.stdio&&Array.isArray(t.stdio)&&t.stdio.length===3},yoe=function(t,e,r){if(typeof e=="function")return yoe(t,null,e);e||(e={}),r=unt(r||Ant);var o=t._writableState,a=t._readableState,n=e.readable||e.readable!==!1&&t.readable,u=e.writable||e.writable!==!1&&t.writable,A=function(){t.writable||p()},p=function(){u=!1,n||r.call(t)},h=function(){n=!1,u||r.call(t)},E=function(C){r.call(t,C?new Error("exited with error code: "+C):null)},I=function(C){r.call(t,C)},v=function(){if(n&&!(a&&a.ended))return r.call(t,new Error("premature close"));if(u&&!(o&&o.ended))return r.call(t,new Error("premature close"))},x=function(){t.req.on("finish",p)};return fnt(t)?(t.on("complete",p),t.on("abort",v),t.req?x():t.on("request",x)):u&&!o&&(t.on("end",A),t.on("close",A)),pnt(t)&&t.on("exit",E),t.on("end",h),t.on("finish",p),e.error!==!1&&t.on("error",I),t.on("close",v),function(){t.removeListener("complete",p),t.removeListener("abort",v),t.removeListener("request",x),t.req&&t.req.removeListener("finish",p),t.removeListener("end",A),t.removeListener("close",A),t.removeListener("finish",p),t.removeListener("exit",E),t.removeListener("end",h),t.removeListener("error",I),t.removeListener("close",v)}};Eoe.exports=yoe});var Ioe=_((CLt,woe)=>{var hnt=SO(),gnt=bO(),xO=ve("fs"),JI=function(){},dnt=/^v?\.0/.test(process.version),_S=function(t){return typeof t=="function"},mnt=function(t){return!dnt||!xO?!1:(t instanceof(xO.ReadStream||JI)||t instanceof(xO.WriteStream||JI))&&_S(t.close)},ynt=function(t){return t.setHeader&&_S(t.abort)},Ent=function(t,e,r,o){o=hnt(o);var a=!1;t.on("close",function(){a=!0}),gnt(t,{readable:e,writable:r},function(u){if(u)return o(u);a=!0,o()});var n=!1;return function(u){if(!a&&!n){if(n=!0,mnt(t))return t.close(JI);if(ynt(t))return t.abort();if(_S(t.destroy))return t.destroy();o(u||new Error("stream was destroyed"))}}},Coe=function(t){t()},Cnt=function(t,e){return t.pipe(e)},wnt=function(){var t=Array.prototype.slice.call(arguments),e=_S(t[t.length-1]||JI)&&t.pop()||JI;if(Array.isArray(t[0])&&(t=t[0]),t.length<2)throw new Error("pump requires two streams per minimum");var r,o=t.map(function(a,n){var u=n<t.length-1,A=n>0;return Ent(a,u,A,function(p){r||(r=p),p&&o.forEach(Coe),!u&&(o.forEach(Coe),e(r))})});return t.reduce(Cnt)};woe.exports=wnt});var voe=_((wLt,Boe)=>{"use strict";var{PassThrough:Int}=ve("stream");Boe.exports=t=>{t={...t};let{array:e}=t,{encoding:r}=t,o=r==="buffer",a=!1;e?a=!(r||o):r=r||"utf8",o&&(r=null);let n=new Int({objectMode:a});r&&n.setEncoding(r);let u=0,A=[];return n.on("data",p=>{A.push(p),a?u=A.length:u+=p.length}),n.getBufferedValue=()=>e?A:o?Buffer.concat(A,u):A.join(""),n.getBufferedLength=()=>u,n}});var Doe=_((ILt,ey)=>{"use strict";var Bnt=Ioe(),vnt=voe(),HS=class extends Error{constructor(){super("maxBuffer exceeded"),this.name="MaxBufferError"}};async function qS(t,e){if(!t)return Promise.reject(new Error("Expected a stream"));e={maxBuffer:1/0,...e};let{maxBuffer:r}=e,o;return await new Promise((a,n)=>{let u=A=>{A&&(A.bufferedData=o.getBufferedValue()),n(A)};o=Bnt(t,vnt(e),A=>{if(A){u(A);return}a()}),o.on("data",()=>{o.getBufferedLength()>r&&u(new HS)})}),o.getBufferedValue()}ey.exports=qS;ey.exports.default=qS;ey.exports.buffer=(t,e)=>qS(t,{...e,encoding:"buffer"});ey.exports.array=(t,e)=>qS(t,{...e,array:!0});ey.exports.MaxBufferError=HS});var Soe=_((vLt,Poe)=>{"use strict";var Dnt=new Set([200,203,204,206,300,301,308,404,405,410,414,501]),Pnt=new Set([200,203,204,300,301,302,303,307,308,404,405,410,414,501]),Snt=new Set([500,502,503,504]),bnt={date:!0,connection:!0,"keep-alive":!0,"proxy-authenticate":!0,"proxy-authorization":!0,te:!0,trailer:!0,"transfer-encoding":!0,upgrade:!0},xnt={"content-length":!0,"content-encoding":!0,"transfer-encoding":!0,"content-range":!0};function Eg(t){let e=parseInt(t,10);return isFinite(e)?e:0}function knt(t){return t?Snt.has(t.status):!0}function kO(t){let e={};if(!t)return e;let r=t.trim().split(/,/);for(let o of r){let[a,n]=o.split(/=/,2);e[a.trim()]=n===void 0?!0:n.trim().replace(/^"|"$/g,"")}return e}function Qnt(t){let e=[];for(let r in t){let o=t[r];e.push(o===!0?r:r+"="+o)}if(e.length)return e.join(", ")}Poe.exports=class{constructor(e,r,{shared:o,cacheHeuristic:a,immutableMinTimeToLive:n,ignoreCargoCult:u,_fromObject:A}={}){if(A){this._fromObject(A);return}if(!r||!r.headers)throw Error("Response headers missing");this._assertRequestHasHeaders(e),this._responseTime=this.now(),this._isShared=o!==!1,this._cacheHeuristic=a!==void 0?a:.1,this._immutableMinTtl=n!==void 0?n:24*3600*1e3,this._status="status"in r?r.status:200,this._resHeaders=r.headers,this._rescc=kO(r.headers["cache-control"]),this._method="method"in e?e.method:"GET",this._url=e.url,this._host=e.headers.host,this._noAuthorization=!e.headers.authorization,this._reqHeaders=r.headers.vary?e.headers:null,this._reqcc=kO(e.headers["cache-control"]),u&&"pre-check"in this._rescc&&"post-check"in this._rescc&&(delete this._rescc["pre-check"],delete this._rescc["post-check"],delete this._rescc["no-cache"],delete this._rescc["no-store"],delete this._rescc["must-revalidate"],this._resHeaders=Object.assign({},this._resHeaders,{"cache-control":Qnt(this._rescc)}),delete this._resHeaders.expires,delete this._resHeaders.pragma),r.headers["cache-control"]==null&&/no-cache/.test(r.headers.pragma)&&(this._rescc["no-cache"]=!0)}now(){return Date.now()}storable(){return!!(!this._reqcc["no-store"]&&(this._method==="GET"||this._method==="HEAD"||this._method==="POST"&&this._hasExplicitExpiration())&&Pnt.has(this._status)&&!this._rescc["no-store"]&&(!this._isShared||!this._rescc.private)&&(!this._isShared||this._noAuthorization||this._allowsStoringAuthenticated())&&(this._resHeaders.expires||this._rescc["max-age"]||this._isShared&&this._rescc["s-maxage"]||this._rescc.public||Dnt.has(this._status)))}_hasExplicitExpiration(){return this._isShared&&this._rescc["s-maxage"]||this._rescc["max-age"]||this._resHeaders.expires}_assertRequestHasHeaders(e){if(!e||!e.headers)throw Error("Request headers missing")}satisfiesWithoutRevalidation(e){this._assertRequestHasHeaders(e);let r=kO(e.headers["cache-control"]);return r["no-cache"]||/no-cache/.test(e.headers.pragma)||r["max-age"]&&this.age()>r["max-age"]||r["min-fresh"]&&this.timeToLive()<1e3*r["min-fresh"]||this.stale()&&!(r["max-stale"]&&!this._rescc["must-revalidate"]&&(r["max-stale"]===!0||r["max-stale"]>this.age()-this.maxAge()))?!1:this._requestMatches(e,!1)}_requestMatches(e,r){return(!this._url||this._url===e.url)&&this._host===e.headers.host&&(!e.method||this._method===e.method||r&&e.method==="HEAD")&&this._varyMatches(e)}_allowsStoringAuthenticated(){return this._rescc["must-revalidate"]||this._rescc.public||this._rescc["s-maxage"]}_varyMatches(e){if(!this._resHeaders.vary)return!0;if(this._resHeaders.vary==="*")return!1;let r=this._resHeaders.vary.trim().toLowerCase().split(/\s*,\s*/);for(let o of r)if(e.headers[o]!==this._reqHeaders[o])return!1;return!0}_copyWithoutHopByHopHeaders(e){let r={};for(let o in e)bnt[o]||(r[o]=e[o]);if(e.connection){let o=e.connection.trim().split(/\s*,\s*/);for(let a of o)delete r[a]}if(r.warning){let o=r.warning.split(/,/).filter(a=>!/^\s*1[0-9][0-9]/.test(a));o.length?r.warning=o.join(",").trim():delete r.warning}return r}responseHeaders(){let e=this._copyWithoutHopByHopHeaders(this._resHeaders),r=this.age();return r>3600*24&&!this._hasExplicitExpiration()&&this.maxAge()>3600*24&&(e.warning=(e.warning?`${e.warning}, `:"")+'113 - "rfc7234 5.5.4"'),e.age=`${Math.round(r)}`,e.date=new Date(this.now()).toUTCString(),e}date(){let e=Date.parse(this._resHeaders.date);return isFinite(e)?e:this._responseTime}age(){let e=this._ageValue(),r=(this.now()-this._responseTime)/1e3;return e+r}_ageValue(){return Eg(this._resHeaders.age)}maxAge(){if(!this.storable()||this._rescc["no-cache"]||this._isShared&&this._resHeaders["set-cookie"]&&!this._rescc.public&&!this._rescc.immutable||this._resHeaders.vary==="*")return 0;if(this._isShared){if(this._rescc["proxy-revalidate"])return 0;if(this._rescc["s-maxage"])return Eg(this._rescc["s-maxage"])}if(this._rescc["max-age"])return Eg(this._rescc["max-age"]);let e=this._rescc.immutable?this._immutableMinTtl:0,r=this.date();if(this._resHeaders.expires){let o=Date.parse(this._resHeaders.expires);return Number.isNaN(o)||o<r?0:Math.max(e,(o-r)/1e3)}if(this._resHeaders["last-modified"]){let o=Date.parse(this._resHeaders["last-modified"]);if(isFinite(o)&&r>o)return Math.max(e,(r-o)/1e3*this._cacheHeuristic)}return e}timeToLive(){let e=this.maxAge()-this.age(),r=e+Eg(this._rescc["stale-if-error"]),o=e+Eg(this._rescc["stale-while-revalidate"]);return Math.max(0,e,r,o)*1e3}stale(){return this.maxAge()<=this.age()}_useStaleIfError(){return this.maxAge()+Eg(this._rescc["stale-if-error"])>this.age()}useStaleWhileRevalidate(){return this.maxAge()+Eg(this._rescc["stale-while-revalidate"])>this.age()}static fromObject(e){return new this(void 0,void 0,{_fromObject:e})}_fromObject(e){if(this._responseTime)throw Error("Reinitialized");if(!e||e.v!==1)throw Error("Invalid serialization");this._responseTime=e.t,this._isShared=e.sh,this._cacheHeuristic=e.ch,this._immutableMinTtl=e.imm!==void 0?e.imm:24*3600*1e3,this._status=e.st,this._resHeaders=e.resh,this._rescc=e.rescc,this._method=e.m,this._url=e.u,this._host=e.h,this._noAuthorization=e.a,this._reqHeaders=e.reqh,this._reqcc=e.reqcc}toObject(){return{v:1,t:this._responseTime,sh:this._isShared,ch:this._cacheHeuristic,imm:this._immutableMinTtl,st:this._status,resh:this._resHeaders,rescc:this._rescc,m:this._method,u:this._url,h:this._host,a:this._noAuthorization,reqh:this._reqHeaders,reqcc:this._reqcc}}revalidationHeaders(e){this._assertRequestHasHeaders(e);let r=this._copyWithoutHopByHopHeaders(e.headers);if(delete r["if-range"],!this._requestMatches(e,!0)||!this.storable())return delete r["if-none-match"],delete r["if-modified-since"],r;if(this._resHeaders.etag&&(r["if-none-match"]=r["if-none-match"]?`${r["if-none-match"]}, ${this._resHeaders.etag}`:this._resHeaders.etag),r["accept-ranges"]||r["if-match"]||r["if-unmodified-since"]||this._method&&this._method!="GET"){if(delete r["if-modified-since"],r["if-none-match"]){let a=r["if-none-match"].split(/,/).filter(n=>!/^\s*W\//.test(n));a.length?r["if-none-match"]=a.join(",").trim():delete r["if-none-match"]}}else this._resHeaders["last-modified"]&&!r["if-modified-since"]&&(r["if-modified-since"]=this._resHeaders["last-modified"]);return r}revalidatedPolicy(e,r){if(this._assertRequestHasHeaders(e),this._useStaleIfError()&&knt(r))return{modified:!1,matches:!1,policy:this};if(!r||!r.headers)throw Error("Response headers missing");let o=!1;if(r.status!==void 0&&r.status!=304?o=!1:r.headers.etag&&!/^\s*W\//.test(r.headers.etag)?o=this._resHeaders.etag&&this._resHeaders.etag.replace(/^\s*W\//,"")===r.headers.etag:this._resHeaders.etag&&r.headers.etag?o=this._resHeaders.etag.replace(/^\s*W\//,"")===r.headers.etag.replace(/^\s*W\//,""):this._resHeaders["last-modified"]?o=this._resHeaders["last-modified"]===r.headers["last-modified"]:!this._resHeaders.etag&&!this._resHeaders["last-modified"]&&!r.headers.etag&&!r.headers["last-modified"]&&(o=!0),!o)return{policy:new this.constructor(e,r),modified:r.status!=304,matches:!1};let a={};for(let u in this._resHeaders)a[u]=u in r.headers&&!xnt[u]?r.headers[u]:this._resHeaders[u];let n=Object.assign({},r,{status:this._status,method:this._method,headers:a});return{policy:new this.constructor(e,n,{shared:this._isShared,cacheHeuristic:this._cacheHeuristic,immutableMinTimeToLive:this._immutableMinTtl}),modified:!1,matches:!0}}}});var jS=_((DLt,boe)=>{"use strict";boe.exports=t=>{let e={};for(let[r,o]of Object.entries(t))e[r.toLowerCase()]=o;return e}});var koe=_((PLt,xoe)=>{"use strict";var Fnt=ve("stream").Readable,Rnt=jS(),QO=class extends Fnt{constructor(e,r,o,a){if(typeof e!="number")throw new TypeError("Argument `statusCode` should be a number");if(typeof r!="object")throw new TypeError("Argument `headers` should be an object");if(!(o instanceof Buffer))throw new TypeError("Argument `body` should be a buffer");if(typeof a!="string")throw new TypeError("Argument `url` should be a string");super(),this.statusCode=e,this.headers=Rnt(r),this.body=o,this.url=a}_read(){this.push(this.body),this.push(null)}};xoe.exports=QO});var Foe=_((SLt,Qoe)=>{"use strict";var Tnt=["destroy","setTimeout","socket","headers","trailers","rawHeaders","statusCode","httpVersion","httpVersionMinor","httpVersionMajor","rawTrailers","statusMessage"];Qoe.exports=(t,e)=>{let r=new Set(Object.keys(t).concat(Tnt));for(let o of r)o in e||(e[o]=typeof t[o]=="function"?t[o].bind(t):t[o])}});var Toe=_((bLt,Roe)=>{"use strict";var Nnt=ve("stream").PassThrough,Lnt=Foe(),Mnt=t=>{if(!(t&&t.pipe))throw new TypeError("Parameter `response` must be a response stream.");let e=new Nnt;return Lnt(t,e),t.pipe(e)};Roe.exports=Mnt});var Noe=_(FO=>{FO.stringify=function t(e){if(typeof e>"u")return e;if(e&&Buffer.isBuffer(e))return JSON.stringify(":base64:"+e.toString("base64"));if(e&&e.toJSON&&(e=e.toJSON()),e&&typeof e=="object"){var r="",o=Array.isArray(e);r=o?"[":"{";var a=!0;for(var n in e){var u=typeof e[n]=="function"||!o&&typeof e[n]>"u";Object.hasOwnProperty.call(e,n)&&!u&&(a||(r+=","),a=!1,o?e[n]==null?r+="null":r+=t(e[n]):e[n]!==void 0&&(r+=t(n)+":"+t(e[n])))}return r+=o?"]":"}",r}else return typeof e=="string"?JSON.stringify(/^:/.test(e)?":"+e:e):typeof e>"u"?"null":JSON.stringify(e)};FO.parse=function(t){return JSON.parse(t,function(e,r){return typeof r=="string"?/^:base64:/.test(r)?Buffer.from(r.substring(8),"base64"):/^:/.test(r)?r.substring(1):r:r})}});var Uoe=_((kLt,Ooe)=>{"use strict";var Ont=ve("events"),Loe=Noe(),Unt=t=>{let e={redis:"@keyv/redis",rediss:"@keyv/redis",mongodb:"@keyv/mongo",mongo:"@keyv/mongo",sqlite:"@keyv/sqlite",postgresql:"@keyv/postgres",postgres:"@keyv/postgres",mysql:"@keyv/mysql",etcd:"@keyv/etcd",offline:"@keyv/offline",tiered:"@keyv/tiered"};if(t.adapter||t.uri){let r=t.adapter||/^[^:+]*/.exec(t.uri)[0];return new(ve(e[r]))(t)}return new Map},Moe=["sqlite","postgres","mysql","mongo","redis","tiered"],RO=class extends Ont{constructor(e,{emitErrors:r=!0,...o}={}){if(super(),this.opts={namespace:"keyv",serialize:Loe.stringify,deserialize:Loe.parse,...typeof e=="string"?{uri:e}:e,...o},!this.opts.store){let n={...this.opts};this.opts.store=Unt(n)}if(this.opts.compression){let n=this.opts.compression;this.opts.serialize=n.serialize.bind(n),this.opts.deserialize=n.deserialize.bind(n)}typeof this.opts.store.on=="function"&&r&&this.opts.store.on("error",n=>this.emit("error",n)),this.opts.store.namespace=this.opts.namespace;let a=n=>async function*(){for await(let[u,A]of typeof n=="function"?n(this.opts.store.namespace):n){let p=await this.opts.deserialize(A);if(!(this.opts.store.namespace&&!u.includes(this.opts.store.namespace))){if(typeof p.expires=="number"&&Date.now()>p.expires){this.delete(u);continue}yield[this._getKeyUnprefix(u),p.value]}}};typeof this.opts.store[Symbol.iterator]=="function"&&this.opts.store instanceof Map?this.iterator=a(this.opts.store):typeof this.opts.store.iterator=="function"&&this.opts.store.opts&&this._checkIterableAdaptar()&&(this.iterator=a(this.opts.store.iterator.bind(this.opts.store)))}_checkIterableAdaptar(){return Moe.includes(this.opts.store.opts.dialect)||Moe.findIndex(e=>this.opts.store.opts.url.includes(e))>=0}_getKeyPrefix(e){return`${this.opts.namespace}:${e}`}_getKeyPrefixArray(e){return e.map(r=>`${this.opts.namespace}:${r}`)}_getKeyUnprefix(e){return e.split(":").splice(1).join(":")}get(e,r){let{store:o}=this.opts,a=Array.isArray(e),n=a?this._getKeyPrefixArray(e):this._getKeyPrefix(e);if(a&&o.getMany===void 0){let u=[];for(let A of n)u.push(Promise.resolve().then(()=>o.get(A)).then(p=>typeof p=="string"?this.opts.deserialize(p):this.opts.compression?this.opts.deserialize(p):p).then(p=>{if(p!=null)return typeof p.expires=="number"&&Date.now()>p.expires?this.delete(A).then(()=>{}):r&&r.raw?p:p.value}));return Promise.allSettled(u).then(A=>{let p=[];for(let h of A)p.push(h.value);return p})}return Promise.resolve().then(()=>a?o.getMany(n):o.get(n)).then(u=>typeof u=="string"?this.opts.deserialize(u):this.opts.compression?this.opts.deserialize(u):u).then(u=>{if(u!=null)return a?u.map((A,p)=>{if(typeof A=="string"&&(A=this.opts.deserialize(A)),A!=null){if(typeof A.expires=="number"&&Date.now()>A.expires){this.delete(e[p]).then(()=>{});return}return r&&r.raw?A:A.value}}):typeof u.expires=="number"&&Date.now()>u.expires?this.delete(e).then(()=>{}):r&&r.raw?u:u.value})}set(e,r,o){let a=this._getKeyPrefix(e);typeof o>"u"&&(o=this.opts.ttl),o===0&&(o=void 0);let{store:n}=this.opts;return Promise.resolve().then(()=>{let u=typeof o=="number"?Date.now()+o:null;return typeof r=="symbol"&&this.emit("error","symbol cannot be serialized"),r={value:r,expires:u},this.opts.serialize(r)}).then(u=>n.set(a,u,o)).then(()=>!0)}delete(e){let{store:r}=this.opts;if(Array.isArray(e)){let a=this._getKeyPrefixArray(e);if(r.deleteMany===void 0){let n=[];for(let u of a)n.push(r.delete(u));return Promise.allSettled(n).then(u=>u.every(A=>A.value===!0))}return Promise.resolve().then(()=>r.deleteMany(a))}let o=this._getKeyPrefix(e);return Promise.resolve().then(()=>r.delete(o))}clear(){let{store:e}=this.opts;return Promise.resolve().then(()=>e.clear())}has(e){let r=this._getKeyPrefix(e),{store:o}=this.opts;return Promise.resolve().then(async()=>typeof o.has=="function"?o.has(r):await o.get(r)!==void 0)}disconnect(){let{store:e}=this.opts;if(typeof e.disconnect=="function")return e.disconnect()}};Ooe.exports=RO});var qoe=_((FLt,Hoe)=>{"use strict";var _nt=ve("events"),GS=ve("url"),Hnt=foe(),qnt=Doe(),TO=Soe(),_oe=koe(),jnt=jS(),Gnt=Toe(),Ynt=Uoe(),XI=class t{constructor(e,r){if(typeof e!="function")throw new TypeError("Parameter `request` must be a function");return this.cache=new Ynt({uri:typeof r=="string"&&r,store:typeof r!="string"&&r,namespace:"cacheable-request"}),this.createCacheableRequest(e)}createCacheableRequest(e){return(r,o)=>{let a;if(typeof r=="string")a=NO(GS.parse(r)),r={};else if(r instanceof GS.URL)a=NO(GS.parse(r.toString())),r={};else{let[I,...v]=(r.path||"").split("?"),x=v.length>0?`?${v.join("?")}`:"";a=NO({...r,pathname:I,search:x})}r={headers:{},method:"GET",cache:!0,strictTtl:!1,automaticFailover:!1,...r,...Wnt(a)},r.headers=jnt(r.headers);let n=new _nt,u=Hnt(GS.format(a),{stripWWW:!1,removeTrailingSlash:!1,stripAuthentication:!1}),A=`${r.method}:${u}`,p=!1,h=!1,E=I=>{h=!0;let v=!1,x,C=new Promise(L=>{x=()=>{v||(v=!0,L())}}),R=L=>{if(p&&!I.forceRefresh){L.status=L.statusCode;let z=TO.fromObject(p.cachePolicy).revalidatedPolicy(I,L);if(!z.modified){let te=z.policy.responseHeaders();L=new _oe(p.statusCode,te,p.body,p.url),L.cachePolicy=z.policy,L.fromCache=!0}}L.fromCache||(L.cachePolicy=new TO(I,L,I),L.fromCache=!1);let U;I.cache&&L.cachePolicy.storable()?(U=Gnt(L),(async()=>{try{let z=qnt.buffer(L);if(await Promise.race([C,new Promise(ce=>L.once("end",ce))]),v)return;let te=await z,ae={cachePolicy:L.cachePolicy.toObject(),url:L.url,statusCode:L.fromCache?p.statusCode:L.statusCode,body:te},le=I.strictTtl?L.cachePolicy.timeToLive():void 0;I.maxTtl&&(le=le?Math.min(le,I.maxTtl):I.maxTtl),await this.cache.set(A,ae,le)}catch(z){n.emit("error",new t.CacheError(z))}})()):I.cache&&p&&(async()=>{try{await this.cache.delete(A)}catch(z){n.emit("error",new t.CacheError(z))}})(),n.emit("response",U||L),typeof o=="function"&&o(U||L)};try{let L=e(I,R);L.once("error",x),L.once("abort",x),n.emit("request",L)}catch(L){n.emit("error",new t.RequestError(L))}};return(async()=>{let I=async x=>{await Promise.resolve();let C=x.cache?await this.cache.get(A):void 0;if(typeof C>"u")return E(x);let R=TO.fromObject(C.cachePolicy);if(R.satisfiesWithoutRevalidation(x)&&!x.forceRefresh){let L=R.responseHeaders(),U=new _oe(C.statusCode,L,C.body,C.url);U.cachePolicy=R,U.fromCache=!0,n.emit("response",U),typeof o=="function"&&o(U)}else p=C,x.headers=R.revalidationHeaders(x),E(x)},v=x=>n.emit("error",new t.CacheError(x));this.cache.once("error",v),n.on("response",()=>this.cache.removeListener("error",v));try{await I(r)}catch(x){r.automaticFailover&&!h&&E(r),n.emit("error",new t.CacheError(x))}})(),n}}};function Wnt(t){let e={...t};return e.path=`${t.pathname||"/"}${t.search||""}`,delete e.pathname,delete e.search,e}function NO(t){return{protocol:t.protocol,auth:t.auth,hostname:t.hostname||t.host||"localhost",port:t.port,pathname:t.pathname,search:t.search}}XI.RequestError=class extends Error{constructor(t){super(t.message),this.name="RequestError",Object.assign(this,t)}};XI.CacheError=class extends Error{constructor(t){super(t.message),this.name="CacheError",Object.assign(this,t)}};Hoe.exports=XI});var Goe=_((NLt,joe)=>{"use strict";var Knt=["aborted","complete","headers","httpVersion","httpVersionMinor","httpVersionMajor","method","rawHeaders","rawTrailers","setTimeout","socket","statusCode","statusMessage","trailers","url"];joe.exports=(t,e)=>{if(e._readableState.autoDestroy)throw new Error("The second stream must have the `autoDestroy` option set to `false`");let r=new Set(Object.keys(t).concat(Knt)),o={};for(let a of r)a in e||(o[a]={get(){let n=t[a];return typeof n=="function"?n.bind(t):n},set(n){t[a]=n},enumerable:!0,configurable:!1});return Object.defineProperties(e,o),t.once("aborted",()=>{e.destroy(),e.emit("aborted")}),t.once("close",()=>{t.complete&&e.readable?e.once("end",()=>{e.emit("close")}):e.emit("close")}),e}});var Woe=_((LLt,Yoe)=>{"use strict";var{Transform:Vnt,PassThrough:znt}=ve("stream"),LO=ve("zlib"),Jnt=Goe();Yoe.exports=t=>{let e=(t.headers["content-encoding"]||"").toLowerCase();if(!["gzip","deflate","br"].includes(e))return t;let r=e==="br";if(r&&typeof LO.createBrotliDecompress!="function")return t.destroy(new Error("Brotli is not supported on Node.js < 12")),t;let o=!0,a=new Vnt({transform(A,p,h){o=!1,h(null,A)},flush(A){A()}}),n=new znt({autoDestroy:!1,destroy(A,p){t.destroy(),p(A)}}),u=r?LO.createBrotliDecompress():LO.createUnzip();return u.once("error",A=>{if(o&&!t.readable){n.end();return}n.destroy(A)}),Jnt(t,n),t.pipe(a).pipe(u).pipe(n),n}});var OO=_((MLt,Koe)=>{"use strict";var MO=class{constructor(e={}){if(!(e.maxSize&&e.maxSize>0))throw new TypeError("`maxSize` must be a number greater than 0");this.maxSize=e.maxSize,this.onEviction=e.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_set(e,r){if(this.cache.set(e,r),this._size++,this._size>=this.maxSize){if(this._size=0,typeof this.onEviction=="function")for(let[o,a]of this.oldCache.entries())this.onEviction(o,a);this.oldCache=this.cache,this.cache=new Map}}get(e){if(this.cache.has(e))return this.cache.get(e);if(this.oldCache.has(e)){let r=this.oldCache.get(e);return this.oldCache.delete(e),this._set(e,r),r}}set(e,r){return this.cache.has(e)?this.cache.set(e,r):this._set(e,r),this}has(e){return this.cache.has(e)||this.oldCache.has(e)}peek(e){if(this.cache.has(e))return this.cache.get(e);if(this.oldCache.has(e))return this.oldCache.get(e)}delete(e){let r=this.cache.delete(e);return r&&this._size--,this.oldCache.delete(e)||r}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}*keys(){for(let[e]of this)yield e}*values(){for(let[,e]of this)yield e}*[Symbol.iterator](){for(let e of this.cache)yield e;for(let e of this.oldCache){let[r]=e;this.cache.has(r)||(yield e)}}get size(){let e=0;for(let r of this.oldCache.keys())this.cache.has(r)||e++;return Math.min(this._size+e,this.maxSize)}};Koe.exports=MO});var _O=_((OLt,Xoe)=>{"use strict";var Xnt=ve("events"),Znt=ve("tls"),$nt=ve("http2"),eit=OO(),ra=Symbol("currentStreamsCount"),Voe=Symbol("request"),Kl=Symbol("cachedOriginSet"),ty=Symbol("gracefullyClosing"),tit=["maxDeflateDynamicTableSize","maxSessionMemory","maxHeaderListPairs","maxOutstandingPings","maxReservedRemoteStreams","maxSendHeaderBlockLength","paddingStrategy","localAddress","path","rejectUnauthorized","minDHSize","ca","cert","clientCertEngine","ciphers","key","pfx","servername","minVersion","maxVersion","secureProtocol","crl","honorCipherOrder","ecdhCurve","dhparam","secureOptions","sessionIdContext"],rit=(t,e,r)=>{let o=0,a=t.length;for(;o<a;){let n=o+a>>>1;r(t[n],e)?o=n+1:a=n}return o},nit=(t,e)=>t.remoteSettings.maxConcurrentStreams>e.remoteSettings.maxConcurrentStreams,UO=(t,e)=>{for(let r of t)r[Kl].length<e[Kl].length&&r[Kl].every(o=>e[Kl].includes(o))&&r[ra]+e[ra]<=e.remoteSettings.maxConcurrentStreams&&Joe(r)},iit=(t,e)=>{for(let r of t)e[Kl].length<r[Kl].length&&e[Kl].every(o=>r[Kl].includes(o))&&e[ra]+r[ra]<=r.remoteSettings.maxConcurrentStreams&&Joe(e)},zoe=({agent:t,isFree:e})=>{let r={};for(let o in t.sessions){let n=t.sessions[o].filter(u=>{let A=u[Cg.kCurrentStreamsCount]<u.remoteSettings.maxConcurrentStreams;return e?A:!A});n.length!==0&&(r[o]=n)}return r},Joe=t=>{t[ty]=!0,t[ra]===0&&t.close()},Cg=class t extends Xnt{constructor({timeout:e=6e4,maxSessions:r=1/0,maxFreeSessions:o=10,maxCachedTlsSessions:a=100}={}){super(),this.sessions={},this.queue={},this.timeout=e,this.maxSessions=r,this.maxFreeSessions=o,this._freeSessionsCount=0,this._sessionsCount=0,this.settings={enablePush:!1},this.tlsSessionCache=new eit({maxSize:a})}static normalizeOrigin(e,r){return typeof e=="string"&&(e=new URL(e)),r&&e.hostname!==r&&(e.hostname=r),e.origin}normalizeOptions(e){let r="";if(e)for(let o of tit)e[o]&&(r+=`:${e[o]}`);return r}_tryToCreateNewSession(e,r){if(!(e in this.queue)||!(r in this.queue[e]))return;let o=this.queue[e][r];this._sessionsCount<this.maxSessions&&!o.completed&&(o.completed=!0,o())}getSession(e,r,o){return new Promise((a,n)=>{Array.isArray(o)?(o=[...o],a()):o=[{resolve:a,reject:n}];let u=this.normalizeOptions(r),A=t.normalizeOrigin(e,r&&r.servername);if(A===void 0){for(let{reject:E}of o)E(new TypeError("The `origin` argument needs to be a string or an URL object"));return}if(u in this.sessions){let E=this.sessions[u],I=-1,v=-1,x;for(let C of E){let R=C.remoteSettings.maxConcurrentStreams;if(R<I)break;if(C[Kl].includes(A)){let L=C[ra];if(L>=R||C[ty]||C.destroyed)continue;x||(I=R),L>v&&(x=C,v=L)}}if(x){if(o.length!==1){for(let{reject:C}of o){let R=new Error(`Expected the length of listeners to be 1, got ${o.length}. +Please report this to https://github.com/szmarczak/http2-wrapper/`);C(R)}return}o[0].resolve(x);return}}if(u in this.queue){if(A in this.queue[u]){this.queue[u][A].listeners.push(...o),this._tryToCreateNewSession(u,A);return}}else this.queue[u]={};let p=()=>{u in this.queue&&this.queue[u][A]===h&&(delete this.queue[u][A],Object.keys(this.queue[u]).length===0&&delete this.queue[u])},h=()=>{let E=`${A}:${u}`,I=!1;try{let v=$nt.connect(e,{createConnection:this.createConnection,settings:this.settings,session:this.tlsSessionCache.get(E),...r});v[ra]=0,v[ty]=!1;let x=()=>v[ra]<v.remoteSettings.maxConcurrentStreams,C=!0;v.socket.once("session",L=>{this.tlsSessionCache.set(E,L)}),v.once("error",L=>{for(let{reject:U}of o)U(L);this.tlsSessionCache.delete(E)}),v.setTimeout(this.timeout,()=>{v.destroy()}),v.once("close",()=>{if(I){C&&this._freeSessionsCount--,this._sessionsCount--;let L=this.sessions[u];L.splice(L.indexOf(v),1),L.length===0&&delete this.sessions[u]}else{let L=new Error("Session closed without receiving a SETTINGS frame");L.code="HTTP2WRAPPER_NOSETTINGS";for(let{reject:U}of o)U(L);p()}this._tryToCreateNewSession(u,A)});let R=()=>{if(!(!(u in this.queue)||!x())){for(let L of v[Kl])if(L in this.queue[u]){let{listeners:U}=this.queue[u][L];for(;U.length!==0&&x();)U.shift().resolve(v);let z=this.queue[u];if(z[L].listeners.length===0&&(delete z[L],Object.keys(z).length===0)){delete this.queue[u];break}if(!x())break}}};v.on("origin",()=>{v[Kl]=v.originSet,x()&&(R(),UO(this.sessions[u],v))}),v.once("remoteSettings",()=>{if(v.ref(),v.unref(),this._sessionsCount++,h.destroyed){let L=new Error("Agent has been destroyed");for(let U of o)U.reject(L);v.destroy();return}v[Kl]=v.originSet;{let L=this.sessions;if(u in L){let U=L[u];U.splice(rit(U,v,nit),0,v)}else L[u]=[v]}this._freeSessionsCount+=1,I=!0,this.emit("session",v),R(),p(),v[ra]===0&&this._freeSessionsCount>this.maxFreeSessions&&v.close(),o.length!==0&&(this.getSession(A,r,o),o.length=0),v.on("remoteSettings",()=>{R(),UO(this.sessions[u],v)})}),v[Voe]=v.request,v.request=(L,U)=>{if(v[ty])throw new Error("The session is gracefully closing. No new streams are allowed.");let z=v[Voe](L,U);return v.ref(),++v[ra],v[ra]===v.remoteSettings.maxConcurrentStreams&&this._freeSessionsCount--,z.once("close",()=>{if(C=x(),--v[ra],!v.destroyed&&!v.closed&&(iit(this.sessions[u],v),x()&&!v.closed)){C||(this._freeSessionsCount++,C=!0);let te=v[ra]===0;te&&v.unref(),te&&(this._freeSessionsCount>this.maxFreeSessions||v[ty])?v.close():(UO(this.sessions[u],v),R())}}),z}}catch(v){for(let x of o)x.reject(v);p()}};h.listeners=o,h.completed=!1,h.destroyed=!1,this.queue[u][A]=h,this._tryToCreateNewSession(u,A)})}request(e,r,o,a){return new Promise((n,u)=>{this.getSession(e,r,[{reject:u,resolve:A=>{try{n(A.request(o,a))}catch(p){u(p)}}}])})}createConnection(e,r){return t.connect(e,r)}static connect(e,r){r.ALPNProtocols=["h2"];let o=e.port||443,a=e.hostname||e.host;return typeof r.servername>"u"&&(r.servername=a),Znt.connect(o,a,r)}closeFreeSessions(){for(let e of Object.values(this.sessions))for(let r of e)r[ra]===0&&r.close()}destroy(e){for(let r of Object.values(this.sessions))for(let o of r)o.destroy(e);for(let r of Object.values(this.queue))for(let o of Object.values(r))o.destroyed=!0;this.queue={}}get freeSessions(){return zoe({agent:this,isFree:!0})}get busySessions(){return zoe({agent:this,isFree:!1})}};Cg.kCurrentStreamsCount=ra;Cg.kGracefullyClosing=ty;Xoe.exports={Agent:Cg,globalAgent:new Cg}});var qO=_((ULt,Zoe)=>{"use strict";var{Readable:sit}=ve("stream"),HO=class extends sit{constructor(e,r){super({highWaterMark:r,autoDestroy:!1}),this.statusCode=null,this.statusMessage="",this.httpVersion="2.0",this.httpVersionMajor=2,this.httpVersionMinor=0,this.headers={},this.trailers={},this.req=null,this.aborted=!1,this.complete=!1,this.upgrade=null,this.rawHeaders=[],this.rawTrailers=[],this.socket=e,this.connection=e,this._dumped=!1}_destroy(e){this.req._request.destroy(e)}setTimeout(e,r){return this.req.setTimeout(e,r),this}_dump(){this._dumped||(this._dumped=!0,this.removeAllListeners("data"),this.resume())}_read(){this.req&&this.req._request.resume()}};Zoe.exports=HO});var jO=_((_Lt,$oe)=>{"use strict";$oe.exports=t=>{let e={protocol:t.protocol,hostname:typeof t.hostname=="string"&&t.hostname.startsWith("[")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||""}${t.search||""}`};return typeof t.port=="string"&&t.port.length!==0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||""}:${t.password||""}`),e}});var tae=_((HLt,eae)=>{"use strict";eae.exports=(t,e,r)=>{for(let o of r)t.on(o,(...a)=>e.emit(o,...a))}});var nae=_((qLt,rae)=>{"use strict";rae.exports=t=>{switch(t){case":method":case":scheme":case":authority":case":path":return!0;default:return!1}}});var sae=_((GLt,iae)=>{"use strict";var ry=(t,e,r)=>{iae.exports[e]=class extends t{constructor(...a){super(typeof r=="string"?r:r(a)),this.name=`${super.name} [${e}]`,this.code=e}}};ry(TypeError,"ERR_INVALID_ARG_TYPE",t=>{let e=t[0].includes(".")?"property":"argument",r=t[1],o=Array.isArray(r);return o&&(r=`${r.slice(0,-1).join(", ")} or ${r.slice(-1)}`),`The "${t[0]}" ${e} must be ${o?"one of":"of"} type ${r}. Received ${typeof t[2]}`});ry(TypeError,"ERR_INVALID_PROTOCOL",t=>`Protocol "${t[0]}" not supported. Expected "${t[1]}"`);ry(Error,"ERR_HTTP_HEADERS_SENT",t=>`Cannot ${t[0]} headers after they are sent to the client`);ry(TypeError,"ERR_INVALID_HTTP_TOKEN",t=>`${t[0]} must be a valid HTTP token [${t[1]}]`);ry(TypeError,"ERR_HTTP_INVALID_HEADER_VALUE",t=>`Invalid value "${t[0]} for header "${t[1]}"`);ry(TypeError,"ERR_INVALID_CHAR",t=>`Invalid character in ${t[0]} [${t[1]}]`)});var VO=_((YLt,fae)=>{"use strict";var oit=ve("http2"),{Writable:ait}=ve("stream"),{Agent:oae,globalAgent:lit}=_O(),cit=qO(),uit=jO(),Ait=tae(),fit=nae(),{ERR_INVALID_ARG_TYPE:GO,ERR_INVALID_PROTOCOL:pit,ERR_HTTP_HEADERS_SENT:aae,ERR_INVALID_HTTP_TOKEN:hit,ERR_HTTP_INVALID_HEADER_VALUE:git,ERR_INVALID_CHAR:dit}=sae(),{HTTP2_HEADER_STATUS:lae,HTTP2_HEADER_METHOD:cae,HTTP2_HEADER_PATH:uae,HTTP2_METHOD_CONNECT:mit}=oit.constants,Qo=Symbol("headers"),YO=Symbol("origin"),WO=Symbol("session"),Aae=Symbol("options"),YS=Symbol("flushedHeaders"),ZI=Symbol("jobs"),yit=/^[\^`\-\w!#$%&*+.|~]+$/,Eit=/[^\t\u0020-\u007E\u0080-\u00FF]/,KO=class extends ait{constructor(e,r,o){super({autoDestroy:!1});let a=typeof e=="string"||e instanceof URL;if(a&&(e=uit(e instanceof URL?e:new URL(e))),typeof r=="function"||r===void 0?(o=r,r=a?e:{...e}):r={...e,...r},r.h2session)this[WO]=r.h2session;else if(r.agent===!1)this.agent=new oae({maxFreeSessions:0});else if(typeof r.agent>"u"||r.agent===null)typeof r.createConnection=="function"?(this.agent=new oae({maxFreeSessions:0}),this.agent.createConnection=r.createConnection):this.agent=lit;else if(typeof r.agent.request=="function")this.agent=r.agent;else throw new GO("options.agent",["Agent-like Object","undefined","false"],r.agent);if(r.protocol&&r.protocol!=="https:")throw new pit(r.protocol,"https:");let n=r.port||r.defaultPort||this.agent&&this.agent.defaultPort||443,u=r.hostname||r.host||"localhost";delete r.hostname,delete r.host,delete r.port;let{timeout:A}=r;if(r.timeout=void 0,this[Qo]=Object.create(null),this[ZI]=[],this.socket=null,this.connection=null,this.method=r.method||"GET",this.path=r.path,this.res=null,this.aborted=!1,this.reusedSocket=!1,r.headers)for(let[p,h]of Object.entries(r.headers))this.setHeader(p,h);r.auth&&!("authorization"in this[Qo])&&(this[Qo].authorization="Basic "+Buffer.from(r.auth).toString("base64")),r.session=r.tlsSession,r.path=r.socketPath,this[Aae]=r,n===443?(this[YO]=`https://${u}`,":authority"in this[Qo]||(this[Qo][":authority"]=u)):(this[YO]=`https://${u}:${n}`,":authority"in this[Qo]||(this[Qo][":authority"]=`${u}:${n}`)),A&&this.setTimeout(A),o&&this.once("response",o),this[YS]=!1}get method(){return this[Qo][cae]}set method(e){e&&(this[Qo][cae]=e.toUpperCase())}get path(){return this[Qo][uae]}set path(e){e&&(this[Qo][uae]=e)}get _mustNotHaveABody(){return this.method==="GET"||this.method==="HEAD"||this.method==="DELETE"}_write(e,r,o){if(this._mustNotHaveABody){o(new Error("The GET, HEAD and DELETE methods must NOT have a body"));return}this.flushHeaders();let a=()=>this._request.write(e,r,o);this._request?a():this[ZI].push(a)}_final(e){if(this.destroyed)return;this.flushHeaders();let r=()=>{if(this._mustNotHaveABody){e();return}this._request.end(e)};this._request?r():this[ZI].push(r)}abort(){this.res&&this.res.complete||(this.aborted||process.nextTick(()=>this.emit("abort")),this.aborted=!0,this.destroy())}_destroy(e,r){this.res&&this.res._dump(),this._request&&this._request.destroy(),r(e)}async flushHeaders(){if(this[YS]||this.destroyed)return;this[YS]=!0;let e=this.method===mit,r=o=>{if(this._request=o,this.destroyed){o.destroy();return}e||Ait(o,this,["timeout","continue","close","error"]);let a=u=>(...A)=>{!this.writable&&!this.destroyed?u(...A):this.once("finish",()=>{u(...A)})};o.once("response",a((u,A,p)=>{let h=new cit(this.socket,o.readableHighWaterMark);this.res=h,h.req=this,h.statusCode=u[lae],h.headers=u,h.rawHeaders=p,h.once("end",()=>{this.aborted?(h.aborted=!0,h.emit("aborted")):(h.complete=!0,h.socket=null,h.connection=null)}),e?(h.upgrade=!0,this.emit("connect",h,o,Buffer.alloc(0))?this.emit("close"):o.destroy()):(o.on("data",E=>{!h._dumped&&!h.push(E)&&o.pause()}),o.once("end",()=>{h.push(null)}),this.emit("response",h)||h._dump())})),o.once("headers",a(u=>this.emit("information",{statusCode:u[lae]}))),o.once("trailers",a((u,A,p)=>{let{res:h}=this;h.trailers=u,h.rawTrailers=p}));let{socket:n}=o.session;this.socket=n,this.connection=n;for(let u of this[ZI])u();this.emit("socket",this.socket)};if(this[WO])try{r(this[WO].request(this[Qo]))}catch(o){this.emit("error",o)}else{this.reusedSocket=!0;try{r(await this.agent.request(this[YO],this[Aae],this[Qo]))}catch(o){this.emit("error",o)}}}getHeader(e){if(typeof e!="string")throw new GO("name","string",e);return this[Qo][e.toLowerCase()]}get headersSent(){return this[YS]}removeHeader(e){if(typeof e!="string")throw new GO("name","string",e);if(this.headersSent)throw new aae("remove");delete this[Qo][e.toLowerCase()]}setHeader(e,r){if(this.headersSent)throw new aae("set");if(typeof e!="string"||!yit.test(e)&&!fit(e))throw new hit("Header name",e);if(typeof r>"u")throw new git(r,e);if(Eit.test(r))throw new dit("header content",e);this[Qo][e.toLowerCase()]=r}setNoDelay(){}setSocketKeepAlive(){}setTimeout(e,r){let o=()=>this._request.setTimeout(e,r);return this._request?o():this[ZI].push(o),this}get maxHeadersCount(){if(!this.destroyed&&this._request)return this._request.session.localSettings.maxHeaderListSize}set maxHeadersCount(e){}};fae.exports=KO});var hae=_((WLt,pae)=>{"use strict";var Cit=ve("tls");pae.exports=(t={},e=Cit.connect)=>new Promise((r,o)=>{let a=!1,n,u=async()=>{await p,n.off("timeout",A),n.off("error",o),t.resolveSocket?(r({alpnProtocol:n.alpnProtocol,socket:n,timeout:a}),a&&(await Promise.resolve(),n.emit("timeout"))):(n.destroy(),r({alpnProtocol:n.alpnProtocol,timeout:a}))},A=async()=>{a=!0,u()},p=(async()=>{try{n=await e(t,u),n.on("error",o),n.once("timeout",A)}catch(h){o(h)}})()})});var dae=_((KLt,gae)=>{"use strict";var wit=ve("net");gae.exports=t=>{let e=t.host,r=t.headers&&t.headers.host;return r&&(r.startsWith("[")?r.indexOf("]")===-1?e=r:e=r.slice(1,-1):e=r.split(":",1)[0]),wit.isIP(e)?"":e}});var Eae=_((VLt,JO)=>{"use strict";var mae=ve("http"),zO=ve("https"),Iit=hae(),Bit=OO(),vit=VO(),Dit=dae(),Pit=jO(),WS=new Bit({maxSize:100}),$I=new Map,yae=(t,e,r)=>{e._httpMessage={shouldKeepAlive:!0};let o=()=>{t.emit("free",e,r)};e.on("free",o);let a=()=>{t.removeSocket(e,r)};e.on("close",a);let n=()=>{t.removeSocket(e,r),e.off("close",a),e.off("free",o),e.off("agentRemove",n)};e.on("agentRemove",n),t.emit("free",e,r)},Sit=async t=>{let e=`${t.host}:${t.port}:${t.ALPNProtocols.sort()}`;if(!WS.has(e)){if($I.has(e))return(await $I.get(e)).alpnProtocol;let{path:r,agent:o}=t;t.path=t.socketPath;let a=Iit(t);$I.set(e,a);try{let{socket:n,alpnProtocol:u}=await a;if(WS.set(e,u),t.path=r,u==="h2")n.destroy();else{let{globalAgent:A}=zO,p=zO.Agent.prototype.createConnection;o?o.createConnection===p?yae(o,n,t):n.destroy():A.createConnection===p?yae(A,n,t):n.destroy()}return $I.delete(e),u}catch(n){throw $I.delete(e),n}}return WS.get(e)};JO.exports=async(t,e,r)=>{if((typeof t=="string"||t instanceof URL)&&(t=Pit(new URL(t))),typeof e=="function"&&(r=e,e=void 0),e={ALPNProtocols:["h2","http/1.1"],...t,...e,resolveSocket:!0},!Array.isArray(e.ALPNProtocols)||e.ALPNProtocols.length===0)throw new Error("The `ALPNProtocols` option must be an Array with at least one entry");e.protocol=e.protocol||"https:";let o=e.protocol==="https:";e.host=e.hostname||e.host||"localhost",e.session=e.tlsSession,e.servername=e.servername||Dit(e),e.port=e.port||(o?443:80),e._defaultAgent=o?zO.globalAgent:mae.globalAgent;let a=e.agent;if(a){if(a.addRequest)throw new Error("The `options.agent` object can contain only `http`, `https` or `http2` properties");e.agent=a[o?"https":"http"]}return o&&await Sit(e)==="h2"?(a&&(e.agent=a.http2),new vit(e,r)):mae.request(e,r)};JO.exports.protocolCache=WS});var wae=_((zLt,Cae)=>{"use strict";var bit=ve("http2"),xit=_O(),XO=VO(),kit=qO(),Qit=Eae(),Fit=(t,e,r)=>new XO(t,e,r),Rit=(t,e,r)=>{let o=new XO(t,e,r);return o.end(),o};Cae.exports={...bit,ClientRequest:XO,IncomingMessage:kit,...xit,request:Fit,get:Rit,auto:Qit}});var $O=_(ZO=>{"use strict";Object.defineProperty(ZO,"__esModule",{value:!0});var Iae=Qf();ZO.default=t=>Iae.default.nodeStream(t)&&Iae.default.function_(t.getBoundary)});var Pae=_(e4=>{"use strict";Object.defineProperty(e4,"__esModule",{value:!0});var vae=ve("fs"),Dae=ve("util"),Bae=Qf(),Tit=$O(),Nit=Dae.promisify(vae.stat);e4.default=async(t,e)=>{if(e&&"content-length"in e)return Number(e["content-length"]);if(!t)return 0;if(Bae.default.string(t))return Buffer.byteLength(t);if(Bae.default.buffer(t))return t.length;if(Tit.default(t))return Dae.promisify(t.getLength.bind(t))();if(t instanceof vae.ReadStream){let{size:r}=await Nit(t.path);return r===0?void 0:r}}});var r4=_(t4=>{"use strict";Object.defineProperty(t4,"__esModule",{value:!0});function Lit(t,e,r){let o={};for(let a of r)o[a]=(...n)=>{e.emit(a,...n)},t.on(a,o[a]);return()=>{for(let a of r)t.off(a,o[a])}}t4.default=Lit});var Sae=_(n4=>{"use strict";Object.defineProperty(n4,"__esModule",{value:!0});n4.default=()=>{let t=[];return{once(e,r,o){e.once(r,o),t.push({origin:e,event:r,fn:o})},unhandleAll(){for(let e of t){let{origin:r,event:o,fn:a}=e;r.removeListener(o,a)}t.length=0}}}});var xae=_(e1=>{"use strict";Object.defineProperty(e1,"__esModule",{value:!0});e1.TimeoutError=void 0;var Mit=ve("net"),Oit=Sae(),bae=Symbol("reentry"),Uit=()=>{},KS=class extends Error{constructor(e,r){super(`Timeout awaiting '${r}' for ${e}ms`),this.event=r,this.name="TimeoutError",this.code="ETIMEDOUT"}};e1.TimeoutError=KS;e1.default=(t,e,r)=>{if(bae in t)return Uit;t[bae]=!0;let o=[],{once:a,unhandleAll:n}=Oit.default(),u=(I,v,x)=>{var C;let R=setTimeout(v,I,I,x);(C=R.unref)===null||C===void 0||C.call(R);let L=()=>{clearTimeout(R)};return o.push(L),L},{host:A,hostname:p}=r,h=(I,v)=>{t.destroy(new KS(I,v))},E=()=>{for(let I of o)I();n()};if(t.once("error",I=>{if(E(),t.listenerCount("error")===0)throw I}),t.once("close",E),a(t,"response",I=>{a(I,"end",E)}),typeof e.request<"u"&&u(e.request,h,"request"),typeof e.socket<"u"){let I=()=>{h(e.socket,"socket")};t.setTimeout(e.socket,I),o.push(()=>{t.removeListener("timeout",I)})}return a(t,"socket",I=>{var v;let{socketPath:x}=t;if(I.connecting){let C=!!(x??Mit.isIP((v=p??A)!==null&&v!==void 0?v:"")!==0);if(typeof e.lookup<"u"&&!C&&typeof I.address().address>"u"){let R=u(e.lookup,h,"lookup");a(I,"lookup",R)}if(typeof e.connect<"u"){let R=()=>u(e.connect,h,"connect");C?a(I,"connect",R()):a(I,"lookup",L=>{L===null&&a(I,"connect",R())})}typeof e.secureConnect<"u"&&r.protocol==="https:"&&a(I,"connect",()=>{let R=u(e.secureConnect,h,"secureConnect");a(I,"secureConnect",R)})}if(typeof e.send<"u"){let C=()=>u(e.send,h,"send");I.connecting?a(I,"connect",()=>{a(t,"upload-complete",C())}):a(t,"upload-complete",C())}}),typeof e.response<"u"&&a(t,"upload-complete",()=>{let I=u(e.response,h,"response");a(t,"response",I)}),E}});var Qae=_(i4=>{"use strict";Object.defineProperty(i4,"__esModule",{value:!0});var kae=Qf();i4.default=t=>{t=t;let e={protocol:t.protocol,hostname:kae.default.string(t.hostname)&&t.hostname.startsWith("[")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||""}${t.search||""}`};return kae.default.string(t.port)&&t.port.length>0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||""}:${t.password||""}`),e}});var Fae=_(s4=>{"use strict";Object.defineProperty(s4,"__esModule",{value:!0});var _it=ve("url"),Hit=["protocol","host","hostname","port","pathname","search"];s4.default=(t,e)=>{var r,o;if(e.path){if(e.pathname)throw new TypeError("Parameters `path` and `pathname` are mutually exclusive.");if(e.search)throw new TypeError("Parameters `path` and `search` are mutually exclusive.");if(e.searchParams)throw new TypeError("Parameters `path` and `searchParams` are mutually exclusive.")}if(e.search&&e.searchParams)throw new TypeError("Parameters `search` and `searchParams` are mutually exclusive.");if(!t){if(!e.protocol)throw new TypeError("No URL protocol specified");t=`${e.protocol}//${(o=(r=e.hostname)!==null&&r!==void 0?r:e.host)!==null&&o!==void 0?o:""}`}let a=new _it.URL(t);if(e.path){let n=e.path.indexOf("?");n===-1?e.pathname=e.path:(e.pathname=e.path.slice(0,n),e.search=e.path.slice(n+1)),delete e.path}for(let n of Hit)e[n]&&(a[n]=e[n].toString());return a}});var Rae=_(a4=>{"use strict";Object.defineProperty(a4,"__esModule",{value:!0});var o4=class{constructor(){this.weakMap=new WeakMap,this.map=new Map}set(e,r){typeof e=="object"?this.weakMap.set(e,r):this.map.set(e,r)}get(e){return typeof e=="object"?this.weakMap.get(e):this.map.get(e)}has(e){return typeof e=="object"?this.weakMap.has(e):this.map.has(e)}};a4.default=o4});var c4=_(l4=>{"use strict";Object.defineProperty(l4,"__esModule",{value:!0});var qit=async t=>{let e=[],r=0;for await(let o of t)e.push(o),r+=Buffer.byteLength(o);return Buffer.isBuffer(e[0])?Buffer.concat(e,r):Buffer.from(e.join(""))};l4.default=qit});var Nae=_(wg=>{"use strict";Object.defineProperty(wg,"__esModule",{value:!0});wg.dnsLookupIpVersionToFamily=wg.isDnsLookupIpVersion=void 0;var Tae={auto:0,ipv4:4,ipv6:6};wg.isDnsLookupIpVersion=t=>t in Tae;wg.dnsLookupIpVersionToFamily=t=>{if(wg.isDnsLookupIpVersion(t))return Tae[t];throw new Error("Invalid DNS lookup IP version")}});var u4=_(VS=>{"use strict";Object.defineProperty(VS,"__esModule",{value:!0});VS.isResponseOk=void 0;VS.isResponseOk=t=>{let{statusCode:e}=t,r=t.request.options.followRedirect?299:399;return e>=200&&e<=r||e===304}});var Mae=_(A4=>{"use strict";Object.defineProperty(A4,"__esModule",{value:!0});var Lae=new Set;A4.default=t=>{Lae.has(t)||(Lae.add(t),process.emitWarning(`Got: ${t}`,{type:"DeprecationWarning"}))}});var Oae=_(f4=>{"use strict";Object.defineProperty(f4,"__esModule",{value:!0});var Ai=Qf(),jit=(t,e)=>{if(Ai.default.null_(t.encoding))throw new TypeError("To get a Buffer, set `options.responseType` to `buffer` instead");Ai.assert.any([Ai.default.string,Ai.default.undefined],t.encoding),Ai.assert.any([Ai.default.boolean,Ai.default.undefined],t.resolveBodyOnly),Ai.assert.any([Ai.default.boolean,Ai.default.undefined],t.methodRewriting),Ai.assert.any([Ai.default.boolean,Ai.default.undefined],t.isStream),Ai.assert.any([Ai.default.string,Ai.default.undefined],t.responseType),t.responseType===void 0&&(t.responseType="text");let{retry:r}=t;if(e?t.retry={...e.retry}:t.retry={calculateDelay:o=>o.computedValue,limit:0,methods:[],statusCodes:[],errorCodes:[],maxRetryAfter:void 0},Ai.default.object(r)?(t.retry={...t.retry,...r},t.retry.methods=[...new Set(t.retry.methods.map(o=>o.toUpperCase()))],t.retry.statusCodes=[...new Set(t.retry.statusCodes)],t.retry.errorCodes=[...new Set(t.retry.errorCodes)]):Ai.default.number(r)&&(t.retry.limit=r),Ai.default.undefined(t.retry.maxRetryAfter)&&(t.retry.maxRetryAfter=Math.min(...[t.timeout.request,t.timeout.connect].filter(Ai.default.number))),Ai.default.object(t.pagination)){e&&(t.pagination={...e.pagination,...t.pagination});let{pagination:o}=t;if(!Ai.default.function_(o.transform))throw new Error("`options.pagination.transform` must be implemented");if(!Ai.default.function_(o.shouldContinue))throw new Error("`options.pagination.shouldContinue` must be implemented");if(!Ai.default.function_(o.filter))throw new TypeError("`options.pagination.filter` must be implemented");if(!Ai.default.function_(o.paginate))throw new Error("`options.pagination.paginate` must be implemented")}return t.responseType==="json"&&t.headers.accept===void 0&&(t.headers.accept="application/json"),t};f4.default=jit});var Uae=_(t1=>{"use strict";Object.defineProperty(t1,"__esModule",{value:!0});t1.retryAfterStatusCodes=void 0;t1.retryAfterStatusCodes=new Set([413,429,503]);var Git=({attemptCount:t,retryOptions:e,error:r,retryAfter:o})=>{if(t>e.limit)return 0;let a=e.methods.includes(r.options.method),n=e.errorCodes.includes(r.code),u=r.response&&e.statusCodes.includes(r.response.statusCode);if(!a||!n&&!u)return 0;if(r.response){if(o)return e.maxRetryAfter===void 0||o>e.maxRetryAfter?0:o;if(r.response.statusCode===413)return 0}let A=Math.random()*100;return 2**(t-1)*1e3+A};t1.default=Git});var i1=_(Bn=>{"use strict";Object.defineProperty(Bn,"__esModule",{value:!0});Bn.UnsupportedProtocolError=Bn.ReadError=Bn.TimeoutError=Bn.UploadError=Bn.CacheError=Bn.HTTPError=Bn.MaxRedirectsError=Bn.RequestError=Bn.setNonEnumerableProperties=Bn.knownHookEvents=Bn.withoutBody=Bn.kIsNormalizedAlready=void 0;var _ae=ve("util"),Hae=ve("stream"),Yit=ve("fs"),sh=ve("url"),qae=ve("http"),p4=ve("http"),Wit=ve("https"),Kit=roe(),Vit=coe(),jae=qoe(),zit=Woe(),Jit=wae(),Xit=jS(),ot=Qf(),Zit=Pae(),Gae=$O(),$it=r4(),Yae=xae(),est=Qae(),Wae=Fae(),tst=Rae(),rst=c4(),Kae=Nae(),nst=u4(),oh=Mae(),ist=Oae(),sst=Uae(),h4,$s=Symbol("request"),XS=Symbol("response"),ny=Symbol("responseSize"),iy=Symbol("downloadedSize"),sy=Symbol("bodySize"),oy=Symbol("uploadedSize"),zS=Symbol("serverResponsesPiped"),Vae=Symbol("unproxyEvents"),zae=Symbol("isFromCache"),g4=Symbol("cancelTimeouts"),Jae=Symbol("startedReading"),ay=Symbol("stopReading"),JS=Symbol("triggerRead"),ah=Symbol("body"),r1=Symbol("jobs"),Xae=Symbol("originalResponse"),Zae=Symbol("retryTimeout");Bn.kIsNormalizedAlready=Symbol("isNormalizedAlready");var ost=ot.default.string(process.versions.brotli);Bn.withoutBody=new Set(["GET","HEAD"]);Bn.knownHookEvents=["init","beforeRequest","beforeRedirect","beforeError","beforeRetry","afterResponse"];function ast(t){for(let e in t){let r=t[e];if(!ot.default.string(r)&&!ot.default.number(r)&&!ot.default.boolean(r)&&!ot.default.null_(r)&&!ot.default.undefined(r))throw new TypeError(`The \`searchParams\` value '${String(r)}' must be a string, number, boolean or null`)}}function lst(t){return ot.default.object(t)&&!("statusCode"in t)}var d4=new tst.default,cst=async t=>new Promise((e,r)=>{let o=a=>{r(a)};t.pending||e(),t.once("error",o),t.once("ready",()=>{t.off("error",o),e()})}),ust=new Set([300,301,302,303,304,307,308]),Ast=["context","body","json","form"];Bn.setNonEnumerableProperties=(t,e)=>{let r={};for(let o of t)if(o)for(let a of Ast)a in o&&(r[a]={writable:!0,configurable:!0,enumerable:!1,value:o[a]});Object.defineProperties(e,r)};var Ji=class extends Error{constructor(e,r,o){var a;if(super(e),Error.captureStackTrace(this,this.constructor),this.name="RequestError",this.code=r.code,o instanceof ib?(Object.defineProperty(this,"request",{enumerable:!1,value:o}),Object.defineProperty(this,"response",{enumerable:!1,value:o[XS]}),Object.defineProperty(this,"options",{enumerable:!1,value:o.options})):Object.defineProperty(this,"options",{enumerable:!1,value:o}),this.timings=(a=this.request)===null||a===void 0?void 0:a.timings,ot.default.string(r.stack)&&ot.default.string(this.stack)){let n=this.stack.indexOf(this.message)+this.message.length,u=this.stack.slice(n).split(` +`).reverse(),A=r.stack.slice(r.stack.indexOf(r.message)+r.message.length).split(` +`).reverse();for(;A.length!==0&&A[0]===u[0];)u.shift();this.stack=`${this.stack.slice(0,n)}${u.reverse().join(` +`)}${A.reverse().join(` +`)}`}}};Bn.RequestError=Ji;var ZS=class extends Ji{constructor(e){super(`Redirected ${e.options.maxRedirects} times. Aborting.`,{},e),this.name="MaxRedirectsError"}};Bn.MaxRedirectsError=ZS;var $S=class extends Ji{constructor(e){super(`Response code ${e.statusCode} (${e.statusMessage})`,{},e.request),this.name="HTTPError"}};Bn.HTTPError=$S;var eb=class extends Ji{constructor(e,r){super(e.message,e,r),this.name="CacheError"}};Bn.CacheError=eb;var tb=class extends Ji{constructor(e,r){super(e.message,e,r),this.name="UploadError"}};Bn.UploadError=tb;var rb=class extends Ji{constructor(e,r,o){super(e.message,e,o),this.name="TimeoutError",this.event=e.event,this.timings=r}};Bn.TimeoutError=rb;var n1=class extends Ji{constructor(e,r){super(e.message,e,r),this.name="ReadError"}};Bn.ReadError=n1;var nb=class extends Ji{constructor(e){super(`Unsupported protocol "${e.url.protocol}"`,{},e),this.name="UnsupportedProtocolError"}};Bn.UnsupportedProtocolError=nb;var fst=["socket","connect","continue","information","upgrade","timeout"],ib=class extends Hae.Duplex{constructor(e,r={},o){super({autoDestroy:!1,highWaterMark:0}),this[iy]=0,this[oy]=0,this.requestInitialized=!1,this[zS]=new Set,this.redirects=[],this[ay]=!1,this[JS]=!1,this[r1]=[],this.retryCount=0,this._progressCallbacks=[];let a=()=>this._unlockWrite(),n=()=>this._lockWrite();this.on("pipe",h=>{h.prependListener("data",a),h.on("data",n),h.prependListener("end",a),h.on("end",n)}),this.on("unpipe",h=>{h.off("data",a),h.off("data",n),h.off("end",a),h.off("end",n)}),this.on("pipe",h=>{h instanceof p4.IncomingMessage&&(this.options.headers={...h.headers,...this.options.headers})});let{json:u,body:A,form:p}=r;if((u||A||p)&&this._lockWrite(),Bn.kIsNormalizedAlready in r)this.options=r;else try{this.options=this.constructor.normalizeArguments(e,r,o)}catch(h){ot.default.nodeStream(r.body)&&r.body.destroy(),this.destroy(h);return}(async()=>{var h;try{this.options.body instanceof Yit.ReadStream&&await cst(this.options.body);let{url:E}=this.options;if(!E)throw new TypeError("Missing `url` property");if(this.requestUrl=E.toString(),decodeURI(this.requestUrl),await this._finalizeBody(),await this._makeRequest(),this.destroyed){(h=this[$s])===null||h===void 0||h.destroy();return}for(let I of this[r1])I();this[r1].length=0,this.requestInitialized=!0}catch(E){if(E instanceof Ji){this._beforeError(E);return}this.destroyed||this.destroy(E)}})()}static normalizeArguments(e,r,o){var a,n,u,A,p;let h=r;if(ot.default.object(e)&&!ot.default.urlInstance(e))r={...o,...e,...r};else{if(e&&r&&r.url!==void 0)throw new TypeError("The `url` option is mutually exclusive with the `input` argument");r={...o,...r},e!==void 0&&(r.url=e),ot.default.urlInstance(r.url)&&(r.url=new sh.URL(r.url.toString()))}if(r.cache===!1&&(r.cache=void 0),r.dnsCache===!1&&(r.dnsCache=void 0),ot.assert.any([ot.default.string,ot.default.undefined],r.method),ot.assert.any([ot.default.object,ot.default.undefined],r.headers),ot.assert.any([ot.default.string,ot.default.urlInstance,ot.default.undefined],r.prefixUrl),ot.assert.any([ot.default.object,ot.default.undefined],r.cookieJar),ot.assert.any([ot.default.object,ot.default.string,ot.default.undefined],r.searchParams),ot.assert.any([ot.default.object,ot.default.string,ot.default.undefined],r.cache),ot.assert.any([ot.default.object,ot.default.number,ot.default.undefined],r.timeout),ot.assert.any([ot.default.object,ot.default.undefined],r.context),ot.assert.any([ot.default.object,ot.default.undefined],r.hooks),ot.assert.any([ot.default.boolean,ot.default.undefined],r.decompress),ot.assert.any([ot.default.boolean,ot.default.undefined],r.ignoreInvalidCookies),ot.assert.any([ot.default.boolean,ot.default.undefined],r.followRedirect),ot.assert.any([ot.default.number,ot.default.undefined],r.maxRedirects),ot.assert.any([ot.default.boolean,ot.default.undefined],r.throwHttpErrors),ot.assert.any([ot.default.boolean,ot.default.undefined],r.http2),ot.assert.any([ot.default.boolean,ot.default.undefined],r.allowGetBody),ot.assert.any([ot.default.string,ot.default.undefined],r.localAddress),ot.assert.any([Kae.isDnsLookupIpVersion,ot.default.undefined],r.dnsLookupIpVersion),ot.assert.any([ot.default.object,ot.default.undefined],r.https),ot.assert.any([ot.default.boolean,ot.default.undefined],r.rejectUnauthorized),r.https&&(ot.assert.any([ot.default.boolean,ot.default.undefined],r.https.rejectUnauthorized),ot.assert.any([ot.default.function_,ot.default.undefined],r.https.checkServerIdentity),ot.assert.any([ot.default.string,ot.default.object,ot.default.array,ot.default.undefined],r.https.certificateAuthority),ot.assert.any([ot.default.string,ot.default.object,ot.default.array,ot.default.undefined],r.https.key),ot.assert.any([ot.default.string,ot.default.object,ot.default.array,ot.default.undefined],r.https.certificate),ot.assert.any([ot.default.string,ot.default.undefined],r.https.passphrase),ot.assert.any([ot.default.string,ot.default.buffer,ot.default.array,ot.default.undefined],r.https.pfx)),ot.assert.any([ot.default.object,ot.default.undefined],r.cacheOptions),ot.default.string(r.method)?r.method=r.method.toUpperCase():r.method="GET",r.headers===o?.headers?r.headers={...r.headers}:r.headers=Xit({...o?.headers,...r.headers}),"slashes"in r)throw new TypeError("The legacy `url.Url` has been deprecated. Use `URL` instead.");if("auth"in r)throw new TypeError("Parameter `auth` is deprecated. Use `username` / `password` instead.");if("searchParams"in r&&r.searchParams&&r.searchParams!==o?.searchParams){let x;if(ot.default.string(r.searchParams)||r.searchParams instanceof sh.URLSearchParams)x=new sh.URLSearchParams(r.searchParams);else{ast(r.searchParams),x=new sh.URLSearchParams;for(let C in r.searchParams){let R=r.searchParams[C];R===null?x.append(C,""):R!==void 0&&x.append(C,R)}}(a=o?.searchParams)===null||a===void 0||a.forEach((C,R)=>{x.has(R)||x.append(R,C)}),r.searchParams=x}if(r.username=(n=r.username)!==null&&n!==void 0?n:"",r.password=(u=r.password)!==null&&u!==void 0?u:"",ot.default.undefined(r.prefixUrl)?r.prefixUrl=(A=o?.prefixUrl)!==null&&A!==void 0?A:"":(r.prefixUrl=r.prefixUrl.toString(),r.prefixUrl!==""&&!r.prefixUrl.endsWith("/")&&(r.prefixUrl+="/")),ot.default.string(r.url)){if(r.url.startsWith("/"))throw new Error("`input` must not start with a slash when using `prefixUrl`");r.url=Wae.default(r.prefixUrl+r.url,r)}else(ot.default.undefined(r.url)&&r.prefixUrl!==""||r.protocol)&&(r.url=Wae.default(r.prefixUrl,r));if(r.url){"port"in r&&delete r.port;let{prefixUrl:x}=r;Object.defineProperty(r,"prefixUrl",{set:R=>{let L=r.url;if(!L.href.startsWith(R))throw new Error(`Cannot change \`prefixUrl\` from ${x} to ${R}: ${L.href}`);r.url=new sh.URL(R+L.href.slice(x.length)),x=R},get:()=>x});let{protocol:C}=r.url;if(C==="unix:"&&(C="http:",r.url=new sh.URL(`http://unix${r.url.pathname}${r.url.search}`)),r.searchParams&&(r.url.search=r.searchParams.toString()),C!=="http:"&&C!=="https:")throw new nb(r);r.username===""?r.username=r.url.username:r.url.username=r.username,r.password===""?r.password=r.url.password:r.url.password=r.password}let{cookieJar:E}=r;if(E){let{setCookie:x,getCookieString:C}=E;ot.assert.function_(x),ot.assert.function_(C),x.length===4&&C.length===0&&(x=_ae.promisify(x.bind(r.cookieJar)),C=_ae.promisify(C.bind(r.cookieJar)),r.cookieJar={setCookie:x,getCookieString:C})}let{cache:I}=r;if(I&&(d4.has(I)||d4.set(I,new jae((x,C)=>{let R=x[$s](x,C);return ot.default.promise(R)&&(R.once=(L,U)=>{if(L==="error")R.catch(U);else if(L==="abort")(async()=>{try{(await R).once("abort",U)}catch{}})();else throw new Error(`Unknown HTTP2 promise event: ${L}`);return R}),R},I))),r.cacheOptions={...r.cacheOptions},r.dnsCache===!0)h4||(h4=new Vit.default),r.dnsCache=h4;else if(!ot.default.undefined(r.dnsCache)&&!r.dnsCache.lookup)throw new TypeError(`Parameter \`dnsCache\` must be a CacheableLookup instance or a boolean, got ${ot.default(r.dnsCache)}`);ot.default.number(r.timeout)?r.timeout={request:r.timeout}:o&&r.timeout!==o.timeout?r.timeout={...o.timeout,...r.timeout}:r.timeout={...r.timeout},r.context||(r.context={});let v=r.hooks===o?.hooks;r.hooks={...r.hooks};for(let x of Bn.knownHookEvents)if(x in r.hooks)if(ot.default.array(r.hooks[x]))r.hooks[x]=[...r.hooks[x]];else throw new TypeError(`Parameter \`${x}\` must be an Array, got ${ot.default(r.hooks[x])}`);else r.hooks[x]=[];if(o&&!v)for(let x of Bn.knownHookEvents)o.hooks[x].length>0&&(r.hooks[x]=[...o.hooks[x],...r.hooks[x]]);if("family"in r&&oh.default('"options.family" was never documented, please use "options.dnsLookupIpVersion"'),o?.https&&(r.https={...o.https,...r.https}),"rejectUnauthorized"in r&&oh.default('"options.rejectUnauthorized" is now deprecated, please use "options.https.rejectUnauthorized"'),"checkServerIdentity"in r&&oh.default('"options.checkServerIdentity" was never documented, please use "options.https.checkServerIdentity"'),"ca"in r&&oh.default('"options.ca" was never documented, please use "options.https.certificateAuthority"'),"key"in r&&oh.default('"options.key" was never documented, please use "options.https.key"'),"cert"in r&&oh.default('"options.cert" was never documented, please use "options.https.certificate"'),"passphrase"in r&&oh.default('"options.passphrase" was never documented, please use "options.https.passphrase"'),"pfx"in r&&oh.default('"options.pfx" was never documented, please use "options.https.pfx"'),"followRedirects"in r)throw new TypeError("The `followRedirects` option does not exist. Use `followRedirect` instead.");if(r.agent){for(let x in r.agent)if(x!=="http"&&x!=="https"&&x!=="http2")throw new TypeError(`Expected the \`options.agent\` properties to be \`http\`, \`https\` or \`http2\`, got \`${x}\``)}return r.maxRedirects=(p=r.maxRedirects)!==null&&p!==void 0?p:0,Bn.setNonEnumerableProperties([o,h],r),ist.default(r,o)}_lockWrite(){let e=()=>{throw new TypeError("The payload has been already provided")};this.write=e,this.end=e}_unlockWrite(){this.write=super.write,this.end=super.end}async _finalizeBody(){let{options:e}=this,{headers:r}=e,o=!ot.default.undefined(e.form),a=!ot.default.undefined(e.json),n=!ot.default.undefined(e.body),u=o||a||n,A=Bn.withoutBody.has(e.method)&&!(e.method==="GET"&&e.allowGetBody);if(this._cannotHaveBody=A,u){if(A)throw new TypeError(`The \`${e.method}\` method cannot be used with a body`);if([n,o,a].filter(p=>p).length>1)throw new TypeError("The `body`, `json` and `form` options are mutually exclusive");if(n&&!(e.body instanceof Hae.Readable)&&!ot.default.string(e.body)&&!ot.default.buffer(e.body)&&!Gae.default(e.body))throw new TypeError("The `body` option must be a stream.Readable, string or Buffer");if(o&&!ot.default.object(e.form))throw new TypeError("The `form` option must be an Object");{let p=!ot.default.string(r["content-type"]);n?(Gae.default(e.body)&&p&&(r["content-type"]=`multipart/form-data; boundary=${e.body.getBoundary()}`),this[ah]=e.body):o?(p&&(r["content-type"]="application/x-www-form-urlencoded"),this[ah]=new sh.URLSearchParams(e.form).toString()):(p&&(r["content-type"]="application/json"),this[ah]=e.stringifyJson(e.json));let h=await Zit.default(this[ah],e.headers);ot.default.undefined(r["content-length"])&&ot.default.undefined(r["transfer-encoding"])&&!A&&!ot.default.undefined(h)&&(r["content-length"]=String(h))}}else A?this._lockWrite():this._unlockWrite();this[sy]=Number(r["content-length"])||void 0}async _onResponseBase(e){let{options:r}=this,{url:o}=r;this[Xae]=e,r.decompress&&(e=zit(e));let a=e.statusCode,n=e;n.statusMessage=n.statusMessage?n.statusMessage:qae.STATUS_CODES[a],n.url=r.url.toString(),n.requestUrl=this.requestUrl,n.redirectUrls=this.redirects,n.request=this,n.isFromCache=e.fromCache||!1,n.ip=this.ip,n.retryCount=this.retryCount,this[zae]=n.isFromCache,this[ny]=Number(e.headers["content-length"])||void 0,this[XS]=e,e.once("end",()=>{this[ny]=this[iy],this.emit("downloadProgress",this.downloadProgress)}),e.once("error",A=>{e.destroy(),this._beforeError(new n1(A,this))}),e.once("aborted",()=>{this._beforeError(new n1({name:"Error",message:"The server aborted pending request",code:"ECONNRESET"},this))}),this.emit("downloadProgress",this.downloadProgress);let u=e.headers["set-cookie"];if(ot.default.object(r.cookieJar)&&u){let A=u.map(async p=>r.cookieJar.setCookie(p,o.toString()));r.ignoreInvalidCookies&&(A=A.map(async p=>p.catch(()=>{})));try{await Promise.all(A)}catch(p){this._beforeError(p);return}}if(r.followRedirect&&e.headers.location&&ust.has(a)){if(e.resume(),this[$s]&&(this[g4](),delete this[$s],this[Vae]()),(a===303&&r.method!=="GET"&&r.method!=="HEAD"||!r.methodRewriting)&&(r.method="GET","body"in r&&delete r.body,"json"in r&&delete r.json,"form"in r&&delete r.form,this[ah]=void 0,delete r.headers["content-length"]),this.redirects.length>=r.maxRedirects){this._beforeError(new ZS(this));return}try{let p=Buffer.from(e.headers.location,"binary").toString(),h=new sh.URL(p,o),E=h.toString();decodeURI(E),h.hostname!==o.hostname||h.port!==o.port?("host"in r.headers&&delete r.headers.host,"cookie"in r.headers&&delete r.headers.cookie,"authorization"in r.headers&&delete r.headers.authorization,(r.username||r.password)&&(r.username="",r.password="")):(h.username=r.username,h.password=r.password),this.redirects.push(E),r.url=h;for(let I of r.hooks.beforeRedirect)await I(r,n);this.emit("redirect",n,r),await this._makeRequest()}catch(p){this._beforeError(p);return}return}if(r.isStream&&r.throwHttpErrors&&!nst.isResponseOk(n)){this._beforeError(new $S(n));return}e.on("readable",()=>{this[JS]&&this._read()}),this.on("resume",()=>{e.resume()}),this.on("pause",()=>{e.pause()}),e.once("end",()=>{this.push(null)}),this.emit("response",e);for(let A of this[zS])if(!A.headersSent){for(let p in e.headers){let h=r.decompress?p!=="content-encoding":!0,E=e.headers[p];h&&A.setHeader(p,E)}A.statusCode=a}}async _onResponse(e){try{await this._onResponseBase(e)}catch(r){this._beforeError(r)}}_onRequest(e){let{options:r}=this,{timeout:o,url:a}=r;Kit.default(e),this[g4]=Yae.default(e,o,a);let n=r.cache?"cacheableResponse":"response";e.once(n,p=>{this._onResponse(p)}),e.once("error",p=>{var h;e.destroy(),(h=e.res)===null||h===void 0||h.removeAllListeners("end"),p=p instanceof Yae.TimeoutError?new rb(p,this.timings,this):new Ji(p.message,p,this),this._beforeError(p)}),this[Vae]=$it.default(e,this,fst),this[$s]=e,this.emit("uploadProgress",this.uploadProgress);let u=this[ah],A=this.redirects.length===0?this:e;ot.default.nodeStream(u)?(u.pipe(A),u.once("error",p=>{this._beforeError(new tb(p,this))})):(this._unlockWrite(),ot.default.undefined(u)?(this._cannotHaveBody||this._noPipe)&&(A.end(),this._lockWrite()):(this._writeRequest(u,void 0,()=>{}),A.end(),this._lockWrite())),this.emit("request",e)}async _createCacheableRequest(e,r){return new Promise((o,a)=>{Object.assign(r,est.default(e)),delete r.url;let n,u=d4.get(r.cache)(r,async A=>{A._readableState.autoDestroy=!1,n&&(await n).emit("cacheableResponse",A),o(A)});r.url=e,u.once("error",a),u.once("request",async A=>{n=A,o(n)})})}async _makeRequest(){var e,r,o,a,n;let{options:u}=this,{headers:A}=u;for(let U in A)if(ot.default.undefined(A[U]))delete A[U];else if(ot.default.null_(A[U]))throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${U}\` header`);if(u.decompress&&ot.default.undefined(A["accept-encoding"])&&(A["accept-encoding"]=ost?"gzip, deflate, br":"gzip, deflate"),u.cookieJar){let U=await u.cookieJar.getCookieString(u.url.toString());ot.default.nonEmptyString(U)&&(u.headers.cookie=U)}for(let U of u.hooks.beforeRequest){let z=await U(u);if(!ot.default.undefined(z)){u.request=()=>z;break}}u.body&&this[ah]!==u.body&&(this[ah]=u.body);let{agent:p,request:h,timeout:E,url:I}=u;if(u.dnsCache&&!("lookup"in u)&&(u.lookup=u.dnsCache.lookup),I.hostname==="unix"){let U=/(?<socketPath>.+?):(?<path>.+)/.exec(`${I.pathname}${I.search}`);if(U?.groups){let{socketPath:z,path:te}=U.groups;Object.assign(u,{socketPath:z,path:te,host:""})}}let v=I.protocol==="https:",x;u.http2?x=Jit.auto:x=v?Wit.request:qae.request;let C=(e=u.request)!==null&&e!==void 0?e:x,R=u.cache?this._createCacheableRequest:C;p&&!u.http2&&(u.agent=p[v?"https":"http"]),u[$s]=C,delete u.request,delete u.timeout;let L=u;if(L.shared=(r=u.cacheOptions)===null||r===void 0?void 0:r.shared,L.cacheHeuristic=(o=u.cacheOptions)===null||o===void 0?void 0:o.cacheHeuristic,L.immutableMinTimeToLive=(a=u.cacheOptions)===null||a===void 0?void 0:a.immutableMinTimeToLive,L.ignoreCargoCult=(n=u.cacheOptions)===null||n===void 0?void 0:n.ignoreCargoCult,u.dnsLookupIpVersion!==void 0)try{L.family=Kae.dnsLookupIpVersionToFamily(u.dnsLookupIpVersion)}catch{throw new Error("Invalid `dnsLookupIpVersion` option value")}u.https&&("rejectUnauthorized"in u.https&&(L.rejectUnauthorized=u.https.rejectUnauthorized),u.https.checkServerIdentity&&(L.checkServerIdentity=u.https.checkServerIdentity),u.https.certificateAuthority&&(L.ca=u.https.certificateAuthority),u.https.certificate&&(L.cert=u.https.certificate),u.https.key&&(L.key=u.https.key),u.https.passphrase&&(L.passphrase=u.https.passphrase),u.https.pfx&&(L.pfx=u.https.pfx));try{let U=await R(I,L);ot.default.undefined(U)&&(U=x(I,L)),u.request=h,u.timeout=E,u.agent=p,u.https&&("rejectUnauthorized"in u.https&&delete L.rejectUnauthorized,u.https.checkServerIdentity&&delete L.checkServerIdentity,u.https.certificateAuthority&&delete L.ca,u.https.certificate&&delete L.cert,u.https.key&&delete L.key,u.https.passphrase&&delete L.passphrase,u.https.pfx&&delete L.pfx),lst(U)?this._onRequest(U):this.writable?(this.once("finish",()=>{this._onResponse(U)}),this._unlockWrite(),this.end(),this._lockWrite()):this._onResponse(U)}catch(U){throw U instanceof jae.CacheError?new eb(U,this):new Ji(U.message,U,this)}}async _error(e){try{for(let r of this.options.hooks.beforeError)e=await r(e)}catch(r){e=new Ji(r.message,r,this)}this.destroy(e)}_beforeError(e){if(this[ay])return;let{options:r}=this,o=this.retryCount+1;this[ay]=!0,e instanceof Ji||(e=new Ji(e.message,e,this));let a=e,{response:n}=a;(async()=>{if(n&&!n.body){n.setEncoding(this._readableState.encoding);try{n.rawBody=await rst.default(n),n.body=n.rawBody.toString()}catch{}}if(this.listenerCount("retry")!==0){let u;try{let A;n&&"retry-after"in n.headers&&(A=Number(n.headers["retry-after"]),Number.isNaN(A)?(A=Date.parse(n.headers["retry-after"])-Date.now(),A<=0&&(A=1)):A*=1e3),u=await r.retry.calculateDelay({attemptCount:o,retryOptions:r.retry,error:a,retryAfter:A,computedValue:sst.default({attemptCount:o,retryOptions:r.retry,error:a,retryAfter:A,computedValue:0})})}catch(A){this._error(new Ji(A.message,A,this));return}if(u){let A=async()=>{try{for(let p of this.options.hooks.beforeRetry)await p(this.options,a,o)}catch(p){this._error(new Ji(p.message,e,this));return}this.destroyed||(this.destroy(),this.emit("retry",o,e))};this[Zae]=setTimeout(A,u);return}}this._error(a)})()}_read(){this[JS]=!0;let e=this[XS];if(e&&!this[ay]){e.readableLength&&(this[JS]=!1);let r;for(;(r=e.read())!==null;){this[iy]+=r.length,this[Jae]=!0;let o=this.downloadProgress;o.percent<1&&this.emit("downloadProgress",o),this.push(r)}}}_write(e,r,o){let a=()=>{this._writeRequest(e,r,o)};this.requestInitialized?a():this[r1].push(a)}_writeRequest(e,r,o){this[$s].destroyed||(this._progressCallbacks.push(()=>{this[oy]+=Buffer.byteLength(e,r);let a=this.uploadProgress;a.percent<1&&this.emit("uploadProgress",a)}),this[$s].write(e,r,a=>{!a&&this._progressCallbacks.length>0&&this._progressCallbacks.shift()(),o(a)}))}_final(e){let r=()=>{for(;this._progressCallbacks.length!==0;)this._progressCallbacks.shift()();if(!($s in this)){e();return}if(this[$s].destroyed){e();return}this[$s].end(o=>{o||(this[sy]=this[oy],this.emit("uploadProgress",this.uploadProgress),this[$s].emit("upload-complete")),e(o)})};this.requestInitialized?r():this[r1].push(r)}_destroy(e,r){var o;this[ay]=!0,clearTimeout(this[Zae]),$s in this&&(this[g4](),!((o=this[XS])===null||o===void 0)&&o.complete||this[$s].destroy()),e!==null&&!ot.default.undefined(e)&&!(e instanceof Ji)&&(e=new Ji(e.message,e,this)),r(e)}get _isAboutToError(){return this[ay]}get ip(){var e;return(e=this.socket)===null||e===void 0?void 0:e.remoteAddress}get aborted(){var e,r,o;return((r=(e=this[$s])===null||e===void 0?void 0:e.destroyed)!==null&&r!==void 0?r:this.destroyed)&&!(!((o=this[Xae])===null||o===void 0)&&o.complete)}get socket(){var e,r;return(r=(e=this[$s])===null||e===void 0?void 0:e.socket)!==null&&r!==void 0?r:void 0}get downloadProgress(){let e;return this[ny]?e=this[iy]/this[ny]:this[ny]===this[iy]?e=1:e=0,{percent:e,transferred:this[iy],total:this[ny]}}get uploadProgress(){let e;return this[sy]?e=this[oy]/this[sy]:this[sy]===this[oy]?e=1:e=0,{percent:e,transferred:this[oy],total:this[sy]}}get timings(){var e;return(e=this[$s])===null||e===void 0?void 0:e.timings}get isFromCache(){return this[zae]}pipe(e,r){if(this[Jae])throw new Error("Failed to pipe. The response has been emitted already.");return e instanceof p4.ServerResponse&&this[zS].add(e),super.pipe(e,r)}unpipe(e){return e instanceof p4.ServerResponse&&this[zS].delete(e),super.unpipe(e),this}};Bn.default=ib});var s1=_(Yc=>{"use strict";var pst=Yc&&Yc.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),hst=Yc&&Yc.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&pst(e,t,r)};Object.defineProperty(Yc,"__esModule",{value:!0});Yc.CancelError=Yc.ParseError=void 0;var $ae=i1(),m4=class extends $ae.RequestError{constructor(e,r){let{options:o}=r.request;super(`${e.message} in "${o.url.toString()}"`,e,r.request),this.name="ParseError"}};Yc.ParseError=m4;var y4=class extends $ae.RequestError{constructor(e){super("Promise was canceled",{},e),this.name="CancelError"}get isCanceled(){return!0}};Yc.CancelError=y4;hst(i1(),Yc)});var tle=_(E4=>{"use strict";Object.defineProperty(E4,"__esModule",{value:!0});var ele=s1(),gst=(t,e,r,o)=>{let{rawBody:a}=t;try{if(e==="text")return a.toString(o);if(e==="json")return a.length===0?"":r(a.toString());if(e==="buffer")return a;throw new ele.ParseError({message:`Unknown body type '${e}'`,name:"Error"},t)}catch(n){throw new ele.ParseError(n,t)}};E4.default=gst});var C4=_(lh=>{"use strict";var dst=lh&&lh.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),mst=lh&&lh.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&dst(e,t,r)};Object.defineProperty(lh,"__esModule",{value:!0});var yst=ve("events"),Est=Qf(),Cst=eoe(),sb=s1(),rle=tle(),nle=i1(),wst=r4(),Ist=c4(),ile=u4(),Bst=["request","response","redirect","uploadProgress","downloadProgress"];function sle(t){let e,r,o=new yst.EventEmitter,a=new Cst((u,A,p)=>{let h=E=>{let I=new nle.default(void 0,t);I.retryCount=E,I._noPipe=!0,p(()=>I.destroy()),p.shouldReject=!1,p(()=>A(new sb.CancelError(I))),e=I,I.once("response",async C=>{var R;if(C.retryCount=E,C.request.aborted)return;let L;try{L=await Ist.default(I),C.rawBody=L}catch{return}if(I._isAboutToError)return;let U=((R=C.headers["content-encoding"])!==null&&R!==void 0?R:"").toLowerCase(),z=["gzip","deflate","br"].includes(U),{options:te}=I;if(z&&!te.decompress)C.body=L;else try{C.body=rle.default(C,te.responseType,te.parseJson,te.encoding)}catch(ae){if(C.body=L.toString(),ile.isResponseOk(C)){I._beforeError(ae);return}}try{for(let[ae,le]of te.hooks.afterResponse.entries())C=await le(C,async ce=>{let Ce=nle.default.normalizeArguments(void 0,{...ce,retry:{calculateDelay:()=>0},throwHttpErrors:!1,resolveBodyOnly:!1},te);Ce.hooks.afterResponse=Ce.hooks.afterResponse.slice(0,ae);for(let Be of Ce.hooks.beforeRetry)await Be(Ce);let de=sle(Ce);return p(()=>{de.catch(()=>{}),de.cancel()}),de})}catch(ae){I._beforeError(new sb.RequestError(ae.message,ae,I));return}if(!ile.isResponseOk(C)){I._beforeError(new sb.HTTPError(C));return}r=C,u(I.options.resolveBodyOnly?C.body:C)});let v=C=>{if(a.isCanceled)return;let{options:R}=I;if(C instanceof sb.HTTPError&&!R.throwHttpErrors){let{response:L}=C;u(I.options.resolveBodyOnly?L.body:L);return}A(C)};I.once("error",v);let x=I.options.body;I.once("retry",(C,R)=>{var L,U;if(x===((L=R.request)===null||L===void 0?void 0:L.options.body)&&Est.default.nodeStream((U=R.request)===null||U===void 0?void 0:U.options.body)){v(R);return}h(C)}),wst.default(I,o,Bst)};h(0)});a.on=(u,A)=>(o.on(u,A),a);let n=u=>{let A=(async()=>{await a;let{options:p}=r.request;return rle.default(r,u,p.parseJson,p.encoding)})();return Object.defineProperties(A,Object.getOwnPropertyDescriptors(a)),A};return a.json=()=>{let{headers:u}=e.options;return!e.writableFinished&&u.accept===void 0&&(u.accept="application/json"),n("json")},a.buffer=()=>n("buffer"),a.text=()=>n("text"),a}lh.default=sle;mst(s1(),lh)});var ole=_(w4=>{"use strict";Object.defineProperty(w4,"__esModule",{value:!0});var vst=s1();function Dst(t,...e){let r=(async()=>{if(t instanceof vst.RequestError)try{for(let a of e)if(a)for(let n of a)t=await n(t)}catch(a){t=a}throw t})(),o=()=>r;return r.json=o,r.text=o,r.buffer=o,r.on=o,r}w4.default=Dst});var cle=_(I4=>{"use strict";Object.defineProperty(I4,"__esModule",{value:!0});var ale=Qf();function lle(t){for(let e of Object.values(t))(ale.default.plainObject(e)||ale.default.array(e))&&lle(e);return Object.freeze(t)}I4.default=lle});var Ale=_(ule=>{"use strict";Object.defineProperty(ule,"__esModule",{value:!0})});var B4=_(zl=>{"use strict";var Pst=zl&&zl.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),Sst=zl&&zl.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&Pst(e,t,r)};Object.defineProperty(zl,"__esModule",{value:!0});zl.defaultHandler=void 0;var fle=Qf(),Vl=C4(),bst=ole(),ab=i1(),xst=cle(),kst={RequestError:Vl.RequestError,CacheError:Vl.CacheError,ReadError:Vl.ReadError,HTTPError:Vl.HTTPError,MaxRedirectsError:Vl.MaxRedirectsError,TimeoutError:Vl.TimeoutError,ParseError:Vl.ParseError,CancelError:Vl.CancelError,UnsupportedProtocolError:Vl.UnsupportedProtocolError,UploadError:Vl.UploadError},Qst=async t=>new Promise(e=>{setTimeout(e,t)}),{normalizeArguments:ob}=ab.default,ple=(...t)=>{let e;for(let r of t)e=ob(void 0,r,e);return e},Fst=t=>t.isStream?new ab.default(void 0,t):Vl.default(t),Rst=t=>"defaults"in t&&"options"in t.defaults,Tst=["get","post","put","patch","head","delete"];zl.defaultHandler=(t,e)=>e(t);var hle=(t,e)=>{if(t)for(let r of t)r(e)},gle=t=>{t._rawHandlers=t.handlers,t.handlers=t.handlers.map(o=>(a,n)=>{let u,A=o(a,p=>(u=n(p),u));if(A!==u&&!a.isStream&&u){let p=A,{then:h,catch:E,finally:I}=p;Object.setPrototypeOf(p,Object.getPrototypeOf(u)),Object.defineProperties(p,Object.getOwnPropertyDescriptors(u)),p.then=h,p.catch=E,p.finally=I}return A});let e=(o,a={},n)=>{var u,A;let p=0,h=E=>t.handlers[p++](E,p===t.handlers.length?Fst:h);if(fle.default.plainObject(o)){let E={...o,...a};ab.setNonEnumerableProperties([o,a],E),a=E,o=void 0}try{let E;try{hle(t.options.hooks.init,a),hle((u=a.hooks)===null||u===void 0?void 0:u.init,a)}catch(v){E=v}let I=ob(o,a,n??t.options);if(I[ab.kIsNormalizedAlready]=!0,E)throw new Vl.RequestError(E.message,E,I);return h(I)}catch(E){if(a.isStream)throw E;return bst.default(E,t.options.hooks.beforeError,(A=a.hooks)===null||A===void 0?void 0:A.beforeError)}};e.extend=(...o)=>{let a=[t.options],n=[...t._rawHandlers],u;for(let A of o)Rst(A)?(a.push(A.defaults.options),n.push(...A.defaults._rawHandlers),u=A.defaults.mutableDefaults):(a.push(A),"handlers"in A&&n.push(...A.handlers),u=A.mutableDefaults);return n=n.filter(A=>A!==zl.defaultHandler),n.length===0&&n.push(zl.defaultHandler),gle({options:ple(...a),handlers:n,mutableDefaults:!!u})};let r=async function*(o,a){let n=ob(o,a,t.options);n.resolveBodyOnly=!1;let u=n.pagination;if(!fle.default.object(u))throw new TypeError("`options.pagination` must be implemented");let A=[],{countLimit:p}=u,h=0;for(;h<u.requestLimit;){h!==0&&await Qst(u.backoff);let E=await e(void 0,void 0,n),I=await u.transform(E),v=[];for(let C of I)if(u.filter(C,A,v)&&(!u.shouldContinue(C,A,v)||(yield C,u.stackAllItems&&A.push(C),v.push(C),--p<=0)))return;let x=u.paginate(E,A,v);if(x===!1)return;x===E.request.options?n=E.request.options:x!==void 0&&(n=ob(void 0,x,n)),h++}};e.paginate=r,e.paginate.all=async(o,a)=>{let n=[];for await(let u of r(o,a))n.push(u);return n},e.paginate.each=r,e.stream=(o,a)=>e(o,{...a,isStream:!0});for(let o of Tst)e[o]=(a,n)=>e(a,{...n,method:o}),e.stream[o]=(a,n)=>e(a,{...n,method:o,isStream:!0});return Object.assign(e,kst),Object.defineProperty(e,"defaults",{value:t.mutableDefaults?t:xst.default(t),writable:t.mutableDefaults,configurable:t.mutableDefaults,enumerable:!0}),e.mergeOptions=ple,e};zl.default=gle;Sst(Ale(),zl)});var yle=_((Ff,lb)=>{"use strict";var Nst=Ff&&Ff.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),dle=Ff&&Ff.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&Nst(e,t,r)};Object.defineProperty(Ff,"__esModule",{value:!0});var Lst=ve("url"),mle=B4(),Mst={options:{method:"GET",retry:{limit:2,methods:["GET","PUT","HEAD","DELETE","OPTIONS","TRACE"],statusCodes:[408,413,429,500,502,503,504,521,522,524],errorCodes:["ETIMEDOUT","ECONNRESET","EADDRINUSE","ECONNREFUSED","EPIPE","ENOTFOUND","ENETUNREACH","EAI_AGAIN"],maxRetryAfter:void 0,calculateDelay:({computedValue:t})=>t},timeout:{},headers:{"user-agent":"got (https://github.com/sindresorhus/got)"},hooks:{init:[],beforeRequest:[],beforeRedirect:[],beforeRetry:[],beforeError:[],afterResponse:[]},cache:void 0,dnsCache:void 0,decompress:!0,throwHttpErrors:!0,followRedirect:!0,isStream:!1,responseType:"text",resolveBodyOnly:!1,maxRedirects:10,prefixUrl:"",methodRewriting:!0,ignoreInvalidCookies:!1,context:{},http2:!1,allowGetBody:!1,https:void 0,pagination:{transform:t=>t.request.options.responseType==="json"?t.body:JSON.parse(t.body),paginate:t=>{if(!Reflect.has(t.headers,"link"))return!1;let e=t.headers.link.split(","),r;for(let o of e){let a=o.split(";");if(a[1].includes("next")){r=a[0].trimStart().trim(),r=r.slice(1,-1);break}}return r?{url:new Lst.URL(r)}:!1},filter:()=>!0,shouldContinue:()=>!0,countLimit:1/0,backoff:0,requestLimit:1e4,stackAllItems:!0},parseJson:t=>JSON.parse(t),stringifyJson:t=>JSON.stringify(t),cacheOptions:{}},handlers:[mle.defaultHandler],mutableDefaults:!1},v4=mle.default(Mst);Ff.default=v4;lb.exports=v4;lb.exports.default=v4;lb.exports.__esModule=!0;dle(B4(),Ff);dle(C4(),Ff)});var sn={};Vt(sn,{Method:()=>Dle,del:()=>qst,get:()=>b4,getNetworkSettings:()=>vle,post:()=>x4,put:()=>Hst,request:()=>o1});function wle(t){let e=new URL(t),r={host:e.hostname,headers:{}};return e.port&&(r.port=Number(e.port)),e.username&&e.password&&(r.proxyAuth=`${e.username}:${e.password}`),{proxy:r}}async function D4(t){return al(Cle,t,()=>oe.readFilePromise(t).then(e=>(Cle.set(t,e),e)))}function _st({statusCode:t,statusMessage:e},r){let o=Ot(r,t,yt.NUMBER),a=`https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/${t}`;return Tm(r,`${o}${e?` (${e})`:""}`,a)}async function ub(t,{configuration:e,customErrorMessage:r}){try{return await t}catch(o){if(o.name!=="HTTPError")throw o;let a=r?.(o,e)??o.response.body?.error;a==null&&(o.message.startsWith("Response code")?a="The remote server failed to provide the requested resource":a=o.message),o.code==="ETIMEDOUT"&&o.event==="socket"&&(a+=`(can be increased via ${Ot(e,"httpTimeout",yt.SETTING)})`);let n=new Jt(35,a,u=>{o.response&&u.reportError(35,` ${Xu(e,{label:"Response Code",value:Hc(yt.NO_HINT,_st(o.response,e))})}`),o.request&&(u.reportError(35,` ${Xu(e,{label:"Request Method",value:Hc(yt.NO_HINT,o.request.options.method)})}`),u.reportError(35,` ${Xu(e,{label:"Request URL",value:Hc(yt.URL,o.request.requestUrl)})}`)),o.request.redirects.length>0&&u.reportError(35,` ${Xu(e,{label:"Request Redirects",value:Hc(yt.NO_HINT,mL(e,o.request.redirects,yt.URL))})}`),o.request.retryCount===o.request.options.retry.limit&&u.reportError(35,` ${Xu(e,{label:"Request Retry Count",value:Hc(yt.NO_HINT,`${Ot(e,o.request.retryCount,yt.NUMBER)} (can be increased via ${Ot(e,"httpRetry",yt.SETTING)})`)})}`)});throw n.originalError=o,n}}function vle(t,e){let r=[...e.configuration.get("networkSettings")].sort(([u],[A])=>A.length-u.length),o={enableNetwork:void 0,httpsCaFilePath:void 0,httpProxy:void 0,httpsProxy:void 0,httpsKeyFilePath:void 0,httpsCertFilePath:void 0},a=Object.keys(o),n=typeof t=="string"?new URL(t):t;for(let[u,A]of r)if(S4.default.isMatch(n.hostname,u))for(let p of a){let h=A.get(p);h!==null&&typeof o[p]>"u"&&(o[p]=h)}for(let u of a)typeof o[u]>"u"&&(o[u]=e.configuration.get(u));return o}async function o1(t,e,{configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u="GET",wrapNetworkRequest:A}){let p={target:t,body:e,configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u},h=async()=>await jst(t,e,p),E=typeof A<"u"?await A(h,p):h;return await(await r.reduceHook(v=>v.wrapNetworkRequest,E,p))()}async function b4(t,{configuration:e,jsonResponse:r,customErrorMessage:o,wrapNetworkRequest:a,...n}){let u=()=>ub(o1(t,null,{configuration:e,wrapNetworkRequest:a,...n}),{configuration:e,customErrorMessage:o}).then(p=>p.body),A=await(typeof a<"u"?u():al(Ele,t,()=>u().then(p=>(Ele.set(t,p),p))));return r?JSON.parse(A.toString()):A}async function Hst(t,e,{customErrorMessage:r,...o}){return(await ub(o1(t,e,{...o,method:"PUT"}),{customErrorMessage:r,configuration:o.configuration})).body}async function x4(t,e,{customErrorMessage:r,...o}){return(await ub(o1(t,e,{...o,method:"POST"}),{customErrorMessage:r,configuration:o.configuration})).body}async function qst(t,{customErrorMessage:e,...r}){return(await ub(o1(t,null,{...r,method:"DELETE"}),{customErrorMessage:e,configuration:r.configuration})).body}async function jst(t,e,{configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u="GET"}){let A=typeof t=="string"?new URL(t):t,p=vle(A,{configuration:r});if(p.enableNetwork===!1)throw new Jt(80,`Request to '${A.href}' has been blocked because of your configuration settings`);if(A.protocol==="http:"&&!S4.default.isMatch(A.hostname,r.get("unsafeHttpWhitelist")))throw new Jt(81,`Unsafe http requests must be explicitly whitelisted in your configuration (${A.hostname})`);let E={agent:{http:p.httpProxy?P4.default.httpOverHttp(wle(p.httpProxy)):Ost,https:p.httpsProxy?P4.default.httpsOverHttp(wle(p.httpsProxy)):Ust},headers:o,method:u};E.responseType=n?"json":"buffer",e!==null&&(Buffer.isBuffer(e)||!a&&typeof e=="string"?E.body=e:E.json=e);let I=r.get("httpTimeout"),v=r.get("httpRetry"),x=r.get("enableStrictSsl"),C=p.httpsCaFilePath,R=p.httpsCertFilePath,L=p.httpsKeyFilePath,{default:U}=await Promise.resolve().then(()=>Ze(yle())),z=C?await D4(C):void 0,te=R?await D4(R):void 0,ae=L?await D4(L):void 0,le=U.extend({timeout:{socket:I},retry:v,https:{rejectUnauthorized:x,certificateAuthority:z,certificate:te,key:ae},...E});return r.getLimit("networkConcurrency")(()=>le(A))}var Ile,Ble,S4,P4,Ele,Cle,Ost,Ust,Dle,Ab=Et(()=>{Pt();Ile=ve("https"),Ble=ve("http"),S4=Ze($o()),P4=Ze(zse());Wl();jl();ql();Ele=new Map,Cle=new Map,Ost=new Ble.Agent({keepAlive:!0}),Ust=new Ile.Agent({keepAlive:!0});Dle=(a=>(a.GET="GET",a.PUT="PUT",a.POST="POST",a.DELETE="DELETE",a))(Dle||{})});var Xi={};Vt(Xi,{availableParallelism:()=>Q4,getArchitecture:()=>a1,getArchitectureName:()=>Vst,getArchitectureSet:()=>k4,getCaller:()=>Zst,major:()=>Gst,openUrl:()=>Yst});function Kst(){if(process.platform==="darwin"||process.platform==="win32")return null;let t;try{t=oe.readFileSync(Wst)}catch{}if(typeof t<"u"){if(t&&(t.includes("GLIBC")||t.includes("libc")))return"glibc";if(t&&t.includes("musl"))return"musl"}let r=(process.report?.getReport()??{}).sharedObjects??[],o=/\/(?:(ld-linux-|[^/]+-linux-gnu\/)|(libc.musl-|ld-musl-))/;return Vp(r,a=>{let n=a.match(o);if(!n)return Vp.skip;if(n[1])return"glibc";if(n[2])return"musl";throw new Error("Assertion failed: Expected the libc variant to have been detected")})??null}function a1(){return Sle=Sle??{os:process.platform,cpu:process.arch,libc:Kst()}}function Vst(t=a1()){return t.libc?`${t.os}-${t.cpu}-${t.libc}`:`${t.os}-${t.cpu}`}function k4(){let t=a1();return ble=ble??{os:[t.os],cpu:[t.cpu],libc:t.libc?[t.libc]:[]}}function Xst(t){let e=zst.exec(t);if(!e)return null;let r=e[2]&&e[2].indexOf("native")===0,o=e[2]&&e[2].indexOf("eval")===0,a=Jst.exec(e[2]);return o&&a!=null&&(e[2]=a[1],e[3]=a[2],e[4]=a[3]),{file:r?null:e[2],methodName:e[1]||"<unknown>",arguments:r?[e[2]]:[],line:e[3]?+e[3]:null,column:e[4]?+e[4]:null}}function Zst(){let e=new Error().stack.split(` +`)[3];return Xst(e)}function Q4(){return typeof fb.default.availableParallelism<"u"?fb.default.availableParallelism():Math.max(1,fb.default.cpus().length)}var fb,Gst,Ple,Yst,Wst,Sle,ble,zst,Jst,pb=Et(()=>{Pt();fb=Ze(ve("os"));hb();ql();Gst=Number(process.versions.node.split(".")[0]),Ple=new Map([["darwin","open"],["linux","xdg-open"],["win32","explorer.exe"]]).get(process.platform),Yst=typeof Ple<"u"?async t=>{try{return await F4(Ple,[t],{cwd:K.cwd()}),!0}catch{return!1}}:void 0,Wst="/usr/bin/ldd";zst=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,Jst=/\((\S*)(?::(\d+))(?::(\d+))\)/});function M4(t,e,r,o,a){let n=VI(r);if(o.isArray||o.type==="ANY"&&Array.isArray(n))return Array.isArray(n)?n.map((u,A)=>R4(t,`${e}[${A}]`,u,o,a)):String(n).split(/,/).map(u=>R4(t,e,u,o,a));if(Array.isArray(n))throw new Error(`Non-array configuration settings "${e}" cannot be an array`);return R4(t,e,r,o,a)}function R4(t,e,r,o,a){let n=VI(r);switch(o.type){case"ANY":return QS(n);case"SHAPE":return rot(t,e,r,o,a);case"MAP":return not(t,e,r,o,a)}if(n===null&&!o.isNullable&&o.default!==null)throw new Error(`Non-nullable configuration settings "${e}" cannot be set to null`);if(o.values?.includes(n))return n;let A=(()=>{if(o.type==="BOOLEAN"&&typeof n!="string")return QI(n);if(typeof n!="string")throw new Error(`Expected configuration setting "${e}" to be a string, got ${typeof n}`);let p=YP(n,{env:t.env});switch(o.type){case"ABSOLUTE_PATH":{let h=a,E=cO(r);return E&&E[0]!=="<"&&(h=K.dirname(E)),K.resolve(h,ue.toPortablePath(p))}case"LOCATOR_LOOSE":return Sf(p,!1);case"NUMBER":return parseInt(p);case"LOCATOR":return Sf(p);case"BOOLEAN":return QI(p);default:return p}})();if(o.values&&!o.values.includes(A))throw new Error(`Invalid value, expected one of ${o.values.join(", ")}`);return A}function rot(t,e,r,o,a){let n=VI(r);if(typeof n!="object"||Array.isArray(n))throw new st(`Object configuration settings "${e}" must be an object`);let u=O4(t,o,{ignoreArrays:!0});if(n===null)return u;for(let[A,p]of Object.entries(n)){let h=`${e}.${A}`;if(!o.properties[A])throw new st(`Unrecognized configuration settings found: ${e}.${A} - run "yarn config -v" to see the list of settings supported in Yarn`);u.set(A,M4(t,h,p,o.properties[A],a))}return u}function not(t,e,r,o,a){let n=VI(r),u=new Map;if(typeof n!="object"||Array.isArray(n))throw new st(`Map configuration settings "${e}" must be an object`);if(n===null)return u;for(let[A,p]of Object.entries(n)){let h=o.normalizeKeys?o.normalizeKeys(A):A,E=`${e}['${h}']`,I=o.valueDefinition;u.set(h,M4(t,E,p,I,a))}return u}function O4(t,e,{ignoreArrays:r=!1}={}){switch(e.type){case"SHAPE":{if(e.isArray&&!r)return[];let o=new Map;for(let[a,n]of Object.entries(e.properties))o.set(a,O4(t,n));return o}case"MAP":return e.isArray&&!r?[]:new Map;case"ABSOLUTE_PATH":return e.default===null?null:t.projectCwd===null?Array.isArray(e.default)?e.default.map(o=>K.normalize(o)):K.isAbsolute(e.default)?K.normalize(e.default):e.isNullable?null:void 0:Array.isArray(e.default)?e.default.map(o=>K.resolve(t.projectCwd,o)):K.resolve(t.projectCwd,e.default);default:return e.default}}function db(t,e,r){if(e.type==="SECRET"&&typeof t=="string"&&r.hideSecrets)return tot;if(e.type==="ABSOLUTE_PATH"&&typeof t=="string"&&r.getNativePaths)return ue.fromPortablePath(t);if(e.isArray&&Array.isArray(t)){let o=[];for(let a of t)o.push(db(a,e,r));return o}if(e.type==="MAP"&&t instanceof Map){if(t.size===0)return;let o=new Map;for(let[a,n]of t.entries()){let u=db(n,e.valueDefinition,r);typeof u<"u"&&o.set(a,u)}return o}if(e.type==="SHAPE"&&t instanceof Map){if(t.size===0)return;let o=new Map;for(let[a,n]of t.entries()){let u=e.properties[a],A=db(n,u,r);typeof A<"u"&&o.set(a,A)}return o}return t}function iot(){let t={};for(let[e,r]of Object.entries(process.env))e=e.toLowerCase(),e.startsWith(mb)&&(e=(0,kle.default)(e.slice(mb.length)),t[e]=r);return t}function N4(){let t=`${mb}rc_filename`;for(let[e,r]of Object.entries(process.env))if(e.toLowerCase()===t&&typeof r=="string")return r;return L4}async function xle(t){try{return await oe.readFilePromise(t)}catch{return Buffer.of()}}async function sot(t,e){return Buffer.compare(...await Promise.all([xle(t),xle(e)]))===0}async function oot(t,e){let[r,o]=await Promise.all([oe.statPromise(t),oe.statPromise(e)]);return r.dev===o.dev&&r.ino===o.ino}async function lot({configuration:t,selfPath:e}){let r=t.get("yarnPath");return t.get("ignorePath")||r===null||r===e||await aot(r,e)?null:r}var kle,Rf,Qle,Fle,Rle,T4,$st,l1,eot,ly,mb,L4,tot,c1,Tle,yb,gb,aot,Ke,u1=Et(()=>{Pt();Nl();kle=Ze(sV()),Rf=Ze(X0());qt();Qle=Ze(ZV()),Fle=ve("module"),Rle=Ze(eg()),T4=ve("stream");use();Gm();tO();rO();nO();Ose();iO();mg();jse();TS();jl();th();Ab();ql();pb();bf();bo();$st=function(){if(!Rf.GITHUB_ACTIONS||!process.env.GITHUB_EVENT_PATH)return!1;let t=ue.toPortablePath(process.env.GITHUB_EVENT_PATH),e;try{e=oe.readJsonSync(t)}catch{return!1}return!(!("repository"in e)||!e.repository||(e.repository.private??!0))}(),l1=new Set(["@yarnpkg/plugin-constraints","@yarnpkg/plugin-exec","@yarnpkg/plugin-interactive-tools","@yarnpkg/plugin-stage","@yarnpkg/plugin-typescript","@yarnpkg/plugin-version","@yarnpkg/plugin-workspace-tools"]),eot=new Set(["isTestEnv","injectNpmUser","injectNpmPassword","injectNpm2FaToken","zipDataEpilogue","cacheCheckpointOverride","cacheVersionOverride","lockfileVersionOverride","binFolder","version","flags","profile","gpg","ignoreNode","wrapOutput","home","confDir","registry","ignoreCwd"]),ly=/^(?!v)[a-z0-9._-]+$/i,mb="yarn_",L4=".yarnrc.yml",tot="********",c1=(E=>(E.ANY="ANY",E.BOOLEAN="BOOLEAN",E.ABSOLUTE_PATH="ABSOLUTE_PATH",E.LOCATOR="LOCATOR",E.LOCATOR_LOOSE="LOCATOR_LOOSE",E.NUMBER="NUMBER",E.STRING="STRING",E.SECRET="SECRET",E.SHAPE="SHAPE",E.MAP="MAP",E))(c1||{}),Tle=yt,yb=(r=>(r.JUNCTIONS="junctions",r.SYMLINKS="symlinks",r))(yb||{}),gb={lastUpdateCheck:{description:"Last timestamp we checked whether new Yarn versions were available",type:"STRING",default:null},yarnPath:{description:"Path to the local executable that must be used over the global one",type:"ABSOLUTE_PATH",default:null},ignorePath:{description:"If true, the local executable will be ignored when using the global one",type:"BOOLEAN",default:!1},globalFolder:{description:"Folder where all system-global files are stored",type:"ABSOLUTE_PATH",default:AO()},cacheFolder:{description:"Folder where the cache files must be written",type:"ABSOLUTE_PATH",default:"./.yarn/cache"},compressionLevel:{description:"Zip files compression level, from 0 to 9 or mixed (a variant of 9, which stores some files uncompressed, when compression doesn't yield good results)",type:"NUMBER",values:["mixed",0,1,2,3,4,5,6,7,8,9],default:0},virtualFolder:{description:"Folder where the virtual packages (cf doc) will be mapped on the disk (must be named __virtual__)",type:"ABSOLUTE_PATH",default:"./.yarn/__virtual__"},installStatePath:{description:"Path of the file where the install state will be persisted",type:"ABSOLUTE_PATH",default:"./.yarn/install-state.gz"},immutablePatterns:{description:"Array of glob patterns; files matching them won't be allowed to change during immutable installs",type:"STRING",default:[],isArray:!0},rcFilename:{description:"Name of the files where the configuration can be found",type:"STRING",default:N4()},enableGlobalCache:{description:"If true, the system-wide cache folder will be used regardless of `cache-folder`",type:"BOOLEAN",default:!0},cacheMigrationMode:{description:"Defines the conditions under which Yarn upgrades should cause the cache archives to be regenerated.",type:"STRING",values:["always","match-spec","required-only"],default:"always"},enableColors:{description:"If true, the CLI is allowed to use colors in its output",type:"BOOLEAN",default:VP,defaultText:"<dynamic>"},enableHyperlinks:{description:"If true, the CLI is allowed to use hyperlinks in its output",type:"BOOLEAN",default:dL,defaultText:"<dynamic>"},enableInlineBuilds:{description:"If true, the CLI will print the build output on the command line",type:"BOOLEAN",default:Rf.isCI,defaultText:"<dynamic>"},enableMessageNames:{description:"If true, the CLI will prefix most messages with codes suitable for search engines",type:"BOOLEAN",default:!0},enableProgressBars:{description:"If true, the CLI is allowed to show a progress bar for long-running events",type:"BOOLEAN",default:!Rf.isCI,defaultText:"<dynamic>"},enableTimers:{description:"If true, the CLI is allowed to print the time spent executing commands",type:"BOOLEAN",default:!0},enableTips:{description:"If true, installs will print a helpful message every day of the week",type:"BOOLEAN",default:!Rf.isCI,defaultText:"<dynamic>"},preferInteractive:{description:"If true, the CLI will automatically use the interactive mode when called from a TTY",type:"BOOLEAN",default:!1},preferTruncatedLines:{description:"If true, the CLI will truncate lines that would go beyond the size of the terminal",type:"BOOLEAN",default:!1},progressBarStyle:{description:"Which style of progress bar should be used (only when progress bars are enabled)",type:"STRING",default:void 0,defaultText:"<dynamic>"},defaultLanguageName:{description:"Default language mode that should be used when a package doesn't offer any insight",type:"STRING",default:"node"},defaultProtocol:{description:"Default resolution protocol used when resolving pure semver and tag ranges",type:"STRING",default:"npm:"},enableTransparentWorkspaces:{description:"If false, Yarn won't automatically resolve workspace dependencies unless they use the `workspace:` protocol",type:"BOOLEAN",default:!0},supportedArchitectures:{description:"Architectures that Yarn will fetch and inject into the resolver",type:"SHAPE",properties:{os:{description:"Array of supported process.platform strings, or null to target them all",type:"STRING",isArray:!0,isNullable:!0,default:["current"]},cpu:{description:"Array of supported process.arch strings, or null to target them all",type:"STRING",isArray:!0,isNullable:!0,default:["current"]},libc:{description:"Array of supported libc libraries, or null to target them all",type:"STRING",isArray:!0,isNullable:!0,default:["current"]}}},enableMirror:{description:"If true, the downloaded packages will be retrieved and stored in both the local and global folders",type:"BOOLEAN",default:!0},enableNetwork:{description:"If false, Yarn will refuse to use the network if required to",type:"BOOLEAN",default:!0},enableOfflineMode:{description:"If true, Yarn will attempt to retrieve files and metadata from the global cache rather than the network",type:"BOOLEAN",default:!1},httpProxy:{description:"URL of the http proxy that must be used for outgoing http requests",type:"STRING",default:null},httpsProxy:{description:"URL of the http proxy that must be used for outgoing https requests",type:"STRING",default:null},unsafeHttpWhitelist:{description:"List of the hostnames for which http queries are allowed (glob patterns are supported)",type:"STRING",default:[],isArray:!0},httpTimeout:{description:"Timeout of each http request in milliseconds",type:"NUMBER",default:6e4},httpRetry:{description:"Retry times on http failure",type:"NUMBER",default:3},networkConcurrency:{description:"Maximal number of concurrent requests",type:"NUMBER",default:50},taskPoolConcurrency:{description:"Maximal amount of concurrent heavy task processing",type:"NUMBER",default:Q4()},taskPoolMode:{description:"Execution strategy for heavy tasks",type:"STRING",values:["async","workers"],default:"workers"},networkSettings:{description:"Network settings per hostname (glob patterns are supported)",type:"MAP",valueDefinition:{description:"",type:"SHAPE",properties:{httpsCaFilePath:{description:"Path to file containing one or multiple Certificate Authority signing certificates",type:"ABSOLUTE_PATH",default:null},enableNetwork:{description:"If false, the package manager will refuse to use the network if required to",type:"BOOLEAN",default:null},httpProxy:{description:"URL of the http proxy that must be used for outgoing http requests",type:"STRING",default:null},httpsProxy:{description:"URL of the http proxy that must be used for outgoing https requests",type:"STRING",default:null},httpsKeyFilePath:{description:"Path to file containing private key in PEM format",type:"ABSOLUTE_PATH",default:null},httpsCertFilePath:{description:"Path to file containing certificate chain in PEM format",type:"ABSOLUTE_PATH",default:null}}}},httpsCaFilePath:{description:"A path to a file containing one or multiple Certificate Authority signing certificates",type:"ABSOLUTE_PATH",default:null},httpsKeyFilePath:{description:"Path to file containing private key in PEM format",type:"ABSOLUTE_PATH",default:null},httpsCertFilePath:{description:"Path to file containing certificate chain in PEM format",type:"ABSOLUTE_PATH",default:null},enableStrictSsl:{description:"If false, SSL certificate errors will be ignored",type:"BOOLEAN",default:!0},logFilters:{description:"Overrides for log levels",type:"SHAPE",isArray:!0,concatenateValues:!0,properties:{code:{description:"Code of the messages covered by this override",type:"STRING",default:void 0},text:{description:"Code of the texts covered by this override",type:"STRING",default:void 0},pattern:{description:"Code of the patterns covered by this override",type:"STRING",default:void 0},level:{description:"Log level override, set to null to remove override",type:"STRING",values:Object.values(JP),isNullable:!0,default:void 0}}},enableTelemetry:{description:"If true, telemetry will be periodically sent, following the rules in https://yarnpkg.com/advanced/telemetry",type:"BOOLEAN",default:!0},telemetryInterval:{description:"Minimal amount of time between two telemetry uploads, in days",type:"NUMBER",default:7},telemetryUserId:{description:"If you desire to tell us which project you are, you can set this field. Completely optional and opt-in.",type:"STRING",default:null},enableHardenedMode:{description:"If true, automatically enable --check-resolutions --refresh-lockfile on installs",type:"BOOLEAN",default:Rf.isPR&&$st,defaultText:"<true on public PRs>"},enableScripts:{description:"If true, packages are allowed to have install scripts by default",type:"BOOLEAN",default:!0},enableStrictSettings:{description:"If true, unknown settings will cause Yarn to abort",type:"BOOLEAN",default:!0},enableImmutableCache:{description:"If true, the cache is reputed immutable and actions that would modify it will throw",type:"BOOLEAN",default:!1},checksumBehavior:{description:"Enumeration defining what to do when a checksum doesn't match expectations",type:"STRING",default:"throw"},injectEnvironmentFiles:{description:"List of all the environment files that Yarn should inject inside the process when it starts",type:"ABSOLUTE_PATH",default:[".env.yarn?"],isArray:!0},packageExtensions:{description:"Map of package corrections to apply on the dependency tree",type:"MAP",valueDefinition:{description:"The extension that will be applied to any package whose version matches the specified range",type:"SHAPE",properties:{dependencies:{description:"The set of dependencies that must be made available to the current package in order for it to work properly",type:"MAP",valueDefinition:{description:"A range",type:"STRING"}},peerDependencies:{description:"Inherited dependencies - the consumer of the package will be tasked to provide them",type:"MAP",valueDefinition:{description:"A semver range",type:"STRING"}},peerDependenciesMeta:{description:"Extra information related to the dependencies listed in the peerDependencies field",type:"MAP",valueDefinition:{description:"The peerDependency meta",type:"SHAPE",properties:{optional:{description:"If true, the selected peer dependency will be marked as optional by the package manager and the consumer omitting it won't be reported as an error",type:"BOOLEAN",default:!1}}}}}}}};aot=process.platform==="win32"?sot:oot;Ke=class t{constructor(e){this.isCI=Rf.isCI;this.projectCwd=null;this.plugins=new Map;this.settings=new Map;this.values=new Map;this.sources=new Map;this.invalid=new Map;this.env={};this.limits=new Map;this.packageExtensions=null;this.startingCwd=e}static{this.deleteProperty=Symbol()}static{this.telemetry=null}static create(e,r,o){let a=new t(e);typeof r<"u"&&!(r instanceof Map)&&(a.projectCwd=r),a.importSettings(gb);let n=typeof o<"u"?o:r instanceof Map?r:new Map;for(let[u,A]of n)a.activatePlugin(u,A);return a}static async find(e,r,{strict:o=!0,usePathCheck:a=null,useRc:n=!0}={}){let u=iot();delete u.rcFilename;let A=new t(e),p=await t.findRcFiles(e),h=await t.findFolderRcFile(Jm());h&&(p.find(Ce=>Ce.path===h.path)||p.unshift(h));let E=qse(p.map(ce=>[ce.path,ce.data])),I=It.dot,v=new Set(Object.keys(gb)),x=({yarnPath:ce,ignorePath:Ce,injectEnvironmentFiles:de})=>({yarnPath:ce,ignorePath:Ce,injectEnvironmentFiles:de}),C=({yarnPath:ce,ignorePath:Ce,injectEnvironmentFiles:de,...Be})=>{let Ee={};for(let[g,me]of Object.entries(Be))v.has(g)&&(Ee[g]=me);return Ee},R=({yarnPath:ce,ignorePath:Ce,...de})=>{let Be={};for(let[Ee,g]of Object.entries(de))v.has(Ee)||(Be[Ee]=g);return Be};if(A.importSettings(x(gb)),A.useWithSource("<environment>",x(u),e,{strict:!1}),E){let[ce,Ce]=E;A.useWithSource(ce,x(Ce),I,{strict:!1})}if(a){if(await lot({configuration:A,selfPath:a})!==null)return A;A.useWithSource("<override>",{ignorePath:!0},e,{strict:!1,overwrite:!0})}let L=await t.findProjectCwd(e);A.startingCwd=e,A.projectCwd=L;let U=Object.assign(Object.create(null),process.env);A.env=U;let z=await Promise.all(A.get("injectEnvironmentFiles").map(async ce=>{let Ce=ce.endsWith("?")?await oe.readFilePromise(ce.slice(0,-1),"utf8").catch(()=>""):await oe.readFilePromise(ce,"utf8");return(0,Qle.parse)(Ce)}));for(let ce of z)for(let[Ce,de]of Object.entries(ce))A.env[Ce]=YP(de,{env:U});if(A.importSettings(C(gb)),A.useWithSource("<environment>",C(u),e,{strict:o}),E){let[ce,Ce]=E;A.useWithSource(ce,C(Ce),I,{strict:o})}let te=ce=>"default"in ce?ce.default:ce,ae=new Map([["@@core",cse]]);if(r!==null)for(let ce of r.plugins.keys())ae.set(ce,te(r.modules.get(ce)));for(let[ce,Ce]of ae)A.activatePlugin(ce,Ce);let le=new Map([]);if(r!==null){let ce=new Map;for(let Be of Fle.builtinModules)ce.set(Be,()=>vf(Be));for(let[Be,Ee]of r.modules)ce.set(Be,()=>Ee);let Ce=new Set,de=async(Be,Ee)=>{let{factory:g,name:me}=vf(Be);if(!g||Ce.has(me))return;let we=new Map(ce),Ae=Z=>{if(we.has(Z))return we.get(Z)();throw new st(`This plugin cannot access the package referenced via ${Z} which is neither a builtin, nor an exposed entry`)},ne=await xm(async()=>te(await g(Ae)),Z=>`${Z} (when initializing ${me}, defined in ${Ee})`);ce.set(me,()=>ne),Ce.add(me),le.set(me,ne)};if(u.plugins)for(let Be of u.plugins.split(";")){let Ee=K.resolve(e,ue.toPortablePath(Be));await de(Ee,"<environment>")}for(let{path:Be,cwd:Ee,data:g}of p)if(n&&Array.isArray(g.plugins))for(let me of g.plugins){let we=typeof me!="string"?me.path:me,Ae=me?.spec??"",ne=me?.checksum??"";if(l1.has(Ae))continue;let Z=K.resolve(Ee,ue.toPortablePath(we));if(!await oe.existsPromise(Z)){if(!Ae){let ht=Ot(A,K.basename(Z,".cjs"),yt.NAME),H=Ot(A,".gitignore",yt.NAME),rt=Ot(A,A.values.get("rcFilename"),yt.NAME),Te=Ot(A,"https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored",yt.URL);throw new st(`Missing source for the ${ht} plugin - please try to remove the plugin from ${rt} then reinstall it manually. This error usually occurs because ${H} is incorrect, check ${Te} to make sure your plugin folder isn't gitignored.`)}if(!Ae.match(/^https?:/)){let ht=Ot(A,K.basename(Z,".cjs"),yt.NAME),H=Ot(A,A.values.get("rcFilename"),yt.NAME);throw new st(`Failed to recognize the source for the ${ht} plugin - please try to delete the plugin from ${H} then reinstall it manually.`)}let xe=await b4(Ae,{configuration:A}),Ne=zi(xe);if(ne&&ne!==Ne){let ht=Ot(A,K.basename(Z,".cjs"),yt.NAME),H=Ot(A,A.values.get("rcFilename"),yt.NAME),rt=Ot(A,`yarn plugin import ${Ae}`,yt.CODE);throw new st(`Failed to fetch the ${ht} plugin from its remote location: its checksum seems to have changed. If this is expected, please remove the plugin from ${H} then run ${rt} to reimport it.`)}await oe.mkdirPromise(K.dirname(Z),{recursive:!0}),await oe.writeFilePromise(Z,xe)}await de(Z,Be)}}for(let[ce,Ce]of le)A.activatePlugin(ce,Ce);if(A.useWithSource("<environment>",R(u),e,{strict:o}),E){let[ce,Ce]=E;A.useWithSource(ce,R(Ce),I,{strict:o})}return A.get("enableGlobalCache")&&(A.values.set("cacheFolder",`${A.get("globalFolder")}/cache`),A.sources.set("cacheFolder","<internal>")),A}static async findRcFiles(e){let r=N4(),o=[],a=e,n=null;for(;a!==n;){n=a;let u=K.join(n,r);if(oe.existsSync(u)){let A=await oe.readFilePromise(u,"utf8"),p;try{p=Ki(A)}catch{let E="";throw A.match(/^\s+(?!-)[^:]+\s+\S+/m)&&(E=" (in particular, make sure you list the colons after each key name)"),new st(`Parse error when loading ${u}; please check it's proper Yaml${E}`)}o.unshift({path:u,cwd:n,data:p})}a=K.dirname(n)}return o}static async findFolderRcFile(e){let r=K.join(e,dr.rc),o;try{o=await oe.readFilePromise(r,"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}let a=Ki(o);return{path:r,cwd:e,data:a}}static async findProjectCwd(e){let r=null,o=e,a=null;for(;o!==a;){if(a=o,oe.existsSync(K.join(a,dr.lockfile)))return a;oe.existsSync(K.join(a,dr.manifest))&&(r=a),o=K.dirname(a)}return r}static async updateConfiguration(e,r,o={}){let a=N4(),n=K.join(e,a),u=oe.existsSync(n)?Ki(await oe.readFilePromise(n,"utf8")):{},A=!1,p;if(typeof r=="function"){try{p=r(u)}catch{p=r({})}if(p===u)return!1}else{p=u;for(let h of Object.keys(r)){let E=u[h],I=r[h],v;if(typeof I=="function")try{v=I(E)}catch{v=I(void 0)}else v=I;E!==v&&(v===t.deleteProperty?delete p[h]:p[h]=v,A=!0)}if(!A)return!1}return await oe.changeFilePromise(n,Da(p),{automaticNewlines:!0}),!0}static async addPlugin(e,r){r.length!==0&&await t.updateConfiguration(e,o=>{let a=o.plugins??[];if(a.length===0)return{...o,plugins:r};let n=[],u=[...r];for(let A of a){let p=typeof A!="string"?A.path:A,h=u.find(E=>E.path===p);h?(n.push(h),u=u.filter(E=>E!==h)):n.push(A)}return n.push(...u),{...o,plugins:n}})}static async updateHomeConfiguration(e){let r=Jm();return await t.updateConfiguration(r,e)}activatePlugin(e,r){this.plugins.set(e,r),typeof r.configuration<"u"&&this.importSettings(r.configuration)}importSettings(e){for(let[r,o]of Object.entries(e))if(o!=null){if(this.settings.has(r))throw new Error(`Cannot redefine settings "${r}"`);this.settings.set(r,o),this.values.set(r,O4(this,o))}}useWithSource(e,r,o,a){try{this.use(e,r,o,a)}catch(n){throw n.message+=` (in ${Ot(this,e,yt.PATH)})`,n}}use(e,r,o,{strict:a=!0,overwrite:n=!1}={}){a=a&&this.get("enableStrictSettings");for(let u of["enableStrictSettings",...Object.keys(r)]){let A=r[u],p=cO(A);if(p&&(e=p),typeof A>"u"||u==="plugins"||e==="<environment>"&&eot.has(u))continue;if(u==="rcFilename")throw new st(`The rcFilename settings can only be set via ${`${mb}RC_FILENAME`.toUpperCase()}, not via a rc file`);let h=this.settings.get(u);if(!h){let I=Jm(),v=e[0]!=="<"?K.dirname(e):null;if(a&&!(v!==null?I===v:!1))throw new st(`Unrecognized or legacy configuration settings found: ${u} - run "yarn config -v" to see the list of settings supported in Yarn`);this.invalid.set(u,e);continue}if(this.sources.has(u)&&!(n||h.type==="MAP"||h.isArray&&h.concatenateValues))continue;let E;try{E=M4(this,u,A,h,o)}catch(I){throw I.message+=` in ${Ot(this,e,yt.PATH)}`,I}if(u==="enableStrictSettings"&&e!=="<environment>"){a=E;continue}if(h.type==="MAP"){let I=this.values.get(u);this.values.set(u,new Map(n?[...I,...E]:[...E,...I])),this.sources.set(u,`${this.sources.get(u)}, ${e}`)}else if(h.isArray&&h.concatenateValues){let I=this.values.get(u);this.values.set(u,n?[...I,...E]:[...E,...I]),this.sources.set(u,`${this.sources.get(u)}, ${e}`)}else this.values.set(u,E),this.sources.set(u,e)}}get(e){if(!this.values.has(e))throw new Error(`Invalid configuration key "${e}"`);return this.values.get(e)}getSpecial(e,{hideSecrets:r=!1,getNativePaths:o=!1}){let a=this.get(e),n=this.settings.get(e);if(typeof n>"u")throw new st(`Couldn't find a configuration settings named "${e}"`);return db(a,n,{hideSecrets:r,getNativePaths:o})}getSubprocessStreams(e,{header:r,prefix:o,report:a}){let n,u,A=oe.createWriteStream(e);if(this.get("enableInlineBuilds")){let p=a.createStreamReporter(`${o} ${Ot(this,"STDOUT","green")}`),h=a.createStreamReporter(`${o} ${Ot(this,"STDERR","red")}`);n=new T4.PassThrough,n.pipe(p),n.pipe(A),u=new T4.PassThrough,u.pipe(h),u.pipe(A)}else n=A,u=A,typeof r<"u"&&n.write(`${r} +`);return{stdout:n,stderr:u}}makeResolver(){let e=[];for(let r of this.plugins.values())for(let o of r.resolvers||[])e.push(new o);return new yg([new kS,new ei,...e])}makeFetcher(){let e=[];for(let r of this.plugins.values())for(let o of r.fetchers||[])e.push(new o);return new Wm([new Km,new Vm,...e])}getLinkers(){let e=[];for(let r of this.plugins.values())for(let o of r.linkers||[])e.push(new o);return e}getSupportedArchitectures(){let e=a1(),r=this.get("supportedArchitectures"),o=r.get("os");o!==null&&(o=o.map(u=>u==="current"?e.os:u));let a=r.get("cpu");a!==null&&(a=a.map(u=>u==="current"?e.cpu:u));let n=r.get("libc");return n!==null&&(n=ol(n,u=>u==="current"?e.libc??ol.skip:u)),{os:o,cpu:a,libc:n}}isInteractive({interactive:e,stdout:r}){return r.isTTY?e??this.get("preferInteractive"):!1}async getPackageExtensions(){if(this.packageExtensions!==null)return this.packageExtensions;this.packageExtensions=new Map;let e=this.packageExtensions,r=(o,a,{userProvided:n=!1}={})=>{if(!Qa(o.range))throw new Error("Only semver ranges are allowed as keys for the packageExtensions setting");let u=new Ut;u.load(a,{yamlCompatibilityMode:!0});let A=xI(e,o.identHash),p=[];A.push([o.range,p]);let h={status:"inactive",userProvided:n,parentDescriptor:o};for(let E of u.dependencies.values())p.push({...h,type:"Dependency",descriptor:E});for(let E of u.peerDependencies.values())p.push({...h,type:"PeerDependency",descriptor:E});for(let[E,I]of u.peerDependenciesMeta)for(let[v,x]of Object.entries(I))p.push({...h,type:"PeerDependencyMeta",selector:E,key:v,value:x})};await this.triggerHook(o=>o.registerPackageExtensions,this,r);for(let[o,a]of this.get("packageExtensions"))r(rh(o,!0),GP(a),{userProvided:!0});return e}normalizeLocator(e){return Qa(e.reference)?Rs(e,`${this.get("defaultProtocol")}${e.reference}`):ly.test(e.reference)?Rs(e,`${this.get("defaultProtocol")}${e.reference}`):e}normalizeDependency(e){return Qa(e.range)?In(e,`${this.get("defaultProtocol")}${e.range}`):ly.test(e.range)?In(e,`${this.get("defaultProtocol")}${e.range}`):e}normalizeDependencyMap(e){return new Map([...e].map(([r,o])=>[r,this.normalizeDependency(o)]))}normalizePackage(e,{packageExtensions:r}){let o=OI(e),a=r.get(e.identHash);if(typeof a<"u"){let u=e.version;if(u!==null){for(let[A,p]of a)if(tA(u,A))for(let h of p)switch(h.status==="inactive"&&(h.status="redundant"),h.type){case"Dependency":typeof o.dependencies.get(h.descriptor.identHash)>"u"&&(h.status="active",o.dependencies.set(h.descriptor.identHash,this.normalizeDependency(h.descriptor)));break;case"PeerDependency":typeof o.peerDependencies.get(h.descriptor.identHash)>"u"&&(h.status="active",o.peerDependencies.set(h.descriptor.identHash,h.descriptor));break;case"PeerDependencyMeta":{let E=o.peerDependenciesMeta.get(h.selector);(typeof E>"u"||!Object.hasOwn(E,h.key)||E[h.key]!==h.value)&&(h.status="active",al(o.peerDependenciesMeta,h.selector,()=>({}))[h.key]=h.value)}break;default:cL(h)}}}let n=u=>u.scope?`${u.scope}__${u.name}`:`${u.name}`;for(let u of o.peerDependenciesMeta.keys()){let A=ea(u);o.peerDependencies.has(A.identHash)||o.peerDependencies.set(A.identHash,In(A,"*"))}for(let u of o.peerDependencies.values()){if(u.scope==="types")continue;let A=n(u),p=eA("types",A),h=rn(p);o.peerDependencies.has(p.identHash)||o.peerDependenciesMeta.has(h)||(o.peerDependencies.set(p.identHash,In(p,"*")),o.peerDependenciesMeta.set(h,{optional:!0}))}return o.dependencies=new Map(Fs(o.dependencies,([,u])=>xa(u))),o.peerDependencies=new Map(Fs(o.peerDependencies,([,u])=>xa(u))),o}getLimit(e){return al(this.limits,e,()=>(0,Rle.default)(this.get(e)))}async triggerHook(e,...r){for(let o of this.plugins.values()){let a=o.hooks;if(!a)continue;let n=e(a);n&&await n(...r)}}async triggerMultipleHooks(e,r){for(let o of r)await this.triggerHook(e,...o)}async reduceHook(e,r,...o){let a=r;for(let n of this.plugins.values()){let u=n.hooks;if(!u)continue;let A=e(u);A&&(a=await A(a,...o))}return a}async firstHook(e,...r){for(let o of this.plugins.values()){let a=o.hooks;if(!a)continue;let n=e(a);if(!n)continue;let u=await n(...r);if(typeof u<"u")return u}return null}}});var Ur={};Vt(Ur,{EndStrategy:()=>q4,ExecError:()=>Eb,PipeError:()=>A1,execvp:()=>F4,pipevp:()=>Wc});function Ig(t){return t!==null&&typeof t.fd=="number"}function U4(){}function _4(){for(let t of Bg)t.kill()}async function Wc(t,e,{cwd:r,env:o=process.env,strict:a=!1,stdin:n=null,stdout:u,stderr:A,end:p=2}){let h=["pipe","pipe","pipe"];n===null?h[0]="ignore":Ig(n)&&(h[0]=n),Ig(u)&&(h[1]=u),Ig(A)&&(h[2]=A);let E=(0,H4.default)(t,e,{cwd:ue.fromPortablePath(r),env:{...o,PWD:ue.fromPortablePath(r)},stdio:h});Bg.add(E),Bg.size===1&&(process.on("SIGINT",U4),process.on("SIGTERM",_4)),!Ig(n)&&n!==null&&n.pipe(E.stdin),Ig(u)||E.stdout.pipe(u,{end:!1}),Ig(A)||E.stderr.pipe(A,{end:!1});let I=()=>{for(let v of new Set([u,A]))Ig(v)||v.end()};return new Promise((v,x)=>{E.on("error",C=>{Bg.delete(E),Bg.size===0&&(process.off("SIGINT",U4),process.off("SIGTERM",_4)),(p===2||p===1)&&I(),x(C)}),E.on("close",(C,R)=>{Bg.delete(E),Bg.size===0&&(process.off("SIGINT",U4),process.off("SIGTERM",_4)),(p===2||p===1&&C!==0)&&I(),C===0||!a?v({code:j4(C,R)}):x(new A1({fileName:t,code:C,signal:R}))})})}async function F4(t,e,{cwd:r,env:o=process.env,encoding:a="utf8",strict:n=!1}){let u=["ignore","pipe","pipe"],A=[],p=[],h=ue.fromPortablePath(r);typeof o.PWD<"u"&&(o={...o,PWD:h});let E=(0,H4.default)(t,e,{cwd:h,env:o,stdio:u});return E.stdout.on("data",I=>{A.push(I)}),E.stderr.on("data",I=>{p.push(I)}),await new Promise((I,v)=>{E.on("error",x=>{let C=Ke.create(r),R=Ot(C,t,yt.PATH);v(new Jt(1,`Process ${R} failed to spawn`,L=>{L.reportError(1,` ${Xu(C,{label:"Thrown Error",value:Hc(yt.NO_HINT,x.message)})}`)}))}),E.on("close",(x,C)=>{let R=a==="buffer"?Buffer.concat(A):Buffer.concat(A).toString(a),L=a==="buffer"?Buffer.concat(p):Buffer.concat(p).toString(a);x===0||!n?I({code:j4(x,C),stdout:R,stderr:L}):v(new Eb({fileName:t,code:x,signal:C,stdout:R,stderr:L}))})})}function j4(t,e){let r=cot.get(e);return typeof r<"u"?128+r:t??1}function uot(t,e,{configuration:r,report:o}){o.reportError(1,` ${Xu(r,t!==null?{label:"Exit Code",value:Hc(yt.NUMBER,t)}:{label:"Exit Signal",value:Hc(yt.CODE,e)})}`)}var H4,q4,A1,Eb,Bg,cot,hb=Et(()=>{Pt();H4=Ze(KR());u1();Wl();jl();q4=(o=>(o[o.Never=0]="Never",o[o.ErrorCode=1]="ErrorCode",o[o.Always=2]="Always",o))(q4||{}),A1=class extends Jt{constructor({fileName:e,code:r,signal:o}){let a=Ke.create(K.cwd()),n=Ot(a,e,yt.PATH);super(1,`Child ${n} reported an error`,u=>{uot(r,o,{configuration:a,report:u})}),this.code=j4(r,o)}},Eb=class extends A1{constructor({fileName:e,code:r,signal:o,stdout:a,stderr:n}){super({fileName:e,code:r,signal:o}),this.stdout=a,this.stderr=n}};Bg=new Set;cot=new Map([["SIGINT",2],["SIGQUIT",3],["SIGKILL",9],["SIGTERM",15]])});function Lle(t){Nle=t}function f1(){return typeof G4>"u"&&(G4=Nle()),G4}var G4,Nle,Y4=Et(()=>{Nle=()=>{throw new Error("Assertion failed: No libzip instance is available, and no factory was configured")}});var Mle=_((Cb,K4)=>{var Aot=Object.assign({},ve("fs")),W4=function(){var t=typeof document<"u"&&document.currentScript?document.currentScript.src:void 0;return typeof __filename<"u"&&(t=t||__filename),function(e){e=e||{};var r=typeof e<"u"?e:{},o,a;r.ready=new Promise(function(We,tt){o=We,a=tt});var n={},u;for(u in r)r.hasOwnProperty(u)&&(n[u]=r[u]);var A=[],p="./this.program",h=function(We,tt){throw tt},E=!1,I=!0,v="";function x(We){return r.locateFile?r.locateFile(We,v):v+We}var C,R,L,U;I&&(E?v=ve("path").dirname(v)+"/":v=__dirname+"/",C=function(tt,Bt){var or=ii(tt);return or?Bt?or:or.toString():(L||(L=Aot),U||(U=ve("path")),tt=U.normalize(tt),L.readFileSync(tt,Bt?null:"utf8"))},R=function(tt){var Bt=C(tt,!0);return Bt.buffer||(Bt=new Uint8Array(Bt)),me(Bt.buffer),Bt},process.argv.length>1&&(p=process.argv[1].replace(/\\/g,"/")),A=process.argv.slice(2),h=function(We){process.exit(We)},r.inspect=function(){return"[Emscripten Module object]"});var z=r.print||console.log.bind(console),te=r.printErr||console.warn.bind(console);for(u in n)n.hasOwnProperty(u)&&(r[u]=n[u]);n=null,r.arguments&&(A=r.arguments),r.thisProgram&&(p=r.thisProgram),r.quit&&(h=r.quit);var ae=0,le=function(We){ae=We},ce;r.wasmBinary&&(ce=r.wasmBinary);var Ce=r.noExitRuntime||!0;typeof WebAssembly!="object"&&Ri("no native wasm support detected");function de(We,tt,Bt){switch(tt=tt||"i8",tt.charAt(tt.length-1)==="*"&&(tt="i32"),tt){case"i1":return Ye[We>>0];case"i8":return Ye[We>>0];case"i16":return op((We>>1)*2);case"i32":return Us((We>>2)*4);case"i64":return Us((We>>2)*4);case"float":return Au((We>>2)*4);case"double":return sp((We>>3)*8);default:Ri("invalid type for getValue: "+tt)}return null}var Be,Ee=!1,g;function me(We,tt){We||Ri("Assertion failed: "+tt)}function we(We){var tt=r["_"+We];return me(tt,"Cannot call unknown function "+We+", make sure it is exported"),tt}function Ae(We,tt,Bt,or,ee){var ye={string:function(rs){var Si=0;if(rs!=null&&rs!==0){var qo=(rs.length<<2)+1;Si=Un(qo),ht(rs,Si,qo)}return Si},array:function(rs){var Si=Un(rs.length);return Te(rs,Si),Si}};function Le(rs){return tt==="string"?xe(rs):tt==="boolean"?!!rs:rs}var ft=we(We),pt=[],Nt=0;if(or)for(var rr=0;rr<or.length;rr++){var $r=ye[Bt[rr]];$r?(Nt===0&&(Nt=Es()),pt[rr]=$r(or[rr])):pt[rr]=or[rr]}var ji=ft.apply(null,pt);return ji=Le(ji),Nt!==0&&qs(Nt),ji}function ne(We,tt,Bt,or){Bt=Bt||[];var ee=Bt.every(function(Le){return Le==="number"}),ye=tt!=="string";return ye&&ee&&!or?we(We):function(){return Ae(We,tt,Bt,arguments,or)}}var Z=new TextDecoder("utf8");function xe(We,tt){if(!We)return"";for(var Bt=We+tt,or=We;!(or>=Bt)&&Se[or];)++or;return Z.decode(Se.subarray(We,or))}function Ne(We,tt,Bt,or){if(!(or>0))return 0;for(var ee=Bt,ye=Bt+or-1,Le=0;Le<We.length;++Le){var ft=We.charCodeAt(Le);if(ft>=55296&&ft<=57343){var pt=We.charCodeAt(++Le);ft=65536+((ft&1023)<<10)|pt&1023}if(ft<=127){if(Bt>=ye)break;tt[Bt++]=ft}else if(ft<=2047){if(Bt+1>=ye)break;tt[Bt++]=192|ft>>6,tt[Bt++]=128|ft&63}else if(ft<=65535){if(Bt+2>=ye)break;tt[Bt++]=224|ft>>12,tt[Bt++]=128|ft>>6&63,tt[Bt++]=128|ft&63}else{if(Bt+3>=ye)break;tt[Bt++]=240|ft>>18,tt[Bt++]=128|ft>>12&63,tt[Bt++]=128|ft>>6&63,tt[Bt++]=128|ft&63}}return tt[Bt]=0,Bt-ee}function ht(We,tt,Bt){return Ne(We,Se,tt,Bt)}function H(We){for(var tt=0,Bt=0;Bt<We.length;++Bt){var or=We.charCodeAt(Bt);or>=55296&&or<=57343&&(or=65536+((or&1023)<<10)|We.charCodeAt(++Bt)&1023),or<=127?++tt:or<=2047?tt+=2:or<=65535?tt+=3:tt+=4}return tt}function rt(We){var tt=H(We)+1,Bt=Ni(tt);return Bt&&Ne(We,Ye,Bt,tt),Bt}function Te(We,tt){Ye.set(We,tt)}function Fe(We,tt){return We%tt>0&&(We+=tt-We%tt),We}var ke,Ye,Se,et,Ue,b,w,S,y,F;function J(We){ke=We,r.HEAP_DATA_VIEW=F=new DataView(We),r.HEAP8=Ye=new Int8Array(We),r.HEAP16=et=new Int16Array(We),r.HEAP32=b=new Int32Array(We),r.HEAPU8=Se=new Uint8Array(We),r.HEAPU16=Ue=new Uint16Array(We),r.HEAPU32=w=new Uint32Array(We),r.HEAPF32=S=new Float32Array(We),r.HEAPF64=y=new Float64Array(We)}var X=r.INITIAL_MEMORY||16777216,$,ie=[],be=[],Re=[],at=!1;function dt(){if(r.preRun)for(typeof r.preRun=="function"&&(r.preRun=[r.preRun]);r.preRun.length;)St(r.preRun.shift());oo(ie)}function jt(){at=!0,oo(be)}function tr(){if(r.postRun)for(typeof r.postRun=="function"&&(r.postRun=[r.postRun]);r.postRun.length;)kr(r.postRun.shift());oo(Re)}function St(We){ie.unshift(We)}function ln(We){be.unshift(We)}function kr(We){Re.unshift(We)}var mr=0,br=null,Kr=null;function Kn(We){mr++,r.monitorRunDependencies&&r.monitorRunDependencies(mr)}function Ms(We){if(mr--,r.monitorRunDependencies&&r.monitorRunDependencies(mr),mr==0&&(br!==null&&(clearInterval(br),br=null),Kr)){var tt=Kr;Kr=null,tt()}}r.preloadedImages={},r.preloadedAudios={};function Ri(We){r.onAbort&&r.onAbort(We),We+="",te(We),Ee=!0,g=1,We="abort("+We+"). Build with -s ASSERTIONS=1 for more info.";var tt=new WebAssembly.RuntimeError(We);throw a(tt),tt}var gs="data:application/octet-stream;base64,";function io(We){return We.startsWith(gs)}var Pi="data:application/octet-stream;base64,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QCAAKAJIIgEgASADaiADEAcaAkAgAyAAKAJsIgFNBEAgACABIANrNgJsDAELIABCADcCbAsgACAAKAJoIANrIgE2AmggACAAKAJYIANrNgJYIAEgACgChC5JBEAgACABNgKELgsgAEH8gAEoAgARAwAgAiADaiECCwJAIAAoAgAiASgCBCIERQ0AIAAoAjwhBSAAIAIgBCACIARJGyICBH8gACgCSCAAKAJoaiAFaiEFIAEgBCACazYCBAJAAkACQAJAIAEoAhwiBCgCFEEBaw4CAQACCyAEQaABaiAFIAEoAgAgAkHcgAEoAgARCAAMAgsgASABKAIwIAUgASgCACACQcSAASgCABEEADYCMAwBCyAFIAEoAgAgAhAHGgsgASABKAIAIAJqNgIAIAEgASgCCCACajYCCCAAKAI8BSAFCyACaiICNgI8AkAgACgChC4iASACakEDSQ0AIAAoAmggAWshAQJAIAAoAnRBgQhPBEAgACAAIAAoAkggAWoiAi0AACACLQABIAAoAnwRAAA2AlQMAQsgAUUNACAAIAFBAWsgACgChAERAgAaCyAAKAKELiAAKAI8IgJBAUZrIgRFDQAgACABIAQgACgCgAERBQAgACAAKAKELiAEazYChC4gACgCPCECCyACQYUCSw0AIAAoAgAoAgRFDQAgACgCMCEBDAELCwJAIAAoAkQiAiAAKAJAIgNNDQAgAAJ/IAAoAjwgACgCaGoiASADSwRAIAAoAkggAWpBACACIAFrIgNBggIgA0GCAkkbIgMQGSABIANqDAELIAFBggJqIgEgA00NASAAKAJIIANqQQAgAiADayICIAEgA2siAyACIANJGyIDEBkgACgCQCADags2AkALC50CAQF/AkAgAAJ/IAAoAqAuIgFBwABGBEAgACgCBCAAKAIQaiAAKQOYLjcAACAAQgA3A5guIAAgACgCEEEIajYCEEEADAELIAFBIE4EQCAAKAIEIAAoAhBqIAApA5guPgAAIAAgAEGcLmo1AgA3A5guIAAgACgCEEEEajYCECAAIAAoAqAuQSBrIgE2AqAuCyABQRBOBEAgACgCBCAAKAIQaiAAKQOYLj0AACAAIAAoAhBBAmo2AhAgACAAKQOYLkIQiDcDmC4gACAAKAKgLkEQayIBNgKgLgsgAUEISA0BIAAgACgCECIBQQFqNgIQ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KAJUIgEEfyABQQAgARAiEBkgACgCVAVBAAsQBiAAQQA2AlQLC9wMAgl/AX4jAEFAaiIGJAACQAJAAkACQAJAIAEoAjBBABAjIgVBAkZBACABKAI4QQAQIyIEQQFGGw0AIAVBAUZBACAEQQJGGw0AIAVBAkciAw0BIARBAkcNAQsgASABLwEMQYAQcjsBDEEAIQMMAQsgASABLwEMQf/vA3E7AQxBACEFIANFBEBB9eABIAEoAjAgAEEIahBpIgVFDQILIAJBgAJxBEAgBSEDDAELIARBAkcEQCAFIQMMAQtB9cYBIAEoAjggAEEIahBpIgNFBEAgBRAcDAILIAMgBTYCAAsgASABLwEMQf7/A3EgAS8BUiIFQQBHcjsBDAJAAkACQAJAAn8CQAJAIAEpAyhC/v///w9WDQAgASkDIEL+////D1YNACACQYAEcUUNASABKQNIQv////8PVA0BCyAFQYECa0H//wNxQQNJIQdBAQwBCyAFQYECa0H//wNxIQQgAkGACnFBgApHDQEgBEEDSSEHQQALIQkgBkIcEBciBEUEQCAAQQhqIgAEQCAAQQA2AgQgAEEONgIACyADEBwMBQsgAkGACHEhBQJAAkAgAkGAAnEEQAJAIAUNACABKQMgQv////8PVg0AIAEpAyhCgICAgBBUDQMLIAQgASkDKBAYIAEpAyAhDAwBCwJAAkACQCAFDQAgASkDIEL/////D1YNACABKQMoIgxC/////w9WDQEgASkDSEKAgICAEFQNBAsgASkDKCIMQv////8PVA0BCyAEIAwQGAsgASkDICIMQv////8PWgRAIAQgDBAYCyABKQNIIgxC/////w9UDQELIAQgDBAYCyAELQAARQRAIABBCGoiAARAIABBADYCBCAAQRQ2AgALIAQQCCADEBwMBQtBASEKQQEgBC0AAAR+IAQpAxAFQgALp0H//wNxIAYQRyEFIAQQCCAFIAM2AgAgBw0BDAILIAMhBSAEQQJLDQELIAZCBxAXIgRFBEAgAEEIaiIABEAgAEEANgIEIABBDjYCAAsgBRAcDAMLIARBAhANIARBhxJBAhAsIAQgAS0AUhBwIAQgAS8BEBANIAQtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAsgBBAIDAILQYGyAkEHIAYQRyEDIAQQCCADIAU2AgBBASELIAMhBQsgBkIuEBciA0UEQCAAQQhqIgAEQCAAQQA2AgQgAEEONgIACyAFEBwMAgsgA0GjEkGoEiACQYACcSIHG0EEECwgB0UEQCADIAkEf0EtBSABLwEIC0H//wNxEA0LIAMgCQR/QS0FIAEvAQoLQf//A3EQDSADIAEvAQwQDSADIAsEf0HjAAUgASgCEAtB//8DcRANIAYgASgCFDYCPAJ/IAZBPGoQjQEiCEUEQEEAIQlBIQwBCwJ/IAgoAhQiBEHQAE4EQCAEQQl0DAELIAhB0AA2AhRBgMACCyEEIAgoAgRBBXQgCCgCCEELdGogCCgCAEEBdmohCSAIKAIMIAQgCCgCEEEFdGpqQaDAAWoLIQQgAyAJQf//A3EQDSADIARB//8DcRANIAMCfyALBEBBACABKQMoQhRUDQEaCyABKAIYCxASIAEpAyAhDCADAn8gAwJ/AkAgBwRAIAxC/v///w9YBEAgASkDKEL/////D1QNAgsgA0F/EBJBfwwDC0F/IAxC/v///w9WDQEaCyAMpwsQEiABKQMoIgxC/////w8gDEL/////D1QbpwsQEiADIAEoAjAiBAR/IAQvAQQFQQALQf//A3EQDSADIAEoAjQgAhBsIAVBgAYQbGpB//8DcRANIAdFBEAgAyABKAI4IgQEfyAELwEEBUEAC0H//wNxEA0gAyABLwE8EA0gAyABLwFAEA0gAyABKAJEEBIgAyABKQNIIgxC/////w8gDEL/////D1QbpxASCyADLQAARQRAIABBCGoiAARAIABBADYCBCAAQRQ2AgALIAMQCCAFEBwMAgsgACAGIAMtAAAEfiADKQMQBUIACxAbIQQgAxAIIARBf0wNACABKAIwIgMEQCAAIAMQYUF/TA0BCyAFBEAgACAFQYAGEGtBf0wNAQsgBRAcIAEoAjQiBQRAIAAgBSACEGtBAEgNAgsgBw0CIAEoAjgiAUUNAiAAIAEQYUEATg0CDAELIAUQHAtBfyEKCyAGQUBrJAAgCgtNAQJ/IAEtAAAhAgJAIAAtAAAiA0UNACACIANHDQADQCABLQABIQIgAC0AASIDRQ0BIAFBAWohASAAQQFqIQAgAiADRg0ACwsgAyACawvcAwICfgF/IAOtIQQgACkDmC4hBQJAIAACfyAAAn4gACgCoC4iBkEDaiIDQT9NBEAgBCAGrYYgBYQMAQsgBkHAAEYEQCAAKAIEIAAoAhBqIAU3AAAgACgCEEEIagwCCyAAKAIEIAAoAhBqIAQgBq2GIAWENwAAIAAgACgCEEEIajYCECAGQT1rIQMgBEHAACAGa62ICyIENwOYLiAAIAM2AqAuIANBOU4EQCAAKAIEIAAoAhBqIAQ3AAAgACAAKAIQQQhqNgIQDAILIANBGU4EQCAAKAIEIAAoAhBqIAQ+AAAgACAAKAIQQQRqNgIQIAAgACkDmC5CIIgiBDcDmC4gACAAKAKgLkEgayIDNgKgLgsgA0EJTgR/IAAoAgQgACgCEGogBD0AACAAIAAoAhBBAmo2AhAgACkDmC5CEIghBCAAKAKgLkEQawUgAwtBAUgNASAAKAIQCyIDQQFqNgIQIAAoAgQgA2ogBDwAAAsgAEEANgKgLiAAQgA3A5guIAAoAgQgACgCEGogAjsAACAAIAAoAhBBAmoiAzYCECAAKAIEIANqIAJBf3M7AAAgACAAKAIQQQJqIgM2AhAgAgRAIAAoAgQgA2ogASACEAcaIAAgACgCECACajYCEAsLrAQCAX8BfgJAIAANACABUA0AIAMEQCADQQA2AgQgA0ESNgIAC0EADwsCQAJAIAAgASACIAMQiQEiBEUNAEEYEAkiAkUEQCADBEAgA0EANgIEIANBDjYCAAsCQCAEKAIoIgBFBEAgBCkDGCEBDAELIABBADYCKCAEKAIoQgA3AyAgBCAEKQMYIgUgBCkDICIBIAEgBVQbIgE3AxgLIAQpAwggAVYEQANAIAQoAgAgAadBBHRqKAIAEAYgAUIBfCIBIAQpAwhUDQALCyAEKAIAEAYgBCgCBBAGIAQQBgwBCyACQQA2AhQgAiAENgIQIAJBABABNgIMIAJBADYCCCACQgA3AgACf0E4EAkiAEUEQCADBEAgA0EANgIEIANBDjYCAAtBAAwBCyAAQQA2AgggAEIANwMAIABCADcDICAAQoCAgIAQNwIsIABBADoAKCAAQQA2AhQgAEIANwIMIABBADsBNCAAIAI2AgggAEEkNgIEIABCPyACQQBCAEEOQSQRDAAiASABQgBTGzcDGCAACyIADQEgAigCECIDBEACQCADKAIoIgBFBEAgAykDGCEBDAELIABBADYCKCADKAIoQgA3AyAgAyADKQMYIgUgAykDICIBIAEgBVQbIgE3AxgLIAMpAwggAVYEQANAIAMoAgAgAadBBHRqKAIAEAYgAUIBfCIBIAMpAwhUDQALCyADKAIAEAYgAygCBBAGIAMQBgsgAhAGC0EAIQALIAALiwwBBn8gACABaiEFAkACQCAAKAIEIgJBAXENACACQQNxRQ0BIAAoAgAiAiABaiEBAkAgACACayIAQciEASgCAEcEQCACQf8BTQRAIAAoAggiBCACQQN2IgJBA3RB3IQBakYaIAAoAgwiAyAERw0CQbSEAUG0hAEoAgBBfiACd3E2AgAMAwsgACgCGCEGAkAgACAAKAIMIgNHBEAgACgCCCICQcSEASgCAEkaIAIgAzYCDCADIAI2AggMAQsCQCAAQRRqIgIoAgAiBA0AIABBEGoiAigCACIEDQBBACEDDAELA0AgAiEHIAQiA0EUaiICKAIAIgQNACADQRBqIQIgAygCECIEDQALIAdBADYCAAsgBkUNAgJAIAAgACgCHCIEQQJ0QeSGAWoiAigCAEYEQCACIAM2AgAgAw0BQbiEAUG4hAEoAgBBfiAEd3E2AgAMBAsgBkEQQRQgBigCECAARhtqIAM2AgAgA0UNAwsgAyAGNgIYIAAoAhAiAgRAIAMgAjYCECACIAM2AhgLIAAoAhQiAkUNAiADIAI2AhQgAiADNgIYDAILIAUoAgQiAkEDcUEDRw0BQbyEASABNgIAIAUgAkF+cTYCBCAAIAFBAXI2AgQgBSABNgIADwsgBCADNgIMIAMgBDYCCAsCQCAFKAIEIgJBAnFFBEAgBUHMhAEoAgBGBEBBzIQBIAA2AgBBwIQBQcCEASgCACABaiIBNgIAIAAgAUEBcjYCBCAAQciEASgCAEcNA0G8hAFBADYCAEHIhAFBADYCAA8LIAVByIQBKAIARgRAQciEASAANgIAQbyEAUG8hAEoAgAgAWoiATYCACAAIAFBAXI2AgQgACABaiABNgIADwsgAkF4cSABaiEBAkAgAkH/AU0EQCAFKAIIIgQgAkEDdiICQQN0QdyEAWpGGiAEIAUoAgwiA0YEQEG0hAFBtIQBKAIAQX4gAndxNgIADAILIAQgAzYCDCADIAQ2AggMAQsgBSgCGCEGAkAgBSAFKAIMIgNHBEAgBSgCCCICQcSEASgCAEkaIAIgAzYCDCADIAI2AggMAQsCQCAFQRRqIgQoAgAiAg0AIAVBEGoiBCgCACICDQBBACEDDAELA0AgBCEHIAIiA0EUaiIEKAIAIgINACADQRBqIQQgAygCECICDQALIAdBADYCAAsgBkUNAAJAIAUgBSgCHCIEQQJ0QeSGAWoiAigCAEYEQCACIAM2AgAgAw0BQbiEAUG4hAEoAgBBfiAEd3E2AgAMAgsgBkEQQRQgBigCECAFRhtqIAM2AgAgA0UNAQsgAyAGNgIYIAUoAhAiAgRAIAMgAjYCECACIAM2AhgLIAUoAhQiAkUNACADIAI2AhQgAiADNgIYCyAAIAFBAXI2AgQgACABaiABNgIAIABByIQBKAIARw0BQbyEASABNgIADwsgBSACQX5xNgIEIAAgAUEBcjYCBCAAIAFqIAE2AgALIAFB/wFNBEAgAUEDdiICQQN0QdyEAWohAQJ/QbSEASgCACIDQQEgAnQiAnFFBEBBtIQBIAIgA3I2AgAgAQwBCyABKAIICyECIAEgADYCCCACIAA2AgwgACABNgIMIAAgAjYCCA8LQR8hAiAAQgA3AhAgAUH///8HTQRAIAFBCHYiAiACQYD+P2pBEHZBCHEiBHQiAiACQYDgH2pBEHZBBHEiA3QiAiACQYCAD2pBEHZBAnEiAnRBD3YgAyAEciACcmsiAkEBdCABIAJBFWp2QQFxckEcaiECCyAAIAI2AhwgAkECdEHkhgFqIQcCQAJAQbiEASgCACIEQQEgAnQiA3FFBEBBuIQBIAMgBHI2AgAgByAANgIAIAAgBzYCGAwBCyABQQBBGSACQQF2ayACQR9GG3QhAiAHKAIAIQMDQCADIgQoAgRBeHEgAUYNAiACQR12IQMgAkEBdCECIAQgA0EEcWoiB0EQaigCACIDDQALIAcgADYCECAAIAQ2AhgLIAAgADYCDCAAIAA2AggPCyAEKAIIIgEgADYCDCAEIAA2AgggAEEANgIYIAAgBDYCDCAAIAE2AggLC1gCAX8BfgJAAn9BACAARQ0AGiAArUIChiICpyIBIABBBHJBgIAESQ0AGkF/IAEgAkIgiKcbCyIBEAkiAEUNACAAQQRrLQAAQQNxRQ0AIABBACABEBkLIAALQwEDfwJAIAJFDQADQCAALQAAIgQgAS0AACIFRgRAIAFBAWohASAAQQFqIQAgAkEBayICDQEMAgsLIAQgBWshAwsgAwsUACAAEEAgACgCABAgIAAoAgQQIAutBAIBfgV/IwBBEGsiBCQAIAAgAWshBgJAAkAgAUEBRgRAIAAgBi0AACACEBkMAQsgAUEJTwRAIAAgBikAADcAACAAIAJBAWtBB3FBAWoiBWohACACIAVrIgFFDQIgBSAGaiECA0AgACACKQAANwAAIAJBCGohAiAAQQhqIQAgAUEIayIBDQALDAILAkACQAJAAkAgAUEEaw4FAAICAgECCyAEIAYoAAAiATYCBCAEIAE2AgAMAgsgBCAGKQAANwMADAELQQghByAEQQhqIQgDQCAIIAYgByABIAEgB0sbIgUQByAFaiEIIAcgBWsiBw0ACyAEIAQpAwg3AwALAkAgBQ0AIAJBEEkNACAEKQMAIQMgAkEQayIGQQR2QQFqQQdxIgEEQANAIAAgAzcACCAAIAM3AAAgAkEQayECIABBEGohACABQQFrIgENAAsLIAZB8ABJDQADQCAAIAM3AHggACADNwBwIAAgAzcAaCAAIAM3AGAgACADNwBYIAAgAzcAUCAAIAM3AEggACADNwBAIAAgAzcAOCAAIAM3ADAgACADNwAoIAAgAzcAICAAIAM3ABggACADNwAQIAAgAzcACCAAIAM3AAAgAEGAAWohACACQYABayICQQ9LDQALCyACQQhPBEBBCCAFayEBA0AgACAEKQMANwAAIAAgAWohACACIAFrIgJBB0sNAAsLIAJFDQEgACAEIAIQBxoLIAAgAmohAAsgBEEQaiQAIAALXwECfyAAKAIIIgEEQCABEAsgAEEANgIICwJAIAAoAgQiAUUNACABKAIAIgJBAXFFDQAgASgCEEF+Rw0AIAEgAkF+cSICNgIAIAINACABECAgAEEANgIECyAAQQA6AAwL1wICBH8BfgJAAkAgACgCQCABp0EEdGooAgAiA0UEQCACBEAgAkEANgIEIAJBFDYCAAsMAQsgACgCACADKQNIIgdBABAUIQMgACgCACEAIANBf0wEQCACBEAgAiAAKAIMNgIAIAIgACgCEDYCBAsMAQtCACEBIwBBEGsiBiQAQX8hAwJAIABCGkEBEBRBf0wEQCACBEAgAiAAKAIMNgIAIAIgACgCEDYCBAsMAQsgAEIEIAZBCmogAhAtIgRFDQBBHiEAQQEhBQNAIAQQDCAAaiEAIAVBAkcEQCAFQQFqIQUMAQsLIAQtAAAEfyAEKQMQIAQpAwhRBUEAC0UEQCACBEAgAkEANgIEIAJBFDYCAAsgBBAIDAELIAQQCCAAIQMLIAZBEGokACADIgBBAEgNASAHIACtfCIBQn9VDQEgAgRAIAJBFjYCBCACQQQ2AgALC0IAIQELIAELYAIBfgF/AkAgAEUNACAAQQhqEF8iAEUNACABIAEoAjBBAWo2AjAgACADNgIIIAAgAjYCBCAAIAE2AgAgAEI/IAEgA0EAQgBBDiACEQoAIgQgBEIAUxs3AxggACEFCyAFCyIAIAAoAiRBAWtBAU0EQCAAQQBCAEEKEA4aIABBADYCJAsLbgACQAJAAkAgA0IQVA0AIAJFDQECfgJAAkACQCACKAIIDgMCAAEECyACKQMAIAB8DAILIAIpAwAgAXwMAQsgAikDAAsiA0IAUw0AIAEgA1oNAgsgBARAIARBADYCBCAEQRI2AgALC0J/IQMLIAMLggICAX8CfgJAQQEgAiADGwRAIAIgA2oQCSIFRQRAIAQEQCAEQQA2AgQgBEEONgIAC0EADwsgAq0hBgJAAkAgAARAIAAgBhATIgBFBEAgBARAIARBADYCBCAEQQ42AgALDAULIAUgACACEAcaIAMNAQwCCyABIAUgBhARIgdCf1cEQCAEBEAgBCABKAIMNgIAIAQgASgCEDYCBAsMBAsgBiAHVQRAIAQEQCAEQQA2AgQgBEERNgIACwwECyADRQ0BCyACIAVqIgBBADoAACACQQFIDQAgBSECA0AgAi0AAEUEQCACQSA6AAALIAJBAWoiAiAASQ0ACwsLIAUPCyAFEAZBAAuBAQEBfwJAIAAEQCADQYAGcSEFQQAhAwNAAkAgAC8BCCACRw0AIAUgACgCBHFFDQAgA0EATg0DIANBAWohAwsgACgCACIADQALCyAEBEAgBEEANgIEIARBCTYCAAtBAA8LIAEEQCABIAAvAQo7AQALIAAvAQpFBEBBwBQPCyAAKAIMC1cBAX9BEBAJIgNFBEBBAA8LIAMgATsBCiADIAA7AQggA0GABjYCBCADQQA2AgACQCABBEAgAyACIAEQYyIANgIMIAANASADEAZBAA8LIANBADYCDAsgAwvuBQIEfwV+IwBB4ABrIgQkACAEQQhqIgNCADcDICADQQA2AhggA0L/////DzcDECADQQA7AQwgA0G/hig2AgggA0EBOgAGIANBADsBBCADQQA2AgAgA0IANwNIIANBgIDYjXg2AkQgA0IANwMoIANCADcDMCADQgA3AzggA0FAa0EAOwEAIANCADcDUCABKQMIUCIDRQRAIAEoAgAoAgApA0ghBwsCfgJAIAMEQCAHIQkMAQsgByEJA0AgCqdBBHQiBSABKAIAaigCACIDKQNIIgggCSAIIAlUGyIJIAEpAyBWBEAgAgRAIAJBADYCBCACQRM2AgALQn8MAwsgAygCMCIGBH8gBi8BBAVBAAtB//8Dca0gCCADKQMgfHxCHnwiCCAHIAcgCFQbIgcgASkDIFYEQCACBEAgAkEANgIEIAJBEzYCAAtCfwwDCyAAKAIAIAEoAgAgBWooAgApA0hBABAUIQYgACgCACEDIAZBf0wEQCACBEAgAiADKAIMNgIAIAIgAygCEDYCBAtCfwwDCyAEQQhqIANBAEEBIAIQaEJ/UQRAIARBCGoQNkJ/DAMLAkACQCABKAIAIAVqKAIAIgMvAQogBC8BEkkNACADKAIQIAQoAhhHDQAgAygCFCAEKAIcRw0AIAMoAjAgBCgCOBBiRQ0AAkAgBCgCICIGIAMoAhhHBEAgBCkDKCEIDAELIAMpAyAiCyAEKQMoIghSDQAgCyEIIAMpAyggBCkDMFENAgsgBC0AFEEIcUUNACAGDQAgCEIAUg0AIAQpAzBQDQELIAIEQCACQQA2AgQgAkEVNgIACyAEQQhqEDZCfwwDCyABKAIAIAVqKAIAKAI0IAQoAjwQbyEDIAEoAgAgBWooAgAiBUEBOgAEIAUgAzYCNCAEQQA2AjwgBEEIahA2IApCAXwiCiABKQMIVA0ACwsgByAJfSIHQv///////////wAgB0L///////////8AVBsLIQcgBEHgAGokACAHC8YBAQJ/QdgAEAkiAUUEQCAABEAgAEEANgIEIABBDjYCAAtBAA8LIAECf0EYEAkiAkUEQCAABEAgAEEANgIEIABBDjYCAAtBAAwBCyACQQA2AhAgAkIANwMIIAJBADYCACACCyIANgJQIABFBEAgARAGQQAPCyABQgA3AwAgAUEANgIQIAFCADcCCCABQgA3AhQgAUEANgJUIAFCADcCHCABQgA3ACEgAUIANwMwIAFCADcDOCABQUBrQgA3AwAgAUIANwNIIAELgBMCD38CfiMAQdAAayIFJAAgBSABNgJMIAVBN2ohEyAFQThqIRBBACEBA0ACQCAOQQBIDQBB/////wcgDmsgAUgEQEGEhAFBPTYCAEF/IQ4MAQsgASAOaiEOCyAFKAJMIgchAQJAAkACQAJAAkACQAJAAkAgBQJ/AkAgBy0AACIGBEADQAJAAkAgBkH/AXEiBkUEQCABIQYMAQsgBkElRw0BIAEhBgNAIAEtAAFBJUcNASAFIAFBAmoiCDYCTCAGQQFqIQYgAS0AAiEMIAghASAMQSVGDQALCyAGIAdrIQEgAARAIAAgByABEC4LIAENDSAFKAJMIQEgBSgCTCwAAUEwa0EKTw0DIAEtAAJBJEcNAyABLAABQTBrIQ9BASERIAFBA2oMBAsgBSABQQFqIgg2AkwgAS0AASEGIAghAQwACwALIA4hDSAADQggEUUNAkEBIQEDQCAEIAFBAnRqKAIAIgAEQCADIAFBA3RqIAAgAhB4QQEhDSABQQFqIgFBCkcNAQwKCwtBASENIAFBCk8NCANAIAQgAUECdGooAgANCCABQQFqIgFBCkcNAAsMCAtBfyEPIAFBAWoLIgE2AkxBACEIAkAgASwAACIKQSBrIgZBH0sNAEEBIAZ0IgZBidEEcUUNAANAAkAgBSABQQFqIgg2AkwgASwAASIKQSBrIgFBIE8NAEEBIAF0IgFBidEEcUUNACABIAZyIQYgCCEBDAELCyAIIQEgBiEICwJAIApBKkYEQCAFAn8CQCABLAABQTBrQQpPDQAgBSgCTCIBLQACQSRHDQAgASwAAUECdCAEakHAAWtBCjYCACABLAABQQN0IANqQYADaygCACELQQEhESABQQNqDAELIBENCEEAIRFBACELIAAEQCACIAIoAgAiAUEEajYCACABKAIAIQsLIAUoAkxBAWoLIgE2AkwgC0F/Sg0BQQAgC2shCyAIQYDAAHIhCAwBCyAFQcwAahB3IgtBAEgNBiAFKAJMIQELQX8hCQJAIAEtAABBLkcNACABLQABQSpGBEACQCABLAACQTBrQQpPDQAgBSgCTCIBLQADQSRHDQAgASwAAkECdCAEakHAAWtBCjYCACABLAACQQN0IANqQYADaygCACEJIAUgAUEEaiIBNgJMDAILIBENByAABH8gAiACKAIAIgFBBGo2AgAgASgCAAVBAAshCSAFIAUoAkxBAmoiATYCTAwBCyAFIAFBAWo2AkwgBUHMAGoQdyEJIAUoAkwhAQtBACEGA0AgBiESQX8hDSABLAAAQcEAa0E5Sw0HIAUgAUEBaiIKNgJMIAEsAAAhBiAKIQEgBiASQTpsakGf7ABqLQAAIgZBAWtBCEkNAAsgBkETRg0CIAZFDQYgD0EATgRAIAQgD0ECdGogBjYCACAFIAMgD0EDdGopAwA3A0AMBAsgAA0BC0EAIQ0MBQsgBUFAayAGIAIQeCAFKAJMIQoMAgsgD0F/Sg0DC0EAIQEgAEUNBAsgCEH//3txIgwgCCAIQYDAAHEbIQZBACENQaQIIQ8gECEIAkACQAJAAn8CQAJAAkACQAJ/AkACQAJAAkACQAJAAkAgCkEBaywAACIBQV9xIAEgAUEPcUEDRhsgASASGyIBQdgAaw4hBBISEhISEhISDhIPBg4ODhIGEhISEgIFAxISCRIBEhIEAAsCQCABQcEAaw4HDhILEg4ODgALIAFB0wBGDQkMEQsgBSkDQCEUQaQIDAULQQAhAQJAAkACQAJAAkACQAJAIBJB/wFxDggAAQIDBBcFBhcLIAUoAkAgDjYCAAwWCyAFKAJAIA42AgAMFQsgBSgCQCAOrDcDAAwUCyAFKAJAIA47AQAMEwsgBSgCQCAOOgAADBILIAUoAkAgDjYCAAwRCyAFKAJAIA6sNwMADBALIAlBCCAJQQhLGyEJIAZBCHIhBkH4ACEBCyAQIQcgAUEgcSEMIAUpA0AiFFBFBEADQCAHQQFrIgcgFKdBD3FBsPAAai0AACAMcjoAACAUQg9WIQogFEIEiCEUIAoNAAsLIAUpA0BQDQMgBkEIcUUNAyABQQR2QaQIaiEPQQIhDQwDCyAQIQEgBSkDQCIUUEUEQANAIAFBAWsiASAUp0EHcUEwcjoAACAUQgdWIQcgFEIDiCEUIAcNAAsLIAEhByAGQQhxRQ0CIAkgECAHayIBQQFqIAEgCUgbIQkMAgsgBSkDQCIUQn9XBEAgBUIAIBR9IhQ3A0BBASENQaQIDAELIAZBgBBxBEBBASENQaUIDAELQaYIQaQIIAZBAXEiDRsLIQ8gECEBAkAgFEKAgICAEFQEQCAUIRUMAQsDQCABQQFrIgEgFCAUQgqAIhVCCn59p0EwcjoAACAUQv////+fAVYhByAVIRQgBw0ACwsgFaciBwRAA0AgAUEBayIBIAcgB0EKbiIMQQpsa0EwcjoAACAHQQlLIQogDCEHIAoNAAsLIAEhBwsgBkH//3txIAYgCUF/ShshBgJAIAUpA0AiFEIAUg0AIAkNAEEAIQkgECEHDAoLIAkgFFAgECAHa2oiASABIAlIGyEJDAkLIAUoAkAiAUGKEiABGyIHQQAgCRB6IgEgByAJaiABGyEIIAwhBiABIAdrIAkgARshCQwICyAJBEAgBSgCQAwCC0EAIQEgAEEgIAtBACAGECcMAgsgBUEANgIMIAUgBSkDQD4CCCAFIAVBCGo2AkBBfyEJIAVBCGoLIQhBACEBAkADQCAIKAIAIgdFDQECQCAFQQRqIAcQeSIHQQBIIgwNACAHIAkgAWtLDQAgCEEEaiEIIAkgASAHaiIBSw0BDAILC0F/IQ0gDA0FCyAAQSAgCyABIAYQJyABRQRAQQAhAQwBC0EAIQggBSgCQCEKA0AgCigCACIHRQ0BIAVBBGogBxB5IgcgCGoiCCABSg0BIAAgBUEEaiAHEC4gCkEEaiEKIAEgCEsNAAsLIABBICALIAEgBkGAwABzECcgCyABIAEgC0gbIQEMBQsgACAFKwNAIAsgCSAGIAFBABEdACEBDAQLIAUgBSkDQDwAN0EBIQkgEyEHIAwhBgwCC0F/IQ0LIAVB0ABqJAAgDQ8LIABBICANIAggB2siDCAJIAkgDEgbIgpqIgggCyAIIAtKGyIBIAggBhAnIAAgDyANEC4gAEEwIAEgCCAGQYCABHMQJyAAQTAgCiAMQQAQJyAAIAcgDBAuIABBICABIAggBkGAwABzECcMAAsAC54DAgR/AX4gAARAIAAoAgAiAQRAIAEQGhogACgCABALCyAAKAIcEAYgACgCIBAQIAAoAiQQECAAKAJQIgMEQCADKAIQIgIEQCADKAIAIgEEfwNAIAIgBEECdGooAgAiAgRAA0AgAigCGCEBIAIQBiABIgINAAsgAygCACEBCyABIARBAWoiBEsEQCADKAIQIQIMAQsLIAMoAhAFIAILEAYLIAMQBgsgACgCQCIBBEAgACkDMFAEfyABBSABED5CAiEFAkAgACkDMEICVA0AQQEhAgNAIAAoAkAgAkEEdGoQPiAFIAApAzBaDQEgBachAiAFQgF8IQUMAAsACyAAKAJACxAGCwJAIAAoAkRFDQBBACECQgEhBQNAIAAoAkwgAkECdGooAgAiAUEBOgAoIAFBDGoiASgCAEUEQCABBEAgAUEANgIEIAFBCDYCAAsLIAUgADUCRFoNASAFpyECIAVCAXwhBQwACwALIAAoAkwQBiAAKAJUIgIEQCACKAIIIgEEQCACKAIMIAERAwALIAIQBgsgAEEIahAxIAAQBgsL6gMCAX4EfwJAIAAEfiABRQRAIAMEQCADQQA2AgQgA0ESNgIAC0J/DwsgAkGDIHEEQAJAIAApAzBQDQBBPEE9IAJBAXEbIQcgAkECcUUEQANAIAAgBCACIAMQUyIFBEAgASAFIAcRAgBFDQYLIARCAXwiBCAAKQMwVA0ADAILAAsDQCAAIAQgAiADEFMiBQRAIAECfyAFECJBAWohBgNAQQAgBkUNARogBSAGQQFrIgZqIggtAABBL0cNAAsgCAsiBkEBaiAFIAYbIAcRAgBFDQULIARCAXwiBCAAKQMwVA0ACwsgAwRAIANBADYCBCADQQk2AgALQn8PC0ESIQYCQAJAIAAoAlAiBUUNACABRQ0AQQkhBiAFKQMIUA0AIAUoAhAgAS0AACIHBH9CpesKIQQgASEAA0AgBCAHrUL/AYN8IQQgAC0AASIHBEAgAEEBaiEAIARC/////w+DQiF+IQQMAQsLIASnBUGFKgsgBSgCAHBBAnRqKAIAIgBFDQADQCABIAAoAgAQOEUEQCACQQhxBEAgACkDCCIEQn9RDQMMBAsgACkDECIEQn9RDQIMAwsgACgCGCIADQALCyADBEAgA0EANgIEIAMgBjYCAAtCfyEECyAEBUJ/Cw8LIAMEQCADQgA3AgALIAQL3AQCB38BfgJAAkAgAEUNACABRQ0AIAJCf1UNAQsgBARAIARBADYCBCAEQRI2AgALQQAPCwJAIAAoAgAiB0UEQEGAAiEHQYACEDwiBkUNASAAKAIQEAYgAEGAAjYCACAAIAY2AhALAkACQCAAKAIQIAEtAAAiBQR/QqXrCiEMIAEhBgNAIAwgBa1C/wGDfCEMIAYtAAEiBQRAIAZBAWohBiAMQv////8Pg0IhfiEMDAELCyAMpwVBhSoLIgYgB3BBAnRqIggoAgAiBQRAA0ACQCAFKAIcIAZHDQAgASAFKAIAEDgNAAJAIANBCHEEQCAFKQMIQn9SDQELIAUpAxBCf1ENBAsgBARAIARBADYCBCAEQQo2AgALQQAPCyAFKAIYIgUNAAsLQSAQCSIFRQ0CIAUgATYCACAFIAgoAgA2AhggCCAFNgIAIAVCfzcDCCAFIAY2AhwgACAAKQMIQgF8Igw3AwggDLogB7hEAAAAAAAA6D+iZEUNACAHQQBIDQAgByAHQQF0IghGDQAgCBA8IgpFDQECQCAMQgAgBxtQBEAgACgCECEJDAELIAAoAhAhCUEAIQQDQCAJIARBAnRqKAIAIgYEQANAIAYoAhghASAGIAogBigCHCAIcEECdGoiCygCADYCGCALIAY2AgAgASIGDQALCyAEQQFqIgQgB0cNAAsLIAkQBiAAIAg2AgAgACAKNgIQCyADQQhxBEAgBSACNwMICyAFIAI3AxBBAQ8LIAQEQCAEQQA2AgQgBEEONgIAC0EADwsgBARAIARBADYCBCAEQQ42AgALQQAL3Q8BF38jAEFAaiIHQgA3AzAgB0IANwM4IAdCADcDICAHQgA3AygCQAJAAkACQAJAIAIEQCACQQNxIQggAkEBa0EDTwRAIAJBfHEhBgNAIAdBIGogASAJQQF0IgxqLwEAQQF0aiIKIAovAQBBAWo7AQAgB0EgaiABIAxBAnJqLwEAQQF0aiIKIAovAQBBAWo7AQAgB0EgaiABIAxBBHJqLwEAQQF0aiIKIAovAQBBAWo7AQAgB0EgaiABIAxBBnJqLwEAQQF0aiIKIAovAQBBAWo7AQAgCUEEaiEJIAZBBGsiBg0ACwsgCARAA0AgB0EgaiABIAlBAXRqLwEAQQF0aiIGIAYvAQBBAWo7AQAgCUEBaiEJIAhBAWsiCA0ACwsgBCgCACEJQQ8hCyAHLwE+IhENAgwBCyAEKAIAIQkLQQ4hC0EAIREgBy8BPA0AQQ0hCyAHLwE6DQBBDCELIAcvATgNAEELIQsgBy8BNg0AQQohCyAHLwE0DQBBCSELIAcvATINAEEIIQsgBy8BMA0AQQchCyAHLwEuDQBBBiELIAcvASwNAEEFIQsgBy8BKg0AQQQhCyAHLwEoDQBBAyELIAcvASYNAEECIQsgBy8BJA0AIAcvASJFBEAgAyADKAIAIgBBBGo2AgAgAEHAAjYBACADIAMoAgAiAEEEajYCACAAQcACNgEAQQEhDQwDCyAJQQBHIRtBASELQQEhCQwBCyALIAkgCSALSxshG0EBIQ5BASEJA0AgB0EgaiAJQQF0ai8BAA0BIAlBAWoiCSALRw0ACyALIQkLQX8hCCAHLwEiIg9BAksNAUEEIAcvASQiECAPQQF0amsiBkEASA0BIAZBAXQgBy8BJiISayIGQQBIDQEgBkEBdCAHLwEoIhNrIgZBAEgNASAGQQF0IAcvASoiFGsiBkEASA0BIAZBAXQgBy8BLCIVayIGQQBIDQEgBkEBdCAHLwEuIhZrIgZBAEgNASAGQQF0IAcvATAiF2siBkEASA0BIAZBAXQgBy8BMiIZayIGQQBIDQEgBkEBdCAHLwE0IhxrIgZBAEgNASAGQQF0IAcvATYiDWsiBkEASA0BIAZBAXQgBy8BOCIYayIGQQBIDQEgBkEBdCAHLwE6IgxrIgZBAEgNASAGQQF0IAcvATwiCmsiBkEASA0BIAZBAXQgEWsiBkEASA0BIAZBACAARSAOchsNASAJIBtLIRpBACEIIAdBADsBAiAHIA87AQQgByAPIBBqIgY7AQYgByAGIBJqIgY7AQggByAGIBNqIgY7AQogByAGIBRqIgY7AQwgByAGIBVqIgY7AQ4gByAGIBZqIgY7ARAgByAGIBdqIgY7ARIgByAGIBlqIgY7ARQgByAGIBxqIgY7ARYgByAGIA1qIgY7ARggByAGIBhqIgY7ARogByAGIAxqIgY7ARwgByAGIApqOwEeAkAgAkUNACACQQFHBEAgAkF+cSEGA0AgASAIQQF0ai8BACIKBEAgByAKQQF0aiIKIAovAQAiCkEBajsBACAFIApBAXRqIAg7AQALIAEgCEEBciIMQQF0ai8BACIKBEAgByAKQQF0aiIKIAovAQAiCkEBajsBACAFIApBAXRqIAw7AQALIAhBAmohCCAGQQJrIgYNAAsLIAJBAXFFDQAgASAIQQF0ai8BACICRQ0AIAcgAkEBdGoiAiACLwEAIgJBAWo7AQAgBSACQQF0aiAIOwEACyAJIBsgGhshDUEUIRBBACEWIAUiCiEYQQAhEgJAAkACQCAADgICAAELQQEhCCANQQpLDQNBgQIhEEHw2QAhGEGw2QAhCkEBIRIMAQsgAEECRiEWQQAhEEHw2gAhGEGw2gAhCiAAQQJHBEAMAQtBASEIIA1BCUsNAgtBASANdCITQQFrIRwgAygCACEUQQAhFSANIQZBACEPQQAhDkF/IQIDQEEBIAZ0IRoCQANAIAkgD2shFwJAIAUgFUEBdGovAQAiCCAQTwRAIAogCCAQa0EBdCIAai8BACERIAAgGGotAAAhAAwBC0EAQeAAIAhBAWogEEkiBhshACAIQQAgBhshEQsgDiAPdiEMQX8gF3QhBiAaIQgDQCAUIAYgCGoiCCAMakECdGoiGSAROwECIBkgFzoAASAZIAA6AAAgCA0AC0EBIAlBAWt0IQYDQCAGIgBBAXYhBiAAIA5xDQALIAdBIGogCUEBdGoiBiAGLwEAQQFrIgY7AQAgAEEBayAOcSAAakEAIAAbIQ4gFUEBaiEVIAZB//8DcUUEQCAJIAtGDQIgASAFIBVBAXRqLwEAQQF0ai8BACEJCyAJIA1NDQAgDiAccSIAIAJGDQALQQEgCSAPIA0gDxsiD2siBnQhAiAJIAtJBEAgCyAPayEMIAkhCAJAA0AgAiAHQSBqIAhBAXRqLwEAayICQQFIDQEgAkEBdCECIAZBAWoiBiAPaiIIIAtJDQALIAwhBgtBASAGdCECC0EBIQggEiACIBNqIhNBtApLcQ0DIBYgE0HQBEtxDQMgAygCACICIABBAnRqIgggDToAASAIIAY6AAAgCCAUIBpBAnRqIhQgAmtBAnY7AQIgACECDAELCyAOBEAgFCAOQQJ0aiIAQQA7AQIgACAXOgABIABBwAA6AAALIAMgAygCACATQQJ0ajYCAAsgBCANNgIAQQAhCAsgCAusAQICfgF/IAFBAmqtIQIgACkDmC4hAwJAIAAoAqAuIgFBA2oiBEE/TQRAIAIgAa2GIAOEIQIMAQsgAUHAAEYEQCAAKAIEIAAoAhBqIAM3AAAgACAAKAIQQQhqNgIQQQMhBAwBCyAAKAIEIAAoAhBqIAIgAa2GIAOENwAAIAAgACgCEEEIajYCECABQT1rIQQgAkHAACABa62IIQILIAAgAjcDmC4gACAENgKgLguXAwICfgN/QYDJADMBACECIAApA5guIQMCQCAAKAKgLiIFQYLJAC8BACIGaiIEQT9NBEAgAiAFrYYgA4QhAgwBCyAFQcAARgRAIAAoAgQgACgCEGogAzcAACAAIAAoAhBBCGo2AhAgBiEEDAELIAAoAgQgACgCEGogAiAFrYYgA4Q3AAAgACAAKAIQQQhqNgIQIARBQGohBCACQcAAIAVrrYghAgsgACACNwOYLiAAIAQ2AqAuIAEEQAJAIARBOU4EQCAAKAIEIAAoAhBqIAI3AAAgACAAKAIQQQhqNgIQDAELIARBGU4EQCAAKAIEIAAoAhBqIAI+AAAgACAAKAIQQQRqNgIQIAAgACkDmC5CIIgiAjcDmC4gACAAKAKgLkEgayIENgKgLgsgBEEJTgR/IAAoAgQgACgCEGogAj0AACAAIAAoAhBBAmo2AhAgACkDmC5CEIghAiAAKAKgLkEQawUgBAtBAUgNACAAIAAoAhAiAUEBajYCECABIAAoAgRqIAI8AAALIABBADYCoC4gAEIANwOYLgsL8hQBEn8gASgCCCICKAIAIQUgAigCDCEHIAEoAgAhCCAAQoCAgIDQxwA3A6ApQQAhAgJAAkAgB0EASgRAQX8hDANAAkAgCCACQQJ0aiIDLwEABEAgACAAKAKgKUEBaiIDNgKgKSAAIANBAnRqQawXaiACNgIAIAAgAmpBqClqQQA6AAAgAiEMDAELIANBADsBAgsgAkEBaiICIAdHDQALIABB/C1qIQ8gAEH4LWohESAAKAKgKSIEQQFKDQIMAQsgAEH8LWohDyAAQfgtaiERQX8hDAsDQCAAIARBAWoiAjYCoCkgACACQQJ0akGsF2ogDEEBaiIDQQAgDEECSCIGGyICNgIAIAggAkECdCIEakEBOwEAIAAgAmpBqClqQQA6AAAgACAAKAL4LUEBazYC+C0gBQRAIA8gDygCACAEIAVqLwECazYCAAsgAyAMIAYbIQwgACgCoCkiBEECSA0ACwsgASAMNgIEIARBAXYhBgNAIAAgBkECdGpBrBdqKAIAIQkCQCAGIgJBAXQiAyAESg0AIAggCUECdGohCiAAIAlqQagpaiENIAYhBQNAAkAgAyAETgRAIAMhAgwBCyAIIABBrBdqIgIgA0EBciIEQQJ0aigCACILQQJ0ai8BACIOIAggAiADQQJ0aigCACIQQQJ0ai8BACICTwRAIAIgDkcEQCADIQIMAgsgAyECIABBqClqIgMgC2otAAAgAyAQai0AAEsNAQsgBCECCyAKLwEAIgQgCCAAIAJBAnRqQawXaigCACIDQQJ0ai8BACILSQRAIAUhAgwCCwJAIAQgC0cNACANLQAAIAAgA2pBqClqLQAASw0AIAUhAgwCCyAAIAVBAnRqQawXaiADNgIAIAIhBSACQQF0IgMgACgCoCkiBEwNAAsLIAAgAkECdGpBrBdqIAk2AgAgBkECTgRAIAZBAWshBiAAKAKgKSEEDAELCyAAKAKgKSEDA0AgByEGIAAgA0EBayIENgKgKSAAKAKwFyEKIAAgACADQQJ0akGsF2ooAgAiCTYCsBdBASECAkAgA0EDSA0AIAggCUECdGohDSAAIAlqQagpaiELQQIhA0EBIQUDQAJAIAMgBE4EQCADIQIMAQsgCCAAQawXaiICIANBAXIiB0ECdGooAgAiBEECdGovAQAiDiAIIAIgA0ECdGooAgAiEEECdGovAQAiAk8EQCACIA5HBEAgAyECDAILIAMhAiAAQagpaiIDIARqLQAAIAMgEGotAABLDQELIAchAgsgDS8BACIHIAggACACQQJ0akGsF2ooAgAiA0ECdGovAQAiBEkEQCAFIQIMAgsCQCAEIAdHDQAgCy0AACAAIANqQagpai0AAEsNACAFIQIMAgsgACAFQQJ0akGsF2ogAzYCACACIQUgAkEBdCIDIAAoAqApIgRMDQALC0ECIQMgAEGsF2oiByACQQJ0aiAJNgIAIAAgACgCpClBAWsiBTYCpCkgACgCsBchAiAHIAVBAnRqIAo2AgAgACAAKAKkKUEBayIFNgKkKSAHIAVBAnRqIAI2AgAgCCAGQQJ0aiINIAggAkECdGoiBS8BACAIIApBAnRqIgQvAQBqOwEAIABBqClqIgkgBmoiCyACIAlqLQAAIgIgCSAKai0AACIKIAIgCksbQQFqOgAAIAUgBjsBAiAEIAY7AQIgACAGNgKwF0EBIQVBASECAkAgACgCoCkiBEECSA0AA0AgDS8BACIKIAggAAJ/IAMgAyAETg0AGiAIIAcgA0EBciICQQJ0aigCACIEQQJ0ai8BACIOIAggByADQQJ0aigCACIQQQJ0ai8BACISTwRAIAMgDiASRw0BGiADIAQgCWotAAAgCSAQai0AAEsNARoLIAILIgJBAnRqQawXaigCACIDQQJ0ai8BACIESQRAIAUhAgwCCwJAIAQgCkcNACALLQAAIAAgA2pBqClqLQAASw0AIAUhAgwCCyAAIAVBAnRqQawXaiADNgIAIAIhBSACQQF0IgMgACgCoCkiBEwNAAsLIAZBAWohByAAIAJBAnRqQawXaiAGNgIAIAAoAqApIgNBAUoNAAsgACAAKAKkKUEBayICNgKkKSAAQawXaiIDIAJBAnRqIAAoArAXNgIAIAEoAgQhCSABKAIIIgIoAhAhBiACKAIIIQogAigCBCEQIAIoAgAhDSABKAIAIQcgAEGkF2pCADcBACAAQZwXakIANwEAIABBlBdqQgA3AQAgAEGMF2oiAUIANwEAQQAhBSAHIAMgACgCpClBAnRqKAIAQQJ0akEAOwECAkAgACgCpCkiAkG7BEoNACACQQFqIQIDQCAHIAAgAkECdGpBrBdqKAIAIgRBAnQiEmoiCyAHIAsvAQJBAnRqLwECIgNBAWogBiADIAZJGyIOOwECIAMgBk8hEwJAIAQgCUoNACAAIA5BAXRqQYwXaiIDIAMvAQBBAWo7AQBBACEDIAQgCk4EQCAQIAQgCmtBAnRqKAIAIQMLIBEgESgCACALLwEAIgQgAyAOamxqNgIAIA1FDQAgDyAPKAIAIAMgDSASai8BAmogBGxqNgIACyAFIBNqIQUgAkEBaiICQb0ERw0ACyAFRQ0AIAAgBkEBdGpBjBdqIQQDQCAGIQIDQCAAIAIiA0EBayICQQF0akGMF2oiDy8BACIKRQ0ACyAPIApBAWs7AQAgACADQQF0akGMF2oiAiACLwEAQQJqOwEAIAQgBC8BAEEBayIDOwEAIAVBAkohAiAFQQJrIQUgAg0ACyAGRQ0AQb0EIQIDQCADQf//A3EiBQRAA0AgACACQQFrIgJBAnRqQawXaigCACIDIAlKDQAgByADQQJ0aiIDLwECIAZHBEAgESARKAIAIAYgAy8BAGxqIgQ2AgAgESAEIAMvAQAgAy8BAmxrNgIAIAMgBjsBAgsgBUEBayIFDQALCyAGQQFrIgZFDQEgACAGQQF0akGMF2ovAQAhAwwACwALIwBBIGsiAiABIgAvAQBBAXQiATsBAiACIAEgAC8BAmpBAXQiATsBBCACIAEgAC8BBGpBAXQiATsBBiACIAEgAC8BBmpBAXQiATsBCCACIAEgAC8BCGpBAXQiATsBCiACIAEgAC8BCmpBAXQiATsBDCACIAEgAC8BDGpBAXQiATsBDiACIAEgAC8BDmpBAXQiATsBECACIAEgAC8BEGpBAXQiATsBEiACIAEgAC8BEmpBAXQiATsBFCACIAEgAC8BFGpBAXQiATsBFiACIAEgAC8BFmpBAXQiATsBGCACIAEgAC8BGGpBAXQiATsBGiACIAEgAC8BGmpBAXQiATsBHCACIAAvARwgAWpBAXQ7AR5BACEAIAxBAE4EQANAIAggAEECdGoiAy8BAiIBBEAgAiABQQF0aiIFIAUvAQAiBUEBajsBACADIAWtQoD+A4NCCIhCgpCAgQh+QpDCiKKIAYNCgYKEiBB+QiCIp0H/AXEgBUH/AXGtQoKQgIEIfkKQwoiiiAGDQoGChIgQfkIYiKdBgP4DcXJBECABa3Y7AQALIAAgDEchASAAQQFqIQAgAQ0ACwsLcgEBfyMAQRBrIgQkAAJ/QQAgAEUNABogAEEIaiEAIAFFBEAgAlBFBEAgAARAIABBADYCBCAAQRI2AgALQQAMAgtBAEIAIAMgABA6DAELIAQgAjcDCCAEIAE2AgAgBEIBIAMgABA6CyEAIARBEGokACAACyIAIAAgASACIAMQJiIARQRAQQAPCyAAKAIwQQAgAiADECULAwABC8gFAQR/IABB//8DcSEDIABBEHYhBEEBIQAgAkEBRgRAIAMgAS0AAGpB8f8DcCIAIARqQfH/A3BBEHQgAHIPCwJAIAEEfyACQRBJDQECQCACQa8rSwRAA0AgAkGwK2shAkG1BSEFIAEhAANAIAMgAC0AAGoiAyAEaiADIAAtAAFqIgNqIAMgAC0AAmoiA2ogAyAALQADaiIDaiADIAAtAARqIgNqIAMgAC0ABWoiA2ogAyAALQAGaiIDaiADIAAtAAdqIgNqIQQgBQRAIABBCGohACAFQQFrIQUMAQsLIARB8f8DcCEEIANB8f8DcCEDIAFBsCtqIQEgAkGvK0sNAAsgAkEISQ0BCwNAIAMgAS0AAGoiACAEaiAAIAEtAAFqIgBqIAAgAS0AAmoiAGogACABLQADaiIAaiAAIAEtAARqIgBqIAAgAS0ABWoiAGogACABLQAGaiIAaiAAIAEtAAdqIgNqIQQgAUEIaiEBIAJBCGsiAkEHSw0ACwsCQCACRQ0AIAJBAWshBiACQQNxIgUEQCABIQADQCACQQFrIQIgAyAALQAAaiIDIARqIQQgAEEBaiIBIQAgBUEBayIFDQALCyAGQQNJDQADQCADIAEtAABqIgAgAS0AAWoiBSABLQACaiIGIAEtAANqIgMgBiAFIAAgBGpqamohBCABQQRqIQEgAkEEayICDQALCyADQfH/A3AgBEHx/wNwQRB0cgVBAQsPCwJAIAJFDQAgAkEBayEGIAJBA3EiBQRAIAEhAANAIAJBAWshAiADIAAtAABqIgMgBGohBCAAQQFqIgEhACAFQQFrIgUNAAsLIAZBA0kNAANAIAMgAS0AAGoiACABLQABaiIFIAEtAAJqIgYgAS0AA2oiAyAGIAUgACAEampqaiEEIAFBBGohASACQQRrIgINAAsLIANB8f8DcCAEQfH/A3BBEHRyCx8AIAAgAiADQcCAASgCABEAACEAIAEgAiADEAcaIAALIwAgACAAKAJAIAIgA0HUgAEoAgARAAA2AkAgASACIAMQBxoLzSoCGH8HfiAAKAIMIgIgACgCECIDaiEQIAMgAWshASAAKAIAIgUgACgCBGohA0F/IAAoAhwiBygCpAF0IQRBfyAHKAKgAXQhCyAHKAI4IQwCf0EAIAcoAiwiEUUNABpBACACIAxJDQAaIAJBhAJqIAwgEWpNCyEWIBBBgwJrIRMgASACaiEXIANBDmshFCAEQX9zIRggC0F/cyESIAcoApwBIRUgBygCmAEhDSAHKAKIASEIIAc1AoQBIR0gBygCNCEOIAcoAjAhGSAQQQFqIQ8DQCAIQThyIQYgBSAIQQN2QQdxayELAn8gAiANIAUpAAAgCK2GIB2EIh2nIBJxQQJ0IgFqIgMtAAAiBA0AGiACIAEgDWoiAS0AAjoAACAGIAEtAAEiAWshBiACQQFqIA0gHSABrYgiHacgEnFBAnQiAWoiAy0AACIEDQAaIAIgASANaiIDLQACOgABIAYgAy0AASIDayEGIA0gHSADrYgiHacgEnFBAnRqIgMtAAAhBCACQQJqCyEBIAtBB2ohBSAGIAMtAAEiAmshCCAdIAKtiCEdAkACQAJAIARB/wFxRQ0AAkACQAJAAkACQANAIARBEHEEQCAVIB0gBK1CD4OIIhqnIBhxQQJ0aiECAn8gCCAEQQ9xIgZrIgRBG0sEQCAEIQggBQwBCyAEQThyIQggBSkAACAErYYgGoQhGiAFIARBA3ZrQQdqCyELIAMzAQIhGyAIIAItAAEiA2shCCAaIAOtiCEaIAItAAAiBEEQcQ0CA0AgBEHAAHFFBEAgCCAVIAIvAQJBAnRqIBqnQX8gBHRBf3NxQQJ0aiICLQABIgNrIQggGiADrYghGiACLQAAIgRBEHFFDQEMBAsLIAdB0f4ANgIEIABB7A42AhggGiEdDAMLIARB/wFxIgJBwABxRQRAIAggDSADLwECQQJ0aiAdp0F/IAJ0QX9zcUECdGoiAy0AASICayEIIB0gAq2IIR0gAy0AACIERQ0HDAELCyAEQSBxBEAgB0G//gA2AgQgASECDAgLIAdB0f4ANgIEIABB0A42AhggASECDAcLIB1BfyAGdEF/c62DIBt8IhunIQUgCCAEQQ9xIgNrIQggGiAErUIPg4ghHSABIBdrIgYgAjMBAiAaQX8gA3RBf3Otg3ynIgRPDQIgBCAGayIGIBlNDQEgBygCjEdFDQEgB0HR/gA2AgQgAEG5DDYCGAsgASECIAshBQwFCwJAIA5FBEAgDCARIAZraiEDDAELIAYgDk0EQCAMIA4gBmtqIQMMAQsgDCARIAYgDmsiBmtqIQMgBSAGTQ0AIAUgBmshBQJAAkAgASADTSABIA8gAWusIhogBq0iGyAaIBtUGyIapyIGaiICIANLcQ0AIAMgBmogAUsgASADT3ENACABIAMgBhAHGiACIQEMAQsgASADIAMgAWsiASABQR91IgFqIAFzIgIQByACaiEBIBogAq0iHn0iHFANACACIANqIQIDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgASACKQAANwAAIAEgAikAGDcAGCABIAIpABA3ABAgASACKQAINwAIIBpCIH0hGiACQSBqIQIgAUEgaiEBIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAEgAikAADcAACABIAIpABg3ABggASACKQAQNwAQIAEgAikACDcACCABIAIpADg3ADggASACKQAwNwAwIAEgAikAKDcAKCABIAIpACA3ACAgASACKQBYNwBYIAEgAikAUDcAUCABIAIpAEg3AEggASACKQBANwBAIAEgAikAYDcAYCABIAIpAGg3AGggASACKQBwNwBwIAEgAikAeDcAeCACQYABaiECIAFBgAFqIQEgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAEgAikAADcAACABIAIpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCABIAIpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCABIAIoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCABIAIvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCABIAItAAA6AAAgAkEBaiECIAFBAWohAQsgHEIAUg0ACwsgDiEGIAwhAwsgBSAGSwRAAkACQCABIANNIAEgDyABa6wiGiAGrSIbIBogG1QbIhqnIglqIgIgA0txDQAgAyAJaiABSyABIANPcQ0AIAEgAyAJEAcaDAELIAEgAyADIAFrIgEgAUEfdSIBaiABcyIBEAcgAWohAiAaIAGtIh59IhxQDQAgASADaiEBA0ACQCAcIB4gHCAeVBsiG0IgVARAIBshGgwBCyAbIhpCIH0iIEIFiEIBfEIDgyIfUEUEQANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCAaQiB9IRogAUEgaiEBIAJBIGohAiAfQgF9Ih9CAFINAAsLICBC4ABUDQADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggAiABKQA4NwA4IAIgASkAMDcAMCACIAEpACg3ACggAiABKQAgNwAgIAIgASkAWDcAWCACIAEpAFA3AFAgAiABKQBINwBIIAIgASkAQDcAQCACIAEpAGA3AGAgAiABKQBoNwBoIAIgASkAcDcAcCACIAEpAHg3AHggAUGAAWohASACQYABaiECIBpCgAF9IhpCH1YNAAsLIBpCEFoEQCACIAEpAAA3AAAgAiABKQAINwAIIBpCEH0hGiACQRBqIQIgAUEQaiEBCyAaQghaBEAgAiABKQAANwAAIBpCCH0hGiACQQhqIQIgAUEIaiEBCyAaQgRaBEAgAiABKAAANgAAIBpCBH0hGiACQQRqIQIgAUEEaiEBCyAaQgJaBEAgAiABLwAAOwAAIBpCAn0hGiACQQJqIQIgAUECaiEBCyAcIBt9IRwgGlBFBEAgAiABLQAAOgAAIAJBAWohAiABQQFqIQELIBxCAFINAAsLIAUgBmshAUEAIARrIQUCQCAEQQdLBEAgBCEDDAELIAEgBE0EQCAEIQMMAQsgAiAEayEFA0ACQCACIAUpAAA3AAAgBEEBdCEDIAEgBGshASACIARqIQIgBEEDSw0AIAMhBCABIANLDQELC0EAIANrIQULIAIgBWohBAJAIAUgDyACa6wiGiABrSIbIBogG1QbIhqnIgFIIAVBf0pxDQAgBUEBSCABIARqIAJLcQ0AIAIgBCABEAcgAWohAgwDCyACIAQgAyADQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANAiABIARqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAILAkAgASADTSABIA8gAWusIhogBa0iGyAaIBtUGyIapyIEaiICIANLcQ0AIAMgBGogAUsgASADT3ENACABIAMgBBAHGgwCCyABIAMgAyABayIBIAFBH3UiAWogAXMiARAHIAFqIQIgGiABrSIefSIcUA0BIAEgA2ohAQNAAkAgHCAeIBwgHlQbIhtCIFQEQCAbIRoMAQsgGyIaQiB9IiBCBYhCAXxCA4MiH1BFBEADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggGkIgfSEaIAFBIGohASACQSBqIQIgH0IBfSIfQgBSDQALCyAgQuAAVA0AA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIAIgASkAODcAOCACIAEpADA3ADAgAiABKQAoNwAoIAIgASkAIDcAICACIAEpAFg3AFggAiABKQBQNwBQIAIgASkASDcASCACIAEpAEA3AEAgAiABKQBgNwBgIAIgASkAaDcAaCACIAEpAHA3AHAgAiABKQB4NwB4IAFBgAFqIQEgAkGAAWohAiAaQoABfSIaQh9WDQALCyAaQhBaBEAgAiABKQAANwAAIAIgASkACDcACCAaQhB9IRogAkEQaiECIAFBEGohAQsgGkIIWgRAIAIgASkAADcAACAaQgh9IRogAkEIaiECIAFBCGohAQsgGkIEWgRAIAIgASgAADYAACAaQgR9IRogAkEEaiECIAFBBGohAQsgGkICWgRAIAIgAS8AADsAACAaQgJ9IRogAkECaiECIAFBAmohAQsgHCAbfSEcIBpQRQRAIAIgAS0AADoAACACQQFqIQIgAUEBaiEBCyAcUEUNAAsMAQsCQAJAIBYEQAJAIAQgBUkEQCAHKAKYRyAESw0BCyABIARrIQMCQEEAIARrIgVBf0ogDyABa6wiGiAbIBogG1QbIhqnIgIgBUpxDQAgBUEBSCACIANqIAFLcQ0AIAEgAyACEAcgAmohAgwFCyABIAMgBCAEQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANBCABIANqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAQLIBAgAWsiCUEBaiIGIAUgBSAGSxshAyABIARrIQIgAUEHcUUNAiADRQ0CIAEgAi0AADoAACACQQFqIQIgAUEBaiIGQQdxQQAgA0EBayIFGw0BIAYhASAFIQMgCSEGDAILAkAgBCAFSQRAIAcoAphHIARLDQELIAEgASAEayIGKQAANwAAIAEgBUEBa0EHcUEBaiIDaiECIAUgA2siBEUNAyADIAZqIQEDQCACIAEpAAA3AAAgAUEIaiEBIAJBCGohAiAEQQhrIgQNAAsMAwsgASAEIAUQPyECDAILIAEgAi0AADoAASAJQQFrIQYgA0ECayEFIAJBAWohAgJAIAFBAmoiCkEHcUUNACAFRQ0AIAEgAi0AADoAAiAJQQJrIQYgA0EDayEFIAJBAWohAgJAIAFBA2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAAyAJQQNrIQYgA0EEayEFIAJBAWohAgJAIAFBBGoiCkEHcUUNACAFRQ0AIAEgAi0AADoABCAJQQRrIQYgA0EFayEFIAJBAWohAgJAIAFBBWoiCkEHcUUNACAFRQ0AIAEgAi0AADoABSAJQQVrIQYgA0EGayEFIAJBAWohAgJAIAFBBmoiCkEHcUUNACAFRQ0AIAEgAi0AADoABiAJQQZrIQYgA0EHayEFIAJBAWohAgJAIAFBB2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAByAJQQdrIQYgA0EIayEDIAFBCGohASACQQFqIQIMBgsgCiEBIAUhAwwFCyAKIQEgBSEDDAQLIAohASAFIQMMAwsgCiEBIAUhAwwCCyAKIQEgBSEDDAELIAohASAFIQMLAkACQCAGQRdNBEAgA0UNASADQQFrIQUgA0EHcSIEBEADQCABIAItAAA6AAAgA0EBayEDIAFBAWohASACQQFqIQIgBEEBayIEDQALCyAFQQdJDQEDQCABIAItAAA6AAAgASACLQABOgABIAEgAi0AAjoAAiABIAItAAM6AAMgASACLQAEOgAEIAEgAi0ABToABSABIAItAAY6AAYgASACLQAHOgAHIAFBCGohASACQQhqIQIgA0EIayIDDQALDAELIAMNAQsgASECDAELIAEgBCADED8hAgsgCyEFDAELIAEgAy0AAjoAACABQQFqIQILIAUgFE8NACACIBNJDQELCyAAIAI2AgwgACAFIAhBA3ZrIgE2AgAgACATIAJrQYMCajYCECAAIBQgAWtBDmo2AgQgByAIQQdxIgA2AogBIAcgHUJ/IACthkJ/hYM+AoQBC+cFAQR/IAMgAiACIANLGyEEIAAgAWshAgJAIABBB3FFDQAgBEUNACAAIAItAAA6AAAgA0EBayEGIAJBAWohAiAAQQFqIgdBB3FBACAEQQFrIgUbRQRAIAchACAFIQQgBiEDDAELIAAgAi0AADoAASADQQJrIQYgBEECayEFIAJBAWohAgJAIABBAmoiB0EHcUUNACAFRQ0AIAAgAi0AADoAAiADQQNrIQYgBEEDayEFIAJBAWohAgJAIABBA2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAAyADQQRrIQYgBEEEayEFIAJBAWohAgJAIABBBGoiB0EHcUUNACAFRQ0AIAAgAi0AADoABCADQQVrIQYgBEEFayEFIAJBAWohAgJAIABBBWoiB0EHcUUNACAFRQ0AIAAgAi0AADoABSADQQZrIQYgBEEGayEFIAJBAWohAgJAIABBBmoiB0EHcUUNACAFRQ0AIAAgAi0AADoABiADQQdrIQYgBEEHayEFIAJBAWohAgJAIABBB2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAByADQQhrIQMgBEEIayEEIABBCGohACACQQFqIQIMBgsgByEAIAUhBCAGIQMMBQsgByEAIAUhBCAGIQMMBAsgByEAIAUhBCAGIQMMAwsgByEAIAUhBCAGIQMMAgsgByEAIAUhBCAGIQMMAQsgByEAIAUhBCAGIQMLAkAgA0EXTQRAIARFDQEgBEEBayEBIARBB3EiAwRAA0AgACACLQAAOgAAIARBAWshBCAAQQFqIQAgAkEBaiECIANBAWsi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CyAAIAMtAAAEfiADKQMQBUIAC6dB//8DcSADKAIEEEcLIQUgAxAICyAEQRBqJAAgBQvgAQICfwF+QTAQCSICRQRAIAEEQCABQQA2AgQgAUEONgIAC0EADwsgAkIANwMIIAJBADYCACACQgA3AxAgAkIANwMYIAJCADcDICACQgA3ACUgAFAEQCACDwsCQCAAQv////8AVg0AIACnQQR0EAkiA0UNACACIAM2AgBBACEBQgEhBANAIAMgAUEEdGoiAUIANwIAIAFCADcABSAAIARSBEAgBKchASAEQgF8IQQMAQsLIAIgADcDCCACIAA3AxAgAg8LIAEEQCABQQA2AgQgAUEONgIAC0EAEBAgAhAGQQAL7gECA38BfiMAQRBrIgQkAAJAIARBDGpCBBAXIgNFBEBBfyECDAELAkAgAQRAIAJBgAZxIQUDQAJAIAUgASgCBHFFDQACQCADKQMIQgBUBEAgA0EAOgAADAELIANCADcDECADQQE6AAALIAMgAS8BCBANIAMgAS8BChANIAMtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAtBfyECDAQLQX8hAiAAIARBDGpCBBAbQQBIDQMgATMBCiIGUA0AIAAgASgCDCAGEBtBAEgNAwsgASgCACIBDQALC0EAIQILIAMQCAsgBEEQaiQAIAILPAEBfyAABEAgAUGABnEhAQNAIAEgACgCBHEEQCACIAAvAQpqQQRqIQILIAAoAgAiAA0ACwsgAkH//wNxC5wBAQN/IABFBEBBAA8LIAAhAwNAAn8CQAJAIAAvAQgiAUH04AFNBEAgAUEBRg0BIAFB9cYBRg0BDAILIAFBgbICRg0AIAFB9eABRw0BCyAAKAIAIQEgAEEANgIAIAAoAgwQBiAAEAYgASADIAAgA0YbIQMCQCACRQRAQQAhAgwBCyACIAE2AgALIAEMAQsgACICKAIACyIADQALIAMLsgQCBX8BfgJAAkACQCAAIAGtEBciAQRAIAEtAAANAUEAIQAMAgsgBARAIARBADYCBCAEQQ42AgALQQAPC0EAIQADQCABLQAABH4gASkDCCABKQMQfQVCAAtCBFQNASABEAwhByABIAEQDCIGrRATIghFBEBBACECIAQEQCAEQQA2AgQgBEEVNgIACyABEAggAEUNAwNAIAAoAgAhASAAKAIMEAYg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DCAAQRg2AggLDAMLIAAgBiAFLwFqQQAgBCABEQYAIQEgBhALIAFFDQILAkAgDUUEQCABIQMMAQsgACABIAUvAWgQgQEhAyABEAsgA0UNAQsCQCAJRSAMckUEQCADIQEMAQsgACADQQEQgAEhASADEAsgAUUNAQsgASEDDAELQQAhAwsgBUHwAGokACADC4UBAQF/IAFFBEAgAEEIaiIABEAgAEEANgIEIABBEjYCAAtBAA8LQTgQCSIDRQRAIABBCGoiAARAIABBADYCBCAAQQ42AgALQQAPCyADQQA2AhAgA0IANwIIIANCADcDKCADQQA2AgQgAyACNgIAIANCADcDGCADQQA2AjAgACABQTsgAxBCCw8AIAAgASACQQBBABCCAQusAgECfyABRQRAIABBCGoiAARAIABBADYCBCAAQRI2AgALQQAPCwJAIAJBfUsNACACQf//A3FBCEYNACAAQQhqIgAEQCAAQQA2AgQgAEEQNgIAC0EADwsCQEGwwAAQCSIFBEAgBUEANgIIIAVCADcCACAFQYiBAUGogQEgAxs2AqhAIAUgAjYCFCAFIAM6ABAgBUEAOgAPIAVBADsBDCAFIAMgAkF9SyIGcToADiAFQQggAiAGG0H//wNxIAQgBUGIgQFBqIEBIAMbKAIAEQAAIgI2AqxAIAINASAFEDEgBRAGCyAAQQhqIgAEQCAAQQA2AgQgAEEONgIAC0EADwsgACABQTogBRBCIgAEfyAABSAFKAKsQCAFKAKoQCgCBBEDACAFEDEgBRAGQQALC6ABAQF/IAIgACgCBCIDIAIgA0kbIgIEQCAAIAMgAms2AgQCQAJAAkACQCAAKAIcIgMoAhRBAWsOAgEAAgsgA0GgAWogASAAKAIAIAJB3IABKAIAEQgADAILIAAgACgCMCABIAAoAgAgAkHEgAEoAgARBAA2AjAMAQsgASAAKAIAIAIQBxoLIAAgACgCACACajYCACAAIAAoAgggAmo2AggLC7cCAQR/QX4hAgJAIABFDQAgACgCIEUNACAAKAIkIgRFDQAgACgCHCIBRQ0AIAEoAgAgAEcNAAJAAkAgASgCICIDQTlrDjkBAgICAgICAgICAgIBAgICAQICAgICAgICAgICAgICAgICAQICAgICAgICAgICAQICAgICAgICAgEACyADQZoFRg0AIANBKkcN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DCABajYCDCAGIAYoAgggAWo2AgggBSAFKAIUIAFqNgIUIAUgBSgCECABazYCECAGIAYoAhAgAWsiATYCECABDQAgBiAGKAIENgIIC0EAIQRBACEJIAMoAhBFDQAMCgsgAygCHCgCJCEGIAMgAygCGCIBQQFqNgIYIAEgBmotAAAhASADIARBAWo2AhAgAygCBCAEaiABOgAAIAEEQCADKAIQIQQMAQsLIAMoAhwoAixFDQAgAygCECIGIAlNDQAgBQJ/IAUoAjAhBEEAIAMoAgQgCWoiAUUNABogBCABIAYgCWtB1IABKAIAEQAACzYCMAsgA0HnADYCIAsCQCADKAIcKAIsBEAgAygCDCADKAIQIgFBAmpJBH8gBRAKIAMoAhANAkEABSABCyADKAIEaiAFKAIwOwAAIAMgAygCEEECajYCECADQaABakHkgAEoAgARAQAaCyADQfEANgIgIAUQCiADKAIQRQ0BDAcLDAYLIAUoAgQNAQsgAygCPA0AIApFDQEgAygCIEGaBUYNAQsCfyADKAKIASIBRQRAIAMgChCFAQwBCwJAAkACQCADKAKMAUECaw4CAAECCwJ/AkADQAJAAkAgAygCPA0AIAMQLyADKAI8DQAgCg0BQQAMBAsgAygCSCADKAJoai0AACEEIAMgAygC8C0iAUEBajYC8C0gASADKALsLWpBADoAACADIAMoAvAtIgFBAWo2AvAtIAEgAygC7C1qQQA6AAAgAyADKALwLSIBQQFqNgLwLSABIAMoAuwtaiAEOgAAIAMgBEECdGoiASABLwHkAUEBajsB5AEgAyADKAI8QQFrNgI8IAMgAygCaEEBaiIBNgJoIAMoAvAtIAMoAvQtRw0BQQAhBCADIAMoAlgiBkEATgR/IAMoAkggBmoFQQALIAEgBmtBABAPIAMgAygCaDYCWCADKAIAEAogAygCACgCEA0BDAILCyADQQA2AoQuIApBBEYEQCADIAMoAlgiAUEATgR/IAMoAkggAWoFQQALIAMoAmggAWtBARAPIAMgAygCaDYCWCADKAIAEApBA0ECIAMoAgAoAhAbDAILIAMoAvAtBEBBACEEIAMgAygCWCIBQQBOBH8gAygCSCABagVBAAsgAygCaCABa0EAEA8gAyADKAJoNgJYIAMoAgAQCiADKAIAKAIQRQ0BC0EBIQQLIAQL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bGl0ZXJhbC9sZW5ndGhzIHNldABpbnZhbGlkIGNvZGUgbGVuZ3RocyBzZXQAdW5rbm93biBoZWFkZXIgZmxhZ3Mgc2V0AGludmFsaWQgZGlzdGFuY2VzIHNldABpbnZhbGlkIGJpdCBsZW5ndGggcmVwZWF0AEZpbGUgYWxyZWFkeSBleGlzdHMAdG9vIG1hbnkgbGVuZ3RoIG9yIGRpc3RhbmNlIHN5bWJvbHMAaW52YWxpZCBzdG9yZWQgYmxvY2sgbGVuZ3RocwAlcyVzJXMAYnVmZmVyIGVycm9yAE5vIGVycm9yAHN0cmVhbSBlcnJvcgBUZWxsIGVycm9yAEludGVybmFsIGVycm9yAFNlZWsgZXJyb3IAV3JpdGUgZXJyb3IAZmlsZSBlcnJvcgBSZWFkIGVycm9yAFpsaWIgZXJyb3IAZGF0YSBlcnJvcgBDUkMgZXJyb3IAaW5jb21wYXRpYmxlIHZlcnNpb24AaW52YWxpZCBjb2RlIC0tIG1pc3NpbmcgZW5kLW9mLWJsb2NrAGluY29ycmVjdCBoZWFkZXIgY2hlY2sAaW5jb3JyZWN0IGxlbmd0aCBjaGVjawBpbmNvcnJlY3QgZGF0YSBjaGVjawBpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjawBoZWFkZXIgY3JjIG1pc21hdGNoADEuMi4xMy56bGliLW5nAGludmFsaWQgd2luZG93IHNpemUAUmVhZC1vbmx5IGFyY2hpdmUATm90IGEgemlwIGFyY2hpdmUAUmVzb3VyY2Ugc3RpbGwgaW4gdXNlAE1hbGxvYyBmYWlsdXJlAGludmFsaWQgYmxvY2sgdHlwZQBGYWlsdXJlIHRvIGNyZWF0ZSB0ZW1wb3JhcnkgZmlsZQBDYW4ndCBvcGVuIGZpbGUATm8gc3VjaCBmaWxlAFByZW1hdHVyZSBlbmQgb2YgZmlsZQBDYW4ndCByZW1vdmUgZmlsZQBpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUAaW52YWxpZCBkaXN0YW5jZSBjb2RlAHVua25vd24gY29tcHJlc3Npb24gbWV0aG9kAHN0cmVhbSBlbmQAQ29tcHJlc3NlZCBkYXRhIGludmFsaWQATXVsdGktZGlzayB6aXAgYXJjaGl2ZXMgbm90IHN1cHBvcnRl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UgAIANIACAAyAAgAsgAIAHIACADyAAgACgAIAIoACABKAAgAygAIACoACACqAAgAagAIAOoACAAaAAgAmgAIAFoACADaAAgAOgAIALoACAB6AAgA+gAIAAYACACGAAgARgAIAMYACAAmAAgApgAIAGYACADmAAgAFgAIAJYACABWAAgA1gAIADYACAC2AAgAdgAIAPYACAAOAAgAjgAIAE4ACADOAAgALgAIAK4ACABuAAgA7gAIAB4ACACeAAgAXgAIAN4ACAA+AAgAvgAIAH4ACAD+AAgAAQAIAIEACABBAAgAwQAIACEACAChAAgAYQAIAOEACAARAAgAkQAIAFEACADRAAgAMQAIALEACABxAAgA8QAIAAkACACJAAgASQAIAMkACAApAAgAqQAIAGkACADpAAgAGQAIAJkACABZAAgA2QAIADkACAC5AAgAeQAIAPkACAAFAAgAhQAIAEUACADFAAgAJQAIAKUACABlAAgA5QAIABUACACVAAgAVQAIANUACAA1AAgAtQAIAHUACAD1AAgADQAIAI0ACABNAAgAzQAIAC0ACACtAAgAbQAIAO0ACAAdAAgAnQAIAF0ACADdAAgAPQAIAL0ACAB9AAgA/QAIABMACQATAQkAkwAJAJMBCQBTAAkAUwEJANMACQDTAQkAMwAJADMBCQCzAAkAswEJAHMACQBzAQkA8wAJAPMBCQALAAkACwEJAIsACQCLAQkASwAJAEsBCQDLAAkAywEJACsACQArAQkAqwAJAKsBCQBrAAkAawEJAOsACQDrAQkAGwAJABsBCQCbAAkAmwEJAFsACQBbAQkA2wAJANsBCQA7AAkAOwEJALsACQC7AQkAewAJAHsBCQD7AAkA+wEJAAcACQAHAQkAhwAJAIcBCQBHAAkARwEJAMcACQDHAQkAJwAJACcBCQCnAAkApwEJAGcACQBnAQkA5wAJAOcBCQAXAAkAFwEJAJcACQCXAQkAVwAJAFcBCQDXAAkA1wEJADcACQA3AQkAtwAJALcBCQB3AAkAdwEJAPcACQD3AQkADwAJAA8BCQCPAAkAjwEJAE8ACQBPAQkAzwAJAM8BCQAvAAkALwEJAK8ACQCvAQkAbwAJAG8BCQDvAAkA7wEJAB8ACQAfAQkAnwAJAJ8BCQBfAAkAXwEJAN8ACQDfAQkAPwAJAD8BCQC/AAkA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SXMgYSBkaXJlY3RvcnkAVGV4dCBmaWxlIGJ1c3kARXhlYyBmb3JtYXQgZXJyb3IASW52YWxpZCBhcmd1bWVudABBcmd1bWVudCBsaXN0IHRvbyBsb25nAFN5bWJvbGljIGxpbmsgbG9vcABGaWxlbmFtZSB0b28gbG9uZwBUb28gbWFueSBvcGVuIGZpbGVzIGluIHN5c3RlbQBObyBmaWxlIGRlc2NyaXB0b3JzIGF2YWlsYWJsZQBCYWQgZmlsZSBkZXNjcmlwdG9yAE5vIGNoaWxkIHByb2Nlc3MAQmFkIGFkZHJlc3MARmlsZSB0b28gbGFyZ2UAVG9vIG1hbnkgbGlua3MATm8gbG9ja3MgYXZhaWxhYmxlAFJlc291cmNlIGRlYWRsb2NrIHdvdWxkIG9jY3VyAFN0YXRlIG5vdCByZWNvdmVyYWJsZQBQcmV2aW91cyBvd25lciBkaWVkAE9wZXJhdGlvbiBjYW5jZWxlZABGdW5jdGlvbiBub3QgaW1wbGVtZW50ZWQATm8gbWVzc2FnZSBvZiBkZXNpcmVkIHR5cGUASWRlbnRpZmllciByZW1vdmVkAERldmljZSBub3QgYSBzdHJlYW0ATm8gZGF0YSBhdmFpbGFibGUARGV2aWNlIHRpbWVvdXQAT3V0IG9mIHN0cmVhbXMgcmVzb3VyY2VzAExpbmsgaGFzIGJlZW4gc2V2ZXJlZABQcm90b2NvbCBlcnJvcgBCYWQgbWVzc2FnZQBGaWxlIGRlc2NyaXB0b3IgaW4gYmFkIHN0YXRlAE5vdCBhIHNvY2tldABEZXN0aW5hdGlvbiBhZGRyZXNzIHJlcXVpcmVkAE1lc3NhZ2UgdG9vIGxhcmdlAFByb3RvY29sIHdyb25nIHR5cGUgZm9yIHNvY2tldABQcm90b2NvbCBub3QgYXZhaWxhYmxlAFByb3RvY29sIG5vdCBzdXBwb3J0ZWQAU29ja2V0IHR5cGUgbm90IHN1cHBvcnRlZABOb3Qgc3VwcG9ydGVkAFByb3RvY29sIGZhbWlseSBub3Qgc3VwcG9ydGVkAEFkZHJlc3MgZmFtaWx5IG5vdCBzdXBwb3J0ZWQgYnkgcHJvdG9jb2wAQWRkcmVzcyBub3QgYXZhaWxhYmxlAE5ldHdvcmsgaXMgZG93bgBOZXR3b3JrIHVucmVhY2hhYmxlAENvbm5lY3Rpb24gcmVzZXQgYnkgbmV0d29yawBDb25uZWN0aW9uIGFib3J0ZWQATm8gYnVmZmVyIHNwYWNlIGF2YWlsYWJsZQBTb2NrZXQgaXMgY29ubmVjdGVkAFNvY2tldCBub3QgY29ubmVjdGVkAENhbm5vdCBzZW5kIGFmdGVyIHNvY2tldCBzaHV0ZG93bgBPcGVyYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcwBPcGVyYXRpb24gaW4gcHJvZ3Jlc3MAU3RhbGUgZmlsZSBoYW5kbGUAUmVtb3RlIEkvTyBlcnJvcgBRdW90YSBleGNlZWRlZABObyBtZWRpdW0gZm91bmQAV3JvbmcgbWVkaXVtIHR5cGUATm8gZXJyb3IgaW5mb3JtYXRpb24AQcCAAQuFARMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAGwAAABwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAACIAAAAjAAAAgERQADEAAAAyAAAAMwAAADQAAAA1AAAANgAAADcAAAA4AAAAOQAAADIAAAAzAAAANAAAADUAAAA2AAAANwAAADgAQfSCAQsCXEQAQbCDAQsQ/////////////////////w==";io(Pi)||(Pi=x(Pi));function Os(We){try{if(We==Pi&&ce)return new Uint8Array(ce);var tt=ii(We);if(tt)return tt;if(R)return R(We);throw"sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)"}catch(Bt){Ri(Bt)}}function so(We,tt){var Bt,or,ee;try{ee=Os(We),or=new WebAssembly.Module(ee),Bt=new WebAssembly.Instance(or,tt)}catch(Le){var ye=Le.toString();throw te("failed to compile wasm module: "+ye),(ye.includes("imported Memory")||ye.includes("memory import"))&&te("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)."),Le}return[Bt,or]}function uc(){var We={a:Ha};function tt(ee,ye){var Le=ee.exports;r.asm=Le,Be=r.asm.g,J(Be.buffer),$=r.asm.W,ln(r.asm.h),Ms("wasm-instantiate")}if(Kn("wasm-instantiate"),r.instantiateWasm)try{var Bt=r.instantiateWasm(We,tt);return Bt}catch(ee){return te("Module.instantiateWasm callback failed with error: "+ee),!1}var or=so(Pi,We);return tt(or[0]),r.asm}function Au(We){return F.getFloat32(We,!0)}function sp(We){return F.getFloat64(We,!0)}function op(We){return F.getInt16(We,!0)}function Us(We){return F.getInt32(We,!0)}function Dn(We,tt){F.setInt32(We,tt,!0)}function oo(We){for(;We.length>0;){var tt=We.shift();if(typeof tt=="function"){tt(r);continue}var Bt=tt.func;typeof Bt=="number"?tt.arg===void 0?$.get(Bt)():$.get(Bt)(tt.arg):Bt(tt.arg===void 0?null:tt.arg)}}function _s(We,tt){var Bt=new Date(Us((We>>2)*4)*1e3);Dn((tt>>2)*4,Bt.getUTCSeconds()),Dn((tt+4>>2)*4,Bt.getUTCMinutes()),Dn((tt+8>>2)*4,Bt.getUTCHours()),Dn((tt+12>>2)*4,Bt.getUTCDate()),Dn((tt+16>>2)*4,Bt.getUTCMonth()),Dn((tt+20>>2)*4,Bt.getUTCFullYear()-1900),Dn((tt+24>>2)*4,Bt.getUTCDay()),Dn((tt+36>>2)*4,0),Dn((tt+32>>2)*4,0);var or=Date.UTC(Bt.getUTCFullYear(),0,1,0,0,0,0),ee=(Bt.getTime()-or)/(1e3*60*60*24)|0;return Dn((tt+28>>2)*4,ee),_s.GMTString||(_s.GMTString=rt("GMT")),Dn((tt+40>>2)*4,_s.GMTString),tt}function ml(We,tt){return _s(We,tt)}function yl(We,tt,Bt){Se.copyWithin(We,tt,tt+Bt)}function ao(We){try{return Be.grow(We-ke.byteLength+65535>>>16),J(Be.buffer),1}catch{}}function Vn(We){var tt=Se.length;We=We>>>0;var Bt=2147483648;if(We>Bt)return!1;for(var or=1;or<=4;or*=2){var ee=tt*(1+.2/or);ee=Math.min(ee,We+100663296);var ye=Math.min(Bt,Fe(Math.max(We,ee),65536)),Le=ao(ye);if(Le)return!0}return!1}function Mn(We){le(We)}function Ti(We){var tt=Date.now()/1e3|0;return We&&Dn((We>>2)*4,tt),tt}function On(){if(On.called)return;On.called=!0;var We=new Date().getFullYear(),tt=new Date(We,0,1),Bt=new Date(We,6,1),or=tt.getTimezoneOffset(),ee=Bt.getTimezoneOffset(),ye=Math.max(or,ee);Dn((ys()>>2)*4,ye*60),Dn((ms()>>2)*4,+(or!=ee));function Le($r){var ji=$r.toTimeString().match(/\(([A-Za-z ]+)\)$/);return ji?ji[1]:"GMT"}var ft=Le(tt),pt=Le(Bt),Nt=rt(ft),rr=rt(pt);ee<or?(Dn((Ci()>>2)*4,Nt),Dn((Ci()+4>>2)*4,rr)):(Dn((Ci()>>2)*4,rr),Dn((Ci()+4>>2)*4,Nt))}function _i(We){On();var tt=Date.UTC(Us((We+20>>2)*4)+1900,Us((We+16>>2)*4),Us((We+12>>2)*4),Us((We+8>>2)*4),Us((We+4>>2)*4),Us((We>>2)*4),0),Bt=new Date(tt);Dn((We+24>>2)*4,Bt.getUTCDay());var or=Date.UTC(Bt.getUTCFullYear(),0,1,0,0,0,0),ee=(Bt.getTime()-or)/(1e3*60*60*24)|0;return Dn((We+28>>2)*4,ee),Bt.getTime()/1e3|0}var ir=typeof atob=="function"?atob:function(We){var tt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",Bt="",or,ee,ye,Le,ft,pt,Nt,rr=0;We=We.replace(/[^A-Za-z0-9\+\/\=]/g,"");do Le=tt.indexOf(We.charAt(rr++)),ft=tt.indexOf(We.charAt(rr++)),pt=tt.indexOf(We.charAt(rr++)),Nt=tt.indexOf(We.charAt(rr++)),or=Le<<2|ft>>4,ee=(ft&15)<<4|pt>>2,ye=(pt&3)<<6|Nt,Bt=Bt+String.fromCharCode(or),pt!==64&&(Bt=Bt+String.fromCharCode(ee)),Nt!==64&&(Bt=Bt+String.fromCharCode(ye));while(rr<We.length);return Bt};function Me(We){if(typeof I=="boolean"&&I){var tt;try{tt=Buffer.from(We,"base64")}catch{tt=new Buffer(We,"base64")}return new Uint8Array(tt.buffer,tt.byteOffset,tt.byteLength)}try{for(var Bt=ir(We),or=new Uint8Array(Bt.length),ee=0;ee<Bt.length;++ee)or[ee]=Bt.charCodeAt(ee);return or}catch{throw new Error("Converting base64 string to bytes failed.")}}function ii(We){if(io(We))return Me(We.slice(gs.length))}var Ha={e:ml,c:yl,d:Vn,a:Mn,b:Ti,f:_i},hr=uc(),Ac=r.___wasm_call_ctors=hr.h,fu=r._zip_ext_count_symlinks=hr.i,fc=r._zip_file_get_external_attributes=hr.j,El=r._zipstruct_statS=hr.k,vA=r._zipstruct_stat_size=hr.l,pu=r._zipstruct_stat_mtime=hr.m,Ie=r._zipstruct_stat_crc=hr.n,Tt=r._zipstruct_errorS=hr.o,pc=r._zipstruct_error_code_zip=hr.p,Hi=r._zipstruct_stat_comp_size=hr.q,hu=r._zipstruct_stat_comp_method=hr.r,Yt=r._zip_close=hr.s,Cl=r._zip_delete=hr.t,DA=r._zip_dir_add=hr.u,ap=r._zip_discard=hr.v,hc=r._zip_error_init_with_code=hr.w,PA=r._zip_get_error=hr.x,Qn=r._zip_file_get_error=hr.y,hi=r._zip_error_strerror=hr.z,gc=r._zip_fclose=hr.A,SA=r._zip_file_add=hr.B,aa=r._free=hr.C,Ni=r._malloc=hr.D,_o=r._zip_source_error=hr.E,Xe=r._zip_source_seek=hr.F,lo=r._zip_file_set_external_attributes=hr.G,dc=r._zip_file_set_mtime=hr.H,gu=r._zip_fopen_index=hr.I,qi=r._zip_fread=hr.J,du=r._zip_get_name=hr.K,bA=r._zip_get_num_entries=hr.L,qa=r._zip_source_read=hr.M,mc=r._zip_name_locate=hr.N,ds=r._zip_open_from_source=hr.O,Ht=r._zip_set_file_compression=hr.P,Fn=r._zip_source_buffer=hr.Q,Ei=r._zip_source_buffer_create=hr.R,la=r._zip_source_close=hr.S,co=r._zip_source_free=hr.T,Hs=r._zip_source_keep=hr.U,ca=r._zip_source_open=hr.V,ua=r._zip_source_tell=hr.X,Ho=r._zip_stat_index=hr.Y,Ci=r.__get_tzname=hr.Z,ms=r.__get_daylight=hr._,ys=r.__get_timezone=hr.$,Es=r.stackSave=hr.aa,qs=r.stackRestore=hr.ba,Un=r.stackAlloc=hr.ca;r.cwrap=ne,r.getValue=de;var Pn;Kr=function We(){Pn||Cs(),Pn||(Kr=We)};function Cs(We){if(We=We||A,mr>0||(dt(),mr>0))return;function tt(){Pn||(Pn=!0,r.calledRun=!0,!Ee&&(jt(),o(r),r.onRuntimeInitialized&&r.onRuntimeInitialized(),tr()))}r.setStatus?(r.setStatus("Running..."),setTimeout(function(){setTimeout(function(){r.setStatus("")},1),tt()},1)):tt()}if(r.run=Cs,r.preInit)for(typeof r.preInit=="function"&&(r.preInit=[r.preInit]);r.preInit.length>0;)r.preInit.pop()();return Cs(),e}}();typeof Cb=="object"&&typeof K4=="object"?K4.exports=W4:typeof define=="function"&&define.amd?define([],function(){return W4}):typeof Cb=="object"&&(Cb.createModule=W4)});var Tf,Ole,Ule,_le=Et(()=>{Tf=["number","number"],Ole=(Z=>(Z[Z.ZIP_ER_OK=0]="ZIP_ER_OK",Z[Z.ZIP_ER_MULTIDISK=1]="ZIP_ER_MULTIDISK",Z[Z.ZIP_ER_RENAME=2]="ZIP_ER_RENAME",Z[Z.ZIP_ER_CLOSE=3]="ZIP_ER_CLOSE",Z[Z.ZIP_ER_SEEK=4]="ZIP_ER_SEEK",Z[Z.ZIP_ER_READ=5]="ZIP_ER_READ",Z[Z.ZIP_ER_WRITE=6]="ZIP_ER_WRITE",Z[Z.ZIP_ER_CRC=7]="ZIP_ER_CRC",Z[Z.ZIP_ER_ZIPCLOSED=8]="ZIP_ER_ZIPCLOSED",Z[Z.ZIP_ER_NOENT=9]="ZIP_ER_NOENT",Z[Z.ZIP_ER_EXISTS=10]="ZIP_ER_EXISTS",Z[Z.ZIP_ER_OPEN=11]="ZIP_ER_OPEN",Z[Z.ZIP_ER_TMPOPEN=12]="ZIP_ER_TMPOPEN",Z[Z.ZIP_ER_ZLIB=13]="ZIP_ER_ZLIB",Z[Z.ZIP_ER_MEMORY=14]="ZIP_ER_MEMORY",Z[Z.ZIP_ER_CHANGED=15]="ZIP_ER_CHANGED",Z[Z.ZIP_ER_COMPNOTSUPP=16]="ZIP_ER_COMPNOTSUPP",Z[Z.ZIP_ER_EOF=17]="ZIP_ER_EOF",Z[Z.ZIP_ER_INVAL=18]="ZIP_ER_INVAL",Z[Z.ZIP_ER_NOZIP=19]="ZIP_ER_NOZIP",Z[Z.ZIP_ER_INTERNAL=20]="ZIP_ER_INTERNAL",Z[Z.ZIP_ER_INCONS=21]="ZIP_ER_INCONS",Z[Z.ZIP_ER_REMOVE=22]="ZIP_ER_REMOVE",Z[Z.ZIP_ER_DELETED=23]="ZIP_ER_DELETED",Z[Z.ZIP_ER_ENCRNOTSUPP=24]="ZIP_ER_ENCRNOTSUPP",Z[Z.ZIP_ER_RDONLY=25]="ZIP_ER_RDONLY",Z[Z.ZIP_ER_NOPASSWD=26]="ZIP_ER_NOPASSWD",Z[Z.ZIP_ER_WRONGPASSWD=27]="ZIP_ER_WRONGPASSWD",Z[Z.ZIP_ER_OPNOTSUPP=28]="ZIP_ER_OPNOTSUPP",Z[Z.ZIP_ER_INUSE=29]="ZIP_ER_INUSE",Z[Z.ZIP_ER_TELL=30]="ZIP_ER_TELL",Z[Z.ZIP_ER_COMPRESSED_DATA=31]="ZIP_ER_COMPRESSED_DATA",Z))(Ole||{}),Ule=t=>({get HEAPU8(){return t.HEAPU8},errors:Ole,SEEK_SET:0,SEEK_CUR:1,SEEK_END:2,ZIP_CHECKCONS:4,ZIP_EXCL:2,ZIP_RDONLY:16,ZIP_FL_OVERWRITE:8192,ZIP_FL_COMPRESSED:4,ZIP_OPSYS_DOS:0,ZIP_OPSYS_AMIGA:1,ZIP_OPSYS_OPENVMS:2,ZIP_OPSYS_UNIX:3,ZIP_OPSYS_VM_CMS:4,ZIP_OPSYS_ATARI_ST:5,ZIP_OPSYS_OS_2:6,ZIP_OPSYS_MACINTOSH:7,ZIP_OPSYS_Z_SYSTEM:8,ZIP_OPSYS_CPM:9,ZIP_OPSYS_WINDOWS_NTFS:10,ZIP_OPSYS_MVS:11,ZIP_OPSYS_VSE:12,ZIP_OPSYS_ACORN_RISC:13,ZIP_OPSYS_VFAT:14,ZIP_OPSYS_ALTERNATE_MVS:15,ZIP_OPSYS_BEOS:16,ZIP_OPSYS_TANDEM:17,ZIP_OPSYS_OS_400:18,ZIP_OPSYS_OS_X:19,ZIP_CM_DEFAULT:-1,ZIP_CM_STORE:0,ZIP_CM_DEFLATE:8,uint08S:t._malloc(1),uint32S:t._malloc(4),malloc:t._malloc,free:t._free,getValue:t.getValue,openFromSource:t.cwrap("zip_open_from_source","number",["number","number","number"]),close:t.cwrap("zip_close","number",["number"]),discard:t.cwrap("zip_discard",null,["number"]),getError:t.cwrap("zip_get_error","number",["number"]),getName:t.cwrap("zip_get_name","string",["number","number","number"]),getNumEntries:t.cwrap("zip_get_num_entries","number",["number","number"]),delete:t.cwrap("zip_delete","number",["number","number"]),statIndex:t.cwrap("zip_stat_index","number",["number",...Tf,"number","number"]),fopenIndex:t.cwrap("zip_fopen_index","number",["number",...Tf,"number"]),fread:t.cwrap("zip_fread","number",["number","number","number","number"]),fclose:t.cwrap("zip_fclose","number",["number"]),dir:{add:t.cwrap("zip_dir_add","number",["number","string"])},file:{add:t.cwrap("zip_file_add","number",["number","string","number","number"]),getError:t.cwrap("zip_file_get_error","number",["number"]),getExternalAttributes:t.cwrap("zip_file_get_external_attributes","number",["number",...Tf,"number","number","number"]),setExternalAttributes:t.cwrap("zip_file_set_external_attributes","number",["number",...Tf,"number","number","number"]),setMtime:t.cwrap("zip_file_set_mtime","number",["number",...Tf,"number","number"]),setCompression:t.cwrap("zip_set_file_compression","number",["number",...Tf,"number","number"])},ext:{countSymlinks:t.cwrap("zip_ext_count_symlinks","number",["number"])},error:{initWithCode:t.cwrap("zip_error_init_with_code",null,["number","number"]),strerror:t.cwrap("zip_error_strerror","string",["number"])},name:{locate:t.cwrap("zip_name_locate","number",["number","string","number"])},source:{fromUnattachedBuffer:t.cwrap("zip_source_buffer_create","number",["number",...Tf,"number","number"]),fromBuffer:t.cwrap("zip_source_buffer","number",["number","number",...Tf,"number"]),free:t.cwrap("zip_source_free",null,["number"]),keep:t.cwrap("zip_source_keep",null,["number"]),open:t.cwrap("zip_source_open","number",["number"]),close:t.cwrap("zip_source_close","number",["number"]),seek:t.cwrap("zip_source_seek","number",["number",...Tf,"number"]),tell:t.cwrap("zip_source_tell","number",["number"]),read:t.cwrap("zip_source_read","number",["number","number","number"]),error:t.cwrap("zip_source_error","number",["number"])},struct:{statS:t.cwrap("zipstruct_statS","number",[]),statSize:t.cwrap("zipstruct_stat_size","number",["number"]),statCompSize:t.cwrap("zipstruct_stat_comp_size","number",["number"]),statCompMethod:t.cwrap("zipstruct_stat_comp_method","number",["number"]),statMtime:t.cwrap("zipstruct_stat_mtime","number",["number"]),statCrc:t.cwrap("zipstruct_stat_crc","number",["number"]),errorS:t.cwrap("zipstruct_errorS","number",[]),errorCodeZip:t.cwrap("zipstruct_error_code_zip","number",["number"])}})});function V4(t,e){let r=t.indexOf(e);if(r<=0)return null;let o=r;for(;r>=0&&(o=r+e.length,t[o]!==K.sep);){if(t[r-1]===K.sep)return null;r=t.indexOf(e,o)}return t.length>o&&t[o]!==K.sep?null:t.slice(0,o)}var rA,Hle=Et(()=>{Pt();Pt();nA();rA=class t extends Op{static async openPromise(e,r){let o=new t(r);try{return await e(o)}finally{o.saveAndClose()}}constructor(e={}){let r=e.fileExtensions,o=e.readOnlyArchives,a=typeof r>"u"?A=>V4(A,".zip"):A=>{for(let p of r){let h=V4(A,p);if(h)return h}return null},n=(A,p)=>new Zi(p,{baseFs:A,readOnly:o,stats:A.statSync(p)}),u=async(A,p)=>{let h={baseFs:A,readOnly:o,stats:await A.statPromise(p)};return()=>new Zi(p,h)};super({...e,factorySync:n,factoryPromise:u,getMountPoint:a})}}});function fot(t){if(typeof t=="string"&&String(+t)===t)return+t;if(typeof t=="number"&&Number.isFinite(t))return t<0?Date.now()/1e3:t;if(qle.types.isDate(t))return t.getTime()/1e3;throw new Error("Invalid time")}function wb(){return Buffer.from([80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])}var na,z4,qle,J4,jle,Ib,Zi,X4=Et(()=>{Pt();Pt();Pt();Pt();Pt();Pt();na=ve("fs"),z4=ve("stream"),qle=ve("util"),J4=Ze(ve("zlib"));Y4();jle="mixed";Ib=class extends Error{constructor(e,r){super(e),this.name="Libzip Error",this.code=r}},Zi=class extends _u{constructor(r,o={}){super();this.listings=new Map;this.entries=new Map;this.fileSources=new Map;this.fds=new Map;this.nextFd=0;this.ready=!1;this.readOnly=!1;let a=o;if(this.level=typeof a.level<"u"?a.level:jle,r??=wb(),typeof r=="string"){let{baseFs:A=new Tn}=a;this.baseFs=A,this.path=r}else this.path=null,this.baseFs=null;if(o.stats)this.stats=o.stats;else if(typeof r=="string")try{this.stats=this.baseFs.statSync(r)}catch(A){if(A.code==="ENOENT"&&a.create)this.stats=wa.makeDefaultStats();else throw A}else this.stats=wa.makeDefaultStats();this.libzip=f1();let n=this.libzip.malloc(4);try{let A=0;o.readOnly&&(A|=this.libzip.ZIP_RDONLY,this.readOnly=!0),typeof r=="string"&&(r=a.create?wb():this.baseFs.readFileSync(r));let p=this.allocateUnattachedSource(r);try{this.zip=this.libzip.openFromSource(p,A,n),this.lzSource=p}catch(h){throw this.libzip.source.free(p),h}if(this.zip===0){let h=this.libzip.struct.errorS();throw this.libzip.error.initWithCode(h,this.libzip.getValue(n,"i32")),this.makeLibzipError(h)}}finally{this.libzip.free(n)}this.listings.set(It.root,new Set);let u=this.libzip.getNumEntries(this.zip,0);for(let A=0;A<u;++A){let p=this.libzip.getName(this.zip,A,0);if(K.isAbsolute(p))continue;let h=K.resolve(It.root,p);this.registerEntry(h,A),p.endsWith("/")&&this.registerListing(h)}if(this.symlinkCount=this.libzip.ext.countSymlinks(this.zip),this.symlinkCount===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));this.ready=!0}makeLibzipError(r){let o=this.libzip.struct.errorCodeZip(r),a=this.libzip.error.strerror(r),n=new Ib(a,this.libzip.errors[o]);if(o===this.libzip.errors.ZIP_ER_CHANGED)throw new Error(`Assertion failed: Unexpected libzip error: ${n.message}`);return n}getExtractHint(r){for(let o of this.entries.keys()){let a=this.pathUtils.extname(o);if(r.relevantExtensions.has(a))return!0}return!1}getAllFiles(){return Array.from(this.entries.keys())}getRealPath(){if(!this.path)throw new Error("ZipFS don't have real paths when loaded from a buffer");return this.path}prepareClose(){if(!this.ready)throw nr.EBUSY("archive closed, close");N0(this)}getBufferAndClose(){if(this.prepareClose(),this.entries.size===0)return this.discardAndClose(),wb();try{if(this.libzip.source.keep(this.lzSource),this.libzip.close(this.zip)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(this.libzip.source.open(this.lzSource)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(this.libzip.source.seek(this.lzSource,0,0,this.libzip.SEEK_END)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));let r=this.libzip.source.tell(this.lzSource);if(r===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(this.libzip.source.seek(this.lzSource,0,0,this.libzip.SEEK_SET)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));let o=this.libzip.malloc(r);if(!o)throw new Error("Couldn't allocate enough memory");try{let a=this.libzip.source.read(this.lzSource,o,r);if(a===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(a<r)throw new Error("Incomplete read");if(a>r)throw new Error("Overread");let n=Buffer.from(this.libzip.HEAPU8.subarray(o,o+r));return process.env.YARN_IS_TEST_ENV&&process.env.YARN_ZIP_DATA_EPILOGUE&&(n=Buffer.concat([n,Buffer.from(process.env.YARN_ZIP_DATA_EPILOGUE)])),n}finally{this.libzip.free(o)}}finally{this.libzip.source.close(this.lzSource),this.libzip.source.free(this.lzSource),this.ready=!1}}discardAndClose(){this.prepareClose(),this.libzip.discard(this.zip),this.ready=!1}saveAndClose(){if(!this.path||!this.baseFs)throw new Error("ZipFS cannot be saved and must be discarded when loaded from a buffer");if(this.readOnly){this.discardAndClose();return}let r=this.baseFs.existsSync(this.path)||this.stats.mode===wa.DEFAULT_MODE?void 0:this.stats.mode;this.baseFs.writeFileSync(this.path,this.getBufferAndClose(),{mode:r}),this.ready=!1}resolve(r){return K.resolve(It.root,r)}async openPromise(r,o,a){return this.openSync(r,o,a)}openSync(r,o,a){let n=this.nextFd++;return this.fds.set(n,{cursor:0,p:r}),n}hasOpenFileHandles(){return!!this.fds.size}async opendirPromise(r,o){return this.opendirSync(r,o)}opendirSync(r,o={}){let a=this.resolveFilename(`opendir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw nr.ENOENT(`opendir '${r}'`);let n=this.listings.get(a);if(!n)throw nr.ENOTDIR(`opendir '${r}'`);let u=[...n],A=this.openSync(a,"r");return uD(this,a,u,{onClose:()=>{this.closeSync(A)}})}async readPromise(r,o,a,n,u){return this.readSync(r,o,a,n,u)}readSync(r,o,a=0,n=o.byteLength,u=-1){let A=this.fds.get(r);if(typeof A>"u")throw nr.EBADF("read");let p=u===-1||u===null?A.cursor:u,h=this.readFileSync(A.p);h.copy(o,a,p,p+n);let E=Math.max(0,Math.min(h.length-p,n));return(u===-1||u===null)&&(A.cursor+=E),E}async writePromise(r,o,a,n,u){return typeof o=="string"?this.writeSync(r,o,u):this.writeSync(r,o,a,n,u)}writeSync(r,o,a,n,u){throw typeof this.fds.get(r)>"u"?nr.EBADF("read"):new Error("Unimplemented")}async closePromise(r){return this.closeSync(r)}closeSync(r){if(typeof this.fds.get(r)>"u")throw nr.EBADF("read");this.fds.delete(r)}createReadStream(r,{encoding:o}={}){if(r===null)throw new Error("Unimplemented");let a=this.openSync(r,"r"),n=Object.assign(new z4.PassThrough({emitClose:!0,autoDestroy:!0,destroy:(A,p)=>{clearImmediate(u),this.closeSync(a),p(A)}}),{close(){n.destroy()},bytesRead:0,path:r,pending:!1}),u=setImmediate(async()=>{try{let A=await this.readFilePromise(r,o);n.bytesRead=A.length,n.end(A)}catch(A){n.destroy(A)}});return n}createWriteStream(r,{encoding:o}={}){if(this.readOnly)throw nr.EROFS(`open '${r}'`);if(r===null)throw new Error("Unimplemented");let a=[],n=this.openSync(r,"w"),u=Object.assign(new z4.PassThrough({autoDestroy:!0,emitClose:!0,destroy:(A,p)=>{try{A?p(A):(this.writeFileSync(r,Buffer.concat(a),o),p(null))}catch(h){p(h)}finally{this.closeSync(n)}}}),{close(){u.destroy()},bytesWritten:0,path:r,pending:!1});return u.on("data",A=>{let p=Buffer.from(A);u.bytesWritten+=p.length,a.push(p)}),u}async realpathPromise(r){return this.realpathSync(r)}realpathSync(r){let o=this.resolveFilename(`lstat '${r}'`,r);if(!this.entries.has(o)&&!this.listings.has(o))throw nr.ENOENT(`lstat '${r}'`);return o}async existsPromise(r){return this.existsSync(r)}existsSync(r){if(!this.ready)throw nr.EBUSY(`archive closed, existsSync '${r}'`);if(this.symlinkCount===0){let a=K.resolve(It.root,r);return this.entries.has(a)||this.listings.has(a)}let o;try{o=this.resolveFilename(`stat '${r}'`,r,void 0,!1)}catch{return!1}return o===void 0?!1:this.entries.has(o)||this.listings.has(o)}async accessPromise(r,o){return this.accessSync(r,o)}accessSync(r,o=na.constants.F_OK){let a=this.resolveFilename(`access '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw nr.ENOENT(`access '${r}'`);if(this.readOnly&&o&na.constants.W_OK)throw nr.EROFS(`access '${r}'`)}async statPromise(r,o={bigint:!1}){return o.bigint?this.statSync(r,{bigint:!0}):this.statSync(r)}statSync(r,o={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`stat '${r}'`,r,void 0,o.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(o.throwIfNoEntry===!1)return;throw nr.ENOENT(`stat '${r}'`)}if(r[r.length-1]==="/"&&!this.listings.has(a))throw nr.ENOTDIR(`stat '${r}'`);return this.statImpl(`stat '${r}'`,a,o)}}async fstatPromise(r,o){return this.fstatSync(r,o)}fstatSync(r,o){let a=this.fds.get(r);if(typeof a>"u")throw nr.EBADF("fstatSync");let{p:n}=a,u=this.resolveFilename(`stat '${n}'`,n);if(!this.entries.has(u)&&!this.listings.has(u))throw nr.ENOENT(`stat '${n}'`);if(n[n.length-1]==="/"&&!this.listings.has(u))throw nr.ENOTDIR(`stat '${n}'`);return this.statImpl(`fstat '${n}'`,u,o)}async lstatPromise(r,o={bigint:!1}){return o.bigint?this.lstatSync(r,{bigint:!0}):this.lstatSync(r)}lstatSync(r,o={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`lstat '${r}'`,r,!1,o.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(o.throwIfNoEntry===!1)return;throw nr.ENOENT(`lstat '${r}'`)}if(r[r.length-1]==="/"&&!this.listings.has(a))throw nr.ENOTDIR(`lstat '${r}'`);return this.statImpl(`lstat '${r}'`,a,o)}}statImpl(r,o,a={}){let n=this.entries.get(o);if(typeof n<"u"){let u=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,n,0,0,u)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let p=this.stats.uid,h=this.stats.gid,E=this.libzip.struct.statSize(u)>>>0,I=512,v=Math.ceil(E/I),x=(this.libzip.struct.statMtime(u)>>>0)*1e3,C=x,R=x,L=x,U=new Date(C),z=new Date(R),te=new Date(L),ae=new Date(x),le=this.listings.has(o)?na.constants.S_IFDIR:this.isSymbolicLink(n)?na.constants.S_IFLNK:na.constants.S_IFREG,ce=le===na.constants.S_IFDIR?493:420,Ce=le|this.getUnixMode(n,ce)&511,de=this.libzip.struct.statCrc(u),Be=Object.assign(new wa.StatEntry,{uid:p,gid:h,size:E,blksize:I,blocks:v,atime:U,birthtime:z,ctime:te,mtime:ae,atimeMs:C,birthtimeMs:R,ctimeMs:L,mtimeMs:x,mode:Ce,crc:de});return a.bigint===!0?wa.convertToBigIntStats(Be):Be}if(this.listings.has(o)){let u=this.stats.uid,A=this.stats.gid,p=0,h=512,E=0,I=this.stats.mtimeMs,v=this.stats.mtimeMs,x=this.stats.mtimeMs,C=this.stats.mtimeMs,R=new Date(I),L=new Date(v),U=new Date(x),z=new Date(C),te=na.constants.S_IFDIR|493,le=Object.assign(new wa.StatEntry,{uid:u,gid:A,size:p,blksize:h,blocks:E,atime:R,birthtime:L,ctime:U,mtime:z,atimeMs:I,birthtimeMs:v,ctimeMs:x,mtimeMs:C,mode:te,crc:0});return a.bigint===!0?wa.convertToBigIntStats(le):le}throw new Error("Unreachable")}getUnixMode(r,o){if(this.libzip.file.getExternalAttributes(this.zip,r,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.libzip.getValue(this.libzip.uint08S,"i8")>>>0!==this.libzip.ZIP_OPSYS_UNIX?o:this.libzip.getValue(this.libzip.uint32S,"i32")>>>16}registerListing(r){let o=this.listings.get(r);if(o)return o;this.registerListing(K.dirname(r)).add(K.basename(r));let n=new Set;return this.listings.set(r,n),n}registerEntry(r,o){this.registerListing(K.dirname(r)).add(K.basename(r)),this.entries.set(r,o)}unregisterListing(r){this.listings.delete(r),this.listings.get(K.dirname(r))?.delete(K.basename(r))}unregisterEntry(r){this.unregisterListing(r);let o=this.entries.get(r);this.entries.delete(r),!(typeof o>"u")&&(this.fileSources.delete(o),this.isSymbolicLink(o)&&this.symlinkCount--)}deleteEntry(r,o){if(this.unregisterEntry(r),this.libzip.delete(this.zip,o)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}resolveFilename(r,o,a=!0,n=!0){if(!this.ready)throw nr.EBUSY(`archive closed, ${r}`);let u=K.resolve(It.root,o);if(u==="/")return It.root;let A=this.entries.get(u);if(a&&A!==void 0)if(this.symlinkCount!==0&&this.isSymbolicLink(A)){let p=this.getFileSource(A).toString();return this.resolveFilename(r,K.resolve(K.dirname(u),p),!0,n)}else return u;for(;;){let p=this.resolveFilename(r,K.dirname(u),!0,n);if(p===void 0)return p;let h=this.listings.has(p),E=this.entries.has(p);if(!h&&!E){if(n===!1)return;throw nr.ENOENT(r)}if(!h)throw nr.ENOTDIR(r);if(u=K.resolve(p,K.basename(u)),!a||this.symlinkCount===0)break;let I=this.libzip.name.locate(this.zip,u.slice(1),0);if(I===-1)break;if(this.isSymbolicLink(I)){let v=this.getFileSource(I).toString();u=K.resolve(K.dirname(u),v)}else break}return u}allocateBuffer(r){Buffer.isBuffer(r)||(r=Buffer.from(r));let o=this.libzip.malloc(r.byteLength);if(!o)throw new Error("Couldn't allocate enough memory");return new Uint8Array(this.libzip.HEAPU8.buffer,o,r.byteLength).set(r),{buffer:o,byteLength:r.byteLength}}allocateUnattachedSource(r){let o=this.libzip.struct.errorS(),{buffer:a,byteLength:n}=this.allocateBuffer(r),u=this.libzip.source.fromUnattachedBuffer(a,n,0,1,o);if(u===0)throw this.libzip.free(o),this.makeLibzipError(o);return u}allocateSource(r){let{buffer:o,byteLength:a}=this.allocateBuffer(r),n=this.libzip.source.fromBuffer(this.zip,o,a,0,1);if(n===0)throw this.libzip.free(o),this.makeLibzipError(this.libzip.getError(this.zip));return n}setFileSource(r,o){let a=Buffer.isBuffer(o)?o:Buffer.from(o),n=K.relative(It.root,r),u=this.allocateSource(o);try{let A=this.libzip.file.add(this.zip,n,u,this.libzip.ZIP_FL_OVERWRITE);if(A===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(this.level!=="mixed"){let p=this.level===0?this.libzip.ZIP_CM_STORE:this.libzip.ZIP_CM_DEFLATE;if(this.libzip.file.setCompression(this.zip,A,0,p,this.level)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}return this.fileSources.set(A,a),A}catch(A){throw this.libzip.source.free(u),A}}isSymbolicLink(r){if(this.symlinkCount===0)return!1;if(this.libzip.file.getExternalAttributes(this.zip,r,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.libzip.getValue(this.libzip.uint08S,"i8")>>>0!==this.libzip.ZIP_OPSYS_UNIX?!1:(this.libzip.getValue(this.libzip.uint32S,"i32")>>>16&na.constants.S_IFMT)===na.constants.S_IFLNK}getFileSource(r,o={asyncDecompress:!1}){let a=this.fileSources.get(r);if(typeof a<"u")return a;let n=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,r,0,0,n)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let A=this.libzip.struct.statCompSize(n),p=this.libzip.struct.statCompMethod(n),h=this.libzip.malloc(A);try{let E=this.libzip.fopenIndex(this.zip,r,0,this.libzip.ZIP_FL_COMPRESSED);if(E===0)throw this.makeLibzipError(this.libzip.getError(this.zip));try{let I=this.libzip.fread(E,h,A,0);if(I===-1)throw this.makeLibzipError(this.libzip.file.getError(E));if(I<A)throw new Error("Incomplete read");if(I>A)throw new Error("Overread");let v=this.libzip.HEAPU8.subarray(h,h+A),x=Buffer.from(v);if(p===0)return this.fileSources.set(r,x),x;if(o.asyncDecompress)return new Promise((C,R)=>{J4.default.inflateRaw(x,(L,U)=>{L?R(L):(this.fileSources.set(r,U),C(U))})});{let C=J4.default.inflateRawSync(x);return this.fileSources.set(r,C),C}}finally{this.libzip.fclose(E)}}finally{this.libzip.free(h)}}async fchmodPromise(r,o){return this.chmodPromise(this.fdToPath(r,"fchmod"),o)}fchmodSync(r,o){return this.chmodSync(this.fdToPath(r,"fchmodSync"),o)}async chmodPromise(r,o){return this.chmodSync(r,o)}chmodSync(r,o){if(this.readOnly)throw nr.EROFS(`chmod '${r}'`);o&=493;let a=this.resolveFilename(`chmod '${r}'`,r,!1),n=this.entries.get(a);if(typeof n>"u")throw new Error(`Assertion failed: The entry should have been registered (${a})`);let A=this.getUnixMode(n,na.constants.S_IFREG|0)&-512|o;if(this.libzip.file.setExternalAttributes(this.zip,n,0,0,this.libzip.ZIP_OPSYS_UNIX,A<<16)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}async fchownPromise(r,o,a){return this.chownPromise(this.fdToPath(r,"fchown"),o,a)}fchownSync(r,o,a){return this.chownSync(this.fdToPath(r,"fchownSync"),o,a)}async chownPromise(r,o,a){return this.chownSync(r,o,a)}chownSync(r,o,a){throw new Error("Unimplemented")}async renamePromise(r,o){return this.renameSync(r,o)}renameSync(r,o){throw new Error("Unimplemented")}async copyFilePromise(r,o,a){let{indexSource:n,indexDest:u,resolvedDestP:A}=this.prepareCopyFile(r,o,a),p=await this.getFileSource(n,{asyncDecompress:!0}),h=this.setFileSource(A,p);h!==u&&this.registerEntry(A,h)}copyFileSync(r,o,a=0){let{indexSource:n,indexDest:u,resolvedDestP:A}=this.prepareCopyFile(r,o,a),p=this.getFileSource(n),h=this.setFileSource(A,p);h!==u&&this.registerEntry(A,h)}prepareCopyFile(r,o,a=0){if(this.readOnly)throw nr.EROFS(`copyfile '${r} -> '${o}'`);if(a&na.constants.COPYFILE_FICLONE_FORCE)throw nr.ENOSYS("unsupported clone operation",`copyfile '${r}' -> ${o}'`);let n=this.resolveFilename(`copyfile '${r} -> ${o}'`,r),u=this.entries.get(n);if(typeof u>"u")throw nr.EINVAL(`copyfile '${r}' -> '${o}'`);let A=this.resolveFilename(`copyfile '${r}' -> ${o}'`,o),p=this.entries.get(A);if(a&(na.constants.COPYFILE_EXCL|na.constants.COPYFILE_FICLONE_FORCE)&&typeof p<"u")throw nr.EEXIST(`copyfile '${r}' -> '${o}'`);return{indexSource:u,resolvedDestP:A,indexDest:p}}async appendFilePromise(r,o,a){if(this.readOnly)throw nr.EROFS(`open '${r}'`);return typeof a>"u"?a={flag:"a"}:typeof a=="string"?a={flag:"a",encoding:a}:typeof a.flag>"u"&&(a={flag:"a",...a}),this.writeFilePromise(r,o,a)}appendFileSync(r,o,a={}){if(this.readOnly)throw nr.EROFS(`open '${r}'`);return typeof a>"u"?a={flag:"a"}:typeof a=="string"?a={flag:"a",encoding:a}:typeof a.flag>"u"&&(a={flag:"a",...a}),this.writeFileSync(r,o,a)}fdToPath(r,o){let a=this.fds.get(r)?.p;if(typeof a>"u")throw nr.EBADF(o);return a}async writeFilePromise(r,o,a){let{encoding:n,mode:u,index:A,resolvedP:p}=this.prepareWriteFile(r,a);A!==void 0&&typeof a=="object"&&a.flag&&a.flag.includes("a")&&(o=Buffer.concat([await this.getFileSource(A,{asyncDecompress:!0}),Buffer.from(o)])),n!==null&&(o=o.toString(n));let h=this.setFileSource(p,o);h!==A&&this.registerEntry(p,h),u!==null&&await this.chmodPromise(p,u)}writeFileSync(r,o,a){let{encoding:n,mode:u,index:A,resolvedP:p}=this.prepareWriteFile(r,a);A!==void 0&&typeof a=="object"&&a.flag&&a.flag.includes("a")&&(o=Buffer.concat([this.getFileSource(A),Buffer.from(o)])),n!==null&&(o=o.toString(n));let h=this.setFileSource(p,o);h!==A&&this.registerEntry(p,h),u!==null&&this.chmodSync(p,u)}prepareWriteFile(r,o){if(typeof r=="number"&&(r=this.fdToPath(r,"read")),this.readOnly)throw nr.EROFS(`open '${r}'`);let a=this.resolveFilename(`open '${r}'`,r);if(this.listings.has(a))throw nr.EISDIR(`open '${r}'`);let n=null,u=null;typeof o=="string"?n=o:typeof o=="object"&&({encoding:n=null,mode:u=null}=o);let A=this.entries.get(a);return{encoding:n,mode:u,resolvedP:a,index:A}}async unlinkPromise(r){return this.unlinkSync(r)}unlinkSync(r){if(this.readOnly)throw nr.EROFS(`unlink '${r}'`);let o=this.resolveFilename(`unlink '${r}'`,r);if(this.listings.has(o))throw nr.EISDIR(`unlink '${r}'`);let a=this.entries.get(o);if(typeof a>"u")throw nr.EINVAL(`unlink '${r}'`);this.deleteEntry(o,a)}async utimesPromise(r,o,a){return this.utimesSync(r,o,a)}utimesSync(r,o,a){if(this.readOnly)throw nr.EROFS(`utimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r);this.utimesImpl(n,a)}async lutimesPromise(r,o,a){return this.lutimesSync(r,o,a)}lutimesSync(r,o,a){if(this.readOnly)throw nr.EROFS(`lutimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r,!1);this.utimesImpl(n,a)}utimesImpl(r,o){this.listings.has(r)&&(this.entries.has(r)||this.hydrateDirectory(r));let a=this.entries.get(r);if(a===void 0)throw new Error("Unreachable");if(this.libzip.file.setMtime(this.zip,a,0,fot(o),0)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}async mkdirPromise(r,o){return this.mkdirSync(r,o)}mkdirSync(r,{mode:o=493,recursive:a=!1}={}){if(a)return this.mkdirpSync(r,{chmod:o});if(this.readOnly)throw nr.EROFS(`mkdir '${r}'`);let n=this.resolveFilename(`mkdir '${r}'`,r);if(this.entries.has(n)||this.listings.has(n))throw nr.EEXIST(`mkdir '${r}'`);this.hydrateDirectory(n),this.chmodSync(n,o)}async rmdirPromise(r,o){return this.rmdirSync(r,o)}rmdirSync(r,{recursive:o=!1}={}){if(this.readOnly)throw nr.EROFS(`rmdir '${r}'`);if(o){this.removeSync(r);return}let a=this.resolveFilename(`rmdir '${r}'`,r),n=this.listings.get(a);if(!n)throw nr.ENOTDIR(`rmdir '${r}'`);if(n.size>0)throw nr.ENOTEMPTY(`rmdir '${r}'`);let u=this.entries.get(a);if(typeof u>"u")throw nr.EINVAL(`rmdir '${r}'`);this.deleteEntry(r,u)}async rmPromise(r,o){return this.rmSync(r,o)}rmSync(r,{recursive:o=!1}={}){if(this.readOnly)throw nr.EROFS(`rm '${r}'`);if(o){this.removeSync(r);return}let a=this.resolveFilename(`rm '${r}'`,r),n=this.listings.get(a);if(!n)throw nr.ENOTDIR(`rm '${r}'`);if(n.size>0)throw nr.ENOTEMPTY(`rm '${r}'`);let u=this.entries.get(a);if(typeof u>"u")throw nr.EINVAL(`rm '${r}'`);this.deleteEntry(r,u)}hydrateDirectory(r){let o=this.libzip.dir.add(this.zip,K.relative(It.root,r));if(o===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.registerListing(r),this.registerEntry(r,o),o}async linkPromise(r,o){return this.linkSync(r,o)}linkSync(r,o){throw nr.EOPNOTSUPP(`link '${r}' -> '${o}'`)}async symlinkPromise(r,o){return this.symlinkSync(r,o)}symlinkSync(r,o){if(this.readOnly)throw nr.EROFS(`symlink '${r}' -> '${o}'`);let a=this.resolveFilename(`symlink '${r}' -> '${o}'`,o);if(this.listings.has(a))throw nr.EISDIR(`symlink '${r}' -> '${o}'`);if(this.entries.has(a))throw nr.EEXIST(`symlink '${r}' -> '${o}'`);let n=this.setFileSource(a,r);if(this.registerEntry(a,n),this.libzip.file.setExternalAttributes(this.zip,n,0,0,this.libzip.ZIP_OPSYS_UNIX,(na.constants.S_IFLNK|511)<<16)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));this.symlinkCount+=1}async readFilePromise(r,o){typeof o=="object"&&(o=o?o.encoding:void 0);let a=await this.readFileBuffer(r,{asyncDecompress:!0});return o?a.toString(o):a}readFileSync(r,o){typeof o=="object"&&(o=o?o.encoding:void 0);let a=this.readFileBuffer(r);return o?a.toString(o):a}readFileBuffer(r,o={asyncDecompress:!1}){typeof r=="number"&&(r=this.fdToPath(r,"read"));let a=this.resolveFilename(`open '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw nr.ENOENT(`open '${r}'`);if(r[r.length-1]==="/"&&!this.listings.has(a))throw nr.ENOTDIR(`open '${r}'`);if(this.listings.has(a))throw nr.EISDIR("read");let n=this.entries.get(a);if(n===void 0)throw new Error("Unreachable");return this.getFileSource(n,o)}async readdirPromise(r,o){return this.readdirSync(r,o)}readdirSync(r,o){let a=this.resolveFilename(`scandir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw nr.ENOENT(`scandir '${r}'`);let n=this.listings.get(a);if(!n)throw nr.ENOTDIR(`scandir '${r}'`);if(o?.recursive)if(o?.withFileTypes){let u=Array.from(n,A=>Object.assign(this.statImpl("lstat",K.join(r,A)),{name:A,path:It.dot}));for(let A of u){if(!A.isDirectory())continue;let p=K.join(A.path,A.name),h=this.listings.get(K.join(a,p));for(let E of h)u.push(Object.assign(this.statImpl("lstat",K.join(r,p,E)),{name:E,path:p}))}return u}else{let u=[...n];for(let A of u){let p=this.listings.get(K.join(a,A));if(!(typeof p>"u"))for(let h of p)u.push(K.join(A,h))}return u}else return o?.withFileTypes?Array.from(n,u=>Object.assign(this.statImpl("lstat",K.join(r,u)),{name:u,path:void 0})):[...n]}async readlinkPromise(r){let o=this.prepareReadlink(r);return(await this.getFileSource(o,{asyncDecompress:!0})).toString()}readlinkSync(r){let o=this.prepareReadlink(r);return this.getFileSource(o).toString()}prepareReadlink(r){let o=this.resolveFilename(`readlink '${r}'`,r,!1);if(!this.entries.has(o)&&!this.listings.has(o))throw nr.ENOENT(`readlink '${r}'`);if(r[r.length-1]==="/"&&!this.listings.has(o))throw nr.ENOTDIR(`open '${r}'`);if(this.listings.has(o))throw nr.EINVAL(`readlink '${r}'`);let a=this.entries.get(o);if(a===void 0)throw new Error("Unreachable");if(!this.isSymbolicLink(a))throw nr.EINVAL(`readlink '${r}'`);return a}async truncatePromise(r,o=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>"u")throw nr.EINVAL(`open '${r}'`);let u=await this.getFileSource(n,{asyncDecompress:!0}),A=Buffer.alloc(o,0);return u.copy(A),await this.writeFilePromise(r,A)}truncateSync(r,o=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>"u")throw nr.EINVAL(`open '${r}'`);let u=this.getFileSource(n),A=Buffer.alloc(o,0);return u.copy(A),this.writeFileSync(r,A)}async ftruncatePromise(r,o){return this.truncatePromise(this.fdToPath(r,"ftruncate"),o)}ftruncateSync(r,o){return this.truncateSync(this.fdToPath(r,"ftruncateSync"),o)}watch(r,o,a){let n;switch(typeof o){case"function":case"string":case"undefined":n=!0;break;default:({persistent:n=!0}=o);break}if(!n)return{on:()=>{},close:()=>{}};let u=setInterval(()=>{},24*60*60*1e3);return{on:()=>{},close:()=>{clearInterval(u)}}}watchFile(r,o,a){let n=K.resolve(It.root,r);return jd(this,n,o,a)}unwatchFile(r,o){let a=K.resolve(It.root,r);return T0(this,a,o)}}});function Yle(t,e,r=Buffer.alloc(0),o){let a=new Zi(r),n=I=>I===e||I.startsWith(`${e}/`)?I.slice(0,e.length):null,u=async(I,v)=>()=>a,A=(I,v)=>a,p={...t},h=new Tn(p),E=new Op({baseFs:h,getMountPoint:n,factoryPromise:u,factorySync:A,magicByte:21,maxAge:1/0,typeCheck:o?.typeCheck});return xw(Gle.default,new Up(E)),a}var Gle,Wle=Et(()=>{Pt();Gle=Ze(ve("fs"));X4()});var Kle=Et(()=>{Hle();X4();Wle()});var p1={};Vt(p1,{DEFAULT_COMPRESSION_LEVEL:()=>jle,LibzipError:()=>Ib,ZipFS:()=>Zi,ZipOpenFS:()=>rA,getArchivePart:()=>V4,getLibzipPromise:()=>hot,getLibzipSync:()=>pot,makeEmptyArchive:()=>wb,mountMemoryDrive:()=>Yle});function pot(){return f1()}async function hot(){return f1()}var Vle,nA=Et(()=>{Y4();Vle=Ze(Mle());_le();Kle();Lle(()=>{let t=(0,Vle.default)();return Ule(t)})});var h1,zle=Et(()=>{Pt();qt();g1();h1=class extends it{constructor(){super(...arguments);this.cwd=ge.String("--cwd",process.cwd(),{description:"The directory to run the command in"});this.commandName=ge.String();this.args=ge.Proxy()}static{this.usage={description:"run a command using yarn's portable shell",details:` + This command will run a command using Yarn's portable shell. + + Make sure to escape glob patterns, redirections, and other features that might be expanded by your own shell. + + Note: To escape something from Yarn's shell, you might have to escape it twice, the first time from your own shell. + + Note: Don't use this command in Yarn scripts, as Yarn's shell is automatically used. + + For a list of features, visit: https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-shell/README.md. + `,examples:[["Run a simple command","$0 echo Hello"],["Run a command with a glob pattern","$0 echo '*.js'"],["Run a command with a redirection","$0 echo Hello World '>' hello.txt"],["Run a command with an escaped glob pattern (The double escape is needed in Unix shells)",`$0 echo '"*.js"'`],["Run a command with a variable (Double quotes are needed in Unix shells, to prevent them from expanding the variable)",'$0 "GREETING=Hello echo $GREETING World"']]}}async execute(){let r=this.args.length>0?`${this.commandName} ${this.args.join(" ")}`:this.commandName;return await cy(r,[],{cwd:ue.toPortablePath(this.cwd),stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}}});var ll,Jle=Et(()=>{ll=class extends Error{constructor(e){super(e),this.name="ShellError"}}});var Db={};Vt(Db,{fastGlobOptions:()=>$le,isBraceExpansion:()=>Z4,isGlobPattern:()=>got,match:()=>dot,micromatchOptions:()=>vb});function got(t){if(!Bb.default.scan(t,vb).isGlob)return!1;try{Bb.default.parse(t,vb)}catch{return!1}return!0}function dot(t,{cwd:e,baseFs:r}){return(0,Xle.default)(t,{...$le,cwd:ue.fromPortablePath(e),fs:mD(Zle.default,new Up(r))})}function Z4(t){return Bb.default.scan(t,vb).isBrace}var Xle,Zle,Bb,vb,$le,ece=Et(()=>{Pt();Xle=Ze(ES()),Zle=Ze(ve("fs")),Bb=Ze($o()),vb={strictBrackets:!0},$le={onlyDirectories:!1,onlyFiles:!1}});function $4(){}function eU(){for(let t of vg)t.kill()}function ice(t,e,r,o){return a=>{let n=a[0]instanceof iA.Transform?"pipe":a[0],u=a[1]instanceof iA.Transform?"pipe":a[1],A=a[2]instanceof iA.Transform?"pipe":a[2],p=(0,rce.default)(t,e,{...o,stdio:[n,u,A]});return vg.add(p),vg.size===1&&(process.on("SIGINT",$4),process.on("SIGTERM",eU)),a[0]instanceof iA.Transform&&a[0].pipe(p.stdin),a[1]instanceof iA.Transform&&p.stdout.pipe(a[1],{end:!1}),a[2]instanceof iA.Transform&&p.stderr.pipe(a[2],{end:!1}),{stdin:p.stdin,promise:new Promise(h=>{p.on("error",E=>{switch(vg.delete(p),vg.size===0&&(process.off("SIGINT",$4),process.off("SIGTERM",eU)),E.code){case"ENOENT":a[2].write(`command not found: ${t} +`),h(127);break;case"EACCES":a[2].write(`permission denied: ${t} +`),h(128);break;default:a[2].write(`uncaught error: ${E.message} +`),h(1);break}}),p.on("close",E=>{vg.delete(p),vg.size===0&&(process.off("SIGINT",$4),process.off("SIGTERM",eU)),h(E!==null?E:129)})})}}}function sce(t){return e=>{let r=e[0]==="pipe"?new iA.PassThrough:e[0];return{stdin:r,promise:Promise.resolve().then(()=>t({stdin:r,stdout:e[1],stderr:e[2]}))}}}function Pb(t,e){return rU.start(t,e)}function tce(t,e=null){let r=new iA.PassThrough,o=new nce.StringDecoder,a="";return r.on("data",n=>{let u=o.write(n),A;do if(A=u.indexOf(` +`),A!==-1){let p=a+u.substring(0,A);u=u.substring(A+1),a="",t(e!==null?`${e} ${p}`:p)}while(A!==-1);a+=u}),r.on("end",()=>{let n=o.end();n!==""&&t(e!==null?`${e} ${n}`:n)}),r}function oce(t,{prefix:e}){return{stdout:tce(r=>t.stdout.write(`${r} +`),t.stdout.isTTY?e:null),stderr:tce(r=>t.stderr.write(`${r} +`),t.stderr.isTTY?e:null)}}var rce,iA,nce,vg,Jl,tU,rU,nU=Et(()=>{rce=Ze(KR()),iA=ve("stream"),nce=ve("string_decoder"),vg=new Set;Jl=class{constructor(e){this.stream=e}close(){}get(){return this.stream}},tU=class{constructor(){this.stream=null}close(){if(this.stream===null)throw new Error("Assertion failed: No stream attached");this.stream.end()}attach(e){this.stream=e}get(){if(this.stream===null)throw new Error("Assertion failed: No stream attached");return this.stream}},rU=class t{constructor(e,r){this.stdin=null;this.stdout=null;this.stderr=null;this.pipe=null;this.ancestor=e,this.implementation=r}static start(e,{stdin:r,stdout:o,stderr:a}){let n=new t(null,e);return n.stdin=r,n.stdout=o,n.stderr=a,n}pipeTo(e,r=1){let o=new t(this,e),a=new tU;return o.pipe=a,o.stdout=this.stdout,o.stderr=this.stderr,(r&1)===1?this.stdout=a:this.ancestor!==null&&(this.stderr=this.ancestor.stdout),(r&2)===2?this.stderr=a:this.ancestor!==null&&(this.stderr=this.ancestor.stderr),o}async exec(){let e=["ignore","ignore","ignore"];if(this.pipe)e[0]="pipe";else{if(this.stdin===null)throw new Error("Assertion failed: No input stream registered");e[0]=this.stdin.get()}let r;if(this.stdout===null)throw new Error("Assertion failed: No output stream registered");r=this.stdout,e[1]=r.get();let o;if(this.stderr===null)throw new Error("Assertion failed: No error stream registered");o=this.stderr,e[2]=o.get();let a=this.implementation(e);return this.pipe&&this.pipe.attach(a.stdin),await a.promise.then(n=>(r.close(),o.close(),n))}async run(){let e=[];for(let o=this;o;o=o.ancestor)e.push(o.exec());return(await Promise.all(e))[0]}}});var E1={};Vt(E1,{EntryCommand:()=>h1,ShellError:()=>ll,execute:()=>cy,globUtils:()=>Db});function ace(t,e,r){let o=new cl.PassThrough({autoDestroy:!0});switch(t){case 0:(e&1)===1&&r.stdin.pipe(o,{end:!1}),(e&2)===2&&r.stdin instanceof cl.Writable&&o.pipe(r.stdin,{end:!1});break;case 1:(e&1)===1&&r.stdout.pipe(o,{end:!1}),(e&2)===2&&o.pipe(r.stdout,{end:!1});break;case 2:(e&1)===1&&r.stderr.pipe(o,{end:!1}),(e&2)===2&&o.pipe(r.stderr,{end:!1});break;default:throw new ll(`Bad file descriptor: "${t}"`)}return o}function bb(t,e={}){let r={...t,...e};return r.environment={...t.environment,...e.environment},r.variables={...t.variables,...e.variables},r}async function yot(t,e,r){let o=[],a=new cl.PassThrough;return a.on("data",n=>o.push(n)),await xb(t,e,bb(r,{stdout:a})),Buffer.concat(o).toString().replace(/[\r\n]+$/,"")}async function lce(t,e,r){let o=t.map(async n=>{let u=await Dg(n.args,e,r);return{name:n.name,value:u.join(" ")}});return(await Promise.all(o)).reduce((n,u)=>(n[u.name]=u.value,n),{})}function Sb(t){return t.match(/[^ \r\n\t]+/g)||[]}async function hce(t,e,r,o,a=o){switch(t.name){case"$":o(String(process.pid));break;case"#":o(String(e.args.length));break;case"@":if(t.quoted)for(let n of e.args)a(n);else for(let n of e.args){let u=Sb(n);for(let A=0;A<u.length-1;++A)a(u[A]);o(u[u.length-1])}break;case"*":{let n=e.args.join(" ");if(t.quoted)o(n);else for(let u of Sb(n))a(u)}break;case"PPID":o(String(process.ppid));break;case"RANDOM":o(String(Math.floor(Math.random()*32768)));break;default:{let n=parseInt(t.name,10),u,A=Number.isFinite(n);if(A?n>=0&&n<e.args.length&&(u=e.args[n]):Object.hasOwn(r.variables,t.name)?u=r.variables[t.name]:Object.hasOwn(r.environment,t.name)&&(u=r.environment[t.name]),typeof u<"u"&&t.alternativeValue?u=(await Dg(t.alternativeValue,e,r)).join(" "):typeof u>"u"&&(t.defaultValue?u=(await Dg(t.defaultValue,e,r)).join(" "):t.alternativeValue&&(u="")),typeof u>"u")throw A?new ll(`Unbound argument #${n}`):new ll(`Unbound variable "${t.name}"`);if(t.quoted)o(u);else{let p=Sb(u);for(let E=0;E<p.length-1;++E)a(p[E]);let h=p[p.length-1];typeof h<"u"&&o(h)}}break}}async function d1(t,e,r){if(t.type==="number"){if(Number.isInteger(t.value))return t.value;throw new Error(`Invalid number: "${t.value}", only integers are allowed`)}else if(t.type==="variable"){let o=[];await hce({...t,quoted:!0},e,r,n=>o.push(n));let a=Number(o.join(" "));return Number.isNaN(a)?d1({type:"variable",name:o.join(" ")},e,r):d1({type:"number",value:a},e,r)}else return Eot[t.type](await d1(t.left,e,r),await d1(t.right,e,r))}async function Dg(t,e,r){let o=new Map,a=[],n=[],u=E=>{n.push(E)},A=()=>{n.length>0&&a.push(n.join("")),n=[]},p=E=>{u(E),A()},h=(E,I,v)=>{let x=JSON.stringify({type:E,fd:I}),C=o.get(x);typeof C>"u"&&o.set(x,C=[]),C.push(v)};for(let E of t){let I=!1;switch(E.type){case"redirection":{let v=await Dg(E.args,e,r);for(let x of v)h(E.subtype,E.fd,x)}break;case"argument":for(let v of E.segments)switch(v.type){case"text":u(v.text);break;case"glob":u(v.pattern),I=!0;break;case"shell":{let x=await yot(v.shell,e,r);if(v.quoted)u(x);else{let C=Sb(x);for(let R=0;R<C.length-1;++R)p(C[R]);u(C[C.length-1])}}break;case"variable":await hce(v,e,r,u,p);break;case"arithmetic":u(String(await d1(v.arithmetic,e,r)));break}break}if(A(),I){let v=a.pop();if(typeof v>"u")throw new Error("Assertion failed: Expected a glob pattern to have been set");let x=await e.glob.match(v,{cwd:r.cwd,baseFs:e.baseFs});if(x.length===0){let C=Z4(v)?". Note: Brace expansion of arbitrary strings isn't currently supported. For more details, please read this issue: https://github.com/yarnpkg/berry/issues/22":"";throw new ll(`No matches found: "${v}"${C}`)}for(let C of x.sort())p(C)}}if(o.size>0){let E=[];for(let[I,v]of o.entries())E.splice(E.length,0,I,String(v.length),...v);a.splice(0,0,"__ysh_set_redirects",...E,"--")}return a}function m1(t,e,r){e.builtins.has(t[0])||(t=["command",...t]);let o=ue.fromPortablePath(r.cwd),a=r.environment;typeof a.PWD<"u"&&(a={...a,PWD:o});let[n,...u]=t;if(n==="command")return ice(u[0],u.slice(1),e,{cwd:o,env:a});let A=e.builtins.get(n);if(typeof A>"u")throw new Error(`Assertion failed: A builtin should exist for "${n}"`);return sce(async({stdin:p,stdout:h,stderr:E})=>{let{stdin:I,stdout:v,stderr:x}=r;r.stdin=p,r.stdout=h,r.stderr=E;try{return await A(u,e,r)}finally{r.stdin=I,r.stdout=v,r.stderr=x}})}function Cot(t,e,r){return o=>{let a=new cl.PassThrough,n=xb(t,e,bb(r,{stdin:a}));return{stdin:a,promise:n}}}function wot(t,e,r){return o=>{let a=new cl.PassThrough,n=xb(t,e,r);return{stdin:a,promise:n}}}function cce(t,e,r,o){if(e.length===0)return t;{let a;do a=String(Math.random());while(Object.hasOwn(o.procedures,a));return o.procedures={...o.procedures},o.procedures[a]=t,m1([...e,"__ysh_run_procedure",a],r,o)}}async function uce(t,e,r){let o=t,a=null,n=null;for(;o;){let u=o.then?{...r}:r,A;switch(o.type){case"command":{let p=await Dg(o.args,e,r),h=await lce(o.envs,e,r);A=o.envs.length?m1(p,e,bb(u,{environment:h})):m1(p,e,u)}break;case"subshell":{let p=await Dg(o.args,e,r),h=Cot(o.subshell,e,u);A=cce(h,p,e,u)}break;case"group":{let p=await Dg(o.args,e,r),h=wot(o.group,e,u);A=cce(h,p,e,u)}break;case"envs":{let p=await lce(o.envs,e,r);u.environment={...u.environment,...p},A=m1(["true"],e,u)}break}if(typeof A>"u")throw new Error("Assertion failed: An action should have been generated");if(a===null)n=Pb(A,{stdin:new Jl(u.stdin),stdout:new Jl(u.stdout),stderr:new Jl(u.stderr)});else{if(n===null)throw new Error("Assertion failed: The execution pipeline should have been setup");switch(a){case"|":n=n.pipeTo(A,1);break;case"|&":n=n.pipeTo(A,3);break}}o.then?(a=o.then.type,o=o.then.chain):o=null}if(n===null)throw new Error("Assertion failed: The execution pipeline should have been setup");return await n.run()}async function Iot(t,e,r,{background:o=!1}={}){function a(n){let u=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],A=u[n%u.length];return Ace.default.hex(A)}if(o){let n=r.nextBackgroundJobIndex++,u=a(n),A=`[${n}]`,p=u(A),{stdout:h,stderr:E}=oce(r,{prefix:p});return r.backgroundJobs.push(uce(t,e,bb(r,{stdout:h,stderr:E})).catch(I=>E.write(`${I.message} +`)).finally(()=>{r.stdout.isTTY&&r.stdout.write(`Job ${p}, '${u(Jd(t))}' has ended +`)})),0}return await uce(t,e,r)}async function Bot(t,e,r,{background:o=!1}={}){let a,n=A=>{a=A,r.variables["?"]=String(A)},u=async A=>{try{return await Iot(A.chain,e,r,{background:o&&typeof A.then>"u"})}catch(p){if(!(p instanceof ll))throw p;return r.stderr.write(`${p.message} +`),1}};for(n(await u(t));t.then;){if(r.exitCode!==null)return r.exitCode;switch(t.then.type){case"&&":a===0&&n(await u(t.then.line));break;case"||":a!==0&&n(await u(t.then.line));break;default:throw new Error(`Assertion failed: Unsupported command type: "${t.then.type}"`)}t=t.then.line}return a}async function xb(t,e,r){let o=r.backgroundJobs;r.backgroundJobs=[];let a=0;for(let{command:n,type:u}of t){if(a=await Bot(n,e,r,{background:u==="&"}),r.exitCode!==null)return r.exitCode;r.variables["?"]=String(a)}return await Promise.all(r.backgroundJobs),r.backgroundJobs=o,a}function gce(t){switch(t.type){case"variable":return t.name==="@"||t.name==="#"||t.name==="*"||Number.isFinite(parseInt(t.name,10))||"defaultValue"in t&&!!t.defaultValue&&t.defaultValue.some(e=>y1(e))||"alternativeValue"in t&&!!t.alternativeValue&&t.alternativeValue.some(e=>y1(e));case"arithmetic":return iU(t.arithmetic);case"shell":return sU(t.shell);default:return!1}}function y1(t){switch(t.type){case"redirection":return t.args.some(e=>y1(e));case"argument":return t.segments.some(e=>gce(e));default:throw new Error(`Assertion failed: Unsupported argument type: "${t.type}"`)}}function iU(t){switch(t.type){case"variable":return gce(t);case"number":return!1;default:return iU(t.left)||iU(t.right)}}function sU(t){return t.some(({command:e})=>{for(;e;){let r=e.chain;for(;r;){let o;switch(r.type){case"subshell":o=sU(r.subshell);break;case"command":o=r.envs.some(a=>a.args.some(n=>y1(n)))||r.args.some(a=>y1(a));break}if(o)return!0;if(!r.then)break;r=r.then.chain}if(!e.then)break;e=e.then.line}return!1})}async function cy(t,e=[],{baseFs:r=new Tn,builtins:o={},cwd:a=ue.toPortablePath(process.cwd()),env:n=process.env,stdin:u=process.stdin,stdout:A=process.stdout,stderr:p=process.stderr,variables:h={},glob:E=Db}={}){let I={};for(let[C,R]of Object.entries(n))typeof R<"u"&&(I[C]=R);let v=new Map(mot);for(let[C,R]of Object.entries(o))v.set(C,R);u===null&&(u=new cl.PassThrough,u.end());let x=CD(t,E);if(!sU(x)&&x.length>0&&e.length>0){let{command:C}=x[x.length-1];for(;C.then;)C=C.then.line;let R=C.chain;for(;R.then;)R=R.then.chain;R.type==="command"&&(R.args=R.args.concat(e.map(L=>({type:"argument",segments:[{type:"text",text:L}]}))))}return await xb(x,{args:e,baseFs:r,builtins:v,initialStdin:u,initialStdout:A,initialStderr:p,glob:E},{cwd:a,environment:I,exitCode:null,procedures:{},stdin:u,stdout:A,stderr:p,variables:Object.assign({},h,{"?":0}),nextBackgroundJobIndex:1,backgroundJobs:[]})}var Ace,fce,cl,pce,mot,Eot,g1=Et(()=>{Pt();Nl();Ace=Ze(pN()),fce=ve("os"),cl=ve("stream"),pce=ve("timers/promises");zle();Jle();ece();nU();nU();mot=new Map([["cd",async([t=(0,fce.homedir)(),...e],r,o)=>{let a=K.resolve(o.cwd,ue.toPortablePath(t));if(!(await r.baseFs.statPromise(a).catch(u=>{throw u.code==="ENOENT"?new ll(`cd: no such file or directory: ${t}`):u})).isDirectory())throw new ll(`cd: not a directory: ${t}`);return o.cwd=a,0}],["pwd",async(t,e,r)=>(r.stdout.write(`${ue.fromPortablePath(r.cwd)} +`),0)],[":",async(t,e,r)=>0],["true",async(t,e,r)=>0],["false",async(t,e,r)=>1],["exit",async([t,...e],r,o)=>o.exitCode=parseInt(t??o.variables["?"],10)],["echo",async(t,e,r)=>(r.stdout.write(`${t.join(" ")} +`),0)],["sleep",async([t],e,r)=>{if(typeof t>"u")throw new ll("sleep: missing operand");let o=Number(t);if(Number.isNaN(o))throw new ll(`sleep: invalid time interval '${t}'`);return await(0,pce.setTimeout)(1e3*o,0)}],["__ysh_run_procedure",async(t,e,r)=>{let o=r.procedures[t[0]];return await Pb(o,{stdin:new Jl(r.stdin),stdout:new Jl(r.stdout),stderr:new Jl(r.stderr)}).run()}],["__ysh_set_redirects",async(t,e,r)=>{let o=r.stdin,a=r.stdout,n=r.stderr,u=[],A=[],p=[],h=0;for(;t[h]!=="--";){let I=t[h++],{type:v,fd:x}=JSON.parse(I),C=z=>{switch(x){case null:case 0:u.push(z);break;default:throw new Error(`Unsupported file descriptor: "${x}"`)}},R=z=>{switch(x){case null:case 1:A.push(z);break;case 2:p.push(z);break;default:throw new Error(`Unsupported file descriptor: "${x}"`)}},L=Number(t[h++]),U=h+L;for(let z=h;z<U;++h,++z)switch(v){case"<":C(()=>e.baseFs.createReadStream(K.resolve(r.cwd,ue.toPortablePath(t[z]))));break;case"<<<":C(()=>{let te=new cl.PassThrough;return process.nextTick(()=>{te.write(`${t[z]} +`),te.end()}),te});break;case"<&":C(()=>ace(Number(t[z]),1,r));break;case">":case">>":{let te=K.resolve(r.cwd,ue.toPortablePath(t[z]));R(te==="/dev/null"?new cl.Writable({autoDestroy:!0,emitClose:!0,write(ae,le,ce){setImmediate(ce)}}):e.baseFs.createWriteStream(te,v===">>"?{flags:"a"}:void 0))}break;case">&":R(ace(Number(t[z]),2,r));break;default:throw new Error(`Assertion failed: Unsupported redirection type: "${v}"`)}}if(u.length>0){let I=new cl.PassThrough;o=I;let v=x=>{if(x===u.length)I.end();else{let C=u[x]();C.pipe(I,{end:!1}),C.on("end",()=>{v(x+1)})}};v(0)}if(A.length>0){let I=new cl.PassThrough;a=I;for(let v of A)I.pipe(v)}if(p.length>0){let I=new cl.PassThrough;n=I;for(let v of p)I.pipe(v)}let E=await Pb(m1(t.slice(h+1),e,r),{stdin:new Jl(o),stdout:new Jl(a),stderr:new Jl(n)}).run();return await Promise.all(A.map(I=>new Promise((v,x)=>{I.on("error",C=>{x(C)}),I.on("close",()=>{v()}),I.end()}))),await Promise.all(p.map(I=>new Promise((v,x)=>{I.on("error",C=>{x(C)}),I.on("close",()=>{v()}),I.end()}))),E}]]);Eot={addition:(t,e)=>t+e,subtraction:(t,e)=>t-e,multiplication:(t,e)=>t*e,division:(t,e)=>Math.trunc(t/e)}});var kb=_((l4t,dce)=>{function vot(t,e){for(var r=-1,o=t==null?0:t.length,a=Array(o);++r<o;)a[r]=e(t[r],r,t);return a}dce.exports=vot});var Ice=_((c4t,wce)=>{var mce=lg(),Dot=kb(),Pot=Hl(),Sot=Ym(),bot=1/0,yce=mce?mce.prototype:void 0,Ece=yce?yce.toString:void 0;function Cce(t){if(typeof t=="string")return t;if(Pot(t))return Dot(t,Cce)+"";if(Sot(t))return Ece?Ece.call(t):"";var e=t+"";return e=="0"&&1/t==-bot?"-0":e}wce.exports=Cce});var C1=_((u4t,Bce)=>{var xot=Ice();function kot(t){return t==null?"":xot(t)}Bce.exports=kot});var oU=_((A4t,vce)=>{function Qot(t,e,r){var o=-1,a=t.length;e<0&&(e=-e>a?0:a+e),r=r>a?a:r,r<0&&(r+=a),a=e>r?0:r-e>>>0,e>>>=0;for(var n=Array(a);++o<a;)n[o]=t[o+e];return n}vce.exports=Qot});var Pce=_((f4t,Dce)=>{var Fot=oU();function Rot(t,e,r){var o=t.length;return r=r===void 0?o:r,!e&&r>=o?t:Fot(t,e,r)}Dce.exports=Rot});var aU=_((p4t,Sce)=>{var Tot="\\ud800-\\udfff",Not="\\u0300-\\u036f",Lot="\\ufe20-\\ufe2f",Mot="\\u20d0-\\u20ff",Oot=Not+Lot+Mot,Uot="\\ufe0e\\ufe0f",_ot="\\u200d",Hot=RegExp("["+_ot+Tot+Oot+Uot+"]");function qot(t){return Hot.test(t)}Sce.exports=qot});var xce=_((h4t,bce)=>{function jot(t){return t.split("")}bce.exports=jot});var Mce=_((g4t,Lce)=>{var kce="\\ud800-\\udfff",Got="\\u0300-\\u036f",Yot="\\ufe20-\\ufe2f",Wot="\\u20d0-\\u20ff",Kot=Got+Yot+Wot,Vot="\\ufe0e\\ufe0f",zot="["+kce+"]",lU="["+Kot+"]",cU="\\ud83c[\\udffb-\\udfff]",Jot="(?:"+lU+"|"+cU+")",Qce="[^"+kce+"]",Fce="(?:\\ud83c[\\udde6-\\uddff]){2}",Rce="[\\ud800-\\udbff][\\udc00-\\udfff]",Xot="\\u200d",Tce=Jot+"?",Nce="["+Vot+"]?",Zot="(?:"+Xot+"(?:"+[Qce,Fce,Rce].join("|")+")"+Nce+Tce+")*",$ot=Nce+Tce+Zot,eat="(?:"+[Qce+lU+"?",lU,Fce,Rce,zot].join("|")+")",tat=RegExp(cU+"(?="+cU+")|"+eat+$ot,"g");function rat(t){return t.match(tat)||[]}Lce.exports=rat});var Uce=_((d4t,Oce)=>{var nat=xce(),iat=aU(),sat=Mce();function oat(t){return iat(t)?sat(t):nat(t)}Oce.exports=oat});var Hce=_((m4t,_ce)=>{var aat=Pce(),lat=aU(),cat=Uce(),uat=C1();function Aat(t){return function(e){e=uat(e);var r=lat(e)?cat(e):void 0,o=r?r[0]:e.charAt(0),a=r?aat(r,1).join(""):e.slice(1);return o[t]()+a}}_ce.exports=Aat});var jce=_((y4t,qce)=>{var fat=Hce(),pat=fat("toUpperCase");qce.exports=pat});var uU=_((E4t,Gce)=>{var hat=C1(),gat=jce();function dat(t){return gat(hat(t).toLowerCase())}Gce.exports=dat});var Yce=_((C4t,Qb)=>{function mat(){var t=0,e=1,r=2,o=3,a=4,n=5,u=6,A=7,p=8,h=9,E=10,I=11,v=12,x=13,C=14,R=15,L=16,U=17,z=0,te=1,ae=2,le=3,ce=4;function Ce(g,me){return 55296<=g.charCodeAt(me)&&g.charCodeAt(me)<=56319&&56320<=g.charCodeAt(me+1)&&g.charCodeAt(me+1)<=57343}function de(g,me){me===void 0&&(me=0);var we=g.charCodeAt(me);if(55296<=we&&we<=56319&&me<g.length-1){var Ae=we,ne=g.charCodeAt(me+1);return 56320<=ne&&ne<=57343?(Ae-55296)*1024+(ne-56320)+65536:Ae}if(56320<=we&&we<=57343&&me>=1){var Ae=g.charCodeAt(me-1),ne=we;return 55296<=Ae&&Ae<=56319?(Ae-55296)*1024+(ne-56320)+65536:ne}return we}function Be(g,me,we){var Ae=[g].concat(me).concat([we]),ne=Ae[Ae.length-2],Z=we,xe=Ae.lastIndexOf(C);if(xe>1&&Ae.slice(1,xe).every(function(H){return H==o})&&[o,x,U].indexOf(g)==-1)return ae;var Ne=Ae.lastIndexOf(a);if(Ne>0&&Ae.slice(1,Ne).every(function(H){return H==a})&&[v,a].indexOf(ne)==-1)return Ae.filter(function(H){return H==a}).length%2==1?le:ce;if(ne==t&&Z==e)return z;if(ne==r||ne==t||ne==e)return Z==C&&me.every(function(H){return H==o})?ae:te;if(Z==r||Z==t||Z==e)return te;if(ne==u&&(Z==u||Z==A||Z==h||Z==E))return z;if((ne==h||ne==A)&&(Z==A||Z==p))return z;if((ne==E||ne==p)&&Z==p)return z;if(Z==o||Z==R)return z;if(Z==n)return z;if(ne==v)return z;var ht=Ae.indexOf(o)!=-1?Ae.lastIndexOf(o)-1:Ae.length-2;return[x,U].indexOf(Ae[ht])!=-1&&Ae.slice(ht+1,-1).every(function(H){return H==o})&&Z==C||ne==R&&[L,U].indexOf(Z)!=-1?z:me.indexOf(a)!=-1?ae:ne==a&&Z==a?z:te}this.nextBreak=function(g,me){if(me===void 0&&(me=0),me<0)return 0;if(me>=g.length-1)return g.length;for(var we=Ee(de(g,me)),Ae=[],ne=me+1;ne<g.length;ne++)if(!Ce(g,ne-1)){var Z=Ee(de(g,ne));if(Be(we,Ae,Z))return ne;Ae.push(Z)}return g.length},this.splitGraphemes=function(g){for(var me=[],we=0,Ae;(Ae=this.nextBreak(g,we))<g.length;)me.push(g.slice(we,Ae)),we=Ae;return we<g.length&&me.push(g.slice(we)),me},this.iterateGraphemes=function(g){var me=0,we={next:function(){var Ae,ne;return(ne=this.nextBreak(g,me))<g.length?(Ae=g.slice(me,ne),me=ne,{value:Ae,done:!1}):me<g.length?(Ae=g.slice(me),me=g.length,{value:Ae,done:!1}):{value:void 0,done:!0}}.bind(this)};return typeof Symbol<"u"&&Symbol.iterator&&(we[Symbol.iterator]=function(){return we}),we},this.countGraphemes=function(g){for(var me=0,we=0,Ae;(Ae=this.nextBreak(g,we))<g.length;)we=Ae,me++;return we<g.length&&me++,me};function Ee(g){return 1536<=g&&g<=1541||g==1757||g==1807||g==2274||g==3406||g==69821||70082<=g&&g<=70083||g==72250||72326<=g&&g<=72329||g==73030?v:g==13?t:g==10?e:0<=g&&g<=9||11<=g&&g<=12||14<=g&&g<=31||127<=g&&g<=159||g==173||g==1564||g==6158||g==8203||8206<=g&&g<=8207||g==8232||g==8233||8234<=g&&g<=8238||8288<=g&&g<=8292||g==8293||8294<=g&&g<=8303||55296<=g&&g<=57343||g==65279||65520<=g&&g<=65528||65529<=g&&g<=65531||113824<=g&&g<=113827||119155<=g&&g<=119162||g==917504||g==917505||917506<=g&&g<=917535||917632<=g&&g<=917759||918e3<=g&&g<=921599?r:768<=g&&g<=879||1155<=g&&g<=1159||1160<=g&&g<=1161||1425<=g&&g<=1469||g==1471||1473<=g&&g<=1474||1476<=g&&g<=1477||g==1479||1552<=g&&g<=1562||1611<=g&&g<=1631||g==1648||1750<=g&&g<=1756||1759<=g&&g<=1764||1767<=g&&g<=1768||1770<=g&&g<=1773||g==1809||1840<=g&&g<=1866||1958<=g&&g<=1968||2027<=g&&g<=2035||2070<=g&&g<=2073||2075<=g&&g<=2083||2085<=g&&g<=2087||2089<=g&&g<=2093||2137<=g&&g<=2139||2260<=g&&g<=2273||2275<=g&&g<=2306||g==2362||g==2364||2369<=g&&g<=2376||g==2381||2385<=g&&g<=2391||2402<=g&&g<=2403||g==2433||g==2492||g==2494||2497<=g&&g<=2500||g==2509||g==2519||2530<=g&&g<=2531||2561<=g&&g<=2562||g==2620||2625<=g&&g<=2626||2631<=g&&g<=2632||2635<=g&&g<=2637||g==2641||2672<=g&&g<=2673||g==2677||2689<=g&&g<=2690||g==2748||2753<=g&&g<=2757||2759<=g&&g<=2760||g==2765||2786<=g&&g<=2787||2810<=g&&g<=2815||g==2817||g==2876||g==2878||g==2879||2881<=g&&g<=2884||g==2893||g==2902||g==2903||2914<=g&&g<=2915||g==2946||g==3006||g==3008||g==3021||g==3031||g==3072||3134<=g&&g<=3136||3142<=g&&g<=3144||3146<=g&&g<=3149||3157<=g&&g<=3158||3170<=g&&g<=3171||g==3201||g==3260||g==3263||g==3266||g==3270||3276<=g&&g<=3277||3285<=g&&g<=3286||3298<=g&&g<=3299||3328<=g&&g<=3329||3387<=g&&g<=3388||g==3390||3393<=g&&g<=3396||g==3405||g==3415||3426<=g&&g<=3427||g==3530||g==3535||3538<=g&&g<=3540||g==3542||g==3551||g==3633||3636<=g&&g<=3642||3655<=g&&g<=3662||g==3761||3764<=g&&g<=3769||3771<=g&&g<=3772||3784<=g&&g<=3789||3864<=g&&g<=3865||g==3893||g==3895||g==3897||3953<=g&&g<=3966||3968<=g&&g<=3972||3974<=g&&g<=3975||3981<=g&&g<=3991||3993<=g&&g<=4028||g==4038||4141<=g&&g<=4144||4146<=g&&g<=4151||4153<=g&&g<=4154||4157<=g&&g<=4158||4184<=g&&g<=4185||4190<=g&&g<=4192||4209<=g&&g<=4212||g==4226||4229<=g&&g<=4230||g==4237||g==4253||4957<=g&&g<=4959||5906<=g&&g<=5908||5938<=g&&g<=5940||5970<=g&&g<=5971||6002<=g&&g<=6003||6068<=g&&g<=6069||6071<=g&&g<=6077||g==6086||6089<=g&&g<=6099||g==6109||6155<=g&&g<=6157||6277<=g&&g<=6278||g==6313||6432<=g&&g<=6434||6439<=g&&g<=6440||g==6450||6457<=g&&g<=6459||6679<=g&&g<=6680||g==6683||g==6742||6744<=g&&g<=6750||g==6752||g==6754||6757<=g&&g<=6764||6771<=g&&g<=6780||g==6783||6832<=g&&g<=6845||g==6846||6912<=g&&g<=6915||g==6964||6966<=g&&g<=6970||g==6972||g==6978||7019<=g&&g<=7027||7040<=g&&g<=7041||7074<=g&&g<=7077||7080<=g&&g<=7081||7083<=g&&g<=7085||g==7142||7144<=g&&g<=7145||g==7149||7151<=g&&g<=7153||7212<=g&&g<=7219||7222<=g&&g<=7223||7376<=g&&g<=7378||7380<=g&&g<=7392||7394<=g&&g<=7400||g==7405||g==7412||7416<=g&&g<=7417||7616<=g&&g<=7673||7675<=g&&g<=7679||g==8204||8400<=g&&g<=8412||8413<=g&&g<=8416||g==8417||8418<=g&&g<=8420||8421<=g&&g<=8432||11503<=g&&g<=11505||g==11647||11744<=g&&g<=11775||12330<=g&&g<=12333||12334<=g&&g<=12335||12441<=g&&g<=12442||g==42607||42608<=g&&g<=42610||42612<=g&&g<=42621||42654<=g&&g<=42655||42736<=g&&g<=42737||g==43010||g==43014||g==43019||43045<=g&&g<=43046||43204<=g&&g<=43205||43232<=g&&g<=43249||43302<=g&&g<=43309||43335<=g&&g<=43345||43392<=g&&g<=43394||g==43443||43446<=g&&g<=43449||g==43452||g==43493||43561<=g&&g<=43566||43569<=g&&g<=43570||43573<=g&&g<=43574||g==43587||g==43596||g==43644||g==43696||43698<=g&&g<=43700||43703<=g&&g<=43704||43710<=g&&g<=43711||g==43713||43756<=g&&g<=43757||g==43766||g==44005||g==44008||g==44013||g==64286||65024<=g&&g<=65039||65056<=g&&g<=65071||65438<=g&&g<=65439||g==66045||g==66272||66422<=g&&g<=66426||68097<=g&&g<=68099||68101<=g&&g<=68102||68108<=g&&g<=68111||68152<=g&&g<=68154||g==68159||68325<=g&&g<=68326||g==69633||69688<=g&&g<=69702||69759<=g&&g<=69761||69811<=g&&g<=69814||69817<=g&&g<=69818||69888<=g&&g<=69890||69927<=g&&g<=69931||69933<=g&&g<=69940||g==70003||70016<=g&&g<=70017||70070<=g&&g<=70078||70090<=g&&g<=70092||70191<=g&&g<=70193||g==70196||70198<=g&&g<=70199||g==70206||g==70367||70371<=g&&g<=70378||70400<=g&&g<=70401||g==70460||g==70462||g==70464||g==70487||70502<=g&&g<=70508||70512<=g&&g<=70516||70712<=g&&g<=70719||70722<=g&&g<=70724||g==70726||g==70832||70835<=g&&g<=70840||g==70842||g==70845||70847<=g&&g<=70848||70850<=g&&g<=70851||g==71087||71090<=g&&g<=71093||71100<=g&&g<=71101||71103<=g&&g<=71104||71132<=g&&g<=71133||71219<=g&&g<=71226||g==71229||71231<=g&&g<=71232||g==71339||g==71341||71344<=g&&g<=71349||g==71351||71453<=g&&g<=71455||71458<=g&&g<=71461||71463<=g&&g<=71467||72193<=g&&g<=72198||72201<=g&&g<=72202||72243<=g&&g<=72248||72251<=g&&g<=72254||g==72263||72273<=g&&g<=72278||72281<=g&&g<=72283||72330<=g&&g<=72342||72344<=g&&g<=72345||72752<=g&&g<=72758||72760<=g&&g<=72765||g==72767||72850<=g&&g<=72871||72874<=g&&g<=72880||72882<=g&&g<=72883||72885<=g&&g<=72886||73009<=g&&g<=73014||g==73018||73020<=g&&g<=73021||73023<=g&&g<=73029||g==73031||92912<=g&&g<=92916||92976<=g&&g<=92982||94095<=g&&g<=94098||113821<=g&&g<=113822||g==119141||119143<=g&&g<=119145||119150<=g&&g<=119154||119163<=g&&g<=119170||119173<=g&&g<=119179||119210<=g&&g<=119213||119362<=g&&g<=119364||121344<=g&&g<=121398||121403<=g&&g<=121452||g==121461||g==121476||121499<=g&&g<=121503||121505<=g&&g<=121519||122880<=g&&g<=122886||122888<=g&&g<=122904||122907<=g&&g<=122913||122915<=g&&g<=122916||122918<=g&&g<=122922||125136<=g&&g<=125142||125252<=g&&g<=125258||917536<=g&&g<=917631||917760<=g&&g<=917999?o:127462<=g&&g<=127487?a:g==2307||g==2363||2366<=g&&g<=2368||2377<=g&&g<=2380||2382<=g&&g<=2383||2434<=g&&g<=2435||2495<=g&&g<=2496||2503<=g&&g<=2504||2507<=g&&g<=2508||g==2563||2622<=g&&g<=2624||g==2691||2750<=g&&g<=2752||g==2761||2763<=g&&g<=2764||2818<=g&&g<=2819||g==2880||2887<=g&&g<=2888||2891<=g&&g<=2892||g==3007||3009<=g&&g<=3010||3014<=g&&g<=3016||3018<=g&&g<=3020||3073<=g&&g<=3075||3137<=g&&g<=3140||3202<=g&&g<=3203||g==3262||3264<=g&&g<=3265||3267<=g&&g<=3268||3271<=g&&g<=3272||3274<=g&&g<=3275||3330<=g&&g<=3331||3391<=g&&g<=3392||3398<=g&&g<=3400||3402<=g&&g<=3404||3458<=g&&g<=3459||3536<=g&&g<=3537||3544<=g&&g<=3550||3570<=g&&g<=3571||g==3635||g==3763||3902<=g&&g<=3903||g==3967||g==4145||4155<=g&&g<=4156||4182<=g&&g<=4183||g==4228||g==6070||6078<=g&&g<=6085||6087<=g&&g<=6088||6435<=g&&g<=6438||6441<=g&&g<=6443||6448<=g&&g<=6449||6451<=g&&g<=6456||6681<=g&&g<=6682||g==6741||g==6743||6765<=g&&g<=6770||g==6916||g==6965||g==6971||6973<=g&&g<=6977||6979<=g&&g<=6980||g==7042||g==7073||7078<=g&&g<=7079||g==7082||g==7143||7146<=g&&g<=7148||g==7150||7154<=g&&g<=7155||7204<=g&&g<=7211||7220<=g&&g<=7221||g==7393||7410<=g&&g<=7411||g==7415||43043<=g&&g<=43044||g==43047||43136<=g&&g<=43137||43188<=g&&g<=43203||43346<=g&&g<=43347||g==43395||43444<=g&&g<=43445||43450<=g&&g<=43451||43453<=g&&g<=43456||43567<=g&&g<=43568||43571<=g&&g<=43572||g==43597||g==43755||43758<=g&&g<=43759||g==43765||44003<=g&&g<=44004||44006<=g&&g<=44007||44009<=g&&g<=44010||g==44012||g==69632||g==69634||g==69762||69808<=g&&g<=69810||69815<=g&&g<=69816||g==69932||g==70018||70067<=g&&g<=70069||70079<=g&&g<=70080||70188<=g&&g<=70190||70194<=g&&g<=70195||g==70197||70368<=g&&g<=70370||70402<=g&&g<=70403||g==70463||70465<=g&&g<=70468||70471<=g&&g<=70472||70475<=g&&g<=70477||70498<=g&&g<=70499||70709<=g&&g<=70711||70720<=g&&g<=70721||g==70725||70833<=g&&g<=70834||g==70841||70843<=g&&g<=70844||g==70846||g==70849||71088<=g&&g<=71089||71096<=g&&g<=71099||g==71102||71216<=g&&g<=71218||71227<=g&&g<=71228||g==71230||g==71340||71342<=g&&g<=71343||g==71350||71456<=g&&g<=71457||g==71462||72199<=g&&g<=72200||g==72249||72279<=g&&g<=72280||g==72343||g==72751||g==72766||g==72873||g==72881||g==72884||94033<=g&&g<=94078||g==119142||g==119149?n:4352<=g&&g<=4447||43360<=g&&g<=43388?u:4448<=g&&g<=4519||55216<=g&&g<=55238?A:4520<=g&&g<=4607||55243<=g&&g<=55291?p:g==44032||g==44060||g==44088||g==44116||g==44144||g==44172||g==44200||g==44228||g==44256||g==44284||g==44312||g==44340||g==44368||g==44396||g==44424||g==44452||g==44480||g==44508||g==44536||g==44564||g==44592||g==44620||g==44648||g==44676||g==44704||g==44732||g==44760||g==44788||g==44816||g==44844||g==44872||g==44900||g==44928||g==44956||g==44984||g==45012||g==45040||g==45068||g==45096||g==45124||g==45152||g==45180||g==45208||g==45236||g==45264||g==45292||g==45320||g==45348||g==45376||g==45404||g==45432||g==45460||g==45488||g==45516||g==45544||g==45572||g==45600||g==45628||g==45656||g==45684||g==45712||g==45740||g==45768||g==45796||g==45824||g==45852||g==45880||g==45908||g==45936||g==45964||g==45992||g==46020||g==46048||g==46076||g==46104||g==46132||g==46160||g==46188||g==46216||g==46244||g==46272||g==46300||g==46328||g==46356||g==46384||g==46412||g==46440||g==46468||g==46496||g==46524||g==46552||g==46580||g==46608||g==46636||g==46664||g==46692||g==46720||g==46748||g==46776||g==46804||g==46832||g==46860||g==46888||g==46916||g==46944||g==46972||g==47e3||g==47028||g==47056||g==47084||g==47112||g==47140||g==47168||g==47196||g==47224||g==47252||g==47280||g==47308||g==47336||g==47364||g==47392||g==47420||g==47448||g==47476||g==47504||g==47532||g==47560||g==47588||g==47616||g==47644||g==47672||g==47700||g==47728||g==47756||g==47784||g==47812||g==47840||g==47868||g==47896||g==47924||g==47952||g==47980||g==48008||g==48036||g==48064||g==48092||g==48120||g==48148||g==48176||g==48204||g==48232||g==48260||g==48288||g==48316||g==48344||g==48372||g==48400||g==48428||g==48456||g==48484||g==48512||g==48540||g==48568||g==48596||g==48624||g==48652||g==48680||g==48708||g==48736||g==48764||g==48792||g==48820||g==48848||g==48876||g==48904||g==48932||g==48960||g==48988||g==49016||g==49044||g==49072||g==49100||g==49128||g==49156||g==49184||g==49212||g==49240||g==49268||g==49296||g==49324||g==49352||g==49380||g==49408||g==49436||g==49464||g==49492||g==49520||g==49548||g==49576||g==49604||g==49632||g==49660||g==49688||g==49716||g==49744||g==49772||g==49800||g==49828||g==49856||g==49884||g==49912||g==49940||g==49968||g==49996||g==50024||g==50052||g==50080||g==50108||g==50136||g==50164||g==50192||g==50220||g==50248||g==50276||g==50304||g==50332||g==50360||g==50388||g==50416||g==50444||g==50472||g==50500||g==50528||g==50556||g==50584||g==50612||g==50640||g==50668||g==50696||g==50724||g==50752||g==50780||g==50808||g==50836||g==50864||g==50892||g==50920||g==50948||g==50976||g==51004||g==51032||g==51060||g==51088||g==51116||g==51144||g==51172||g==51200||g==51228||g==51256||g==51284||g==51312||g==51340||g==51368||g==51396||g==51424||g==51452||g==51480||g==51508||g==51536||g==51564||g==51592||g==51620||g==51648||g==51676||g==51704||g==51732||g==51760||g==51788||g==51816||g==51844||g==51872||g==51900||g==51928||g==51956||g==51984||g==52012||g==52040||g==52068||g==52096||g==52124||g==52152||g==52180||g==52208||g==52236||g==52264||g==52292||g==52320||g==52348||g==52376||g==52404||g==52432||g==52460||g==52488||g==52516||g==52544||g==52572||g==52600||g==52628||g==52656||g==52684||g==52712||g==52740||g==52768||g==52796||g==52824||g==52852||g==52880||g==52908||g==52936||g==52964||g==52992||g==53020||g==53048||g==53076||g==53104||g==53132||g==53160||g==53188||g==53216||g==53244||g==53272||g==53300||g==53328||g==53356||g==53384||g==53412||g==53440||g==53468||g==53496||g==53524||g==53552||g==53580||g==53608||g==53636||g==53664||g==53692||g==53720||g==53748||g==53776||g==53804||g==53832||g==53860||g==53888||g==53916||g==53944||g==53972||g==54e3||g==54028||g==54056||g==54084||g==54112||g==54140||g==54168||g==54196||g==54224||g==54252||g==54280||g==54308||g==54336||g==54364||g==54392||g==54420||g==54448||g==54476||g==54504||g==54532||g==54560||g==54588||g==54616||g==54644||g==54672||g==54700||g==54728||g==54756||g==54784||g==54812||g==54840||g==54868||g==54896||g==54924||g==54952||g==54980||g==55008||g==55036||g==55064||g==55092||g==55120||g==55148||g==55176?h:44033<=g&&g<=44059||44061<=g&&g<=44087||44089<=g&&g<=44115||44117<=g&&g<=44143||44145<=g&&g<=44171||44173<=g&&g<=44199||44201<=g&&g<=44227||44229<=g&&g<=44255||44257<=g&&g<=44283||44285<=g&&g<=44311||44313<=g&&g<=44339||44341<=g&&g<=44367||44369<=g&&g<=44395||44397<=g&&g<=44423||44425<=g&&g<=44451||44453<=g&&g<=44479||44481<=g&&g<=44507||44509<=g&&g<=44535||44537<=g&&g<=44563||44565<=g&&g<=44591||44593<=g&&g<=44619||44621<=g&&g<=44647||44649<=g&&g<=44675||44677<=g&&g<=44703||44705<=g&&g<=44731||44733<=g&&g<=44759||44761<=g&&g<=44787||44789<=g&&g<=44815||44817<=g&&g<=44843||44845<=g&&g<=44871||44873<=g&&g<=44899||44901<=g&&g<=44927||44929<=g&&g<=44955||44957<=g&&g<=44983||44985<=g&&g<=45011||45013<=g&&g<=45039||45041<=g&&g<=45067||45069<=g&&g<=45095||45097<=g&&g<=45123||45125<=g&&g<=45151||45153<=g&&g<=45179||45181<=g&&g<=45207||45209<=g&&g<=45235||45237<=g&&g<=45263||45265<=g&&g<=45291||45293<=g&&g<=45319||45321<=g&&g<=45347||45349<=g&&g<=45375||45377<=g&&g<=45403||45405<=g&&g<=45431||45433<=g&&g<=45459||45461<=g&&g<=45487||45489<=g&&g<=45515||45517<=g&&g<=45543||45545<=g&&g<=45571||45573<=g&&g<=45599||45601<=g&&g<=45627||45629<=g&&g<=45655||45657<=g&&g<=45683||45685<=g&&g<=45711||45713<=g&&g<=45739||45741<=g&&g<=45767||45769<=g&&g<=45795||45797<=g&&g<=45823||45825<=g&&g<=45851||45853<=g&&g<=45879||45881<=g&&g<=45907||45909<=g&&g<=45935||45937<=g&&g<=45963||45965<=g&&g<=45991||45993<=g&&g<=46019||46021<=g&&g<=46047||46049<=g&&g<=46075||46077<=g&&g<=46103||46105<=g&&g<=46131||46133<=g&&g<=46159||46161<=g&&g<=46187||46189<=g&&g<=46215||46217<=g&&g<=46243||46245<=g&&g<=46271||46273<=g&&g<=46299||46301<=g&&g<=46327||46329<=g&&g<=46355||46357<=g&&g<=46383||46385<=g&&g<=46411||46413<=g&&g<=46439||46441<=g&&g<=46467||46469<=g&&g<=46495||46497<=g&&g<=46523||46525<=g&&g<=46551||46553<=g&&g<=46579||46581<=g&&g<=46607||46609<=g&&g<=46635||46637<=g&&g<=46663||46665<=g&&g<=46691||46693<=g&&g<=46719||46721<=g&&g<=46747||46749<=g&&g<=46775||46777<=g&&g<=46803||46805<=g&&g<=46831||46833<=g&&g<=46859||46861<=g&&g<=46887||46889<=g&&g<=46915||46917<=g&&g<=46943||46945<=g&&g<=46971||46973<=g&&g<=46999||47001<=g&&g<=47027||47029<=g&&g<=47055||47057<=g&&g<=47083||47085<=g&&g<=47111||47113<=g&&g<=47139||47141<=g&&g<=47167||47169<=g&&g<=47195||47197<=g&&g<=47223||47225<=g&&g<=47251||47253<=g&&g<=47279||47281<=g&&g<=47307||47309<=g&&g<=47335||47337<=g&&g<=47363||47365<=g&&g<=47391||47393<=g&&g<=47419||47421<=g&&g<=47447||47449<=g&&g<=47475||47477<=g&&g<=47503||47505<=g&&g<=47531||47533<=g&&g<=47559||47561<=g&&g<=47587||47589<=g&&g<=47615||47617<=g&&g<=47643||47645<=g&&g<=47671||47673<=g&&g<=47699||47701<=g&&g<=47727||47729<=g&&g<=47755||47757<=g&&g<=47783||47785<=g&&g<=47811||47813<=g&&g<=47839||47841<=g&&g<=47867||47869<=g&&g<=47895||47897<=g&&g<=47923||47925<=g&&g<=47951||47953<=g&&g<=47979||47981<=g&&g<=48007||48009<=g&&g<=48035||48037<=g&&g<=48063||48065<=g&&g<=48091||48093<=g&&g<=48119||48121<=g&&g<=48147||48149<=g&&g<=48175||48177<=g&&g<=48203||48205<=g&&g<=48231||48233<=g&&g<=48259||48261<=g&&g<=48287||48289<=g&&g<=48315||48317<=g&&g<=48343||48345<=g&&g<=48371||48373<=g&&g<=48399||48401<=g&&g<=48427||48429<=g&&g<=48455||48457<=g&&g<=48483||48485<=g&&g<=48511||48513<=g&&g<=48539||48541<=g&&g<=48567||48569<=g&&g<=48595||48597<=g&&g<=48623||48625<=g&&g<=48651||48653<=g&&g<=48679||48681<=g&&g<=48707||48709<=g&&g<=48735||48737<=g&&g<=48763||48765<=g&&g<=48791||48793<=g&&g<=48819||48821<=g&&g<=48847||48849<=g&&g<=48875||48877<=g&&g<=48903||48905<=g&&g<=48931||48933<=g&&g<=48959||48961<=g&&g<=48987||48989<=g&&g<=49015||49017<=g&&g<=49043||49045<=g&&g<=49071||49073<=g&&g<=49099||49101<=g&&g<=49127||49129<=g&&g<=49155||49157<=g&&g<=49183||49185<=g&&g<=49211||49213<=g&&g<=49239||49241<=g&&g<=49267||49269<=g&&g<=49295||49297<=g&&g<=49323||49325<=g&&g<=49351||49353<=g&&g<=49379||49381<=g&&g<=49407||49409<=g&&g<=49435||49437<=g&&g<=49463||49465<=g&&g<=49491||49493<=g&&g<=49519||49521<=g&&g<=49547||49549<=g&&g<=49575||49577<=g&&g<=49603||49605<=g&&g<=49631||49633<=g&&g<=49659||49661<=g&&g<=49687||49689<=g&&g<=49715||49717<=g&&g<=49743||49745<=g&&g<=49771||49773<=g&&g<=49799||49801<=g&&g<=49827||49829<=g&&g<=49855||49857<=g&&g<=49883||49885<=g&&g<=49911||49913<=g&&g<=49939||49941<=g&&g<=49967||49969<=g&&g<=49995||49997<=g&&g<=50023||50025<=g&&g<=50051||50053<=g&&g<=50079||50081<=g&&g<=50107||50109<=g&&g<=50135||50137<=g&&g<=50163||50165<=g&&g<=50191||50193<=g&&g<=50219||50221<=g&&g<=50247||50249<=g&&g<=50275||50277<=g&&g<=50303||50305<=g&&g<=50331||50333<=g&&g<=50359||50361<=g&&g<=50387||50389<=g&&g<=50415||50417<=g&&g<=50443||50445<=g&&g<=50471||50473<=g&&g<=50499||50501<=g&&g<=50527||50529<=g&&g<=50555||50557<=g&&g<=50583||50585<=g&&g<=50611||50613<=g&&g<=50639||50641<=g&&g<=50667||50669<=g&&g<=50695||50697<=g&&g<=50723||50725<=g&&g<=50751||50753<=g&&g<=50779||50781<=g&&g<=50807||50809<=g&&g<=50835||50837<=g&&g<=50863||50865<=g&&g<=50891||50893<=g&&g<=50919||50921<=g&&g<=50947||50949<=g&&g<=50975||50977<=g&&g<=51003||51005<=g&&g<=51031||51033<=g&&g<=51059||51061<=g&&g<=51087||51089<=g&&g<=51115||51117<=g&&g<=51143||51145<=g&&g<=51171||51173<=g&&g<=51199||51201<=g&&g<=51227||51229<=g&&g<=51255||51257<=g&&g<=51283||51285<=g&&g<=51311||51313<=g&&g<=51339||51341<=g&&g<=51367||51369<=g&&g<=51395||51397<=g&&g<=51423||51425<=g&&g<=51451||51453<=g&&g<=51479||51481<=g&&g<=51507||51509<=g&&g<=51535||51537<=g&&g<=51563||51565<=g&&g<=51591||51593<=g&&g<=51619||51621<=g&&g<=51647||51649<=g&&g<=51675||51677<=g&&g<=51703||51705<=g&&g<=51731||51733<=g&&g<=51759||51761<=g&&g<=51787||51789<=g&&g<=51815||51817<=g&&g<=51843||51845<=g&&g<=51871||51873<=g&&g<=51899||51901<=g&&g<=51927||51929<=g&&g<=51955||51957<=g&&g<=51983||51985<=g&&g<=52011||52013<=g&&g<=52039||52041<=g&&g<=52067||52069<=g&&g<=52095||52097<=g&&g<=52123||52125<=g&&g<=52151||52153<=g&&g<=52179||52181<=g&&g<=52207||52209<=g&&g<=52235||52237<=g&&g<=52263||52265<=g&&g<=52291||52293<=g&&g<=52319||52321<=g&&g<=52347||52349<=g&&g<=52375||52377<=g&&g<=52403||52405<=g&&g<=52431||52433<=g&&g<=52459||52461<=g&&g<=52487||52489<=g&&g<=52515||52517<=g&&g<=52543||52545<=g&&g<=52571||52573<=g&&g<=52599||52601<=g&&g<=52627||52629<=g&&g<=52655||52657<=g&&g<=52683||52685<=g&&g<=52711||52713<=g&&g<=52739||52741<=g&&g<=52767||52769<=g&&g<=52795||52797<=g&&g<=52823||52825<=g&&g<=52851||52853<=g&&g<=52879||52881<=g&&g<=52907||52909<=g&&g<=52935||52937<=g&&g<=52963||52965<=g&&g<=52991||52993<=g&&g<=53019||53021<=g&&g<=53047||53049<=g&&g<=53075||53077<=g&&g<=53103||53105<=g&&g<=53131||53133<=g&&g<=53159||53161<=g&&g<=53187||53189<=g&&g<=53215||53217<=g&&g<=53243||53245<=g&&g<=53271||53273<=g&&g<=53299||53301<=g&&g<=53327||53329<=g&&g<=53355||53357<=g&&g<=53383||53385<=g&&g<=53411||53413<=g&&g<=53439||53441<=g&&g<=53467||53469<=g&&g<=53495||53497<=g&&g<=53523||53525<=g&&g<=53551||53553<=g&&g<=53579||53581<=g&&g<=53607||53609<=g&&g<=53635||53637<=g&&g<=53663||53665<=g&&g<=53691||53693<=g&&g<=53719||53721<=g&&g<=53747||53749<=g&&g<=53775||53777<=g&&g<=53803||53805<=g&&g<=53831||53833<=g&&g<=53859||53861<=g&&g<=53887||53889<=g&&g<=53915||53917<=g&&g<=53943||53945<=g&&g<=53971||53973<=g&&g<=53999||54001<=g&&g<=54027||54029<=g&&g<=54055||54057<=g&&g<=54083||54085<=g&&g<=54111||54113<=g&&g<=54139||54141<=g&&g<=54167||54169<=g&&g<=54195||54197<=g&&g<=54223||54225<=g&&g<=54251||54253<=g&&g<=54279||54281<=g&&g<=54307||54309<=g&&g<=54335||54337<=g&&g<=54363||54365<=g&&g<=54391||54393<=g&&g<=54419||54421<=g&&g<=54447||54449<=g&&g<=54475||54477<=g&&g<=54503||54505<=g&&g<=54531||54533<=g&&g<=54559||54561<=g&&g<=54587||54589<=g&&g<=54615||54617<=g&&g<=54643||54645<=g&&g<=54671||54673<=g&&g<=54699||54701<=g&&g<=54727||54729<=g&&g<=54755||54757<=g&&g<=54783||54785<=g&&g<=54811||54813<=g&&g<=54839||54841<=g&&g<=54867||54869<=g&&g<=54895||54897<=g&&g<=54923||54925<=g&&g<=54951||54953<=g&&g<=54979||54981<=g&&g<=55007||55009<=g&&g<=55035||55037<=g&&g<=55063||55065<=g&&g<=55091||55093<=g&&g<=55119||55121<=g&&g<=55147||55149<=g&&g<=55175||55177<=g&&g<=55203?E:g==9757||g==9977||9994<=g&&g<=9997||g==127877||127938<=g&&g<=127940||g==127943||127946<=g&&g<=127948||128066<=g&&g<=128067||128070<=g&&g<=128080||g==128110||128112<=g&&g<=128120||g==128124||128129<=g&&g<=128131||128133<=g&&g<=128135||g==128170||128372<=g&&g<=128373||g==128378||g==128400||128405<=g&&g<=128406||128581<=g&&g<=128583||128587<=g&&g<=128591||g==128675||128692<=g&&g<=128694||g==128704||g==128716||129304<=g&&g<=129308||129310<=g&&g<=129311||g==129318||129328<=g&&g<=129337||129341<=g&&g<=129342||129489<=g&&g<=129501?x:127995<=g&&g<=127999?C:g==8205?R:g==9792||g==9794||9877<=g&&g<=9878||g==9992||g==10084||g==127752||g==127806||g==127859||g==127891||g==127908||g==127912||g==127979||g==127981||g==128139||128187<=g&&g<=128188||g==128295||g==128300||g==128488||g==128640||g==128658?L:128102<=g&&g<=128105?U:I}return this}typeof Qb<"u"&&Qb.exports&&(Qb.exports=mat)});var Kce=_((w4t,Wce)=>{var yat=/^(.*?)(\x1b\[[^m]+m|\x1b\]8;;.*?(\x1b\\|\u0007))/,Fb;function Eat(){if(Fb)return Fb;if(typeof Intl.Segmenter<"u"){let t=new Intl.Segmenter("en",{granularity:"grapheme"});return Fb=e=>Array.from(t.segment(e),({segment:r})=>r)}else{let t=Yce(),e=new t;return Fb=r=>e.splitGraphemes(r)}}Wce.exports=(t,e=0,r=t.length)=>{if(e<0||r<0)throw new RangeError("Negative indices aren't supported by this implementation");let o=r-e,a="",n=0,u=0;for(;t.length>0;){let A=t.match(yat)||[t,t,void 0],p=Eat()(A[1]),h=Math.min(e-n,p.length);p=p.slice(h);let E=Math.min(o-u,p.length);a+=p.slice(0,E).join(""),n+=h,u+=E,typeof A[2]<"u"&&(a+=A[2]),t=t.slice(A[0].length)}return a}});var nn,w1=Et(()=>{nn=process.env.YARN_IS_TEST_ENV?"0.0.0":"4.4.0"});function $ce(t,{configuration:e,json:r}){if(!e.get("enableMessageNames"))return"";let a=Ku(t===null?0:t);return!r&&t===null?Ot(e,a,"grey"):a}function AU(t,{configuration:e,json:r}){let o=$ce(t,{configuration:e,json:r});if(!o||t===null||t===0)return o;let a=wr[t],n=`https://yarnpkg.com/advanced/error-codes#${o}---${a}`.toLowerCase();return Tm(e,o,n)}async function uy({configuration:t,stdout:e,forceError:r},o){let a=await Rt.start({configuration:t,stdout:e,includeFooter:!1},async n=>{let u=!1,A=!1;for(let p of o)typeof p.option<"u"&&(p.error||r?(A=!0,n.reportError(50,p.message)):(u=!0,n.reportWarning(50,p.message)),p.callback?.());u&&!A&&n.reportSeparator()});return a.hasErrors()?a.exitCode():null}var Xce,Rb,Cat,Vce,zce,ch,Zce,Jce,wat,Iat,Tb,Bat,Rt,I1=Et(()=>{Xce=Ze(Kce()),Rb=Ze(X0());$D();Wl();w1();jl();Cat="\xB7",Vce=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],zce=80,ch=Rb.default.GITHUB_ACTIONS?{start:t=>`::group::${t} +`,end:t=>`::endgroup:: +`}:Rb.default.TRAVIS?{start:t=>`travis_fold:start:${t} +`,end:t=>`travis_fold:end:${t} +`}:Rb.default.GITLAB?{start:t=>`section_start:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\W+/g,"_")}[collapsed=true]\r\x1B[0K${t} +`,end:t=>`section_end:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\W+/g,"_")}\r\x1B[0K`}:null,Zce=ch!==null,Jce=new Date,wat=["iTerm.app","Apple_Terminal","WarpTerminal","vscode"].includes(process.env.TERM_PROGRAM)||!!process.env.WT_SESSION,Iat=t=>t,Tb=Iat({patrick:{date:[17,3],chars:["\u{1F340}","\u{1F331}"],size:40},simba:{date:[19,7],chars:["\u{1F981}","\u{1F334}"],size:40},jack:{date:[31,10],chars:["\u{1F383}","\u{1F987}"],size:40},hogsfather:{date:[31,12],chars:["\u{1F389}","\u{1F384}"],size:40},default:{chars:["=","-"],size:80}}),Bat=wat&&Object.keys(Tb).find(t=>{let e=Tb[t];return!(e.date&&(e.date[0]!==Jce.getDate()||e.date[1]!==Jce.getMonth()+1))})||"default";Rt=class extends Zs{constructor({configuration:r,stdout:o,json:a=!1,forceSectionAlignment:n=!1,includeNames:u=!0,includePrefix:A=!0,includeFooter:p=!0,includeLogs:h=!a,includeInfos:E=h,includeWarnings:I=h}){super();this.uncommitted=new Set;this.warningCount=0;this.errorCount=0;this.timerFooter=[];this.startTime=Date.now();this.indent=0;this.level=0;this.progress=new Map;this.progressTime=0;this.progressFrame=0;this.progressTimeout=null;this.progressStyle=null;this.progressMaxScaledSize=null;if(TI(this,{configuration:r}),this.configuration=r,this.forceSectionAlignment=n,this.includeNames=u,this.includePrefix=A,this.includeFooter=p,this.includeInfos=E,this.includeWarnings=I,this.json=a,this.stdout=o,r.get("enableProgressBars")&&!a&&o.isTTY&&o.columns>22){let v=r.get("progressBarStyle")||Bat;if(!Object.hasOwn(Tb,v))throw new Error("Assertion failed: Invalid progress bar style");this.progressStyle=Tb[v];let x=Math.min(this.getRecommendedLength(),80);this.progressMaxScaledSize=Math.floor(this.progressStyle.size*x/80)}}static async start(r,o){let a=new this(r),n=process.emitWarning;process.emitWarning=(u,A)=>{if(typeof u!="string"){let h=u;u=h.message,A=A??h.name}let p=typeof A<"u"?`${A}: ${u}`:u;a.reportWarning(0,p)},r.includeVersion&&a.reportInfo(0,fg(r.configuration,`Yarn ${nn}`,2));try{await o(a)}catch(u){a.reportExceptionOnce(u)}finally{await a.finalize(),process.emitWarning=n}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}getRecommendedLength(){let o=this.progressStyle!==null?this.stdout.columns-1:super.getRecommendedLength();return Math.max(40,o-12-this.indent*2)}startSectionSync({reportHeader:r,reportFooter:o,skipIfEmpty:a},n){let u={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(u):(u.action(),u.committed=!0);let A=Date.now();try{return n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(u),u.committed&&o?.(p-A)}}async startSectionPromise({reportHeader:r,reportFooter:o,skipIfEmpty:a},n){let u={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(u):(u.action(),u.committed=!0);let A=Date.now();try{return await n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(u),u.committed&&o?.(p-A)}}startTimerImpl(r,o,a){return{cb:typeof o=="function"?o:a,reportHeader:()=>{this.level+=1,this.reportInfo(null,`\u250C ${r}`),this.indent+=1,ch!==null&&!this.json&&this.includeInfos&&this.stdout.write(ch.start(r))},reportFooter:A=>{if(this.indent-=1,ch!==null&&!this.json&&this.includeInfos){this.stdout.write(ch.end(r));for(let p of this.timerFooter)p()}this.configuration.get("enableTimers")&&A>200?this.reportInfo(null,`\u2514 Completed in ${Ot(this.configuration,A,yt.DURATION)}`):this.reportInfo(null,"\u2514 Completed"),this.level-=1},skipIfEmpty:(typeof o=="function"?{}:o).skipIfEmpty}}startTimerSync(r,o,a){let{cb:n,...u}=this.startTimerImpl(r,o,a);return this.startSectionSync(u,n)}async startTimerPromise(r,o,a){let{cb:n,...u}=this.startTimerImpl(r,o,a);return this.startSectionPromise(u,n)}reportSeparator(){this.indent===0?this.writeLine(""):this.reportInfo(null,"")}reportInfo(r,o){if(!this.includeInfos)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"",u=`${this.formatPrefix(n,"blueBright")}${o}`;this.json?this.reportJson({type:"info",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(u)}reportWarning(r,o){if(this.warningCount+=1,!this.includeWarnings)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"";this.json?this.reportJson({type:"warning",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(`${this.formatPrefix(n,"yellowBright")}${o}`)}reportError(r,o){this.errorCount+=1,this.timerFooter.push(()=>this.reportErrorImpl(r,o)),this.reportErrorImpl(r,o)}reportErrorImpl(r,o){this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"";this.json?this.reportJson({type:"error",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(`${this.formatPrefix(n,"redBright")}${o}`,{truncate:!1})}reportFold(r,o){if(!ch)return;let a=`${ch.start(r)}${o}${ch.end(r)}`;this.timerFooter.push(()=>this.stdout.write(a))}reportProgress(r){if(this.progressStyle===null)return{...Promise.resolve(),stop:()=>{}};if(r.hasProgress&&r.hasTitle)throw new Error("Unimplemented: Progress bars can't have both progress and titles.");let o=!1,a=Promise.resolve().then(async()=>{let u={progress:r.hasProgress?0:void 0,title:r.hasTitle?"":void 0};this.progress.set(r,{definition:u,lastScaledSize:r.hasProgress?-1:void 0,lastTitle:void 0}),this.refreshProgress({delta:-1});for await(let{progress:A,title:p}of r)o||u.progress===A&&u.title===p||(u.progress=A,u.title=p,this.refreshProgress());n()}),n=()=>{o||(o=!0,this.progress.delete(r),this.refreshProgress({delta:1}))};return{...a,stop:n}}reportJson(r){this.json&&this.writeLine(`${JSON.stringify(r)}`)}async finalize(){if(!this.includeFooter)return;let r="";this.errorCount>0?r="Failed with errors":this.warningCount>0?r="Done with warnings":r="Done";let o=Ot(this.configuration,Date.now()-this.startTime,yt.DURATION),a=this.configuration.get("enableTimers")?`${r} in ${o}`:r;this.errorCount>0?this.reportError(0,a):this.warningCount>0?this.reportWarning(0,a):this.reportInfo(0,a)}writeLine(r,{truncate:o}={}){this.clearProgress({clear:!0}),this.stdout.write(`${this.truncate(r,{truncate:o})} +`),this.writeProgress()}writeLines(r,{truncate:o}={}){this.clearProgress({delta:r.length});for(let a of r)this.stdout.write(`${this.truncate(a,{truncate:o})} +`);this.writeProgress()}commit(){let r=this.uncommitted;this.uncommitted=new Set;for(let o of r)o.committed=!0,o.action()}clearProgress({delta:r=0,clear:o=!1}){this.progressStyle!==null&&this.progress.size+r>0&&(this.stdout.write(`\x1B[${this.progress.size+r}A`),(r>0||o)&&this.stdout.write("\x1B[0J"))}writeProgress(){if(this.progressStyle===null||(this.progressTimeout!==null&&clearTimeout(this.progressTimeout),this.progressTimeout=null,this.progress.size===0))return;let r=Date.now();r-this.progressTime>zce&&(this.progressFrame=(this.progressFrame+1)%Vce.length,this.progressTime=r);let o=Vce[this.progressFrame];for(let a of this.progress.values()){let n="";if(typeof a.lastScaledSize<"u"){let h=this.progressStyle.chars[0].repeat(a.lastScaledSize),E=this.progressStyle.chars[1].repeat(this.progressMaxScaledSize-a.lastScaledSize);n=` ${h}${E}`}let u=this.formatName(null),A=u?`${u}: `:"",p=a.definition.title?` ${a.definition.title}`:"";this.stdout.write(`${Ot(this.configuration,"\u27A4","blueBright")} ${A}${o}${n}${p} +`)}this.progressTimeout=setTimeout(()=>{this.refreshProgress({force:!0})},zce)}refreshProgress({delta:r=0,force:o=!1}={}){let a=!1,n=!1;if(o||this.progress.size===0)a=!0;else for(let u of this.progress.values()){let A=typeof u.definition.progress<"u"?Math.trunc(this.progressMaxScaledSize*u.definition.progress):void 0,p=u.lastScaledSize;u.lastScaledSize=A;let h=u.lastTitle;if(u.lastTitle=u.definition.title,A!==p||(n=h!==u.definition.title)){a=!0;break}}a&&(this.clearProgress({delta:r,clear:n}),this.writeProgress())}truncate(r,{truncate:o}={}){return this.progressStyle===null&&(o=!1),typeof o>"u"&&(o=this.configuration.get("preferTruncatedLines")),o&&(r=(0,Xce.default)(r,0,this.stdout.columns-1)),r}formatName(r){return this.includeNames?$ce(r,{configuration:this.configuration,json:this.json}):""}formatPrefix(r,o){return this.includePrefix?`${Ot(this.configuration,"\u27A4",o)} ${r}${this.formatIndent()}`:""}formatNameWithHyperlink(r){return this.includeNames?AU(r,{configuration:this.configuration,json:this.json}):""}formatIndent(){return this.level>0||!this.forceSectionAlignment?"\u2502 ".repeat(this.indent):`${Cat} `}}});var An={};Vt(An,{PackageManager:()=>rue,detectPackageManager:()=>nue,executePackageAccessibleBinary:()=>lue,executePackageScript:()=>Nb,executePackageShellcode:()=>fU,executeWorkspaceAccessibleBinary:()=>kat,executeWorkspaceLifecycleScript:()=>oue,executeWorkspaceScript:()=>sue,getPackageAccessibleBinaries:()=>Lb,getWorkspaceAccessibleBinaries:()=>aue,hasPackageScript:()=>Sat,hasWorkspaceScript:()=>pU,isNodeScript:()=>hU,makeScriptEnv:()=>B1,maybeExecuteWorkspaceLifecycleScript:()=>xat,prepareExternalProject:()=>Pat});async function uh(t,e,r,o=[]){if(process.platform==="win32"){let a=`@goto #_undefined_# 2>NUL || @title %COMSPEC% & @setlocal & @"${r}" ${o.map(n=>`"${n.replace('"','""')}"`).join(" ")} %*`;await oe.writeFilePromise(K.format({dir:t,name:e,ext:".cmd"}),a)}await oe.writeFilePromise(K.join(t,e),`#!/bin/sh +exec "${r}" ${o.map(a=>`'${a.replace(/'/g,`'"'"'`)}'`).join(" ")} "$@" +`,{mode:493})}async function nue(t){let e=await Ut.tryFind(t);if(e?.packageManager){let o=DS(e.packageManager);if(o?.name){let a=`found ${JSON.stringify({packageManager:e.packageManager})} in manifest`,[n]=o.reference.split(".");switch(o.name){case"yarn":return{packageManagerField:!0,packageManager:Number(n)===1?"Yarn Classic":"Yarn",reason:a};case"npm":return{packageManagerField:!0,packageManager:"npm",reason:a};case"pnpm":return{packageManagerField:!0,packageManager:"pnpm",reason:a}}}}let r;try{r=await oe.readFilePromise(K.join(t,dr.lockfile),"utf8")}catch{}return r!==void 0?r.match(/^__metadata:$/m)?{packageManager:"Yarn",reason:'"__metadata" key found in yarn.lock'}:{packageManager:"Yarn Classic",reason:'"__metadata" key not found in yarn.lock, must be a Yarn classic lockfile'}:oe.existsSync(K.join(t,"package-lock.json"))?{packageManager:"npm",reason:`found npm's "package-lock.json" lockfile`}:oe.existsSync(K.join(t,"pnpm-lock.yaml"))?{packageManager:"pnpm",reason:`found pnpm's "pnpm-lock.yaml" lockfile`}:null}async function B1({project:t,locator:e,binFolder:r,ignoreCorepack:o,lifecycleScript:a,baseEnv:n=t?.configuration.env??process.env}){let u={};for(let[E,I]of Object.entries(n))typeof I<"u"&&(u[E.toLowerCase()!=="path"?E:"PATH"]=I);let A=ue.fromPortablePath(r);u.BERRY_BIN_FOLDER=ue.fromPortablePath(A);let p=process.env.COREPACK_ROOT&&!o?ue.join(process.env.COREPACK_ROOT,"dist/yarn.js"):process.argv[1];if(await Promise.all([uh(r,"node",process.execPath),...nn!==null?[uh(r,"run",process.execPath,[p,"run"]),uh(r,"yarn",process.execPath,[p]),uh(r,"yarnpkg",process.execPath,[p]),uh(r,"node-gyp",process.execPath,[p,"run","--top-level","node-gyp"])]:[]]),t&&(u.INIT_CWD=ue.fromPortablePath(t.configuration.startingCwd),u.PROJECT_CWD=ue.fromPortablePath(t.cwd)),u.PATH=u.PATH?`${A}${ue.delimiter}${u.PATH}`:`${A}`,u.npm_execpath=`${A}${ue.sep}yarn`,u.npm_node_execpath=`${A}${ue.sep}node`,e){if(!t)throw new Error("Assertion failed: Missing project");let E=t.tryWorkspaceByLocator(e),I=E?E.manifest.version??"":t.storedPackages.get(e.locatorHash).version??"";u.npm_package_name=rn(e),u.npm_package_version=I;let v;if(E)v=E.cwd;else{let x=t.storedPackages.get(e.locatorHash);if(!x)throw new Error(`Package for ${qr(t.configuration,e)} not found in the project`);let C=t.configuration.getLinkers(),R={project:t,report:new Rt({stdout:new Ah.PassThrough,configuration:t.configuration})},L=C.find(U=>U.supportsPackage(x,R));if(!L)throw new Error(`The package ${qr(t.configuration,x)} isn't supported by any of the available linkers`);v=await L.findPackageLocation(x,R)}u.npm_package_json=ue.fromPortablePath(K.join(v,dr.manifest))}let h=nn!==null?`yarn/${nn}`:`yarn/${vf("@yarnpkg/core").version}-core`;return u.npm_config_user_agent=`${h} npm/? node/${process.version} ${process.platform} ${process.arch}`,a&&(u.npm_lifecycle_event=a),t&&await t.configuration.triggerHook(E=>E.setupScriptEnvironment,t,u,async(E,I,v)=>await uh(r,E,I,v)),u}async function Pat(t,e,{configuration:r,report:o,workspace:a=null,locator:n=null}){await Dat(async()=>{await oe.mktempPromise(async u=>{let A=K.join(u,"pack.log"),p=null,{stdout:h,stderr:E}=r.getSubprocessStreams(A,{prefix:ue.fromPortablePath(t),report:o}),I=n&&Gc(n)?_I(n):n,v=I?ka(I):"an external project";h.write(`Packing ${v} from sources +`);let x=await nue(t),C;x!==null?(h.write(`Using ${x.packageManager} for bootstrap. Reason: ${x.reason} + +`),C=x.packageManager):(h.write(`No package manager configuration detected; defaulting to Yarn + +`),C="Yarn");let R=C==="Yarn"&&!x?.packageManagerField;await oe.mktempPromise(async L=>{let U=await B1({binFolder:L,ignoreCorepack:R}),te=new Map([["Yarn Classic",async()=>{let le=a!==null?["workspace",a]:[],ce=K.join(t,dr.manifest),Ce=await oe.readFilePromise(ce),de=await Wc(process.execPath,[process.argv[1],"set","version","classic","--only-if-needed","--yarn-path"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(de.code!==0)return de.code;await oe.writeFilePromise(ce,Ce),await oe.appendFilePromise(K.join(t,".npmignore"),`/.yarn +`),h.write(` +`),delete U.NODE_ENV;let Be=await Wc("yarn",["install"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(Be.code!==0)return Be.code;h.write(` +`);let Ee=await Wc("yarn",[...le,"pack","--filename",ue.fromPortablePath(e)],{cwd:t,env:U,stdin:p,stdout:h,stderr:E});return Ee.code!==0?Ee.code:0}],["Yarn",async()=>{let le=a!==null?["workspace",a]:[];U.YARN_ENABLE_INLINE_BUILDS="1";let ce=K.join(t,dr.lockfile);await oe.existsPromise(ce)||await oe.writeFilePromise(ce,"");let Ce=await Wc("yarn",[...le,"pack","--install-if-needed","--filename",ue.fromPortablePath(e)],{cwd:t,env:U,stdin:p,stdout:h,stderr:E});return Ce.code!==0?Ce.code:0}],["npm",async()=>{if(a!==null){let me=new Ah.PassThrough,we=km(me);me.pipe(h,{end:!1});let Ae=await Wc("npm",["--version"],{cwd:t,env:U,stdin:p,stdout:me,stderr:E,end:0});if(me.end(),Ae.code!==0)return h.end(),E.end(),Ae.code;let ne=(await we).toString().trim();if(!tA(ne,">=7.x")){let Z=eA(null,"npm"),xe=In(Z,ne),Ne=In(Z,">=7.x");throw new Error(`Workspaces aren't supported by ${jn(r,xe)}; please upgrade to ${jn(r,Ne)} (npm has been detected as the primary package manager for ${Ot(r,t,yt.PATH)})`)}}let le=a!==null?["--workspace",a]:[];delete U.npm_config_user_agent,delete U.npm_config_production,delete U.NPM_CONFIG_PRODUCTION,delete U.NODE_ENV;let ce=await Wc("npm",["install","--legacy-peer-deps"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(ce.code!==0)return ce.code;let Ce=new Ah.PassThrough,de=km(Ce);Ce.pipe(h);let Be=await Wc("npm",["pack","--silent",...le],{cwd:t,env:U,stdin:p,stdout:Ce,stderr:E});if(Be.code!==0)return Be.code;let Ee=(await de).toString().trim().replace(/^.*\n/s,""),g=K.resolve(t,ue.toPortablePath(Ee));return await oe.renamePromise(g,e),0}]]).get(C);if(typeof te>"u")throw new Error("Assertion failed: Unsupported workflow");let ae=await te();if(!(ae===0||typeof ae>"u"))throw oe.detachTemp(u),new Jt(58,`Packing the package failed (exit code ${ae}, logs can be found here: ${Ot(r,A,yt.PATH)})`)})})})}async function Sat(t,e,{project:r}){let o=r.tryWorkspaceByLocator(t);if(o!==null)return pU(o,e);let a=r.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${qr(r.configuration,t)} not found in the project`);return await rA.openPromise(async n=>{let u=r.configuration,A=r.configuration.getLinkers(),p={project:r,report:new Rt({stdout:new Ah.PassThrough,configuration:u})},h=A.find(x=>x.supportsPackage(a,p));if(!h)throw new Error(`The package ${qr(r.configuration,a)} isn't supported by any of the available linkers`);let E=await h.findPackageLocation(a,p),I=new gn(E,{baseFs:n});return(await Ut.find(It.dot,{baseFs:I})).scripts.has(e)})}async function Nb(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A}){return await oe.mktempPromise(async p=>{let{manifest:h,env:E,cwd:I}=await iue(t,{project:a,binFolder:p,cwd:o,lifecycleScript:e}),v=h.scripts.get(e);if(typeof v>"u")return 1;let x=async()=>await cy(v,r,{cwd:I,env:E,stdin:n,stdout:u,stderr:A});return await(await a.configuration.reduceHook(R=>R.wrapScriptExecution,x,a,t,e,{script:v,args:r,cwd:I,env:E,stdin:n,stdout:u,stderr:A}))()})}async function fU(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A}){return await oe.mktempPromise(async p=>{let{env:h,cwd:E}=await iue(t,{project:a,binFolder:p,cwd:o});return await cy(e,r,{cwd:E,env:h,stdin:n,stdout:u,stderr:A})})}async function bat(t,{binFolder:e,cwd:r,lifecycleScript:o}){let a=await B1({project:t.project,locator:t.anchoredLocator,binFolder:e,lifecycleScript:o});return await gU(e,await aue(t)),typeof r>"u"&&(r=K.dirname(await oe.realpathPromise(K.join(t.cwd,"package.json")))),{manifest:t.manifest,binFolder:e,env:a,cwd:r}}async function iue(t,{project:e,binFolder:r,cwd:o,lifecycleScript:a}){let n=e.tryWorkspaceByLocator(t);if(n!==null)return bat(n,{binFolder:r,cwd:o,lifecycleScript:a});let u=e.storedPackages.get(t.locatorHash);if(!u)throw new Error(`Package for ${qr(e.configuration,t)} not found in the project`);return await rA.openPromise(async A=>{let p=e.configuration,h=e.configuration.getLinkers(),E={project:e,report:new Rt({stdout:new Ah.PassThrough,configuration:p})},I=h.find(L=>L.supportsPackage(u,E));if(!I)throw new Error(`The package ${qr(e.configuration,u)} isn't supported by any of the available linkers`);let v=await B1({project:e,locator:t,binFolder:r,lifecycleScript:a});await gU(r,await Lb(t,{project:e}));let x=await I.findPackageLocation(u,E),C=new gn(x,{baseFs:A}),R=await Ut.find(It.dot,{baseFs:C});return typeof o>"u"&&(o=x),{manifest:R,binFolder:r,env:v,cwd:o}})}async function sue(t,e,r,{cwd:o,stdin:a,stdout:n,stderr:u}){return await Nb(t.anchoredLocator,e,r,{cwd:o,project:t.project,stdin:a,stdout:n,stderr:u})}function pU(t,e){return t.manifest.scripts.has(e)}async function oue(t,e,{cwd:r,report:o}){let{configuration:a}=t.project,n=null;await oe.mktempPromise(async u=>{let A=K.join(u,`${e}.log`),p=`# This file contains the result of Yarn calling the "${e}" lifecycle script inside a workspace ("${ue.fromPortablePath(t.cwd)}") +`,{stdout:h,stderr:E}=a.getSubprocessStreams(A,{report:o,prefix:qr(a,t.anchoredLocator),header:p});o.reportInfo(36,`Calling the "${e}" lifecycle script`);let I=await sue(t,e,[],{cwd:r,stdin:n,stdout:h,stderr:E});if(h.end(),E.end(),I!==0)throw oe.detachTemp(u),new Jt(36,`${(0,eue.default)(e)} script failed (exit code ${Ot(a,I,yt.NUMBER)}, logs can be found here: ${Ot(a,A,yt.PATH)}); run ${Ot(a,`yarn ${e}`,yt.CODE)} to investigate`)})}async function xat(t,e,r){pU(t,e)&&await oue(t,e,r)}function hU(t){let e=K.extname(t);if(e.match(/\.[cm]?[jt]sx?$/))return!0;if(e===".exe"||e===".bin")return!1;let r=Buffer.alloc(4),o;try{o=oe.openSync(t,"r")}catch{return!0}try{oe.readSync(o,r,0,r.length,0)}finally{oe.closeSync(o)}let a=r.readUint32BE();return!(a===3405691582||a===3489328638||a===2135247942||(a&4294901760)===1297743872)}async function Lb(t,{project:e}){let r=e.configuration,o=new Map,a=e.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${qr(r,t)} not found in the project`);let n=new Ah.Writable,u=r.getLinkers(),A={project:e,report:new Rt({configuration:r,stdout:n})},p=new Set([t.locatorHash]);for(let E of a.dependencies.values()){let I=e.storedResolutions.get(E.descriptorHash);if(!I)throw new Error(`Assertion failed: The resolution (${jn(r,E)}) should have been registered`);p.add(I)}let h=await Promise.all(Array.from(p,async E=>{let I=e.storedPackages.get(E);if(!I)throw new Error(`Assertion failed: The package (${E}) should have been registered`);if(I.bin.size===0)return ol.skip;let v=u.find(C=>C.supportsPackage(I,A));if(!v)return ol.skip;let x=null;try{x=await v.findPackageLocation(I,A)}catch(C){if(C.code==="LOCATOR_NOT_INSTALLED")return ol.skip;throw C}return{dependency:I,packageLocation:x}}));for(let E of h){if(E===ol.skip)continue;let{dependency:I,packageLocation:v}=E;for(let[x,C]of I.bin){let R=K.resolve(v,C);o.set(x,[I,ue.fromPortablePath(R),hU(R)])}}return o}async function aue(t){return await Lb(t.anchoredLocator,{project:t.project})}async function gU(t,e){await Promise.all(Array.from(e,([r,[,o,a]])=>a?uh(t,r,process.execPath,[o]):uh(t,r,o,[])))}async function lue(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A,nodeArgs:p=[],packageAccessibleBinaries:h}){h??=await Lb(t,{project:a});let E=h.get(e);if(!E)throw new Error(`Binary not found (${e}) for ${qr(a.configuration,t)}`);return await oe.mktempPromise(async I=>{let[,v]=E,x=await B1({project:a,locator:t,binFolder:I});await gU(x.BERRY_BIN_FOLDER,h);let C=hU(ue.toPortablePath(v))?Wc(process.execPath,[...p,v,...r],{cwd:o,env:x,stdin:n,stdout:u,stderr:A}):Wc(v,r,{cwd:o,env:x,stdin:n,stdout:u,stderr:A}),R;try{R=await C}finally{await oe.removePromise(x.BERRY_BIN_FOLDER)}return R.code})}async function kat(t,e,r,{cwd:o,stdin:a,stdout:n,stderr:u,packageAccessibleBinaries:A}){return await lue(t.anchoredLocator,e,r,{project:t.project,cwd:o,stdin:a,stdout:n,stderr:u,packageAccessibleBinaries:A})}var eue,tue,Ah,rue,vat,Dat,dU=Et(()=>{Pt();Pt();nA();g1();eue=Ze(uU()),tue=Ze(eg()),Ah=ve("stream");Gm();Wl();I1();w1();hb();jl();ql();bf();bo();rue=(a=>(a.Yarn1="Yarn Classic",a.Yarn2="Yarn",a.Npm="npm",a.Pnpm="pnpm",a))(rue||{});vat=2,Dat=(0,tue.default)(vat)});var Ay=_((q4t,uue)=>{"use strict";var cue=new Map([["C","cwd"],["f","file"],["z","gzip"],["P","preservePaths"],["U","unlink"],["strip-components","strip"],["stripComponents","strip"],["keep-newer","newer"],["keepNewer","newer"],["keep-newer-files","newer"],["keepNewerFiles","newer"],["k","keep"],["keep-existing","keep"],["keepExisting","keep"],["m","noMtime"],["no-mtime","noMtime"],["p","preserveOwner"],["L","follow"],["h","follow"]]);uue.exports=t=>t?Object.keys(t).map(e=>[cue.has(e)?cue.get(e):e,t[e]]).reduce((e,r)=>(e[r[0]]=r[1],e),Object.create(null)):{}});var py=_((j4t,Eue)=>{"use strict";var Aue=typeof process=="object"&&process?process:{stdout:null,stderr:null},Qat=ve("events"),fue=ve("stream"),pue=ve("string_decoder").StringDecoder,Nf=Symbol("EOF"),Lf=Symbol("maybeEmitEnd"),fh=Symbol("emittedEnd"),Mb=Symbol("emittingEnd"),v1=Symbol("emittedError"),Ob=Symbol("closed"),hue=Symbol("read"),Ub=Symbol("flush"),gue=Symbol("flushChunk"),Fa=Symbol("encoding"),Mf=Symbol("decoder"),_b=Symbol("flowing"),D1=Symbol("paused"),fy=Symbol("resume"),Ts=Symbol("bufferLength"),mU=Symbol("bufferPush"),yU=Symbol("bufferShift"),Fo=Symbol("objectMode"),Ro=Symbol("destroyed"),EU=Symbol("emitData"),due=Symbol("emitEnd"),CU=Symbol("emitEnd2"),Of=Symbol("async"),P1=t=>Promise.resolve().then(t),mue=global._MP_NO_ITERATOR_SYMBOLS_!=="1",Fat=mue&&Symbol.asyncIterator||Symbol("asyncIterator not implemented"),Rat=mue&&Symbol.iterator||Symbol("iterator not implemented"),Tat=t=>t==="end"||t==="finish"||t==="prefinish",Nat=t=>t instanceof ArrayBuffer||typeof t=="object"&&t.constructor&&t.constructor.name==="ArrayBuffer"&&t.byteLength>=0,Lat=t=>!Buffer.isBuffer(t)&&ArrayBuffer.isView(t),Hb=class{constructor(e,r,o){this.src=e,this.dest=r,this.opts=o,this.ondrain=()=>e[fy](),r.on("drain",this.ondrain)}unpipe(){this.dest.removeListener("drain",this.ondrain)}proxyErrors(){}end(){this.unpipe(),this.opts.end&&this.dest.end()}},wU=class extends Hb{unpipe(){this.src.removeListener("error",this.proxyErrors),super.unpipe()}constructor(e,r,o){super(e,r,o),this.proxyErrors=a=>r.emit("error",a),e.on("error",this.proxyErrors)}};Eue.exports=class yue extends fue{constructor(e){super(),this[_b]=!1,this[D1]=!1,this.pipes=[],this.buffer=[],this[Fo]=e&&e.objectMode||!1,this[Fo]?this[Fa]=null:this[Fa]=e&&e.encoding||null,this[Fa]==="buffer"&&(this[Fa]=null),this[Of]=e&&!!e.async||!1,this[Mf]=this[Fa]?new pue(this[Fa]):null,this[Nf]=!1,this[fh]=!1,this[Mb]=!1,this[Ob]=!1,this[v1]=null,this.writable=!0,this.readable=!0,this[Ts]=0,this[Ro]=!1}get bufferLength(){return this[Ts]}get encoding(){return this[Fa]}set encoding(e){if(this[Fo])throw new Error("cannot set encoding in objectMode");if(this[Fa]&&e!==this[Fa]&&(this[Mf]&&this[Mf].lastNeed||this[Ts]))throw new Error("cannot change encoding");this[Fa]!==e&&(this[Mf]=e?new pue(e):null,this.buffer.length&&(this.buffer=this.buffer.map(r=>this[Mf].write(r)))),this[Fa]=e}setEncoding(e){this.encoding=e}get objectMode(){return this[Fo]}set objectMode(e){this[Fo]=this[Fo]||!!e}get async(){return this[Of]}set async(e){this[Of]=this[Of]||!!e}write(e,r,o){if(this[Nf])throw new Error("write after end");if(this[Ro])return this.emit("error",Object.assign(new Error("Cannot call write after a stream was destroyed"),{code:"ERR_STREAM_DESTROYED"})),!0;typeof r=="function"&&(o=r,r="utf8"),r||(r="utf8");let a=this[Of]?P1:n=>n();return!this[Fo]&&!Buffer.isBuffer(e)&&(Lat(e)?e=Buffer.from(e.buffer,e.byteOffset,e.byteLength):Nat(e)?e=Buffer.from(e):typeof e!="string"&&(this.objectMode=!0)),this[Fo]?(this.flowing&&this[Ts]!==0&&this[Ub](!0),this.flowing?this.emit("data",e):this[mU](e),this[Ts]!==0&&this.emit("readable"),o&&a(o),this.flowing):e.length?(typeof e=="string"&&!(r===this[Fa]&&!this[Mf].lastNeed)&&(e=Buffer.from(e,r)),Buffer.isBuffer(e)&&this[Fa]&&(e=this[Mf].write(e)),this.flowing&&this[Ts]!==0&&this[Ub](!0),this.flowing?this.emit("data",e):this[mU](e),this[Ts]!==0&&this.emit("readable"),o&&a(o),this.flowing):(this[Ts]!==0&&this.emit("readable"),o&&a(o),this.flowing)}read(e){if(this[Ro])return null;if(this[Ts]===0||e===0||e>this[Ts])return this[Lf](),null;this[Fo]&&(e=null),this.buffer.length>1&&!this[Fo]&&(this.encoding?this.buffer=[this.buffer.join("")]:this.buffer=[Buffer.concat(this.buffer,this[Ts])]);let r=this[hue](e||null,this.buffer[0]);return this[Lf](),r}[hue](e,r){return e===r.length||e===null?this[yU]():(this.buffer[0]=r.slice(e),r=r.slice(0,e),this[Ts]-=e),this.emit("data",r),!this.buffer.length&&!this[Nf]&&this.emit("drain"),r}end(e,r,o){return typeof e=="function"&&(o=e,e=null),typeof r=="function"&&(o=r,r="utf8"),e&&this.write(e,r),o&&this.once("end",o),this[Nf]=!0,this.writable=!1,(this.flowing||!this[D1])&&this[Lf](),this}[fy](){this[Ro]||(this[D1]=!1,this[_b]=!0,this.emit("resume"),this.buffer.length?this[Ub]():this[Nf]?this[Lf]():this.emit("drain"))}resume(){return this[fy]()}pause(){this[_b]=!1,this[D1]=!0}get destroyed(){return this[Ro]}get flowing(){return this[_b]}get paused(){return this[D1]}[mU](e){this[Fo]?this[Ts]+=1:this[Ts]+=e.length,this.buffer.push(e)}[yU](){return this.buffer.length&&(this[Fo]?this[Ts]-=1:this[Ts]-=this.buffer[0].length),this.buffer.shift()}[Ub](e){do;while(this[gue](this[yU]()));!e&&!this.buffer.length&&!this[Nf]&&this.emit("drain")}[gue](e){return e?(this.emit("data",e),this.flowing):!1}pipe(e,r){if(this[Ro])return;let o=this[fh];return r=r||{},e===Aue.stdout||e===Aue.stderr?r.end=!1:r.end=r.end!==!1,r.proxyErrors=!!r.proxyErrors,o?r.end&&e.end():(this.pipes.push(r.proxyErrors?new wU(this,e,r):new Hb(this,e,r)),this[Of]?P1(()=>this[fy]()):this[fy]()),e}unpipe(e){let r=this.pipes.find(o=>o.dest===e);r&&(this.pipes.splice(this.pipes.indexOf(r),1),r.unpipe())}addListener(e,r){return this.on(e,r)}on(e,r){let o=super.on(e,r);return e==="data"&&!this.pipes.length&&!this.flowing?this[fy]():e==="readable"&&this[Ts]!==0?super.emit("readable"):Tat(e)&&this[fh]?(super.emit(e),this.removeAllListeners(e)):e==="error"&&this[v1]&&(this[Of]?P1(()=>r.call(this,this[v1])):r.call(this,this[v1])),o}get emittedEnd(){return this[fh]}[Lf](){!this[Mb]&&!this[fh]&&!this[Ro]&&this.buffer.length===0&&this[Nf]&&(this[Mb]=!0,this.emit("end"),this.emit("prefinish"),this.emit("finish"),this[Ob]&&this.emit("close"),this[Mb]=!1)}emit(e,r,...o){if(e!=="error"&&e!=="close"&&e!==Ro&&this[Ro])return;if(e==="data")return r?this[Of]?P1(()=>this[EU](r)):this[EU](r):!1;if(e==="end")return this[due]();if(e==="close"){if(this[Ob]=!0,!this[fh]&&!this[Ro])return;let n=super.emit("close");return this.removeAllListeners("close"),n}else if(e==="error"){this[v1]=r;let n=super.emit("error",r);return this[Lf](),n}else if(e==="resume"){let n=super.emit("resume");return this[Lf](),n}else if(e==="finish"||e==="prefinish"){let n=super.emit(e);return this.removeAllListeners(e),n}let a=super.emit(e,r,...o);return this[Lf](),a}[EU](e){for(let o of this.pipes)o.dest.write(e)===!1&&this.pause();let r=super.emit("data",e);return this[Lf](),r}[due](){this[fh]||(this[fh]=!0,this.readable=!1,this[Of]?P1(()=>this[CU]()):this[CU]())}[CU](){if(this[Mf]){let r=this[Mf].end();if(r){for(let o of this.pipes)o.dest.write(r);super.emit("data",r)}}for(let r of this.pipes)r.end();let e=super.emit("end");return this.removeAllListeners("end"),e}collect(){let e=[];this[Fo]||(e.dataLength=0);let r=this.promise();return this.on("data",o=>{e.push(o),this[Fo]||(e.dataLength+=o.length)}),r.then(()=>e)}concat(){return this[Fo]?Promise.reject(new Error("cannot concat in objectMode")):this.collect().then(e=>this[Fo]?Promise.reject(new Error("cannot concat in objectMode")):this[Fa]?e.join(""):Buffer.concat(e,e.dataLength))}promise(){return new Promise((e,r)=>{this.on(Ro,()=>r(new Error("stream destroyed"))),this.on("error",o=>r(o)),this.on("end",()=>e())})}[Fat](){return{next:()=>{let r=this.read();if(r!==null)return Promise.resolve({done:!1,value:r});if(this[Nf])return Promise.resolve({done:!0});let o=null,a=null,n=h=>{this.removeListener("data",u),this.removeListener("end",A),a(h)},u=h=>{this.removeListener("error",n),this.removeListener("end",A),this.pause(),o({value:h,done:!!this[Nf]})},A=()=>{this.removeListener("error",n),this.removeListener("data",u),o({done:!0})},p=()=>n(new Error("stream destroyed"));return new Promise((h,E)=>{a=E,o=h,this.once(Ro,p),this.once("error",n),this.once("end",A),this.once("data",u)})}}}[Rat](){return{next:()=>{let r=this.read();return{value:r,done:r===null}}}}destroy(e){return this[Ro]?(e?this.emit("error",e):this.emit(Ro),this):(this[Ro]=!0,this.buffer.length=0,this[Ts]=0,typeof this.close=="function"&&!this[Ob]&&this.close(),e?this.emit("error",e):this.emit(Ro),this)}static isStream(e){return!!e&&(e instanceof yue||e instanceof fue||e instanceof Qat&&(typeof e.pipe=="function"||typeof e.write=="function"&&typeof e.end=="function"))}}});var wue=_((G4t,Cue)=>{var Mat=ve("zlib").constants||{ZLIB_VERNUM:4736};Cue.exports=Object.freeze(Object.assign(Object.create(null),{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_VERSION_ERROR:-6,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,Z_MIN_WINDOWBITS:8,Z_MAX_WINDOWBITS:15,Z_DEFAULT_WINDOWBITS:15,Z_MIN_CHUNK:64,Z_MAX_CHUNK:1/0,Z_DEFAULT_CHUNK:16384,Z_MIN_MEMLEVEL:1,Z_MAX_MEMLEVEL:9,Z_DEFAULT_MEMLEVEL:8,Z_MIN_LEVEL:-1,Z_MAX_LEVEL:9,Z_DEFAULT_LEVEL:-1,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},Mat))});var MU=_(ul=>{"use strict";var PU=ve("assert"),ph=ve("buffer").Buffer,vue=ve("zlib"),Pg=ul.constants=wue(),Oat=py(),Iue=ph.concat,Sg=Symbol("_superWrite"),gy=class extends Error{constructor(e){super("zlib: "+e.message),this.code=e.code,this.errno=e.errno,this.code||(this.code="ZLIB_ERROR"),this.message="zlib: "+e.message,Error.captureStackTrace(this,this.constructor)}get name(){return"ZlibError"}},Uat=Symbol("opts"),S1=Symbol("flushFlag"),Bue=Symbol("finishFlushFlag"),LU=Symbol("fullFlushFlag"),ti=Symbol("handle"),qb=Symbol("onError"),hy=Symbol("sawError"),IU=Symbol("level"),BU=Symbol("strategy"),vU=Symbol("ended"),Y4t=Symbol("_defaultFullFlush"),jb=class extends Oat{constructor(e,r){if(!e||typeof e!="object")throw new TypeError("invalid options for ZlibBase constructor");super(e),this[hy]=!1,this[vU]=!1,this[Uat]=e,this[S1]=e.flush,this[Bue]=e.finishFlush;try{this[ti]=new vue[r](e)}catch(o){throw new gy(o)}this[qb]=o=>{this[hy]||(this[hy]=!0,this.close(),this.emit("error",o))},this[ti].on("error",o=>this[qb](new gy(o))),this.once("end",()=>this.close)}close(){this[ti]&&(this[ti].close(),this[ti]=null,this.emit("close"))}reset(){if(!this[hy])return PU(this[ti],"zlib binding closed"),this[ti].reset()}flush(e){this.ended||(typeof e!="number"&&(e=this[LU]),this.write(Object.assign(ph.alloc(0),{[S1]:e})))}end(e,r,o){return e&&this.write(e,r),this.flush(this[Bue]),this[vU]=!0,super.end(null,null,o)}get ended(){return this[vU]}write(e,r,o){if(typeof r=="function"&&(o=r,r="utf8"),typeof e=="string"&&(e=ph.from(e,r)),this[hy])return;PU(this[ti],"zlib binding closed");let a=this[ti]._handle,n=a.close;a.close=()=>{};let u=this[ti].close;this[ti].close=()=>{},ph.concat=h=>h;let A;try{let h=typeof e[S1]=="number"?e[S1]:this[S1];A=this[ti]._processChunk(e,h),ph.concat=Iue}catch(h){ph.concat=Iue,this[qb](new gy(h))}finally{this[ti]&&(this[ti]._handle=a,a.close=n,this[ti].close=u,this[ti].removeAllListeners("error"))}this[ti]&&this[ti].on("error",h=>this[qb](new gy(h)));let p;if(A)if(Array.isArray(A)&&A.length>0){p=this[Sg](ph.from(A[0]));for(let h=1;h<A.length;h++)p=this[Sg](A[h])}else p=this[Sg](ph.from(A));return o&&o(),p}[Sg](e){return super.write(e)}},Uf=class extends jb{constructor(e,r){e=e||{},e.flush=e.flush||Pg.Z_NO_FLUSH,e.finishFlush=e.finishFlush||Pg.Z_FINISH,super(e,r),this[LU]=Pg.Z_FULL_FLUSH,this[IU]=e.level,this[BU]=e.strategy}params(e,r){if(!this[hy]){if(!this[ti])throw new Error("cannot switch params when binding is closed");if(!this[ti].params)throw new Error("not supported in this implementation");if(this[IU]!==e||this[BU]!==r){this.flush(Pg.Z_SYNC_FLUSH),PU(this[ti],"zlib binding closed");let o=this[ti].flush;this[ti].flush=(a,n)=>{this.flush(a),n()};try{this[ti].params(e,r)}finally{this[ti].flush=o}this[ti]&&(this[IU]=e,this[BU]=r)}}}},SU=class extends Uf{constructor(e){super(e,"Deflate")}},bU=class extends Uf{constructor(e){super(e,"Inflate")}},DU=Symbol("_portable"),xU=class extends Uf{constructor(e){super(e,"Gzip"),this[DU]=e&&!!e.portable}[Sg](e){return this[DU]?(this[DU]=!1,e[9]=255,super[Sg](e)):super[Sg](e)}},kU=class extends Uf{constructor(e){super(e,"Gunzip")}},QU=class extends Uf{constructor(e){super(e,"DeflateRaw")}},FU=class extends Uf{constructor(e){super(e,"InflateRaw")}},RU=class extends Uf{constructor(e){super(e,"Unzip")}},Gb=class extends jb{constructor(e,r){e=e||{},e.flush=e.flush||Pg.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||Pg.BROTLI_OPERATION_FINISH,super(e,r),this[LU]=Pg.BROTLI_OPERATION_FLUSH}},TU=class extends Gb{constructor(e){super(e,"BrotliCompress")}},NU=class extends Gb{constructor(e){super(e,"BrotliDecompress")}};ul.Deflate=SU;ul.Inflate=bU;ul.Gzip=xU;ul.Gunzip=kU;ul.DeflateRaw=QU;ul.InflateRaw=FU;ul.Unzip=RU;typeof vue.BrotliCompress=="function"?(ul.BrotliCompress=TU,ul.BrotliDecompress=NU):ul.BrotliCompress=ul.BrotliDecompress=class{constructor(){throw new Error("Brotli is not supported in this version of Node.js")}}});var dy=_((V4t,Due)=>{var _at=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform;Due.exports=_at!=="win32"?t=>t:t=>t&&t.replace(/\\/g,"/")});var Yb=_((J4t,Pue)=>{"use strict";var Hat=py(),OU=dy(),UU=Symbol("slurp");Pue.exports=class extends Hat{constructor(e,r,o){switch(super(),this.pause(),this.extended=r,this.globalExtended=o,this.header=e,this.startBlockSize=512*Math.ceil(e.size/512),this.blockRemain=this.startBlockSize,this.remain=e.size,this.type=e.type,this.meta=!1,this.ignore=!1,this.type){case"File":case"OldFile":case"Link":case"SymbolicLink":case"CharacterDevice":case"BlockDevice":case"Directory":case"FIFO":case"ContiguousFile":case"GNUDumpDir":break;case"NextFileHasLongLinkpath":case"NextFileHasLongPath":case"OldGnuLongPath":case"GlobalExtendedHeader":case"ExtendedHeader":case"OldExtendedHeader":this.meta=!0;break;default:this.ignore=!0}this.path=OU(e.path),this.mode=e.mode,this.mode&&(this.mode=this.mode&4095),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=e.size,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=OU(e.linkpath),this.uname=e.uname,this.gname=e.gname,r&&this[UU](r),o&&this[UU](o,!0)}write(e){let r=e.length;if(r>this.blockRemain)throw new Error("writing more to entry than is appropriate");let o=this.remain,a=this.blockRemain;return this.remain=Math.max(0,o-r),this.blockRemain=Math.max(0,a-r),this.ignore?!0:o>=r?super.write(e):super.write(e.slice(0,o))}[UU](e,r){for(let o in e)e[o]!==null&&e[o]!==void 0&&!(r&&o==="path")&&(this[o]=o==="path"||o==="linkpath"?OU(e[o]):e[o])}}});var _U=_(Wb=>{"use strict";Wb.name=new Map([["0","File"],["","OldFile"],["1","Link"],["2","SymbolicLink"],["3","CharacterDevice"],["4","BlockDevice"],["5","Directory"],["6","FIFO"],["7","ContiguousFile"],["g","GlobalExtendedHeader"],["x","ExtendedHeader"],["A","SolarisACL"],["D","GNUDumpDir"],["I","Inode"],["K","NextFileHasLongLinkpath"],["L","NextFileHasLongPath"],["M","ContinuationFile"],["N","OldGnuLongPath"],["S","SparseFile"],["V","TapeVolumeHeader"],["X","OldExtendedHeader"]]);Wb.code=new Map(Array.from(Wb.name).map(t=>[t[1],t[0]]))});var kue=_((Z4t,xue)=>{"use strict";var qat=(t,e)=>{if(Number.isSafeInteger(t))t<0?Gat(t,e):jat(t,e);else throw Error("cannot encode number outside of javascript safe integer range");return e},jat=(t,e)=>{e[0]=128;for(var r=e.length;r>1;r--)e[r-1]=t&255,t=Math.floor(t/256)},Gat=(t,e)=>{e[0]=255;var r=!1;t=t*-1;for(var o=e.length;o>1;o--){var a=t&255;t=Math.floor(t/256),r?e[o-1]=Sue(a):a===0?e[o-1]=0:(r=!0,e[o-1]=bue(a))}},Yat=t=>{let e=t[0],r=e===128?Kat(t.slice(1,t.length)):e===255?Wat(t):null;if(r===null)throw Error("invalid base256 encoding");if(!Number.isSafeInteger(r))throw Error("parsed number outside of javascript safe integer range");return r},Wat=t=>{for(var e=t.length,r=0,o=!1,a=e-1;a>-1;a--){var n=t[a],u;o?u=Sue(n):n===0?u=n:(o=!0,u=bue(n)),u!==0&&(r-=u*Math.pow(256,e-a-1))}return r},Kat=t=>{for(var e=t.length,r=0,o=e-1;o>-1;o--){var a=t[o];a!==0&&(r+=a*Math.pow(256,e-o-1))}return r},Sue=t=>(255^t)&255,bue=t=>(255^t)+1&255;xue.exports={encode:qat,parse:Yat}});var yy=_(($4t,Fue)=>{"use strict";var HU=_U(),my=ve("path").posix,Que=kue(),qU=Symbol("slurp"),Al=Symbol("type"),YU=class{constructor(e,r,o,a){this.cksumValid=!1,this.needPax=!1,this.nullBlock=!1,this.block=null,this.path=null,this.mode=null,this.uid=null,this.gid=null,this.size=null,this.mtime=null,this.cksum=null,this[Al]="0",this.linkpath=null,this.uname=null,this.gname=null,this.devmaj=0,this.devmin=0,this.atime=null,this.ctime=null,Buffer.isBuffer(e)?this.decode(e,r||0,o,a):e&&this.set(e)}decode(e,r,o,a){if(r||(r=0),!e||!(e.length>=r+512))throw new Error("need 512 bytes for header");if(this.path=bg(e,r,100),this.mode=hh(e,r+100,8),this.uid=hh(e,r+108,8),this.gid=hh(e,r+116,8),this.size=hh(e,r+124,12),this.mtime=jU(e,r+136,12),this.cksum=hh(e,r+148,12),this[qU](o),this[qU](a,!0),this[Al]=bg(e,r+156,1),this[Al]===""&&(this[Al]="0"),this[Al]==="0"&&this.path.substr(-1)==="/"&&(this[Al]="5"),this[Al]==="5"&&(this.size=0),this.linkpath=bg(e,r+157,100),e.slice(r+257,r+265).toString()==="ustar\x0000")if(this.uname=bg(e,r+265,32),this.gname=bg(e,r+297,32),this.devmaj=hh(e,r+329,8),this.devmin=hh(e,r+337,8),e[r+475]!==0){let u=bg(e,r+345,155);this.path=u+"/"+this.path}else{let u=bg(e,r+345,130);u&&(this.path=u+"/"+this.path),this.atime=jU(e,r+476,12),this.ctime=jU(e,r+488,12)}let n=8*32;for(let u=r;u<r+148;u++)n+=e[u];for(let u=r+156;u<r+512;u++)n+=e[u];this.cksumValid=n===this.cksum,this.cksum===null&&n===8*32&&(this.nullBlock=!0)}[qU](e,r){for(let o in e)e[o]!==null&&e[o]!==void 0&&!(r&&o==="path")&&(this[o]=e[o])}encode(e,r){if(e||(e=this.block=Buffer.alloc(512),r=0),r||(r=0),!(e.length>=r+512))throw new Error("need 512 bytes for header");let o=this.ctime||this.atime?130:155,a=Vat(this.path||"",o),n=a[0],u=a[1];this.needPax=a[2],this.needPax=xg(e,r,100,n)||this.needPax,this.needPax=gh(e,r+100,8,this.mode)||this.needPax,this.needPax=gh(e,r+108,8,this.uid)||this.needPax,this.needPax=gh(e,r+116,8,this.gid)||this.needPax,this.needPax=gh(e,r+124,12,this.size)||this.needPax,this.needPax=GU(e,r+136,12,this.mtime)||this.needPax,e[r+156]=this[Al].charCodeAt(0),this.needPax=xg(e,r+157,100,this.linkpath)||this.needPax,e.write("ustar\x0000",r+257,8),this.needPax=xg(e,r+265,32,this.uname)||this.needPax,this.needPax=xg(e,r+297,32,this.gname)||this.needPax,this.needPax=gh(e,r+329,8,this.devmaj)||this.needPax,this.needPax=gh(e,r+337,8,this.devmin)||this.needPax,this.needPax=xg(e,r+345,o,u)||this.needPax,e[r+475]!==0?this.needPax=xg(e,r+345,155,u)||this.needPax:(this.needPax=xg(e,r+345,130,u)||this.needPax,this.needPax=GU(e,r+476,12,this.atime)||this.needPax,this.needPax=GU(e,r+488,12,this.ctime)||this.needPax);let A=8*32;for(let p=r;p<r+148;p++)A+=e[p];for(let p=r+156;p<r+512;p++)A+=e[p];return this.cksum=A,gh(e,r+148,8,this.cksum),this.cksumValid=!0,this.needPax}set(e){for(let r in e)e[r]!==null&&e[r]!==void 0&&(this[r]=e[r])}get type(){return HU.name.get(this[Al])||this[Al]}get typeKey(){return this[Al]}set type(e){HU.code.has(e)?this[Al]=HU.code.get(e):this[Al]=e}},Vat=(t,e)=>{let o=t,a="",n,u=my.parse(t).root||".";if(Buffer.byteLength(o)<100)n=[o,a,!1];else{a=my.dirname(o),o=my.basename(o);do Buffer.byteLength(o)<=100&&Buffer.byteLength(a)<=e?n=[o,a,!1]:Buffer.byteLength(o)>100&&Buffer.byteLength(a)<=e?n=[o.substr(0,99),a,!0]:(o=my.join(my.basename(a),o),a=my.dirname(a));while(a!==u&&!n);n||(n=[t.substr(0,99),"",!0])}return n},bg=(t,e,r)=>t.slice(e,e+r).toString("utf8").replace(/\0.*/,""),jU=(t,e,r)=>zat(hh(t,e,r)),zat=t=>t===null?null:new Date(t*1e3),hh=(t,e,r)=>t[e]&128?Que.parse(t.slice(e,e+r)):Xat(t,e,r),Jat=t=>isNaN(t)?null:t,Xat=(t,e,r)=>Jat(parseInt(t.slice(e,e+r).toString("utf8").replace(/\0.*$/,"").trim(),8)),Zat={12:8589934591,8:2097151},gh=(t,e,r,o)=>o===null?!1:o>Zat[r]||o<0?(Que.encode(o,t.slice(e,e+r)),!0):($at(t,e,r,o),!1),$at=(t,e,r,o)=>t.write(elt(o,r),e,r,"ascii"),elt=(t,e)=>tlt(Math.floor(t).toString(8),e),tlt=(t,e)=>(t.length===e-1?t:new Array(e-t.length-1).join("0")+t+" ")+"\0",GU=(t,e,r,o)=>o===null?!1:gh(t,e,r,o.getTime()/1e3),rlt=new Array(156).join("\0"),xg=(t,e,r,o)=>o===null?!1:(t.write(o+rlt,e,r,"utf8"),o.length!==Buffer.byteLength(o)||o.length>r);Fue.exports=YU});var Kb=_((eUt,Rue)=>{"use strict";var nlt=yy(),ilt=ve("path"),b1=class{constructor(e,r){this.atime=e.atime||null,this.charset=e.charset||null,this.comment=e.comment||null,this.ctime=e.ctime||null,this.gid=e.gid||null,this.gname=e.gname||null,this.linkpath=e.linkpath||null,this.mtime=e.mtime||null,this.path=e.path||null,this.size=e.size||null,this.uid=e.uid||null,this.uname=e.uname||null,this.dev=e.dev||null,this.ino=e.ino||null,this.nlink=e.nlink||null,this.global=r||!1}encode(){let e=this.encodeBody();if(e==="")return null;let r=Buffer.byteLength(e),o=512*Math.ceil(1+r/512),a=Buffer.allocUnsafe(o);for(let n=0;n<512;n++)a[n]=0;new nlt({path:("PaxHeader/"+ilt.basename(this.path)).slice(0,99),mode:this.mode||420,uid:this.uid||null,gid:this.gid||null,size:r,mtime:this.mtime||null,type:this.global?"GlobalExtendedHeader":"ExtendedHeader",linkpath:"",uname:this.uname||"",gname:this.gname||"",devmaj:0,devmin:0,atime:this.atime||null,ctime:this.ctime||null}).encode(a),a.write(e,512,r,"utf8");for(let n=r+512;n<a.length;n++)a[n]=0;return a}encodeBody(){return this.encodeField("path")+this.encodeField("ctime")+this.encodeField("atime")+this.encodeField("dev")+this.encodeField("ino")+this.encodeField("nlink")+this.encodeField("charset")+this.encodeField("comment")+this.encodeField("gid")+this.encodeField("gname")+this.encodeField("linkpath")+this.encodeField("mtime")+this.encodeField("size")+this.encodeField("uid")+this.encodeField("uname")}encodeField(e){if(this[e]===null||this[e]===void 0)return"";let r=this[e]instanceof Date?this[e].getTime()/1e3:this[e],o=" "+(e==="dev"||e==="ino"||e==="nlink"?"SCHILY.":"")+e+"="+r+` +`,a=Buffer.byteLength(o),n=Math.floor(Math.log(a)/Math.log(10))+1;return a+n>=Math.pow(10,n)&&(n+=1),n+a+o}};b1.parse=(t,e,r)=>new b1(slt(olt(t),e),r);var slt=(t,e)=>e?Object.keys(t).reduce((r,o)=>(r[o]=t[o],r),e):t,olt=t=>t.replace(/\n$/,"").split(` +`).reduce(alt,Object.create(null)),alt=(t,e)=>{let r=parseInt(e,10);if(r!==Buffer.byteLength(e)+1)return t;e=e.substr((r+" ").length);let o=e.split("="),a=o.shift().replace(/^SCHILY\.(dev|ino|nlink)/,"$1");if(!a)return t;let n=o.join("=");return t[a]=/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(a)?new Date(n*1e3):/^[0-9]+$/.test(n)?+n:n,t};Rue.exports=b1});var Ey=_((tUt,Tue)=>{Tue.exports=t=>{let e=t.length-1,r=-1;for(;e>-1&&t.charAt(e)==="/";)r=e,e--;return r===-1?t:t.slice(0,r)}});var Vb=_((rUt,Nue)=>{"use strict";Nue.exports=t=>class extends t{warn(e,r,o={}){this.file&&(o.file=this.file),this.cwd&&(o.cwd=this.cwd),o.code=r instanceof Error&&r.code||e,o.tarCode=e,!this.strict&&o.recoverable!==!1?(r instanceof Error&&(o=Object.assign(r,o),r=r.message),this.emit("warn",o.tarCode,r,o)):r instanceof Error?this.emit("error",Object.assign(r,o)):this.emit("error",Object.assign(new Error(`${e}: ${r}`),o))}}});var KU=_((iUt,Lue)=>{"use strict";var zb=["|","<",">","?",":"],WU=zb.map(t=>String.fromCharCode(61440+t.charCodeAt(0))),llt=new Map(zb.map((t,e)=>[t,WU[e]])),clt=new Map(WU.map((t,e)=>[t,zb[e]]));Lue.exports={encode:t=>zb.reduce((e,r)=>e.split(r).join(llt.get(r)),t),decode:t=>WU.reduce((e,r)=>e.split(r).join(clt.get(r)),t)}});var VU=_((sUt,Oue)=>{var{isAbsolute:ult,parse:Mue}=ve("path").win32;Oue.exports=t=>{let e="",r=Mue(t);for(;ult(t)||r.root;){let o=t.charAt(0)==="/"&&t.slice(0,4)!=="//?/"?"/":r.root;t=t.substr(o.length),e+=o,r=Mue(t)}return[e,t]}});var _ue=_((oUt,Uue)=>{"use strict";Uue.exports=(t,e,r)=>(t&=4095,r&&(t=(t|384)&-19),e&&(t&256&&(t|=64),t&32&&(t|=8),t&4&&(t|=1)),t)});var i3=_((cUt,eAe)=>{"use strict";var Kue=py(),Vue=Kb(),zue=yy(),oA=ve("fs"),Hue=ve("path"),sA=dy(),Alt=Ey(),Jue=(t,e)=>e?(t=sA(t).replace(/^\.(\/|$)/,""),Alt(e)+"/"+t):sA(t),flt=16*1024*1024,que=Symbol("process"),jue=Symbol("file"),Gue=Symbol("directory"),JU=Symbol("symlink"),Yue=Symbol("hardlink"),x1=Symbol("header"),Jb=Symbol("read"),XU=Symbol("lstat"),Xb=Symbol("onlstat"),ZU=Symbol("onread"),$U=Symbol("onreadlink"),e3=Symbol("openfile"),t3=Symbol("onopenfile"),dh=Symbol("close"),Zb=Symbol("mode"),r3=Symbol("awaitDrain"),zU=Symbol("ondrain"),aA=Symbol("prefix"),Wue=Symbol("hadError"),Xue=Vb(),plt=KU(),Zue=VU(),$ue=_ue(),$b=Xue(class extends Kue{constructor(e,r){if(r=r||{},super(r),typeof e!="string")throw new TypeError("path is required");this.path=sA(e),this.portable=!!r.portable,this.myuid=process.getuid&&process.getuid()||0,this.myuser=process.env.USER||"",this.maxReadSize=r.maxReadSize||flt,this.linkCache=r.linkCache||new Map,this.statCache=r.statCache||new Map,this.preservePaths=!!r.preservePaths,this.cwd=sA(r.cwd||process.cwd()),this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.mtime=r.mtime||null,this.prefix=r.prefix?sA(r.prefix):null,this.fd=null,this.blockLen=null,this.blockRemain=null,this.buf=null,this.offset=null,this.length=null,this.pos=null,this.remain=null,typeof r.onwarn=="function"&&this.on("warn",r.onwarn);let o=!1;if(!this.preservePaths){let[a,n]=Zue(this.path);a&&(this.path=n,o=a)}this.win32=!!r.win32||process.platform==="win32",this.win32&&(this.path=plt.decode(this.path.replace(/\\/g,"/")),e=e.replace(/\\/g,"/")),this.absolute=sA(r.absolute||Hue.resolve(this.cwd,e)),this.path===""&&(this.path="./"),o&&this.warn("TAR_ENTRY_INFO",`stripping ${o} from absolute path`,{entry:this,path:o+this.path}),this.statCache.has(this.absolute)?this[Xb](this.statCache.get(this.absolute)):this[XU]()}emit(e,...r){return e==="error"&&(this[Wue]=!0),super.emit(e,...r)}[XU](){oA.lstat(this.absolute,(e,r)=>{if(e)return this.emit("error",e);this[Xb](r)})}[Xb](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=glt(e),this.emit("stat",e),this[que]()}[que](){switch(this.type){case"File":return this[jue]();case"Directory":return this[Gue]();case"SymbolicLink":return this[JU]();default:return this.end()}}[Zb](e){return $ue(e,this.type==="Directory",this.portable)}[aA](e){return Jue(e,this.prefix)}[x1](){this.type==="Directory"&&this.portable&&(this.noMtime=!0),this.header=new zue({path:this[aA](this.path),linkpath:this.type==="Link"?this[aA](this.linkpath):this.linkpath,mode:this[Zb](this.stat.mode),uid:this.portable?null:this.stat.uid,gid:this.portable?null:this.stat.gid,size:this.stat.size,mtime:this.noMtime?null:this.mtime||this.stat.mtime,type:this.type,uname:this.portable?null:this.stat.uid===this.myuid?this.myuser:"",atime:this.portable?null:this.stat.atime,ctime:this.portable?null:this.stat.ctime}),this.header.encode()&&!this.noPax&&super.write(new Vue({atime:this.portable?null:this.header.atime,ctime:this.portable?null:this.header.ctime,gid:this.portable?null:this.header.gid,mtime:this.noMtime?null:this.mtime||this.header.mtime,path:this[aA](this.path),linkpath:this.type==="Link"?this[aA](this.linkpath):this.linkpath,size:this.header.size,uid:this.portable?null:this.header.uid,uname:this.portable?null:this.header.uname,dev:this.portable?null:this.stat.dev,ino:this.portable?null:this.stat.ino,nlink:this.portable?null:this.stat.nlink}).encode()),super.write(this.header.block)}[Gue](){this.path.substr(-1)!=="/"&&(this.path+="/"),this.stat.size=0,this[x1](),this.end()}[JU](){oA.readlink(this.absolute,(e,r)=>{if(e)return this.emit("error",e);this[$U](r)})}[$U](e){this.linkpath=sA(e),this[x1](),this.end()}[Yue](e){this.type="Link",this.linkpath=sA(Hue.relative(this.cwd,e)),this.stat.size=0,this[x1](),this.end()}[jue](){if(this.stat.nlink>1){let e=this.stat.dev+":"+this.stat.ino;if(this.linkCache.has(e)){let r=this.linkCache.get(e);if(r.indexOf(this.cwd)===0)return this[Yue](r)}this.linkCache.set(e,this.absolute)}if(this[x1](),this.stat.size===0)return this.end();this[e3]()}[e3](){oA.open(this.absolute,"r",(e,r)=>{if(e)return this.emit("error",e);this[t3](r)})}[t3](e){if(this.fd=e,this[Wue])return this[dh]();this.blockLen=512*Math.ceil(this.stat.size/512),this.blockRemain=this.blockLen;let r=Math.min(this.blockLen,this.maxReadSize);this.buf=Buffer.allocUnsafe(r),this.offset=0,this.pos=0,this.remain=this.stat.size,this.length=this.buf.length,this[Jb]()}[Jb](){let{fd:e,buf:r,offset:o,length:a,pos:n}=this;oA.read(e,r,o,a,n,(u,A)=>{if(u)return this[dh](()=>this.emit("error",u));this[ZU](A)})}[dh](e){oA.close(this.fd,e)}[ZU](e){if(e<=0&&this.remain>0){let a=new Error("encountered unexpected EOF");return a.path=this.absolute,a.syscall="read",a.code="EOF",this[dh](()=>this.emit("error",a))}if(e>this.remain){let a=new Error("did not encounter expected EOF");return a.path=this.absolute,a.syscall="read",a.code="EOF",this[dh](()=>this.emit("error",a))}if(e===this.remain)for(let a=e;a<this.length&&e<this.blockRemain;a++)this.buf[a+this.offset]=0,e++,this.remain++;let r=this.offset===0&&e===this.buf.length?this.buf:this.buf.slice(this.offset,this.offset+e);this.write(r)?this[zU]():this[r3](()=>this[zU]())}[r3](e){this.once("drain",e)}write(e){if(this.blockRemain<e.length){let r=new Error("writing more data than expected");return r.path=this.absolute,this.emit("error",r)}return this.remain-=e.length,this.blockRemain-=e.length,this.pos+=e.length,this.offset+=e.length,super.write(e)}[zU](){if(!this.remain)return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),this[dh](e=>e?this.emit("error",e):this.end());this.offset>=this.length&&(this.buf=Buffer.allocUnsafe(Math.min(this.blockRemain,this.buf.length)),this.offset=0),this.length=this.buf.length-this.offset,this[Jb]()}}),n3=class extends $b{[XU](){this[Xb](oA.lstatSync(this.absolute))}[JU](){this[$U](oA.readlinkSync(this.absolute))}[e3](){this[t3](oA.openSync(this.absolute,"r"))}[Jb](){let e=!0;try{let{fd:r,buf:o,offset:a,length:n,pos:u}=this,A=oA.readSync(r,o,a,n,u);this[ZU](A),e=!1}finally{if(e)try{this[dh](()=>{})}catch{}}}[r3](e){e()}[dh](e){oA.closeSync(this.fd),e()}},hlt=Xue(class extends Kue{constructor(e,r){r=r||{},super(r),this.preservePaths=!!r.preservePaths,this.portable=!!r.portable,this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.readEntry=e,this.type=e.type,this.type==="Directory"&&this.portable&&(this.noMtime=!0),this.prefix=r.prefix||null,this.path=sA(e.path),this.mode=this[Zb](e.mode),this.uid=this.portable?null:e.uid,this.gid=this.portable?null:e.gid,this.uname=this.portable?null:e.uname,this.gname=this.portable?null:e.gname,this.size=e.size,this.mtime=this.noMtime?null:r.mtime||e.mtime,this.atime=this.portable?null:e.atime,this.ctime=this.portable?null:e.ctime,this.linkpath=sA(e.linkpath),typeof r.onwarn=="function"&&this.on("warn",r.onwarn);let o=!1;if(!this.preservePaths){let[a,n]=Zue(this.path);a&&(this.path=n,o=a)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.header=new zue({path:this[aA](this.path),linkpath:this.type==="Link"?this[aA](this.linkpath):this.linkpath,mode:this.mode,uid:this.portable?null:this.uid,gid:this.portable?null:this.gid,size:this.size,mtime:this.noMtime?null:this.mtime,type:this.type,uname:this.portable?null:this.uname,atime:this.portable?null:this.atime,ctime:this.portable?null:this.ctime}),o&&this.warn("TAR_ENTRY_INFO",`stripping ${o} from absolute path`,{entry:this,path:o+this.path}),this.header.encode()&&!this.noPax&&super.write(new Vue({atime:this.portable?null:this.atime,ctime:this.portable?null:this.ctime,gid:this.portable?null:this.gid,mtime:this.noMtime?null:this.mtime,path:this[aA](this.path),linkpath:this.type==="Link"?this[aA](this.linkpath):this.linkpath,size:this.size,uid:this.portable?null:this.uid,uname:this.portable?null:this.uname,dev:this.portable?null:this.readEntry.dev,ino:this.portable?null:this.readEntry.ino,nlink:this.portable?null:this.readEntry.nlink}).encode()),super.write(this.header.block),e.pipe(this)}[aA](e){return Jue(e,this.prefix)}[Zb](e){return $ue(e,this.type==="Directory",this.portable)}write(e){let r=e.length;if(r>this.blockRemain)throw new Error("writing more to entry than is appropriate");return this.blockRemain-=r,super.write(e)}end(){return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),super.end()}});$b.Sync=n3;$b.Tar=hlt;var glt=t=>t.isFile()?"File":t.isDirectory()?"Directory":t.isSymbolicLink()?"SymbolicLink":"Unsupported";eAe.exports=$b});var lx=_((AUt,aAe)=>{"use strict";var ox=class{constructor(e,r){this.path=e||"./",this.absolute=r,this.entry=null,this.stat=null,this.readdir=null,this.pending=!1,this.ignore=!1,this.piped=!1}},dlt=py(),mlt=MU(),ylt=Yb(),p3=i3(),Elt=p3.Sync,Clt=p3.Tar,wlt=cP(),tAe=Buffer.alloc(1024),rx=Symbol("onStat"),ex=Symbol("ended"),lA=Symbol("queue"),Cy=Symbol("current"),kg=Symbol("process"),tx=Symbol("processing"),rAe=Symbol("processJob"),cA=Symbol("jobs"),s3=Symbol("jobDone"),nx=Symbol("addFSEntry"),nAe=Symbol("addTarEntry"),c3=Symbol("stat"),u3=Symbol("readdir"),ix=Symbol("onreaddir"),sx=Symbol("pipe"),iAe=Symbol("entry"),o3=Symbol("entryOpt"),A3=Symbol("writeEntryClass"),oAe=Symbol("write"),a3=Symbol("ondrain"),ax=ve("fs"),sAe=ve("path"),Ilt=Vb(),l3=dy(),h3=Ilt(class extends dlt{constructor(e){super(e),e=e||Object.create(null),this.opt=e,this.file=e.file||"",this.cwd=e.cwd||process.cwd(),this.maxReadSize=e.maxReadSize,this.preservePaths=!!e.preservePaths,this.strict=!!e.strict,this.noPax=!!e.noPax,this.prefix=l3(e.prefix||""),this.linkCache=e.linkCache||new Map,this.statCache=e.statCache||new Map,this.readdirCache=e.readdirCache||new Map,this[A3]=p3,typeof e.onwarn=="function"&&this.on("warn",e.onwarn),this.portable=!!e.portable,this.zip=null,e.gzip?(typeof e.gzip!="object"&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new mlt.Gzip(e.gzip),this.zip.on("data",r=>super.write(r)),this.zip.on("end",r=>super.end()),this.zip.on("drain",r=>this[a3]()),this.on("resume",r=>this.zip.resume())):this.on("drain",this[a3]),this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,this.mtime=e.mtime||null,this.filter=typeof e.filter=="function"?e.filter:r=>!0,this[lA]=new wlt,this[cA]=0,this.jobs=+e.jobs||4,this[tx]=!1,this[ex]=!1}[oAe](e){return super.write(e)}add(e){return this.write(e),this}end(e){return e&&this.write(e),this[ex]=!0,this[kg](),this}write(e){if(this[ex])throw new Error("write after end");return e instanceof ylt?this[nAe](e):this[nx](e),this.flowing}[nAe](e){let r=l3(sAe.resolve(this.cwd,e.path));if(!this.filter(e.path,e))e.resume();else{let o=new ox(e.path,r,!1);o.entry=new Clt(e,this[o3](o)),o.entry.on("end",a=>this[s3](o)),this[cA]+=1,this[lA].push(o)}this[kg]()}[nx](e){let r=l3(sAe.resolve(this.cwd,e));this[lA].push(new ox(e,r)),this[kg]()}[c3](e){e.pending=!0,this[cA]+=1;let r=this.follow?"stat":"lstat";ax[r](e.absolute,(o,a)=>{e.pending=!1,this[cA]-=1,o?this.emit("error",o):this[rx](e,a)})}[rx](e,r){this.statCache.set(e.absolute,r),e.stat=r,this.filter(e.path,r)||(e.ignore=!0),this[kg]()}[u3](e){e.pending=!0,this[cA]+=1,ax.readdir(e.absolute,(r,o)=>{if(e.pending=!1,this[cA]-=1,r)return this.emit("error",r);this[ix](e,o)})}[ix](e,r){this.readdirCache.set(e.absolute,r),e.readdir=r,this[kg]()}[kg](){if(!this[tx]){this[tx]=!0;for(let e=this[lA].head;e!==null&&this[cA]<this.jobs;e=e.next)if(this[rAe](e.value),e.value.ignore){let r=e.next;this[lA].removeNode(e),e.next=r}this[tx]=!1,this[ex]&&!this[lA].length&&this[cA]===0&&(this.zip?this.zip.end(tAe):(super.write(tAe),super.end()))}}get[Cy](){return this[lA]&&this[lA].head&&this[lA].head.value}[s3](e){this[lA].shift(),this[cA]-=1,this[kg]()}[rAe](e){if(!e.pending){if(e.entry){e===this[Cy]&&!e.piped&&this[sx](e);return}if(e.stat||(this.statCache.has(e.absolute)?this[rx](e,this.statCache.get(e.absolute)):this[c3](e)),!!e.stat&&!e.ignore&&!(!this.noDirRecurse&&e.stat.isDirectory()&&!e.readdir&&(this.readdirCache.has(e.absolute)?this[ix](e,this.readdirCache.get(e.absolute)):this[u3](e),!e.readdir))){if(e.entry=this[iAe](e),!e.entry){e.ignore=!0;return}e===this[Cy]&&!e.piped&&this[sx](e)}}}[o3](e){return{onwarn:(r,o,a)=>this.warn(r,o,a),noPax:this.noPax,cwd:this.cwd,absolute:e.absolute,preservePaths:this.preservePaths,maxReadSize:this.maxReadSize,strict:this.strict,portable:this.portable,linkCache:this.linkCache,statCache:this.statCache,noMtime:this.noMtime,mtime:this.mtime,prefix:this.prefix}}[iAe](e){this[cA]+=1;try{return new this[A3](e.path,this[o3](e)).on("end",()=>this[s3](e)).on("error",r=>this.emit("error",r))}catch(r){this.emit("error",r)}}[a3](){this[Cy]&&this[Cy].entry&&this[Cy].entry.resume()}[sx](e){e.piped=!0,e.readdir&&e.readdir.forEach(a=>{let n=e.path,u=n==="./"?"":n.replace(/\/*$/,"/");this[nx](u+a)});let r=e.entry,o=this.zip;o?r.on("data",a=>{o.write(a)||r.pause()}):r.on("data",a=>{super.write(a)||r.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}}),f3=class extends h3{constructor(e){super(e),this[A3]=Elt}pause(){}resume(){}[c3](e){let r=this.follow?"statSync":"lstatSync";this[rx](e,ax[r](e.absolute))}[u3](e,r){this[ix](e,ax.readdirSync(e.absolute))}[sx](e){let r=e.entry,o=this.zip;e.readdir&&e.readdir.forEach(a=>{let n=e.path,u=n==="./"?"":n.replace(/\/*$/,"/");this[nx](u+a)}),o?r.on("data",a=>{o.write(a)}):r.on("data",a=>{super[oAe](a)})}};h3.Sync=f3;aAe.exports=h3});var by=_(Q1=>{"use strict";var Blt=py(),vlt=ve("events").EventEmitter,Ra=ve("fs"),m3=Ra.writev;if(!m3){let t=process.binding("fs"),e=t.FSReqWrap||t.FSReqCallback;m3=(r,o,a,n)=>{let u=(p,h)=>n(p,h,o),A=new e;A.oncomplete=u,t.writeBuffers(r,o,a,A)}}var Py=Symbol("_autoClose"),Kc=Symbol("_close"),k1=Symbol("_ended"),Gn=Symbol("_fd"),lAe=Symbol("_finished"),yh=Symbol("_flags"),g3=Symbol("_flush"),y3=Symbol("_handleChunk"),E3=Symbol("_makeBuf"),px=Symbol("_mode"),cx=Symbol("_needDrain"),vy=Symbol("_onerror"),Sy=Symbol("_onopen"),d3=Symbol("_onread"),Iy=Symbol("_onwrite"),Eh=Symbol("_open"),_f=Symbol("_path"),Qg=Symbol("_pos"),uA=Symbol("_queue"),By=Symbol("_read"),cAe=Symbol("_readSize"),mh=Symbol("_reading"),ux=Symbol("_remain"),uAe=Symbol("_size"),Ax=Symbol("_write"),wy=Symbol("_writing"),fx=Symbol("_defaultFlag"),Dy=Symbol("_errored"),hx=class extends Blt{constructor(e,r){if(r=r||{},super(r),this.readable=!0,this.writable=!1,typeof e!="string")throw new TypeError("path must be a string");this[Dy]=!1,this[Gn]=typeof r.fd=="number"?r.fd:null,this[_f]=e,this[cAe]=r.readSize||16*1024*1024,this[mh]=!1,this[uAe]=typeof r.size=="number"?r.size:1/0,this[ux]=this[uAe],this[Py]=typeof r.autoClose=="boolean"?r.autoClose:!0,typeof this[Gn]=="number"?this[By]():this[Eh]()}get fd(){return this[Gn]}get path(){return this[_f]}write(){throw new TypeError("this is a readable stream")}end(){throw new TypeError("this is a readable stream")}[Eh](){Ra.open(this[_f],"r",(e,r)=>this[Sy](e,r))}[Sy](e,r){e?this[vy](e):(this[Gn]=r,this.emit("open",r),this[By]())}[E3](){return Buffer.allocUnsafe(Math.min(this[cAe],this[ux]))}[By](){if(!this[mh]){this[mh]=!0;let e=this[E3]();if(e.length===0)return process.nextTick(()=>this[d3](null,0,e));Ra.read(this[Gn],e,0,e.length,null,(r,o,a)=>this[d3](r,o,a))}}[d3](e,r,o){this[mh]=!1,e?this[vy](e):this[y3](r,o)&&this[By]()}[Kc](){if(this[Py]&&typeof this[Gn]=="number"){let e=this[Gn];this[Gn]=null,Ra.close(e,r=>r?this.emit("error",r):this.emit("close"))}}[vy](e){this[mh]=!0,this[Kc](),this.emit("error",e)}[y3](e,r){let o=!1;return this[ux]-=e,e>0&&(o=super.write(e<r.length?r.slice(0,e):r)),(e===0||this[ux]<=0)&&(o=!1,this[Kc](),super.end()),o}emit(e,r){switch(e){case"prefinish":case"finish":break;case"drain":typeof this[Gn]=="number"&&this[By]();break;case"error":return this[Dy]?void 0:(this[Dy]=!0,super.emit(e,r));default:return super.emit(e,r)}}},C3=class extends hx{[Eh](){let e=!0;try{this[Sy](null,Ra.openSync(this[_f],"r")),e=!1}finally{e&&this[Kc]()}}[By](){let e=!0;try{if(!this[mh]){this[mh]=!0;do{let r=this[E3](),o=r.length===0?0:Ra.readSync(this[Gn],r,0,r.length,null);if(!this[y3](o,r))break}while(!0);this[mh]=!1}e=!1}finally{e&&this[Kc]()}}[Kc](){if(this[Py]&&typeof this[Gn]=="number"){let e=this[Gn];this[Gn]=null,Ra.closeSync(e),this.emit("close")}}},gx=class extends vlt{constructor(e,r){r=r||{},super(r),this.readable=!1,this.writable=!0,this[Dy]=!1,this[wy]=!1,this[k1]=!1,this[cx]=!1,this[uA]=[],this[_f]=e,this[Gn]=typeof r.fd=="number"?r.fd:null,this[px]=r.mode===void 0?438:r.mode,this[Qg]=typeof r.start=="number"?r.start:null,this[Py]=typeof r.autoClose=="boolean"?r.autoClose:!0;let o=this[Qg]!==null?"r+":"w";this[fx]=r.flags===void 0,this[yh]=this[fx]?o:r.flags,this[Gn]===null&&this[Eh]()}emit(e,r){if(e==="error"){if(this[Dy])return;this[Dy]=!0}return super.emit(e,r)}get fd(){return this[Gn]}get path(){return this[_f]}[vy](e){this[Kc](),this[wy]=!0,this.emit("error",e)}[Eh](){Ra.open(this[_f],this[yh],this[px],(e,r)=>this[Sy](e,r))}[Sy](e,r){this[fx]&&this[yh]==="r+"&&e&&e.code==="ENOENT"?(this[yh]="w",this[Eh]()):e?this[vy](e):(this[Gn]=r,this.emit("open",r),this[g3]())}end(e,r){return e&&this.write(e,r),this[k1]=!0,!this[wy]&&!this[uA].length&&typeof this[Gn]=="number"&&this[Iy](null,0),this}write(e,r){return typeof e=="string"&&(e=Buffer.from(e,r)),this[k1]?(this.emit("error",new Error("write() after end()")),!1):this[Gn]===null||this[wy]||this[uA].length?(this[uA].push(e),this[cx]=!0,!1):(this[wy]=!0,this[Ax](e),!0)}[Ax](e){Ra.write(this[Gn],e,0,e.length,this[Qg],(r,o)=>this[Iy](r,o))}[Iy](e,r){e?this[vy](e):(this[Qg]!==null&&(this[Qg]+=r),this[uA].length?this[g3]():(this[wy]=!1,this[k1]&&!this[lAe]?(this[lAe]=!0,this[Kc](),this.emit("finish")):this[cx]&&(this[cx]=!1,this.emit("drain"))))}[g3](){if(this[uA].length===0)this[k1]&&this[Iy](null,0);else if(this[uA].length===1)this[Ax](this[uA].pop());else{let e=this[uA];this[uA]=[],m3(this[Gn],e,this[Qg],(r,o)=>this[Iy](r,o))}}[Kc](){if(this[Py]&&typeof this[Gn]=="number"){let e=this[Gn];this[Gn]=null,Ra.close(e,r=>r?this.emit("error",r):this.emit("close"))}}},w3=class extends gx{[Eh](){let e;if(this[fx]&&this[yh]==="r+")try{e=Ra.openSync(this[_f],this[yh],this[px])}catch(r){if(r.code==="ENOENT")return this[yh]="w",this[Eh]();throw r}else e=Ra.openSync(this[_f],this[yh],this[px]);this[Sy](null,e)}[Kc](){if(this[Py]&&typeof this[Gn]=="number"){let e=this[Gn];this[Gn]=null,Ra.closeSync(e),this.emit("close")}}[Ax](e){let r=!0;try{this[Iy](null,Ra.writeSync(this[Gn],e,0,e.length,this[Qg])),r=!1}finally{if(r)try{this[Kc]()}catch{}}}};Q1.ReadStream=hx;Q1.ReadStreamSync=C3;Q1.WriteStream=gx;Q1.WriteStreamSync=w3});var Ix=_((hUt,mAe)=>{"use strict";var Dlt=Vb(),Plt=yy(),Slt=ve("events"),blt=cP(),xlt=1024*1024,klt=Yb(),AAe=Kb(),Qlt=MU(),I3=Buffer.from([31,139]),Xl=Symbol("state"),Fg=Symbol("writeEntry"),Hf=Symbol("readEntry"),B3=Symbol("nextEntry"),fAe=Symbol("processEntry"),Zl=Symbol("extendedHeader"),F1=Symbol("globalExtendedHeader"),Ch=Symbol("meta"),pAe=Symbol("emitMeta"),fi=Symbol("buffer"),qf=Symbol("queue"),Rg=Symbol("ended"),hAe=Symbol("emittedEnd"),Tg=Symbol("emit"),Ta=Symbol("unzip"),dx=Symbol("consumeChunk"),mx=Symbol("consumeChunkSub"),v3=Symbol("consumeBody"),gAe=Symbol("consumeMeta"),dAe=Symbol("consumeHeader"),yx=Symbol("consuming"),D3=Symbol("bufferConcat"),P3=Symbol("maybeEnd"),R1=Symbol("writing"),wh=Symbol("aborted"),Ex=Symbol("onDone"),Ng=Symbol("sawValidEntry"),Cx=Symbol("sawNullBlock"),wx=Symbol("sawEOF"),Flt=t=>!0;mAe.exports=Dlt(class extends Slt{constructor(e){e=e||{},super(e),this.file=e.file||"",this[Ng]=null,this.on(Ex,r=>{(this[Xl]==="begin"||this[Ng]===!1)&&this.warn("TAR_BAD_ARCHIVE","Unrecognized archive format")}),e.ondone?this.on(Ex,e.ondone):this.on(Ex,r=>{this.emit("prefinish"),this.emit("finish"),this.emit("end"),this.emit("close")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||xlt,this.filter=typeof e.filter=="function"?e.filter:Flt,this.writable=!0,this.readable=!1,this[qf]=new blt,this[fi]=null,this[Hf]=null,this[Fg]=null,this[Xl]="begin",this[Ch]="",this[Zl]=null,this[F1]=null,this[Rg]=!1,this[Ta]=null,this[wh]=!1,this[Cx]=!1,this[wx]=!1,typeof e.onwarn=="function"&&this.on("warn",e.onwarn),typeof e.onentry=="function"&&this.on("entry",e.onentry)}[dAe](e,r){this[Ng]===null&&(this[Ng]=!1);let o;try{o=new Plt(e,r,this[Zl],this[F1])}catch(a){return this.warn("TAR_ENTRY_INVALID",a)}if(o.nullBlock)this[Cx]?(this[wx]=!0,this[Xl]==="begin"&&(this[Xl]="header"),this[Tg]("eof")):(this[Cx]=!0,this[Tg]("nullBlock"));else if(this[Cx]=!1,!o.cksumValid)this.warn("TAR_ENTRY_INVALID","checksum failure",{header:o});else if(!o.path)this.warn("TAR_ENTRY_INVALID","path is required",{header:o});else{let a=o.type;if(/^(Symbolic)?Link$/.test(a)&&!o.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath required",{header:o});else if(!/^(Symbolic)?Link$/.test(a)&&o.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath forbidden",{header:o});else{let n=this[Fg]=new klt(o,this[Zl],this[F1]);if(!this[Ng])if(n.remain){let u=()=>{n.invalid||(this[Ng]=!0)};n.on("end",u)}else this[Ng]=!0;n.meta?n.size>this.maxMetaEntrySize?(n.ignore=!0,this[Tg]("ignoredEntry",n),this[Xl]="ignore",n.resume()):n.size>0&&(this[Ch]="",n.on("data",u=>this[Ch]+=u),this[Xl]="meta"):(this[Zl]=null,n.ignore=n.ignore||!this.filter(n.path,n),n.ignore?(this[Tg]("ignoredEntry",n),this[Xl]=n.remain?"ignore":"header",n.resume()):(n.remain?this[Xl]="body":(this[Xl]="header",n.end()),this[Hf]?this[qf].push(n):(this[qf].push(n),this[B3]())))}}}[fAe](e){let r=!0;return e?Array.isArray(e)?this.emit.apply(this,e):(this[Hf]=e,this.emit("entry",e),e.emittedEnd||(e.on("end",o=>this[B3]()),r=!1)):(this[Hf]=null,r=!1),r}[B3](){do;while(this[fAe](this[qf].shift()));if(!this[qf].length){let e=this[Hf];!e||e.flowing||e.size===e.remain?this[R1]||this.emit("drain"):e.once("drain",o=>this.emit("drain"))}}[v3](e,r){let o=this[Fg],a=o.blockRemain,n=a>=e.length&&r===0?e:e.slice(r,r+a);return o.write(n),o.blockRemain||(this[Xl]="header",this[Fg]=null,o.end()),n.length}[gAe](e,r){let o=this[Fg],a=this[v3](e,r);return this[Fg]||this[pAe](o),a}[Tg](e,r,o){!this[qf].length&&!this[Hf]?this.emit(e,r,o):this[qf].push([e,r,o])}[pAe](e){switch(this[Tg]("meta",this[Ch]),e.type){case"ExtendedHeader":case"OldExtendedHeader":this[Zl]=AAe.parse(this[Ch],this[Zl],!1);break;case"GlobalExtendedHeader":this[F1]=AAe.parse(this[Ch],this[F1],!0);break;case"NextFileHasLongPath":case"OldGnuLongPath":this[Zl]=this[Zl]||Object.create(null),this[Zl].path=this[Ch].replace(/\0.*/,"");break;case"NextFileHasLongLinkpath":this[Zl]=this[Zl]||Object.create(null),this[Zl].linkpath=this[Ch].replace(/\0.*/,"");break;default:throw new Error("unknown meta: "+e.type)}}abort(e){this[wh]=!0,this.emit("abort",e),this.warn("TAR_ABORT",e,{recoverable:!1})}write(e){if(this[wh])return;if(this[Ta]===null&&e){if(this[fi]&&(e=Buffer.concat([this[fi],e]),this[fi]=null),e.length<I3.length)return this[fi]=e,!0;for(let o=0;this[Ta]===null&&o<I3.length;o++)e[o]!==I3[o]&&(this[Ta]=!1);if(this[Ta]===null){let o=this[Rg];this[Rg]=!1,this[Ta]=new Qlt.Unzip,this[Ta].on("data",n=>this[dx](n)),this[Ta].on("error",n=>this.abort(n)),this[Ta].on("end",n=>{this[Rg]=!0,this[dx]()}),this[R1]=!0;let a=this[Ta][o?"end":"write"](e);return this[R1]=!1,a}}this[R1]=!0,this[Ta]?this[Ta].write(e):this[dx](e),this[R1]=!1;let r=this[qf].length?!1:this[Hf]?this[Hf].flowing:!0;return!r&&!this[qf].length&&this[Hf].once("drain",o=>this.emit("drain")),r}[D3](e){e&&!this[wh]&&(this[fi]=this[fi]?Buffer.concat([this[fi],e]):e)}[P3](){if(this[Rg]&&!this[hAe]&&!this[wh]&&!this[yx]){this[hAe]=!0;let e=this[Fg];if(e&&e.blockRemain){let r=this[fi]?this[fi].length:0;this.warn("TAR_BAD_ARCHIVE",`Truncated input (needed ${e.blockRemain} more bytes, only ${r} available)`,{entry:e}),this[fi]&&e.write(this[fi]),e.end()}this[Tg](Ex)}}[dx](e){if(this[yx])this[D3](e);else if(!e&&!this[fi])this[P3]();else{if(this[yx]=!0,this[fi]){this[D3](e);let r=this[fi];this[fi]=null,this[mx](r)}else this[mx](e);for(;this[fi]&&this[fi].length>=512&&!this[wh]&&!this[wx];){let r=this[fi];this[fi]=null,this[mx](r)}this[yx]=!1}(!this[fi]||this[Rg])&&this[P3]()}[mx](e){let r=0,o=e.length;for(;r+512<=o&&!this[wh]&&!this[wx];)switch(this[Xl]){case"begin":case"header":this[dAe](e,r),r+=512;break;case"ignore":case"body":r+=this[v3](e,r);break;case"meta":r+=this[gAe](e,r);break;default:throw new Error("invalid state: "+this[Xl])}r<o&&(this[fi]?this[fi]=Buffer.concat([e.slice(r),this[fi]]):this[fi]=e.slice(r))}end(e){this[wh]||(this[Ta]?this[Ta].end(e):(this[Rg]=!0,this.write(e)))}})});var Bx=_((gUt,wAe)=>{"use strict";var Rlt=Ay(),EAe=Ix(),xy=ve("fs"),Tlt=by(),yAe=ve("path"),S3=Ey();wAe.exports=(t,e,r)=>{typeof t=="function"?(r=t,e=null,t={}):Array.isArray(t)&&(e=t,t={}),typeof e=="function"&&(r=e,e=null),e?e=Array.from(e):e=[];let o=Rlt(t);if(o.sync&&typeof r=="function")throw new TypeError("callback not supported for sync tar functions");if(!o.file&&typeof r=="function")throw new TypeError("callback only supported with file option");return e.length&&Llt(o,e),o.noResume||Nlt(o),o.file&&o.sync?Mlt(o):o.file?Olt(o,r):CAe(o)};var Nlt=t=>{let e=t.onentry;t.onentry=e?r=>{e(r),r.resume()}:r=>r.resume()},Llt=(t,e)=>{let r=new Map(e.map(n=>[S3(n),!0])),o=t.filter,a=(n,u)=>{let A=u||yAe.parse(n).root||".",p=n===A?!1:r.has(n)?r.get(n):a(yAe.dirname(n),A);return r.set(n,p),p};t.filter=o?(n,u)=>o(n,u)&&a(S3(n)):n=>a(S3(n))},Mlt=t=>{let e=CAe(t),r=t.file,o=!0,a;try{let n=xy.statSync(r),u=t.maxReadSize||16*1024*1024;if(n.size<u)e.end(xy.readFileSync(r));else{let A=0,p=Buffer.allocUnsafe(u);for(a=xy.openSync(r,"r");A<n.size;){let h=xy.readSync(a,p,0,u,A);A+=h,e.write(p.slice(0,h))}e.end()}o=!1}finally{if(o&&a)try{xy.closeSync(a)}catch{}}},Olt=(t,e)=>{let r=new EAe(t),o=t.maxReadSize||16*1024*1024,a=t.file,n=new Promise((u,A)=>{r.on("error",A),r.on("end",u),xy.stat(a,(p,h)=>{if(p)A(p);else{let E=new Tlt.ReadStream(a,{readSize:o,size:h.size});E.on("error",A),E.pipe(r)}})});return e?n.then(e,e):n},CAe=t=>new EAe(t)});var SAe=_((dUt,PAe)=>{"use strict";var Ult=Ay(),vx=lx(),IAe=by(),BAe=Bx(),vAe=ve("path");PAe.exports=(t,e,r)=>{if(typeof e=="function"&&(r=e),Array.isArray(t)&&(e=t,t={}),!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");e=Array.from(e);let o=Ult(t);if(o.sync&&typeof r=="function")throw new TypeError("callback not supported for sync tar functions");if(!o.file&&typeof r=="function")throw new TypeError("callback only supported with file option");return o.file&&o.sync?_lt(o,e):o.file?Hlt(o,e,r):o.sync?qlt(o,e):jlt(o,e)};var _lt=(t,e)=>{let r=new vx.Sync(t),o=new IAe.WriteStreamSync(t.file,{mode:t.mode||438});r.pipe(o),DAe(r,e)},Hlt=(t,e,r)=>{let o=new vx(t),a=new IAe.WriteStream(t.file,{mode:t.mode||438});o.pipe(a);let n=new Promise((u,A)=>{a.on("error",A),a.on("close",u),o.on("error",A)});return b3(o,e),r?n.then(r,r):n},DAe=(t,e)=>{e.forEach(r=>{r.charAt(0)==="@"?BAe({file:vAe.resolve(t.cwd,r.substr(1)),sync:!0,noResume:!0,onentry:o=>t.add(o)}):t.add(r)}),t.end()},b3=(t,e)=>{for(;e.length;){let r=e.shift();if(r.charAt(0)==="@")return BAe({file:vAe.resolve(t.cwd,r.substr(1)),noResume:!0,onentry:o=>t.add(o)}).then(o=>b3(t,e));t.add(r)}t.end()},qlt=(t,e)=>{let r=new vx.Sync(t);return DAe(r,e),r},jlt=(t,e)=>{let r=new vx(t);return b3(r,e),r}});var x3=_((mUt,TAe)=>{"use strict";var Glt=Ay(),bAe=lx(),fl=ve("fs"),xAe=by(),kAe=Bx(),QAe=ve("path"),FAe=yy();TAe.exports=(t,e,r)=>{let o=Glt(t);if(!o.file)throw new TypeError("file is required");if(o.gzip)throw new TypeError("cannot append to compressed archives");if(!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");return e=Array.from(e),o.sync?Ylt(o,e):Klt(o,e,r)};var Ylt=(t,e)=>{let r=new bAe.Sync(t),o=!0,a,n;try{try{a=fl.openSync(t.file,"r+")}catch(p){if(p.code==="ENOENT")a=fl.openSync(t.file,"w+");else throw p}let u=fl.fstatSync(a),A=Buffer.alloc(512);e:for(n=0;n<u.size;n+=512){for(let E=0,I=0;E<512;E+=I){if(I=fl.readSync(a,A,E,A.length-E,n+E),n===0&&A[0]===31&&A[1]===139)throw new Error("cannot append to compressed archives");if(!I)break e}let p=new FAe(A);if(!p.cksumValid)break;let h=512*Math.ceil(p.size/512);if(n+h+512>u.size)break;n+=h,t.mtimeCache&&t.mtimeCache.set(p.path,p.mtime)}o=!1,Wlt(t,r,n,a,e)}finally{if(o)try{fl.closeSync(a)}catch{}}},Wlt=(t,e,r,o,a)=>{let n=new xAe.WriteStreamSync(t.file,{fd:o,start:r});e.pipe(n),Vlt(e,a)},Klt=(t,e,r)=>{e=Array.from(e);let o=new bAe(t),a=(u,A,p)=>{let h=(C,R)=>{C?fl.close(u,L=>p(C)):p(null,R)},E=0;if(A===0)return h(null,0);let I=0,v=Buffer.alloc(512),x=(C,R)=>{if(C)return h(C);if(I+=R,I<512&&R)return fl.read(u,v,I,v.length-I,E+I,x);if(E===0&&v[0]===31&&v[1]===139)return h(new Error("cannot append to compressed archives"));if(I<512)return h(null,E);let L=new FAe(v);if(!L.cksumValid)return h(null,E);let U=512*Math.ceil(L.size/512);if(E+U+512>A||(E+=U+512,E>=A))return h(null,E);t.mtimeCache&&t.mtimeCache.set(L.path,L.mtime),I=0,fl.read(u,v,0,512,E,x)};fl.read(u,v,0,512,E,x)},n=new Promise((u,A)=>{o.on("error",A);let p="r+",h=(E,I)=>{if(E&&E.code==="ENOENT"&&p==="r+")return p="w+",fl.open(t.file,p,h);if(E)return A(E);fl.fstat(I,(v,x)=>{if(v)return fl.close(I,()=>A(v));a(I,x.size,(C,R)=>{if(C)return A(C);let L=new xAe.WriteStream(t.file,{fd:I,start:R});o.pipe(L),L.on("error",A),L.on("close",u),RAe(o,e)})})};fl.open(t.file,p,h)});return r?n.then(r,r):n},Vlt=(t,e)=>{e.forEach(r=>{r.charAt(0)==="@"?kAe({file:QAe.resolve(t.cwd,r.substr(1)),sync:!0,noResume:!0,onentry:o=>t.add(o)}):t.add(r)}),t.end()},RAe=(t,e)=>{for(;e.length;){let r=e.shift();if(r.charAt(0)==="@")return kAe({file:QAe.resolve(t.cwd,r.substr(1)),noResume:!0,onentry:o=>t.add(o)}).then(o=>RAe(t,e));t.add(r)}t.end()}});var LAe=_((yUt,NAe)=>{"use strict";var zlt=Ay(),Jlt=x3();NAe.exports=(t,e,r)=>{let o=zlt(t);if(!o.file)throw new TypeError("file is required");if(o.gzip)throw new TypeError("cannot append to compressed archives");if(!e||!Array.isArray(e)||!e.length)throw new TypeError("no files or directories specified");return e=Array.from(e),Xlt(o),Jlt(o,e,r)};var Xlt=t=>{let e=t.filter;t.mtimeCache||(t.mtimeCache=new Map),t.filter=e?(r,o)=>e(r,o)&&!(t.mtimeCache.get(r)>o.mtime):(r,o)=>!(t.mtimeCache.get(r)>o.mtime)}});var UAe=_((EUt,OAe)=>{var{promisify:MAe}=ve("util"),Ih=ve("fs"),Zlt=t=>{if(!t)t={mode:511,fs:Ih};else if(typeof t=="object")t={mode:511,fs:Ih,...t};else if(typeof t=="number")t={mode:t,fs:Ih};else if(typeof t=="string")t={mode:parseInt(t,8),fs:Ih};else throw new TypeError("invalid options argument");return t.mkdir=t.mkdir||t.fs.mkdir||Ih.mkdir,t.mkdirAsync=MAe(t.mkdir),t.stat=t.stat||t.fs.stat||Ih.stat,t.statAsync=MAe(t.stat),t.statSync=t.statSync||t.fs.statSync||Ih.statSync,t.mkdirSync=t.mkdirSync||t.fs.mkdirSync||Ih.mkdirSync,t};OAe.exports=Zlt});var HAe=_((CUt,_Ae)=>{var $lt=process.platform,{resolve:ect,parse:tct}=ve("path"),rct=t=>{if(/\0/.test(t))throw Object.assign(new TypeError("path must be a string without null bytes"),{path:t,code:"ERR_INVALID_ARG_VALUE"});if(t=ect(t),$lt==="win32"){let e=/[*|"<>?:]/,{root:r}=tct(t);if(e.test(t.substr(r.length)))throw Object.assign(new Error("Illegal characters in path."),{path:t,code:"EINVAL"})}return t};_Ae.exports=rct});var WAe=_((wUt,YAe)=>{var{dirname:qAe}=ve("path"),jAe=(t,e,r=void 0)=>r===e?Promise.resolve():t.statAsync(e).then(o=>o.isDirectory()?r:void 0,o=>o.code==="ENOENT"?jAe(t,qAe(e),e):void 0),GAe=(t,e,r=void 0)=>{if(r!==e)try{return t.statSync(e).isDirectory()?r:void 0}catch(o){return o.code==="ENOENT"?GAe(t,qAe(e),e):void 0}};YAe.exports={findMade:jAe,findMadeSync:GAe}});var F3=_((IUt,VAe)=>{var{dirname:KAe}=ve("path"),k3=(t,e,r)=>{e.recursive=!1;let o=KAe(t);return o===t?e.mkdirAsync(t,e).catch(a=>{if(a.code!=="EISDIR")throw a}):e.mkdirAsync(t,e).then(()=>r||t,a=>{if(a.code==="ENOENT")return k3(o,e).then(n=>k3(t,e,n));if(a.code!=="EEXIST"&&a.code!=="EROFS")throw a;return e.statAsync(t).then(n=>{if(n.isDirectory())return r;throw a},()=>{throw a})})},Q3=(t,e,r)=>{let o=KAe(t);if(e.recursive=!1,o===t)try{return e.mkdirSync(t,e)}catch(a){if(a.code!=="EISDIR")throw a;return}try{return e.mkdirSync(t,e),r||t}catch(a){if(a.code==="ENOENT")return Q3(t,e,Q3(o,e,r));if(a.code!=="EEXIST"&&a.code!=="EROFS")throw a;try{if(!e.statSync(t).isDirectory())throw a}catch{throw a}}};VAe.exports={mkdirpManual:k3,mkdirpManualSync:Q3}});var XAe=_((BUt,JAe)=>{var{dirname:zAe}=ve("path"),{findMade:nct,findMadeSync:ict}=WAe(),{mkdirpManual:sct,mkdirpManualSync:oct}=F3(),act=(t,e)=>(e.recursive=!0,zAe(t)===t?e.mkdirAsync(t,e):nct(e,t).then(o=>e.mkdirAsync(t,e).then(()=>o).catch(a=>{if(a.code==="ENOENT")return sct(t,e);throw a}))),lct=(t,e)=>{if(e.recursive=!0,zAe(t)===t)return e.mkdirSync(t,e);let o=ict(e,t);try{return e.mkdirSync(t,e),o}catch(a){if(a.code==="ENOENT")return oct(t,e);throw a}};JAe.exports={mkdirpNative:act,mkdirpNativeSync:lct}});var tfe=_((vUt,efe)=>{var ZAe=ve("fs"),cct=process.version,R3=cct.replace(/^v/,"").split("."),$Ae=+R3[0]>10||+R3[0]==10&&+R3[1]>=12,uct=$Ae?t=>t.mkdir===ZAe.mkdir:()=>!1,Act=$Ae?t=>t.mkdirSync===ZAe.mkdirSync:()=>!1;efe.exports={useNative:uct,useNativeSync:Act}});var afe=_((DUt,ofe)=>{var ky=UAe(),Qy=HAe(),{mkdirpNative:rfe,mkdirpNativeSync:nfe}=XAe(),{mkdirpManual:ife,mkdirpManualSync:sfe}=F3(),{useNative:fct,useNativeSync:pct}=tfe(),Fy=(t,e)=>(t=Qy(t),e=ky(e),fct(e)?rfe(t,e):ife(t,e)),hct=(t,e)=>(t=Qy(t),e=ky(e),pct(e)?nfe(t,e):sfe(t,e));Fy.sync=hct;Fy.native=(t,e)=>rfe(Qy(t),ky(e));Fy.manual=(t,e)=>ife(Qy(t),ky(e));Fy.nativeSync=(t,e)=>nfe(Qy(t),ky(e));Fy.manualSync=(t,e)=>sfe(Qy(t),ky(e));ofe.exports=Fy});var hfe=_((PUt,pfe)=>{"use strict";var $l=ve("fs"),Lg=ve("path"),gct=$l.lchown?"lchown":"chown",dct=$l.lchownSync?"lchownSync":"chownSync",cfe=$l.lchown&&!process.version.match(/v1[1-9]+\./)&&!process.version.match(/v10\.[6-9]/),lfe=(t,e,r)=>{try{return $l[dct](t,e,r)}catch(o){if(o.code!=="ENOENT")throw o}},mct=(t,e,r)=>{try{return $l.chownSync(t,e,r)}catch(o){if(o.code!=="ENOENT")throw o}},yct=cfe?(t,e,r,o)=>a=>{!a||a.code!=="EISDIR"?o(a):$l.chown(t,e,r,o)}:(t,e,r,o)=>o,T3=cfe?(t,e,r)=>{try{return lfe(t,e,r)}catch(o){if(o.code!=="EISDIR")throw o;mct(t,e,r)}}:(t,e,r)=>lfe(t,e,r),Ect=process.version,ufe=(t,e,r)=>$l.readdir(t,e,r),Cct=(t,e)=>$l.readdirSync(t,e);/^v4\./.test(Ect)&&(ufe=(t,e,r)=>$l.readdir(t,r));var Dx=(t,e,r,o)=>{$l[gct](t,e,r,yct(t,e,r,a=>{o(a&&a.code!=="ENOENT"?a:null)}))},Afe=(t,e,r,o,a)=>{if(typeof e=="string")return $l.lstat(Lg.resolve(t,e),(n,u)=>{if(n)return a(n.code!=="ENOENT"?n:null);u.name=e,Afe(t,u,r,o,a)});if(e.isDirectory())N3(Lg.resolve(t,e.name),r,o,n=>{if(n)return a(n);let u=Lg.resolve(t,e.name);Dx(u,r,o,a)});else{let n=Lg.resolve(t,e.name);Dx(n,r,o,a)}},N3=(t,e,r,o)=>{ufe(t,{withFileTypes:!0},(a,n)=>{if(a){if(a.code==="ENOENT")return o();if(a.code!=="ENOTDIR"&&a.code!=="ENOTSUP")return o(a)}if(a||!n.length)return Dx(t,e,r,o);let u=n.length,A=null,p=h=>{if(!A){if(h)return o(A=h);if(--u===0)return Dx(t,e,r,o)}};n.forEach(h=>Afe(t,h,e,r,p))})},wct=(t,e,r,o)=>{if(typeof e=="string")try{let a=$l.lstatSync(Lg.resolve(t,e));a.name=e,e=a}catch(a){if(a.code==="ENOENT")return;throw a}e.isDirectory()&&ffe(Lg.resolve(t,e.name),r,o),T3(Lg.resolve(t,e.name),r,o)},ffe=(t,e,r)=>{let o;try{o=Cct(t,{withFileTypes:!0})}catch(a){if(a.code==="ENOENT")return;if(a.code==="ENOTDIR"||a.code==="ENOTSUP")return T3(t,e,r);throw a}return o&&o.length&&o.forEach(a=>wct(t,a,e,r)),T3(t,e,r)};pfe.exports=N3;N3.sync=ffe});var yfe=_((SUt,L3)=>{"use strict";var gfe=afe(),ec=ve("fs"),Px=ve("path"),dfe=hfe(),Vc=dy(),Sx=class extends Error{constructor(e,r){super("Cannot extract through symbolic link"),this.path=r,this.symlink=e}get name(){return"SylinkError"}},bx=class extends Error{constructor(e,r){super(r+": Cannot cd into '"+e+"'"),this.path=e,this.code=r}get name(){return"CwdError"}},xx=(t,e)=>t.get(Vc(e)),T1=(t,e,r)=>t.set(Vc(e),r),Ict=(t,e)=>{ec.stat(t,(r,o)=>{(r||!o.isDirectory())&&(r=new bx(t,r&&r.code||"ENOTDIR")),e(r)})};L3.exports=(t,e,r)=>{t=Vc(t);let o=e.umask,a=e.mode|448,n=(a&o)!==0,u=e.uid,A=e.gid,p=typeof u=="number"&&typeof A=="number"&&(u!==e.processUid||A!==e.processGid),h=e.preserve,E=e.unlink,I=e.cache,v=Vc(e.cwd),x=(L,U)=>{L?r(L):(T1(I,t,!0),U&&p?dfe(U,u,A,z=>x(z)):n?ec.chmod(t,a,r):r())};if(I&&xx(I,t)===!0)return x();if(t===v)return Ict(t,x);if(h)return gfe(t,{mode:a}).then(L=>x(null,L),x);let R=Vc(Px.relative(v,t)).split("/");kx(v,R,a,I,E,v,null,x)};var kx=(t,e,r,o,a,n,u,A)=>{if(!e.length)return A(null,u);let p=e.shift(),h=Vc(Px.resolve(t+"/"+p));if(xx(o,h))return kx(h,e,r,o,a,n,u,A);ec.mkdir(h,r,mfe(h,e,r,o,a,n,u,A))},mfe=(t,e,r,o,a,n,u,A)=>p=>{p?ec.lstat(t,(h,E)=>{if(h)h.path=h.path&&Vc(h.path),A(h);else if(E.isDirectory())kx(t,e,r,o,a,n,u,A);else if(a)ec.unlink(t,I=>{if(I)return A(I);ec.mkdir(t,r,mfe(t,e,r,o,a,n,u,A))});else{if(E.isSymbolicLink())return A(new Sx(t,t+"/"+e.join("/")));A(p)}}):(u=u||t,kx(t,e,r,o,a,n,u,A))},Bct=t=>{let e=!1,r="ENOTDIR";try{e=ec.statSync(t).isDirectory()}catch(o){r=o.code}finally{if(!e)throw new bx(t,r)}};L3.exports.sync=(t,e)=>{t=Vc(t);let r=e.umask,o=e.mode|448,a=(o&r)!==0,n=e.uid,u=e.gid,A=typeof n=="number"&&typeof u=="number"&&(n!==e.processUid||u!==e.processGid),p=e.preserve,h=e.unlink,E=e.cache,I=Vc(e.cwd),v=L=>{T1(E,t,!0),L&&A&&dfe.sync(L,n,u),a&&ec.chmodSync(t,o)};if(E&&xx(E,t)===!0)return v();if(t===I)return Bct(I),v();if(p)return v(gfe.sync(t,o));let C=Vc(Px.relative(I,t)).split("/"),R=null;for(let L=C.shift(),U=I;L&&(U+="/"+L);L=C.shift())if(U=Vc(Px.resolve(U)),!xx(E,U))try{ec.mkdirSync(U,o),R=R||U,T1(E,U,!0)}catch{let te=ec.lstatSync(U);if(te.isDirectory()){T1(E,U,!0);continue}else if(h){ec.unlinkSync(U),ec.mkdirSync(U,o),R=R||U,T1(E,U,!0);continue}else if(te.isSymbolicLink())return new Sx(U,U+"/"+C.join("/"))}return v(R)}});var O3=_((bUt,Efe)=>{var M3=Object.create(null),{hasOwnProperty:vct}=Object.prototype;Efe.exports=t=>(vct.call(M3,t)||(M3[t]=t.normalize("NFKD")),M3[t])});var Bfe=_((xUt,Ife)=>{var Cfe=ve("assert"),Dct=O3(),Pct=Ey(),{join:wfe}=ve("path"),Sct=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,bct=Sct==="win32";Ife.exports=()=>{let t=new Map,e=new Map,r=h=>h.split("/").slice(0,-1).reduce((I,v)=>(I.length&&(v=wfe(I[I.length-1],v)),I.push(v||"/"),I),[]),o=new Set,a=h=>{let E=e.get(h);if(!E)throw new Error("function does not have any path reservations");return{paths:E.paths.map(I=>t.get(I)),dirs:[...E.dirs].map(I=>t.get(I))}},n=h=>{let{paths:E,dirs:I}=a(h);return E.every(v=>v[0]===h)&&I.every(v=>v[0]instanceof Set&&v[0].has(h))},u=h=>o.has(h)||!n(h)?!1:(o.add(h),h(()=>A(h)),!0),A=h=>{if(!o.has(h))return!1;let{paths:E,dirs:I}=e.get(h),v=new Set;return E.forEach(x=>{let C=t.get(x);Cfe.equal(C[0],h),C.length===1?t.delete(x):(C.shift(),typeof C[0]=="function"?v.add(C[0]):C[0].forEach(R=>v.add(R)))}),I.forEach(x=>{let C=t.get(x);Cfe(C[0]instanceof Set),C[0].size===1&&C.length===1?t.delete(x):C[0].size===1?(C.shift(),v.add(C[0])):C[0].delete(h)}),o.delete(h),v.forEach(x=>u(x)),!0};return{check:n,reserve:(h,E)=>{h=bct?["win32 parallelization disabled"]:h.map(v=>Dct(Pct(wfe(v))).toLowerCase());let I=new Set(h.map(v=>r(v)).reduce((v,x)=>v.concat(x)));return e.set(E,{dirs:I,paths:h}),h.forEach(v=>{let x=t.get(v);x?x.push(E):t.set(v,[E])}),I.forEach(v=>{let x=t.get(v);x?x[x.length-1]instanceof Set?x[x.length-1].add(E):x.push(new Set([E])):t.set(v,[new Set([E])])}),u(E)}}}});var Pfe=_((kUt,Dfe)=>{var xct=process.platform,kct=xct==="win32",Qct=global.__FAKE_TESTING_FS__||ve("fs"),{O_CREAT:Fct,O_TRUNC:Rct,O_WRONLY:Tct,UV_FS_O_FILEMAP:vfe=0}=Qct.constants,Nct=kct&&!!vfe,Lct=512*1024,Mct=vfe|Rct|Fct|Tct;Dfe.exports=Nct?t=>t<Lct?Mct:"w":()=>"w"});var K3=_((QUt,_fe)=>{"use strict";var Oct=ve("assert"),Uct=Ix(),vn=ve("fs"),_ct=by(),jf=ve("path"),Mfe=yfe(),Sfe=KU(),Hct=Bfe(),qct=VU(),pl=dy(),jct=Ey(),Gct=O3(),bfe=Symbol("onEntry"),H3=Symbol("checkFs"),xfe=Symbol("checkFs2"),Rx=Symbol("pruneCache"),q3=Symbol("isReusable"),tc=Symbol("makeFs"),j3=Symbol("file"),G3=Symbol("directory"),Tx=Symbol("link"),kfe=Symbol("symlink"),Qfe=Symbol("hardlink"),Ffe=Symbol("unsupported"),Rfe=Symbol("checkPath"),Bh=Symbol("mkdir"),To=Symbol("onError"),Qx=Symbol("pending"),Tfe=Symbol("pend"),Ry=Symbol("unpend"),U3=Symbol("ended"),_3=Symbol("maybeClose"),Y3=Symbol("skip"),N1=Symbol("doChown"),L1=Symbol("uid"),M1=Symbol("gid"),O1=Symbol("checkedCwd"),Ofe=ve("crypto"),Ufe=Pfe(),Yct=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,U1=Yct==="win32",Wct=(t,e)=>{if(!U1)return vn.unlink(t,e);let r=t+".DELETE."+Ofe.randomBytes(16).toString("hex");vn.rename(t,r,o=>{if(o)return e(o);vn.unlink(r,e)})},Kct=t=>{if(!U1)return vn.unlinkSync(t);let e=t+".DELETE."+Ofe.randomBytes(16).toString("hex");vn.renameSync(t,e),vn.unlinkSync(e)},Nfe=(t,e,r)=>t===t>>>0?t:e===e>>>0?e:r,Lfe=t=>Gct(jct(pl(t))).toLowerCase(),Vct=(t,e)=>{e=Lfe(e);for(let r of t.keys()){let o=Lfe(r);(o===e||o.indexOf(e+"/")===0)&&t.delete(r)}},zct=t=>{for(let e of t.keys())t.delete(e)},_1=class extends Uct{constructor(e){if(e||(e={}),e.ondone=r=>{this[U3]=!0,this[_3]()},super(e),this[O1]=!1,this.reservations=Hct(),this.transform=typeof e.transform=="function"?e.transform:null,this.writable=!0,this.readable=!1,this[Qx]=0,this[U3]=!1,this.dirCache=e.dirCache||new Map,typeof e.uid=="number"||typeof e.gid=="number"){if(typeof e.uid!="number"||typeof e.gid!="number")throw new TypeError("cannot set owner without number uid and gid");if(e.preserveOwner)throw new TypeError("cannot preserve owner in archive and also set owner explicitly");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=null,this.gid=null,this.setOwner=!1;e.preserveOwner===void 0&&typeof e.uid!="number"?this.preserveOwner=process.getuid&&process.getuid()===0:this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():null,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():null,this.forceChown=e.forceChown===!0,this.win32=!!e.win32||U1,this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=pl(jf.resolve(e.cwd||process.cwd())),this.strip=+e.strip||0,this.processUmask=e.noChmod?0:process.umask(),this.umask=typeof e.umask=="number"?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on("entry",r=>this[bfe](r))}warn(e,r,o={}){return(e==="TAR_BAD_ARCHIVE"||e==="TAR_ABORT")&&(o.recoverable=!1),super.warn(e,r,o)}[_3](){this[U3]&&this[Qx]===0&&(this.emit("prefinish"),this.emit("finish"),this.emit("end"),this.emit("close"))}[Rfe](e){if(this.strip){let r=pl(e.path).split("/");if(r.length<this.strip)return!1;if(e.path=r.slice(this.strip).join("/"),e.type==="Link"){let o=pl(e.linkpath).split("/");if(o.length>=this.strip)e.linkpath=o.slice(this.strip).join("/");else return!1}}if(!this.preservePaths){let r=pl(e.path),o=r.split("/");if(o.includes("..")||U1&&/^[a-z]:\.\.$/i.test(o[0]))return this.warn("TAR_ENTRY_ERROR","path contains '..'",{entry:e,path:r}),!1;let[a,n]=qct(r);a&&(e.path=n,this.warn("TAR_ENTRY_INFO",`stripping ${a} from absolute path`,{entry:e,path:r}))}if(jf.isAbsolute(e.path)?e.absolute=pl(jf.resolve(e.path)):e.absolute=pl(jf.resolve(this.cwd,e.path)),!this.preservePaths&&e.absolute.indexOf(this.cwd+"/")!==0&&e.absolute!==this.cwd)return this.warn("TAR_ENTRY_ERROR","path escaped extraction target",{entry:e,path:pl(e.path),resolvedPath:e.absolute,cwd:this.cwd}),!1;if(e.absolute===this.cwd&&e.type!=="Directory"&&e.type!=="GNUDumpDir")return!1;if(this.win32){let{root:r}=jf.win32.parse(e.absolute);e.absolute=r+Sfe.encode(e.absolute.substr(r.length));let{root:o}=jf.win32.parse(e.path);e.path=o+Sfe.encode(e.path.substr(o.length))}return!0}[bfe](e){if(!this[Rfe](e))return e.resume();switch(Oct.equal(typeof e.absolute,"string"),e.type){case"Directory":case"GNUDumpDir":e.mode&&(e.mode=e.mode|448);case"File":case"OldFile":case"ContiguousFile":case"Link":case"SymbolicLink":return this[H3](e);case"CharacterDevice":case"BlockDevice":case"FIFO":default:return this[Ffe](e)}}[To](e,r){e.name==="CwdError"?this.emit("error",e):(this.warn("TAR_ENTRY_ERROR",e,{entry:r}),this[Ry](),r.resume())}[Bh](e,r,o){Mfe(pl(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cache:this.dirCache,cwd:this.cwd,mode:r,noChmod:this.noChmod},o)}[N1](e){return this.forceChown||this.preserveOwner&&(typeof e.uid=="number"&&e.uid!==this.processUid||typeof e.gid=="number"&&e.gid!==this.processGid)||typeof this.uid=="number"&&this.uid!==this.processUid||typeof this.gid=="number"&&this.gid!==this.processGid}[L1](e){return Nfe(this.uid,e.uid,this.processUid)}[M1](e){return Nfe(this.gid,e.gid,this.processGid)}[j3](e,r){let o=e.mode&4095||this.fmode,a=new _ct.WriteStream(e.absolute,{flags:Ufe(e.size),mode:o,autoClose:!1});a.on("error",p=>{a.fd&&vn.close(a.fd,()=>{}),a.write=()=>!0,this[To](p,e),r()});let n=1,u=p=>{if(p){a.fd&&vn.close(a.fd,()=>{}),this[To](p,e),r();return}--n===0&&vn.close(a.fd,h=>{h?this[To](h,e):this[Ry](),r()})};a.on("finish",p=>{let h=e.absolute,E=a.fd;if(e.mtime&&!this.noMtime){n++;let I=e.atime||new Date,v=e.mtime;vn.futimes(E,I,v,x=>x?vn.utimes(h,I,v,C=>u(C&&x)):u())}if(this[N1](e)){n++;let I=this[L1](e),v=this[M1](e);vn.fchown(E,I,v,x=>x?vn.chown(h,I,v,C=>u(C&&x)):u())}u()});let A=this.transform&&this.transform(e)||e;A!==e&&(A.on("error",p=>{this[To](p,e),r()}),e.pipe(A)),A.pipe(a)}[G3](e,r){let o=e.mode&4095||this.dmode;this[Bh](e.absolute,o,a=>{if(a){this[To](a,e),r();return}let n=1,u=A=>{--n===0&&(r(),this[Ry](),e.resume())};e.mtime&&!this.noMtime&&(n++,vn.utimes(e.absolute,e.atime||new Date,e.mtime,u)),this[N1](e)&&(n++,vn.chown(e.absolute,this[L1](e),this[M1](e),u)),u()})}[Ffe](e){e.unsupported=!0,this.warn("TAR_ENTRY_UNSUPPORTED",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[kfe](e,r){this[Tx](e,e.linkpath,"symlink",r)}[Qfe](e,r){let o=pl(jf.resolve(this.cwd,e.linkpath));this[Tx](e,o,"link",r)}[Tfe](){this[Qx]++}[Ry](){this[Qx]--,this[_3]()}[Y3](e){this[Ry](),e.resume()}[q3](e,r){return e.type==="File"&&!this.unlink&&r.isFile()&&r.nlink<=1&&!U1}[H3](e){this[Tfe]();let r=[e.path];e.linkpath&&r.push(e.linkpath),this.reservations.reserve(r,o=>this[xfe](e,o))}[Rx](e){e.type==="SymbolicLink"?zct(this.dirCache):e.type!=="Directory"&&Vct(this.dirCache,e.absolute)}[xfe](e,r){this[Rx](e);let o=A=>{this[Rx](e),r(A)},a=()=>{this[Bh](this.cwd,this.dmode,A=>{if(A){this[To](A,e),o();return}this[O1]=!0,n()})},n=()=>{if(e.absolute!==this.cwd){let A=pl(jf.dirname(e.absolute));if(A!==this.cwd)return this[Bh](A,this.dmode,p=>{if(p){this[To](p,e),o();return}u()})}u()},u=()=>{vn.lstat(e.absolute,(A,p)=>{if(p&&(this.keep||this.newer&&p.mtime>e.mtime)){this[Y3](e),o();return}if(A||this[q3](e,p))return this[tc](null,e,o);if(p.isDirectory()){if(e.type==="Directory"){let h=!this.noChmod&&e.mode&&(p.mode&4095)!==e.mode,E=I=>this[tc](I,e,o);return h?vn.chmod(e.absolute,e.mode,E):E()}if(e.absolute!==this.cwd)return vn.rmdir(e.absolute,h=>this[tc](h,e,o))}if(e.absolute===this.cwd)return this[tc](null,e,o);Wct(e.absolute,h=>this[tc](h,e,o))})};this[O1]?n():a()}[tc](e,r,o){if(e){this[To](e,r),o();return}switch(r.type){case"File":case"OldFile":case"ContiguousFile":return this[j3](r,o);case"Link":return this[Qfe](r,o);case"SymbolicLink":return this[kfe](r,o);case"Directory":case"GNUDumpDir":return this[G3](r,o)}}[Tx](e,r,o,a){vn[o](r,e.absolute,n=>{n?this[To](n,e):(this[Ry](),e.resume()),a()})}},Fx=t=>{try{return[null,t()]}catch(e){return[e,null]}},W3=class extends _1{[tc](e,r){return super[tc](e,r,()=>{})}[H3](e){if(this[Rx](e),!this[O1]){let n=this[Bh](this.cwd,this.dmode);if(n)return this[To](n,e);this[O1]=!0}if(e.absolute!==this.cwd){let n=pl(jf.dirname(e.absolute));if(n!==this.cwd){let u=this[Bh](n,this.dmode);if(u)return this[To](u,e)}}let[r,o]=Fx(()=>vn.lstatSync(e.absolute));if(o&&(this.keep||this.newer&&o.mtime>e.mtime))return this[Y3](e);if(r||this[q3](e,o))return this[tc](null,e);if(o.isDirectory()){if(e.type==="Directory"){let u=!this.noChmod&&e.mode&&(o.mode&4095)!==e.mode,[A]=u?Fx(()=>{vn.chmodSync(e.absolute,e.mode)}):[];return this[tc](A,e)}let[n]=Fx(()=>vn.rmdirSync(e.absolute));this[tc](n,e)}let[a]=e.absolute===this.cwd?[]:Fx(()=>Kct(e.absolute));this[tc](a,e)}[j3](e,r){let o=e.mode&4095||this.fmode,a=A=>{let p;try{vn.closeSync(n)}catch(h){p=h}(A||p)&&this[To](A||p,e),r()},n;try{n=vn.openSync(e.absolute,Ufe(e.size),o)}catch(A){return a(A)}let u=this.transform&&this.transform(e)||e;u!==e&&(u.on("error",A=>this[To](A,e)),e.pipe(u)),u.on("data",A=>{try{vn.writeSync(n,A,0,A.length)}catch(p){a(p)}}),u.on("end",A=>{let p=null;if(e.mtime&&!this.noMtime){let h=e.atime||new Date,E=e.mtime;try{vn.futimesSync(n,h,E)}catch(I){try{vn.utimesSync(e.absolute,h,E)}catch{p=I}}}if(this[N1](e)){let h=this[L1](e),E=this[M1](e);try{vn.fchownSync(n,h,E)}catch(I){try{vn.chownSync(e.absolute,h,E)}catch{p=p||I}}}a(p)})}[G3](e,r){let o=e.mode&4095||this.dmode,a=this[Bh](e.absolute,o);if(a){this[To](a,e),r();return}if(e.mtime&&!this.noMtime)try{vn.utimesSync(e.absolute,e.atime||new Date,e.mtime)}catch{}if(this[N1](e))try{vn.chownSync(e.absolute,this[L1](e),this[M1](e))}catch{}r(),e.resume()}[Bh](e,r){try{return Mfe.sync(pl(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cache:this.dirCache,cwd:this.cwd,mode:r})}catch(o){return o}}[Tx](e,r,o,a){try{vn[o+"Sync"](r,e.absolute),a(),e.resume()}catch(n){return this[To](n,e)}}};_1.Sync=W3;_fe.exports=_1});var Yfe=_((FUt,Gfe)=>{"use strict";var Jct=Ay(),Nx=K3(),qfe=ve("fs"),jfe=by(),Hfe=ve("path"),V3=Ey();Gfe.exports=(t,e,r)=>{typeof t=="function"?(r=t,e=null,t={}):Array.isArray(t)&&(e=t,t={}),typeof e=="function"&&(r=e,e=null),e?e=Array.from(e):e=[];let o=Jct(t);if(o.sync&&typeof r=="function")throw new TypeError("callback not supported for sync tar functions");if(!o.file&&typeof r=="function")throw new TypeError("callback only supported with file option");return e.length&&Xct(o,e),o.file&&o.sync?Zct(o):o.file?$ct(o,r):o.sync?eut(o):tut(o)};var Xct=(t,e)=>{let r=new Map(e.map(n=>[V3(n),!0])),o=t.filter,a=(n,u)=>{let A=u||Hfe.parse(n).root||".",p=n===A?!1:r.has(n)?r.get(n):a(Hfe.dirname(n),A);return r.set(n,p),p};t.filter=o?(n,u)=>o(n,u)&&a(V3(n)):n=>a(V3(n))},Zct=t=>{let e=new Nx.Sync(t),r=t.file,o=qfe.statSync(r),a=t.maxReadSize||16*1024*1024;new jfe.ReadStreamSync(r,{readSize:a,size:o.size}).pipe(e)},$ct=(t,e)=>{let r=new Nx(t),o=t.maxReadSize||16*1024*1024,a=t.file,n=new Promise((u,A)=>{r.on("error",A),r.on("close",u),qfe.stat(a,(p,h)=>{if(p)A(p);else{let E=new jfe.ReadStream(a,{readSize:o,size:h.size});E.on("error",A),E.pipe(r)}})});return e?n.then(e,e):n},eut=t=>new Nx.Sync(t),tut=t=>new Nx(t)});var Wfe=_(As=>{"use strict";As.c=As.create=SAe();As.r=As.replace=x3();As.t=As.list=Bx();As.u=As.update=LAe();As.x=As.extract=Yfe();As.Pack=lx();As.Unpack=K3();As.Parse=Ix();As.ReadEntry=Yb();As.WriteEntry=i3();As.Header=yy();As.Pax=Kb();As.types=_U()});var z3,Kfe,vh,H1,q1,Vfe=Et(()=>{z3=Ze(eg()),Kfe=ve("worker_threads"),vh=Symbol("kTaskInfo"),H1=class{constructor(e,r){this.fn=e;this.limit=(0,z3.default)(r.poolSize)}run(e){return this.limit(()=>this.fn(e))}},q1=class{constructor(e,r){this.source=e;this.workers=[];this.limit=(0,z3.default)(r.poolSize),this.cleanupInterval=setInterval(()=>{if(this.limit.pendingCount===0&&this.limit.activeCount===0){let o=this.workers.pop();o?o.terminate():clearInterval(this.cleanupInterval)}},5e3).unref()}createWorker(){this.cleanupInterval.refresh();let e=new Kfe.Worker(this.source,{eval:!0,execArgv:[...process.execArgv,"--unhandled-rejections=strict"]});return e.on("message",r=>{if(!e[vh])throw new Error("Assertion failed: Worker sent a result without having a task assigned");e[vh].resolve(r),e[vh]=null,e.unref(),this.workers.push(e)}),e.on("error",r=>{e[vh]?.reject(r),e[vh]=null}),e.on("exit",r=>{r!==0&&e[vh]?.reject(new Error(`Worker exited with code ${r}`)),e[vh]=null}),e}run(e){return this.limit(()=>{let r=this.workers.pop()??this.createWorker();return r.ref(),new Promise((o,a)=>{r[vh]={resolve:o,reject:a},r.postMessage(e)})})}}});var Jfe=_((LUt,zfe)=>{var J3;zfe.exports.getContent=()=>(typeof J3>"u"&&(J3=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),J3)});var $i={};Vt($i,{convertToZip:()=>sut,convertToZipWorker:()=>$3,extractArchiveTo:()=>tpe,getDefaultTaskPool:()=>$fe,getTaskPoolForConfiguration:()=>epe,makeArchiveFromDirectory:()=>iut});function rut(t,e){switch(t){case"async":return new H1($3,{poolSize:e});case"workers":return new q1((0,Z3.getContent)(),{poolSize:e});default:throw new Error(`Assertion failed: Unknown value ${t} for taskPoolMode`)}}function $fe(){return typeof X3>"u"&&(X3=rut("workers",Xi.availableParallelism())),X3}function epe(t){return typeof t>"u"?$fe():al(nut,t,()=>{let e=t.get("taskPoolMode"),r=t.get("taskPoolConcurrency");switch(e){case"async":return new H1($3,{poolSize:r});case"workers":return new q1((0,Z3.getContent)(),{poolSize:r});default:throw new Error(`Assertion failed: Unknown value ${e} for taskPoolMode`)}})}async function $3(t){let{tmpFile:e,tgz:r,compressionLevel:o,extractBufferOpts:a}=t,n=new Zi(e,{create:!0,level:o,stats:wa.makeDefaultStats()}),u=Buffer.from(r.buffer,r.byteOffset,r.byteLength);return await tpe(u,n,a),n.saveAndClose(),e}async function iut(t,{baseFs:e=new Tn,prefixPath:r=It.root,compressionLevel:o,inMemory:a=!1}={}){let n;if(a)n=new Zi(null,{level:o});else{let A=await oe.mktempPromise(),p=K.join(A,"archive.zip");n=new Zi(p,{create:!0,level:o})}let u=K.resolve(It.root,r);return await n.copyPromise(u,t,{baseFs:e,stableTime:!0,stableSort:!0}),n}async function sut(t,e={}){let r=await oe.mktempPromise(),o=K.join(r,"archive.zip"),a=e.compressionLevel??e.configuration?.get("compressionLevel")??"mixed",n={prefixPath:e.prefixPath,stripComponents:e.stripComponents};return await(e.taskPool??epe(e.configuration)).run({tmpFile:o,tgz:t,compressionLevel:a,extractBufferOpts:n}),new Zi(o,{level:e.compressionLevel})}async function*out(t){let e=new Zfe.default.Parse,r=new Xfe.PassThrough({objectMode:!0,autoDestroy:!0,emitClose:!0});e.on("entry",o=>{r.write(o)}),e.on("error",o=>{r.destroy(o)}),e.on("close",()=>{r.destroyed||r.end()}),e.end(t);for await(let o of r){let a=o;yield a,a.resume()}}async function tpe(t,e,{stripComponents:r=0,prefixPath:o=It.dot}={}){function a(n){if(n.path[0]==="/")return!0;let u=n.path.split(/\//g);return!!(u.some(A=>A==="..")||u.length<=r)}for await(let n of out(t)){if(a(n))continue;let u=K.normalize(ue.toPortablePath(n.path)).replace(/\/$/,"").split(/\//g);if(u.length<=r)continue;let A=u.slice(r).join("/"),p=K.join(o,A),h=420;switch((n.type==="Directory"||(n.mode??0)&73)&&(h|=73),n.type){case"Directory":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Bi.SAFE_TIME,Bi.SAFE_TIME]}),e.mkdirSync(p,{mode:h}),e.utimesSync(p,Bi.SAFE_TIME,Bi.SAFE_TIME);break;case"OldFile":case"File":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Bi.SAFE_TIME,Bi.SAFE_TIME]}),e.writeFileSync(p,await km(n),{mode:h}),e.utimesSync(p,Bi.SAFE_TIME,Bi.SAFE_TIME);break;case"SymbolicLink":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Bi.SAFE_TIME,Bi.SAFE_TIME]}),e.symlinkSync(n.linkpath,p),e.lutimesSync(p,Bi.SAFE_TIME,Bi.SAFE_TIME);break}}return e}var Xfe,Zfe,Z3,X3,nut,rpe=Et(()=>{Ge();Pt();nA();Xfe=ve("stream"),Zfe=Ze(Wfe());Vfe();ql();Z3=Ze(Jfe());nut=new WeakMap});var ipe=_((e_,npe)=>{(function(t,e){typeof e_=="object"?npe.exports=e():typeof define=="function"&&define.amd?define(e):t.treeify=e()})(e_,function(){function t(a,n){var u=n?"\u2514":"\u251C";return a?u+="\u2500 ":u+="\u2500\u2500\u2510",u}function e(a,n){var u=[];for(var A in a)a.hasOwnProperty(A)&&(n&&typeof a[A]=="function"||u.push(A));return u}function r(a,n,u,A,p,h,E){var I="",v=0,x,C,R=A.slice(0);if(R.push([n,u])&&A.length>0&&(A.forEach(function(U,z){z>0&&(I+=(U[1]?" ":"\u2502")+" "),!C&&U[0]===n&&(C=!0)}),I+=t(a,u)+a,p&&(typeof n!="object"||n instanceof Date)&&(I+=": "+n),C&&(I+=" (circular ref.)"),E(I)),!C&&typeof n=="object"){var L=e(n,h);L.forEach(function(U){x=++v===L.length,r(U,n[U],x,R,p,h,E)})}}var o={};return o.asLines=function(a,n,u,A){var p=typeof u!="function"?u:!1;r(".",a,!1,[],n,p,A||u)},o.asTree=function(a,n,u){var A="";return r(".",a,!1,[],n,u,function(p){A+=p+` +`}),A},o})});var fs={};Vt(fs,{emitList:()=>aut,emitTree:()=>lpe,treeNodeToJson:()=>ape,treeNodeToTreeify:()=>ope});function ope(t,{configuration:e}){let r={},o=0,a=(n,u)=>{let A=Array.isArray(n)?n.entries():Object.entries(n);for(let[p,h]of A){if(!h)continue;let{label:E,value:I,children:v}=h,x=[];typeof E<"u"&&x.push(fg(e,E,2)),typeof I<"u"&&x.push(Ot(e,I[0],I[1])),x.length===0&&x.push(fg(e,`${p}`,2));let C=x.join(": ").trim(),R=`\0${o++}\0`,L=u[`${R}${C}`]={};typeof v<"u"&&a(v,L)}};if(typeof t.children>"u")throw new Error("The root node must only contain children");return a(t.children,r),r}function ape(t){let e=r=>{if(typeof r.children>"u"){if(typeof r.value>"u")throw new Error("Assertion failed: Expected a value to be set if the children are missing");return pg(r.value[0],r.value[1])}let o=Array.isArray(r.children)?r.children.entries():Object.entries(r.children??{}),a=Array.isArray(r.children)?[]:{};for(let[n,u]of o)u&&(a[lut(n)]=e(u));return typeof r.value>"u"?a:{value:pg(r.value[0],r.value[1]),children:a}};return e(t)}function aut(t,{configuration:e,stdout:r,json:o}){let a=t.map(n=>({value:n}));lpe({children:a},{configuration:e,stdout:r,json:o})}function lpe(t,{configuration:e,stdout:r,json:o,separators:a=0}){if(o){let u=Array.isArray(t.children)?t.children.values():Object.values(t.children??{});for(let A of u)A&&r.write(`${JSON.stringify(ape(A))} +`);return}let n=(0,spe.asTree)(ope(t,{configuration:e}),!1,!1);if(n=n.replace(/\0[0-9]+\0/g,""),a>=1&&(n=n.replace(/^([├└]─)/gm,`\u2502 +$1`).replace(/^│\n/,"")),a>=2)for(let u=0;u<2;++u)n=n.replace(/^([│ ].{2}[├│ ].{2}[^\n]+\n)(([│ ]).{2}[├└].{2}[^\n]*\n[│ ].{2}[│ ].{2}[├└]─)/gm,`$1$3 \u2502 +$2`).replace(/^│\n/,"");if(a>=3)throw new Error("Only the first two levels are accepted by treeUtils.emitTree");r.write(n)}function lut(t){return typeof t=="string"?t.replace(/^\0[0-9]+\0/,""):t}var spe,cpe=Et(()=>{spe=Ze(ipe());jl()});function j1(t){let e=t.match(cut);if(!e?.groups)throw new Error("Assertion failed: Expected the checksum to match the requested pattern");let r=e.groups.cacheVersion?parseInt(e.groups.cacheVersion):null;return{cacheKey:e.groups.cacheKey??null,cacheVersion:r,cacheSpec:e.groups.cacheSpec??null,hash:e.groups.hash}}var upe,t_,r_,Lx,Gr,cut,n_=Et(()=>{Ge();Pt();Pt();nA();upe=ve("crypto"),t_=Ze(ve("fs"));Wl();th();ql();bo();r_=Qm(process.env.YARN_CACHE_CHECKPOINT_OVERRIDE??process.env.YARN_CACHE_VERSION_OVERRIDE??9),Lx=Qm(process.env.YARN_CACHE_VERSION_OVERRIDE??10),Gr=class t{constructor(e,{configuration:r,immutable:o=r.get("enableImmutableCache"),check:a=!1}){this.markedFiles=new Set;this.mutexes=new Map;this.cacheId=`-${(0,upe.randomBytes)(8).toString("hex")}.tmp`;this.configuration=r,this.cwd=e,this.immutable=o,this.check=a;let{cacheSpec:n,cacheKey:u}=t.getCacheKey(r);this.cacheSpec=n,this.cacheKey=u}static async find(e,{immutable:r,check:o}={}){let a=new t(e.get("cacheFolder"),{configuration:e,immutable:r,check:o});return await a.setup(),a}static getCacheKey(e){let r=e.get("compressionLevel"),o=r!=="mixed"?`c${r}`:"";return{cacheKey:[Lx,o].join(""),cacheSpec:o}}get mirrorCwd(){if(!this.configuration.get("enableMirror"))return null;let e=`${this.configuration.get("globalFolder")}/cache`;return e!==this.cwd?e:null}getVersionFilename(e){return`${Hm(e)}-${this.cacheKey}.zip`}getChecksumFilename(e,r){let a=j1(r).hash.slice(0,10);return`${Hm(e)}-${a}.zip`}isChecksumCompatible(e){if(e===null)return!1;let{cacheVersion:r,cacheSpec:o}=j1(e);if(r===null||r<r_)return!1;let a=this.configuration.get("cacheMigrationMode");return!(r<Lx&&a==="always"||o!==this.cacheSpec&&a!=="required-only")}getLocatorPath(e,r){return this.mirrorCwd===null?K.resolve(this.cwd,this.getVersionFilename(e)):r===null?K.resolve(this.cwd,this.getVersionFilename(e)):K.resolve(this.cwd,this.getChecksumFilename(e,r))}getLocatorMirrorPath(e){let r=this.mirrorCwd;return r!==null?K.resolve(r,this.getVersionFilename(e)):null}async setup(){if(!this.configuration.get("enableGlobalCache"))if(this.immutable){if(!await oe.existsPromise(this.cwd))throw new Jt(56,"Cache path does not exist.")}else{await oe.mkdirPromise(this.cwd,{recursive:!0});let e=K.resolve(this.cwd,".gitignore");await oe.changeFilePromise(e,`/.gitignore +*.flock +*.tmp +`)}(this.mirrorCwd||!this.immutable)&&await oe.mkdirPromise(this.mirrorCwd||this.cwd,{recursive:!0})}async fetchPackageFromCache(e,r,{onHit:o,onMiss:a,loader:n,...u}){let A=this.getLocatorMirrorPath(e),p=new Tn,h=()=>{let de=new Zi,Be=K.join(It.root,zM(e));return de.mkdirSync(Be,{recursive:!0}),de.writeJsonSync(K.join(Be,dr.manifest),{name:rn(e),mocked:!0}),de},E=async(de,{isColdHit:Be,controlPath:Ee=null})=>{if(Ee===null&&u.unstablePackages?.has(e.locatorHash))return{isValid:!0,hash:null};let g=r&&!Be?j1(r).cacheKey:this.cacheKey,me=!u.skipIntegrityCheck||!r?`${g}/${await wS(de)}`:r;if(Ee!==null){let Ae=!u.skipIntegrityCheck||!r?`${this.cacheKey}/${await wS(Ee)}`:r;if(me!==Ae)throw new Jt(18,"The remote archive doesn't match the local checksum - has the local cache been corrupted?")}let we=null;switch(r!==null&&me!==r&&(this.check?we="throw":j1(r).cacheKey!==j1(me).cacheKey?we="update":we=this.configuration.get("checksumBehavior")),we){case null:case"update":return{isValid:!0,hash:me};case"ignore":return{isValid:!0,hash:r};case"reset":return{isValid:!1,hash:r};default:case"throw":throw new Jt(18,"The remote archive doesn't match the expected checksum")}},I=async de=>{if(!n)throw new Error(`Cache check required but no loader configured for ${qr(this.configuration,e)}`);let Be=await n(),Ee=Be.getRealPath();Be.saveAndClose(),await oe.chmodPromise(Ee,420);let g=await E(de,{controlPath:Ee,isColdHit:!1});if(!g.isValid)throw new Error("Assertion failed: Expected a valid checksum");return g.hash},v=async()=>{if(A===null||!await oe.existsPromise(A)){let de=await n(),Be=de.getRealPath();return de.saveAndClose(),{source:"loader",path:Be}}return{source:"mirror",path:A}},x=async()=>{if(!n)throw new Error(`Cache entry required but missing for ${qr(this.configuration,e)}`);if(this.immutable)throw new Jt(56,`Cache entry required but missing for ${qr(this.configuration,e)}`);let{path:de,source:Be}=await v(),{hash:Ee}=await E(de,{isColdHit:!0}),g=this.getLocatorPath(e,Ee),me=[];Be!=="mirror"&&A!==null&&me.push(async()=>{let Ae=`${A}${this.cacheId}`;await oe.copyFilePromise(de,Ae,t_.default.constants.COPYFILE_FICLONE),await oe.chmodPromise(Ae,420),await oe.renamePromise(Ae,A)}),(!u.mirrorWriteOnly||A===null)&&me.push(async()=>{let Ae=`${g}${this.cacheId}`;await oe.copyFilePromise(de,Ae,t_.default.constants.COPYFILE_FICLONE),await oe.chmodPromise(Ae,420),await oe.renamePromise(Ae,g)});let we=u.mirrorWriteOnly?A??g:g;return await Promise.all(me.map(Ae=>Ae())),[!1,we,Ee]},C=async()=>{let Be=(async()=>{let Ee=u.unstablePackages?.has(e.locatorHash),g=Ee||!r||this.isChecksumCompatible(r)?this.getLocatorPath(e,r):null,me=g!==null?this.markedFiles.has(g)||await p.existsPromise(g):!1,we=!!u.mockedPackages?.has(e.locatorHash)&&(!this.check||!me),Ae=we||me,ne=Ae?o:a;if(ne&&ne(),Ae){let Z=null,xe=g;if(!we)if(this.check)Z=await I(xe);else{let Ne=await E(xe,{isColdHit:!1});if(Ne.isValid)Z=Ne.hash;else return x()}return[we,xe,Z]}else{if(this.immutable&&Ee)throw new Jt(56,`Cache entry required but missing for ${qr(this.configuration,e)}; consider defining ${pe.pretty(this.configuration,"supportedArchitectures",pe.Type.CODE)} to cache packages for multiple systems`);return x()}})();this.mutexes.set(e.locatorHash,Be);try{return await Be}finally{this.mutexes.delete(e.locatorHash)}};for(let de;de=this.mutexes.get(e.locatorHash);)await de;let[R,L,U]=await C();R||this.markedFiles.add(L);let z,te=R?()=>h():()=>new Zi(L,{baseFs:p,readOnly:!0}),ae=new Gd(()=>uL(()=>z=te(),de=>`Failed to open the cache entry for ${qr(this.configuration,e)}: ${de}`),K),le=new Hu(L,{baseFs:ae,pathUtils:K}),ce=()=>{z?.discardAndClose()},Ce=u.unstablePackages?.has(e.locatorHash)?null:U;return[le,ce,Ce]}},cut=/^(?:(?<cacheKey>(?<cacheVersion>[0-9]+)(?<cacheSpec>.*))\/)?(?<hash>.*)$/});var Mx,Ape=Et(()=>{Mx=(r=>(r[r.SCRIPT=0]="SCRIPT",r[r.SHELLCODE=1]="SHELLCODE",r))(Mx||{})});var uut,Ty,i_=Et(()=>{Pt();Nl();bf();bo();uut=[[/^(git(?:\+(?:https|ssh))?:\/\/.*(?:\.git)?)#(.*)$/,(t,e,r,o)=>`${r}#commit=${o}`],[/^https:\/\/((?:[^/]+?)@)?codeload\.github\.com\/([^/]+\/[^/]+)\/tar\.gz\/([0-9a-f]+)$/,(t,e,r="",o,a)=>`https://${r}github.com/${o}.git#commit=${a}`],[/^https:\/\/((?:[^/]+?)@)?github\.com\/([^/]+\/[^/]+?)(?:\.git)?#([0-9a-f]+)$/,(t,e,r="",o,a)=>`https://${r}github.com/${o}.git#commit=${a}`],[/^https?:\/\/[^/]+\/(?:[^/]+\/)*(?:@.+(?:\/|(?:%2f)))?([^/]+)\/(?:-|download)\/\1-[^/]+\.tgz(?:#|$)/,t=>`npm:${t}`],[/^https:\/\/npm\.pkg\.github\.com\/download\/(?:@[^/]+)\/(?:[^/]+)\/(?:[^/]+)\/(?:[0-9a-f]+)(?:#|$)/,t=>`npm:${t}`],[/^https:\/\/npm\.fontawesome\.com\/(?:@[^/]+)\/([^/]+)\/-\/([^/]+)\/\1-\2.tgz(?:#|$)/,t=>`npm:${t}`],[/^https?:\/\/[^/]+\/.*\/(@[^/]+)\/([^/]+)\/-\/\1\/\2-(?:[.\d\w-]+)\.tgz(?:#|$)/,(t,e)=>PS({protocol:"npm:",source:null,selector:t,params:{__archiveUrl:e}})],[/^[^/]+\.tgz#[0-9a-f]+$/,t=>`npm:${t}`]],Ty=class{constructor(e){this.resolver=e;this.resolutions=null}async setup(e,{report:r}){let o=K.join(e.cwd,dr.lockfile);if(!oe.existsSync(o))return;let a=await oe.readFilePromise(o,"utf8"),n=Ki(a);if(Object.hasOwn(n,"__metadata"))return;let u=this.resolutions=new Map;for(let A of Object.keys(n)){let p=jI(A);if(!p){r.reportWarning(14,`Failed to parse the string "${A}" into a proper descriptor`);continue}let h=Qa(p.range)?In(p,`npm:${p.range}`):p,{version:E,resolved:I}=n[A];if(!I)continue;let v;for(let[C,R]of uut){let L=I.match(C);if(L){v=R(E,...L);break}}if(!v){r.reportWarning(14,`${jn(e.configuration,h)}: Only some patterns can be imported from legacy lockfiles (not "${I}")`);continue}let x=h;try{let C=dg(h.range),R=jI(C.selector,!0);R&&(x=R)}catch{}u.set(h.descriptorHash,Rs(x,v))}}supportsDescriptor(e,r){return this.resolutions?this.resolutions.has(e.descriptorHash):!1}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Assertion failed: This resolver doesn't support resolving locators to packages")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!this.resolutions)throw new Error("Assertion failed: The resolution store should have been setup");let a=this.resolutions.get(e.descriptorHash);if(!a)throw new Error("Assertion failed: The resolution should have been registered");let n=YM(a),u=o.project.configuration.normalizeDependency(n);return await this.resolver.getCandidates(u,r,o)}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){throw new Error("Assertion failed: This resolver doesn't support resolving locators to packages")}}});var AA,fpe=Et(()=>{Wl();I1();jl();AA=class extends Zs{constructor({configuration:r,stdout:o,suggestInstall:a=!0}){super();this.errorCount=0;TI(this,{configuration:r}),this.configuration=r,this.stdout=o,this.suggestInstall=a}static async start(r,o){let a=new this(r);try{await o(a)}catch(n){a.reportExceptionOnce(n)}finally{await a.finalize()}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}reportCacheHit(r){}reportCacheMiss(r){}startSectionSync(r,o){return o()}async startSectionPromise(r,o){return await o()}startTimerSync(r,o,a){return(typeof o=="function"?o:a)()}async startTimerPromise(r,o,a){return await(typeof o=="function"?o:a)()}reportSeparator(){}reportInfo(r,o){}reportWarning(r,o){}reportError(r,o){this.errorCount+=1,this.stdout.write(`${Ot(this.configuration,"\u27A4","redBright")} ${this.formatNameWithHyperlink(r)}: ${o} +`)}reportProgress(r){return{...Promise.resolve().then(async()=>{for await(let{}of r);}),stop:()=>{}}}reportJson(r){}reportFold(r,o){}async finalize(){this.errorCount>0&&(this.stdout.write(` +`),this.stdout.write(`${Ot(this.configuration,"\u27A4","redBright")} Errors happened when preparing the environment required to run this command. +`),this.suggestInstall&&this.stdout.write(`${Ot(this.configuration,"\u27A4","redBright")} This might be caused by packages being missing from the lockfile, in which case running "yarn install" might help. +`))}formatNameWithHyperlink(r){return AU(r,{configuration:this.configuration,json:!1})}}});var Ny,s_=Et(()=>{bo();Ny=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return!!(r.project.storedResolutions.get(e.descriptorHash)||r.project.originalPackages.has(BS(e).locatorHash))}supportsLocator(e,r){return!!(r.project.originalPackages.has(e.locatorHash)&&!r.project.lockfileNeedsRefresh)}shouldPersistResolution(e,r){throw new Error("The shouldPersistResolution method shouldn't be called on the lockfile resolver, which would always answer yes")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,o){let a=o.project.storedResolutions.get(e.descriptorHash);if(a){let u=o.project.originalPackages.get(a);if(u)return[u]}let n=o.project.originalPackages.get(BS(e).locatorHash);if(n)return[n];throw new Error("Resolution expected from the lockfile data")}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let o=r.project.originalPackages.get(e.locatorHash);if(!o)throw new Error("The lockfile resolver isn't meant to resolve packages - they should already have been stored into a cache");return o}}});function Gf(){}function Aut(t,e,r,o,a){for(var n=0,u=e.length,A=0,p=0;n<u;n++){var h=e[n];if(h.removed){if(h.value=t.join(o.slice(p,p+h.count)),p+=h.count,n&&e[n-1].added){var I=e[n-1];e[n-1]=e[n],e[n]=I}}else{if(!h.added&&a){var E=r.slice(A,A+h.count);E=E.map(function(x,C){var R=o[p+C];return R.length>x.length?R:x}),h.value=t.join(E)}else h.value=t.join(r.slice(A,A+h.count));A+=h.count,h.added||(p+=h.count)}}var v=e[u-1];return u>1&&typeof v.value=="string"&&(v.added||v.removed)&&t.equals("",v.value)&&(e[u-2].value+=v.value,e.pop()),e}function fut(t){return{newPos:t.newPos,components:t.components.slice(0)}}function put(t,e){if(typeof t=="function")e.callback=t;else if(t)for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e}function gpe(t,e,r){return r=put(r,{ignoreWhitespace:!0}),u_.diff(t,e,r)}function hut(t,e,r){return A_.diff(t,e,r)}function Ox(t){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ox=function(e){return typeof e}:Ox=function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ox(t)}function o_(t){return mut(t)||yut(t)||Eut(t)||Cut()}function mut(t){if(Array.isArray(t))return a_(t)}function yut(t){if(typeof Symbol<"u"&&Symbol.iterator in Object(t))return Array.from(t)}function Eut(t,e){if(t){if(typeof t=="string")return a_(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return a_(t,e)}}function a_(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,o=new Array(e);r<e;r++)o[r]=t[r];return o}function Cut(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function l_(t,e,r,o,a){e=e||[],r=r||[],o&&(t=o(a,t));var n;for(n=0;n<e.length;n+=1)if(e[n]===t)return r[n];var u;if(wut.call(t)==="[object Array]"){for(e.push(t),u=new Array(t.length),r.push(u),n=0;n<t.length;n+=1)u[n]=l_(t[n],e,r,o,a);return e.pop(),r.pop(),u}if(t&&t.toJSON&&(t=t.toJSON()),Ox(t)==="object"&&t!==null){e.push(t),u={},r.push(u);var A=[],p;for(p in t)t.hasOwnProperty(p)&&A.push(p);for(A.sort(),n=0;n<A.length;n+=1)p=A[n],u[p]=l_(t[p],e,r,o,p);e.pop(),r.pop()}else u=t;return u}function dpe(t,e,r,o,a,n,u){u||(u={}),typeof u.context>"u"&&(u.context=4);var A=hut(r,o,u);if(!A)return;A.push({value:"",lines:[]});function p(U){return U.map(function(z){return" "+z})}for(var h=[],E=0,I=0,v=[],x=1,C=1,R=function(z){var te=A[z],ae=te.lines||te.value.replace(/\n$/,"").split(` +`);if(te.lines=ae,te.added||te.removed){var le;if(!E){var ce=A[z-1];E=x,I=C,ce&&(v=u.context>0?p(ce.lines.slice(-u.context)):[],E-=v.length,I-=v.length)}(le=v).push.apply(le,o_(ae.map(function(Ae){return(te.added?"+":"-")+Ae}))),te.added?C+=ae.length:x+=ae.length}else{if(E)if(ae.length<=u.context*2&&z<A.length-2){var Ce;(Ce=v).push.apply(Ce,o_(p(ae)))}else{var de,Be=Math.min(ae.length,u.context);(de=v).push.apply(de,o_(p(ae.slice(0,Be))));var Ee={oldStart:E,oldLines:x-E+Be,newStart:I,newLines:C-I+Be,lines:v};if(z>=A.length-2&&ae.length<=u.context){var g=/\n$/.test(r),me=/\n$/.test(o),we=ae.length==0&&v.length>Ee.oldLines;!g&&we&&r.length>0&&v.splice(Ee.oldLines,0,"\\ No newline at end of file"),(!g&&!we||!me)&&v.push("\\ No newline at end of file")}h.push(Ee),E=0,I=0,v=[]}x+=ae.length,C+=ae.length}},L=0;L<A.length;L++)R(L);return{oldFileName:t,newFileName:e,oldHeader:a,newHeader:n,hunks:h}}var c3t,ppe,hpe,u_,A_,gut,dut,wut,G1,c_,f_=Et(()=>{Gf.prototype={diff:function(e,r){var o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=o.callback;typeof o=="function"&&(a=o,o={}),this.options=o;var n=this;function u(R){return a?(setTimeout(function(){a(void 0,R)},0),!0):R}e=this.castInput(e),r=this.castInput(r),e=this.removeEmpty(this.tokenize(e)),r=this.removeEmpty(this.tokenize(r));var A=r.length,p=e.length,h=1,E=A+p;o.maxEditLength&&(E=Math.min(E,o.maxEditLength));var I=[{newPos:-1,components:[]}],v=this.extractCommon(I[0],r,e,0);if(I[0].newPos+1>=A&&v+1>=p)return u([{value:this.join(r),count:r.length}]);function x(){for(var R=-1*h;R<=h;R+=2){var L=void 0,U=I[R-1],z=I[R+1],te=(z?z.newPos:0)-R;U&&(I[R-1]=void 0);var ae=U&&U.newPos+1<A,le=z&&0<=te&&te<p;if(!ae&&!le){I[R]=void 0;continue}if(!ae||le&&U.newPos<z.newPos?(L=fut(z),n.pushComponent(L.components,void 0,!0)):(L=U,L.newPos++,n.pushComponent(L.components,!0,void 0)),te=n.extractCommon(L,r,e,R),L.newPos+1>=A&&te+1>=p)return u(Aut(n,L.components,r,e,n.useLongestToken));I[R]=L}h++}if(a)(function R(){setTimeout(function(){if(h>E)return a();x()||R()},0)})();else for(;h<=E;){var C=x();if(C)return C}},pushComponent:function(e,r,o){var a=e[e.length-1];a&&a.added===r&&a.removed===o?e[e.length-1]={count:a.count+1,added:r,removed:o}:e.push({count:1,added:r,removed:o})},extractCommon:function(e,r,o,a){for(var n=r.length,u=o.length,A=e.newPos,p=A-a,h=0;A+1<n&&p+1<u&&this.equals(r[A+1],o[p+1]);)A++,p++,h++;return h&&e.components.push({count:h}),e.newPos=A,p},equals:function(e,r){return this.options.comparator?this.options.comparator(e,r):e===r||this.options.ignoreCase&&e.toLowerCase()===r.toLowerCase()},removeEmpty:function(e){for(var r=[],o=0;o<e.length;o++)e[o]&&r.push(e[o]);return r},castInput:function(e){return e},tokenize:function(e){return e.split("")},join:function(e){return e.join("")}};c3t=new Gf;ppe=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,hpe=/\S/,u_=new Gf;u_.equals=function(t,e){return this.options.ignoreCase&&(t=t.toLowerCase(),e=e.toLowerCase()),t===e||this.options.ignoreWhitespace&&!hpe.test(t)&&!hpe.test(e)};u_.tokenize=function(t){for(var e=t.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/),r=0;r<e.length-1;r++)!e[r+1]&&e[r+2]&&ppe.test(e[r])&&ppe.test(e[r+2])&&(e[r]+=e[r+2],e.splice(r+1,2),r--);return e};A_=new Gf;A_.tokenize=function(t){var e=[],r=t.split(/(\n|\r\n)/);r[r.length-1]||r.pop();for(var o=0;o<r.length;o++){var a=r[o];o%2&&!this.options.newlineIsToken?e[e.length-1]+=a:(this.options.ignoreWhitespace&&(a=a.trim()),e.push(a))}return e};gut=new Gf;gut.tokenize=function(t){return t.split(/(\S.+?[.!?])(?=\s+|$)/)};dut=new Gf;dut.tokenize=function(t){return t.split(/([{}:;,]|\s+)/)};wut=Object.prototype.toString,G1=new Gf;G1.useLongestToken=!0;G1.tokenize=A_.tokenize;G1.castInput=function(t){var e=this.options,r=e.undefinedReplacement,o=e.stringifyReplacer,a=o===void 0?function(n,u){return typeof u>"u"?r:u}:o;return typeof t=="string"?t:JSON.stringify(l_(t,null,null,a),a," ")};G1.equals=function(t,e){return Gf.prototype.equals.call(G1,t.replace(/,([\r\n])/g,"$1"),e.replace(/,([\r\n])/g,"$1"))};c_=new Gf;c_.tokenize=function(t){return t.slice()};c_.join=c_.removeEmpty=function(t){return t}});var ype=_((A3t,mpe)=>{var Iut=Hl(),But=Ym(),vut=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Dut=/^\w*$/;function Put(t,e){if(Iut(t))return!1;var r=typeof t;return r=="number"||r=="symbol"||r=="boolean"||t==null||But(t)?!0:Dut.test(t)||!vut.test(t)||e!=null&&t in Object(e)}mpe.exports=Put});var wpe=_((f3t,Cpe)=>{var Epe=PP(),Sut="Expected a function";function p_(t,e){if(typeof t!="function"||e!=null&&typeof e!="function")throw new TypeError(Sut);var r=function(){var o=arguments,a=e?e.apply(this,o):o[0],n=r.cache;if(n.has(a))return n.get(a);var u=t.apply(this,o);return r.cache=n.set(a,u)||n,u};return r.cache=new(p_.Cache||Epe),r}p_.Cache=Epe;Cpe.exports=p_});var Bpe=_((p3t,Ipe)=>{var but=wpe(),xut=500;function kut(t){var e=but(t,function(o){return r.size===xut&&r.clear(),o}),r=e.cache;return e}Ipe.exports=kut});var h_=_((h3t,vpe)=>{var Qut=Bpe(),Fut=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Rut=/\\(\\)?/g,Tut=Qut(function(t){var e=[];return t.charCodeAt(0)===46&&e.push(""),t.replace(Fut,function(r,o,a,n){e.push(a?n.replace(Rut,"$1"):o||r)}),e});vpe.exports=Tut});var Mg=_((g3t,Dpe)=>{var Nut=Hl(),Lut=ype(),Mut=h_(),Out=C1();function Uut(t,e){return Nut(t)?t:Lut(t,e)?[t]:Mut(Out(t))}Dpe.exports=Uut});var Ly=_((d3t,Ppe)=>{var _ut=Ym(),Hut=1/0;function qut(t){if(typeof t=="string"||_ut(t))return t;var e=t+"";return e=="0"&&1/t==-Hut?"-0":e}Ppe.exports=qut});var Ux=_((m3t,Spe)=>{var jut=Mg(),Gut=Ly();function Yut(t,e){e=jut(e,t);for(var r=0,o=e.length;t!=null&&r<o;)t=t[Gut(e[r++])];return r&&r==o?t:void 0}Spe.exports=Yut});var g_=_((y3t,xpe)=>{var Wut=qP(),Kut=Mg(),Vut=II(),bpe=sl(),zut=Ly();function Jut(t,e,r,o){if(!bpe(t))return t;e=Kut(e,t);for(var a=-1,n=e.length,u=n-1,A=t;A!=null&&++a<n;){var p=zut(e[a]),h=r;if(p==="__proto__"||p==="constructor"||p==="prototype")return t;if(a!=u){var E=A[p];h=o?o(E,p,A):void 0,h===void 0&&(h=bpe(E)?E:Vut(e[a+1])?[]:{})}Wut(A,p,h),A=A[p]}return t}xpe.exports=Jut});var Qpe=_((E3t,kpe)=>{var Xut=Ux(),Zut=g_(),$ut=Mg();function eAt(t,e,r){for(var o=-1,a=e.length,n={};++o<a;){var u=e[o],A=Xut(t,u);r(A,u)&&Zut(n,$ut(u,t),A)}return n}kpe.exports=eAt});var Rpe=_((C3t,Fpe)=>{function tAt(t,e){return t!=null&&e in Object(t)}Fpe.exports=tAt});var d_=_((w3t,Tpe)=>{var rAt=Mg(),nAt=EI(),iAt=Hl(),sAt=II(),oAt=QP(),aAt=Ly();function lAt(t,e,r){e=rAt(e,t);for(var o=-1,a=e.length,n=!1;++o<a;){var u=aAt(e[o]);if(!(n=t!=null&&r(t,u)))break;t=t[u]}return n||++o!=a?n:(a=t==null?0:t.length,!!a&&oAt(a)&&sAt(u,a)&&(iAt(t)||nAt(t)))}Tpe.exports=lAt});var Lpe=_((I3t,Npe)=>{var cAt=Rpe(),uAt=d_();function AAt(t,e){return t!=null&&uAt(t,e,cAt)}Npe.exports=AAt});var Ope=_((B3t,Mpe)=>{var fAt=Qpe(),pAt=Lpe();function hAt(t,e){return fAt(t,e,function(r,o){return pAt(t,o)})}Mpe.exports=hAt});var qpe=_((v3t,Hpe)=>{var Upe=lg(),gAt=EI(),dAt=Hl(),_pe=Upe?Upe.isConcatSpreadable:void 0;function mAt(t){return dAt(t)||gAt(t)||!!(_pe&&t&&t[_pe])}Hpe.exports=mAt});var Ype=_((D3t,Gpe)=>{var yAt=xP(),EAt=qpe();function jpe(t,e,r,o,a){var n=-1,u=t.length;for(r||(r=EAt),a||(a=[]);++n<u;){var A=t[n];e>0&&r(A)?e>1?jpe(A,e-1,r,o,a):yAt(a,A):o||(a[a.length]=A)}return a}Gpe.exports=jpe});var Kpe=_((P3t,Wpe)=>{var CAt=Ype();function wAt(t){var e=t==null?0:t.length;return e?CAt(t,1):[]}Wpe.exports=wAt});var m_=_((S3t,Vpe)=>{var IAt=Kpe(),BAt=rL(),vAt=nL();function DAt(t){return vAt(BAt(t,void 0,IAt),t+"")}Vpe.exports=DAt});var y_=_((b3t,zpe)=>{var PAt=Ope(),SAt=m_(),bAt=SAt(function(t,e){return t==null?{}:PAt(t,e)});zpe.exports=bAt});var _x,Jpe=Et(()=>{Wl();_x=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return this.resolver.supportsDescriptor(e,r)}supportsLocator(e,r){return this.resolver.supportsLocator(e,r)}shouldPersistResolution(e,r){return this.resolver.shouldPersistResolution(e,r)}bindDescriptor(e,r,o){return this.resolver.bindDescriptor(e,r,o)}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,o){throw new Jt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}async getSatisfying(e,r,o,a){throw new Jt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}async resolve(e,r){throw new Jt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}}});var ki,E_=Et(()=>{Wl();ki=class extends Zs{reportCacheHit(e){}reportCacheMiss(e){}startSectionSync(e,r){return r()}async startSectionPromise(e,r){return await r()}startTimerSync(e,r,o){return(typeof r=="function"?r:o)()}async startTimerPromise(e,r,o){return await(typeof r=="function"?r:o)()}reportSeparator(){}reportInfo(e,r){}reportWarning(e,r){}reportError(e,r){}reportProgress(e){return{...Promise.resolve().then(async()=>{for await(let{}of e);}),stop:()=>{}}}reportJson(e){}reportFold(e,r){}async finalize(){}}});var Xpe,My,C_=Et(()=>{Pt();Xpe=Ze(ES());Gm();mg();jl();th();bf();bo();My=class{constructor(e,{project:r}){this.workspacesCwds=new Set;this.project=r,this.cwd=e}async setup(){this.manifest=await Ut.tryFind(this.cwd)??new Ut,this.relativeCwd=K.relative(this.project.cwd,this.cwd)||It.dot;let e=this.manifest.name?this.manifest.name:eA(null,`${this.computeCandidateName()}-${zi(this.relativeCwd).substring(0,6)}`);this.anchoredDescriptor=In(e,`${ei.protocol}${this.relativeCwd}`),this.anchoredLocator=Rs(e,`${ei.protocol}${this.relativeCwd}`);let r=this.manifest.workspaceDefinitions.map(({pattern:a})=>a);if(r.length===0)return;let o=await(0,Xpe.default)(r,{cwd:ue.fromPortablePath(this.cwd),onlyDirectories:!0,ignore:["**/node_modules","**/.git","**/.yarn"]});o.sort(),await o.reduce(async(a,n)=>{let u=K.resolve(this.cwd,ue.toPortablePath(n)),A=await oe.existsPromise(K.join(u,"package.json"));await a,A&&this.workspacesCwds.add(u)},Promise.resolve())}get anchoredPackage(){let e=this.project.storedPackages.get(this.anchoredLocator.locatorHash);if(!e)throw new Error(`Assertion failed: Expected workspace ${YI(this.project.configuration,this)} (${Ot(this.project.configuration,K.join(this.cwd,dr.manifest),yt.PATH)}) to have been resolved. Run "yarn install" to update the lockfile`);return e}accepts(e){let r=e.indexOf(":"),o=r!==-1?e.slice(0,r+1):null,a=r!==-1?e.slice(r+1):e;if(o===ei.protocol&&K.normalize(a)===this.relativeCwd||o===ei.protocol&&(a==="*"||a==="^"||a==="~"))return!0;let n=Qa(a);return n?o===ei.protocol?n.test(this.manifest.version??"0.0.0"):this.project.configuration.get("enableTransparentWorkspaces")&&this.manifest.version!==null?n.test(this.manifest.version):!1:!1}computeCandidateName(){return this.cwd===this.project.cwd?"root-workspace":`${K.basename(this.cwd)}`||"unnamed-workspace"}getRecursiveWorkspaceDependencies({dependencies:e=Ut.hardDependencies}={}){let r=new Set,o=a=>{for(let n of e)for(let u of a.manifest[n].values()){let A=this.project.tryWorkspaceByDescriptor(u);A===null||r.has(A)||(r.add(A),o(A))}};return o(this),r}getRecursiveWorkspaceDependents({dependencies:e=Ut.hardDependencies}={}){let r=new Set,o=a=>{for(let n of this.project.workspaces)e.some(A=>[...n.manifest[A].values()].some(p=>{let h=this.project.tryWorkspaceByDescriptor(p);return h!==null&&qI(h.anchoredLocator,a.anchoredLocator)}))&&!r.has(n)&&(r.add(n),o(n))};return o(this),r}getRecursiveWorkspaceChildren(){let e=new Set([this]);for(let r of e)for(let o of r.workspacesCwds){let a=this.project.workspacesByCwd.get(o);a&&e.add(a)}return e.delete(this),Array.from(e)}async persistManifest(){let e={};this.manifest.exportTo(e);let r=K.join(this.cwd,Ut.fileName),o=`${JSON.stringify(e,null,this.manifest.indent)} +`;await oe.changeFilePromise(r,o,{automaticNewlines:!0}),this.manifest.raw=e}}});function TAt({project:t,allDescriptors:e,allResolutions:r,allPackages:o,accessibleLocators:a=new Set,optionalBuilds:n=new Set,peerRequirements:u=new Map,peerWarnings:A=[],peerRequirementNodes:p=new Map,volatileDescriptors:h=new Set}){let E=new Map,I=[],v=new Map,x=new Map,C=new Map,R=new Map,L=new Map(t.workspaces.map(le=>{let ce=le.anchoredLocator.locatorHash,Ce=o.get(ce);if(typeof Ce>"u")throw new Error("Assertion failed: The workspace should have an associated package");return[ce,OI(Ce)]})),U=()=>{let le=oe.mktempSync(),ce=K.join(le,"stacktrace.log"),Ce=String(I.length+1).length,de=I.map((Be,Ee)=>`${`${Ee+1}.`.padStart(Ce," ")} ${ka(Be)} +`).join("");throw oe.writeFileSync(ce,de),oe.detachTemp(le),new Jt(45,`Encountered a stack overflow when resolving peer dependencies; cf ${ue.fromPortablePath(ce)}`)},z=le=>{let ce=r.get(le.descriptorHash);if(typeof ce>"u")throw new Error("Assertion failed: The resolution should have been registered");let Ce=o.get(ce);if(!Ce)throw new Error("Assertion failed: The package could not be found");return Ce},te=(le,ce,Ce,{top:de,optional:Be})=>{I.length>1e3&&U(),I.push(ce);let Ee=ae(le,ce,Ce,{top:de,optional:Be});return I.pop(),Ee},ae=(le,ce,Ce,{top:de,optional:Be})=>{if(Be||n.delete(ce.locatorHash),a.has(ce.locatorHash))return;a.add(ce.locatorHash);let Ee=o.get(ce.locatorHash);if(!Ee)throw new Error(`Assertion failed: The package (${qr(t.configuration,ce)}) should have been registered`);let g=[],me=new Map,we=[],Ae=[],ne=[],Z=[];for(let Ne of Array.from(Ee.dependencies.values())){if(Ee.peerDependencies.has(Ne.identHash)&&Ee.locatorHash!==de)continue;if(Pf(Ne))throw new Error("Assertion failed: Virtual packages shouldn't be encountered when virtualizing a branch");h.delete(Ne.descriptorHash);let ht=Be;if(!ht){let Se=Ee.dependenciesMeta.get(rn(Ne));if(typeof Se<"u"){let et=Se.get(null);typeof et<"u"&&et.optional&&(ht=!0)}}let H=r.get(Ne.descriptorHash);if(!H)throw new Error(`Assertion failed: The resolution (${jn(t.configuration,Ne)}) should have been registered`);let rt=L.get(H)||o.get(H);if(!rt)throw new Error(`Assertion failed: The package (${H}, resolved from ${jn(t.configuration,Ne)}) should have been registered`);if(rt.peerDependencies.size===0){te(Ne,rt,new Map,{top:de,optional:ht});continue}let Te,Fe,ke=new Set,Ye=new Map;we.push(()=>{Te=KM(Ne,ce.locatorHash),Fe=VM(rt,ce.locatorHash),Ee.dependencies.delete(Ne.identHash),Ee.dependencies.set(Te.identHash,Te),r.set(Te.descriptorHash,Fe.locatorHash),e.set(Te.descriptorHash,Te),o.set(Fe.locatorHash,Fe),g.push([rt,Te,Fe])}),Ae.push(()=>{R.set(Fe.locatorHash,Ye);for(let Se of Fe.peerDependencies.values()){let Ue=al(me,Se.identHash,()=>{let b=Ce.get(Se.identHash)??null,w=Ee.dependencies.get(Se.identHash);return!w&&HI(ce,Se)&&(le.identHash===ce.identHash?w=le:(w=In(ce,le.range),e.set(w.descriptorHash,w),r.set(w.descriptorHash,ce.locatorHash),h.delete(w.descriptorHash),b=null)),w||(w=In(Se,"missing:")),{subject:ce,ident:Se,provided:w,root:!b,requests:new Map,hash:`p${zi(ce.locatorHash,Se.identHash).slice(0,5)}`}}).provided;if(Ue.range==="missing:"&&Fe.dependencies.has(Se.identHash)){Fe.peerDependencies.delete(Se.identHash);continue}Ye.set(Se.identHash,{requester:Fe,descriptor:Se,meta:Fe.peerDependenciesMeta.get(rn(Se)),children:new Map}),Fe.dependencies.set(Se.identHash,Ue),Pf(Ue)&&bm(C,Ue.descriptorHash).add(Fe.locatorHash),v.set(Ue.identHash,Ue),Ue.range==="missing:"&&ke.add(Ue.identHash)}Fe.dependencies=new Map(Fs(Fe.dependencies,([Se,et])=>rn(et)))}),ne.push(()=>{if(!o.has(Fe.locatorHash))return;let Se=E.get(rt.locatorHash);typeof Se=="number"&&Se>=2&&U();let et=E.get(rt.locatorHash),Ue=typeof et<"u"?et+1:1;E.set(rt.locatorHash,Ue),te(Te,Fe,Ye,{top:de,optional:ht}),E.set(rt.locatorHash,Ue-1)}),Z.push(()=>{let Se=Ee.dependencies.get(Ne.identHash);if(typeof Se>"u")throw new Error("Assertion failed: Expected the peer dependency to have been turned into a dependency");let et=r.get(Se.descriptorHash);if(typeof et>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let Ue=R.get(et);if(typeof Ue>"u")throw new Error("Assertion failed: Expected the peer requests to be registered");for(let b of me.values()){let w=Ue.get(b.ident.identHash);w&&(b.requests.set(Se.descriptorHash,w),p.set(b.hash,b),b.root||Ce.get(b.ident.identHash)?.children.set(Se.descriptorHash,w))}if(o.has(Fe.locatorHash))for(let b of ke)Fe.dependencies.delete(b)})}for(let Ne of[...we,...Ae])Ne();let xe;do{xe=!0;for(let[Ne,ht,H]of g){let rt=kI(x,Ne.locatorHash),Te=zi(...[...H.dependencies.values()].map(Se=>{let et=Se.range!=="missing:"?r.get(Se.descriptorHash):"missing:";if(typeof et>"u")throw new Error(`Assertion failed: Expected the resolution for ${jn(t.configuration,Se)} to have been registered`);return et===de?`${et} (top)`:et}),ht.identHash),Fe=rt.get(Te);if(typeof Fe>"u"){rt.set(Te,ht);continue}if(Fe===ht)continue;o.delete(H.locatorHash),e.delete(ht.descriptorHash),r.delete(ht.descriptorHash),a.delete(H.locatorHash);let ke=C.get(ht.descriptorHash)||[],Ye=[Ee.locatorHash,...ke];C.delete(ht.descriptorHash);for(let Se of Ye){let et=o.get(Se);typeof et>"u"||(et.dependencies.get(ht.identHash).descriptorHash!==Fe.descriptorHash&&(xe=!1),et.dependencies.set(ht.identHash,Fe))}for(let Se of me.values())Se.provided.descriptorHash===ht.descriptorHash&&(Se.provided=Fe)}}while(!xe);for(let Ne of[...ne,...Z])Ne()};for(let le of t.workspaces){let ce=le.anchoredLocator;h.delete(le.anchoredDescriptor.descriptorHash),te(le.anchoredDescriptor,ce,new Map,{top:ce.locatorHash,optional:!1})}for(let le of p.values()){if(!le.root)continue;let ce=o.get(le.subject.locatorHash);if(typeof ce>"u")continue;for(let de of le.requests.values()){let Be=`p${zi(le.subject.locatorHash,rn(le.ident),de.requester.locatorHash).slice(0,5)}`;u.set(Be,{subject:le.subject.locatorHash,requested:le.ident,rootRequester:de.requester.locatorHash,allRequesters:Array.from(WI(de),Ee=>Ee.requester.locatorHash)})}let Ce=[...WI(le)];if(le.provided.range!=="missing:"){let de=z(le.provided),Be=de.version??"0.0.0",Ee=me=>{if(me.startsWith(ei.protocol)){if(!t.tryWorkspaceByLocator(de))return null;me=me.slice(ei.protocol.length),(me==="^"||me==="~")&&(me="*")}return me},g=!0;for(let me of Ce){let we=Ee(me.descriptor.range);if(we===null){g=!1;continue}if(!tA(Be,we)){g=!1;let Ae=`p${zi(le.subject.locatorHash,rn(le.ident),me.requester.locatorHash).slice(0,5)}`;A.push({type:1,subject:ce,requested:le.ident,requester:me.requester,version:Be,hash:Ae,requirementCount:Ce.length})}}if(!g){let me=Ce.map(we=>Ee(we.descriptor.range));A.push({type:3,node:le,range:me.includes(null)?null:XM(me),hash:le.hash})}}else{let de=!0;for(let Be of Ce)if(!Be.meta?.optional){de=!1;let Ee=`p${zi(le.subject.locatorHash,rn(le.ident),Be.requester.locatorHash).slice(0,5)}`;A.push({type:0,subject:ce,requested:le.ident,requester:Be.requester,hash:Ee})}de||A.push({type:2,node:le,hash:le.hash})}}}function*NAt(t){let e=new Map;if("children"in t)e.set(t,t);else for(let r of t.requests.values())e.set(r,r);for(let[r,o]of e){yield{request:r,root:o};for(let a of r.children.values())e.has(a)||e.set(a,o)}}function LAt(t,e){let r=[],o=[],a=!1;for(let n of t.peerWarnings)if(!(n.type===1||n.type===0)){if(!t.tryWorkspaceByLocator(n.node.subject)){a=!0;continue}if(n.type===3){let u=t.storedResolutions.get(n.node.provided.descriptorHash);if(typeof u>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let A=t.storedPackages.get(u);if(typeof A>"u")throw new Error("Assertion failed: Expected the package to be registered");let p=Vp(NAt(n.node),({request:I,root:v})=>tA(A.version??"0.0.0",I.descriptor.range)?Vp.skip:I===v?Oi(t.configuration,I.requester):`${Oi(t.configuration,I.requester)} (via ${Oi(t.configuration,v.requester)})`),h=[...WI(n.node)].length>1?"and other dependencies request":"requests",E=n.range?qm(t.configuration,n.range):Ot(t.configuration,"but they have non-overlapping ranges!","redBright");r.push(`${Oi(t.configuration,n.node.ident)} is listed by your project with version ${GI(t.configuration,A.version??"0.0.0")} (${Ot(t.configuration,n.hash,yt.CODE)}), which doesn't satisfy what ${p} ${h} (${E}).`)}if(n.type===2){let u=n.node.requests.size>1?" and other dependencies":"";o.push(`${qr(t.configuration,n.node.subject)} doesn't provide ${Oi(t.configuration,n.node.ident)} (${Ot(t.configuration,n.hash,yt.CODE)}), requested by ${Oi(t.configuration,n.node.requests.values().next().value.requester)}${u}.`)}}e.startSectionSync({reportFooter:()=>{e.reportWarning(86,`Some peer dependencies are incorrectly met by your project; run ${Ot(t.configuration,"yarn explain peer-requirements <hash>",yt.CODE)} for details, where ${Ot(t.configuration,"<hash>",yt.CODE)} is the six-letter p-prefixed code.`)},skipIfEmpty:!0},()=>{for(let n of Fs(r,u=>Rm.default(u)))e.reportWarning(60,n);for(let n of Fs(o,u=>Rm.default(u)))e.reportWarning(2,n)}),a&&e.reportWarning(86,`Some peer dependencies are incorrectly met by dependencies; run ${Ot(t.configuration,"yarn explain peer-requirements",yt.CODE)} for details.`)}var Hx,qx,jx,ehe,B_,I_,v_,Gx,xAt,kAt,Zpe,QAt,FAt,RAt,hl,w_,Yx,$pe,kt,the=Et(()=>{Pt();Pt();Nl();qt();Hx=ve("crypto");f_();qx=Ze(y_()),jx=Ze(eg()),ehe=Ze(Jn()),B_=ve("util"),I_=Ze(ve("v8")),v_=Ze(ve("zlib"));n_();u1();i_();s_();Gm();rO();Wl();Jpe();I1();E_();mg();C_();TS();jl();th();ql();pb();dU();bf();bo();Gx=Qm(process.env.YARN_LOCKFILE_VERSION_OVERRIDE??8),xAt=3,kAt=/ *, */g,Zpe=/\/$/,QAt=32,FAt=(0,B_.promisify)(v_.default.gzip),RAt=(0,B_.promisify)(v_.default.gunzip),hl=(r=>(r.UpdateLockfile="update-lockfile",r.SkipBuild="skip-build",r))(hl||{}),w_={restoreLinkersCustomData:["linkersCustomData"],restoreResolutions:["accessibleLocators","conditionalLocators","disabledLocators","optionalBuilds","storedDescriptors","storedResolutions","storedPackages","lockFileChecksum"],restoreBuildState:["skippedBuilds","storedBuildState"]},Yx=(a=>(a[a.NotProvided=0]="NotProvided",a[a.NotCompatible=1]="NotCompatible",a[a.NodeNotProvided=2]="NodeNotProvided",a[a.NodeNotCompatible=3]="NodeNotCompatible",a))(Yx||{}),$pe=t=>zi(`${xAt}`,t),kt=class t{constructor(e,{configuration:r}){this.resolutionAliases=new Map;this.workspaces=[];this.workspacesByCwd=new Map;this.workspacesByIdent=new Map;this.storedResolutions=new Map;this.storedDescriptors=new Map;this.storedPackages=new Map;this.storedChecksums=new Map;this.storedBuildState=new Map;this.accessibleLocators=new Set;this.conditionalLocators=new Set;this.disabledLocators=new Set;this.originalPackages=new Map;this.optionalBuilds=new Set;this.skippedBuilds=new Set;this.lockfileLastVersion=null;this.lockfileNeedsRefresh=!1;this.peerRequirements=new Map;this.peerWarnings=[];this.peerRequirementNodes=new Map;this.linkersCustomData=new Map;this.lockFileChecksum=null;this.installStateChecksum=null;this.configuration=r,this.cwd=e}static async find(e,r){if(!e.projectCwd)throw new st(`No project found in ${r}`);let o=e.projectCwd,a=r,n=null;for(;n!==e.projectCwd;){if(n=a,oe.existsSync(K.join(n,dr.manifest))){o=n;break}a=K.dirname(n)}let u=new t(e.projectCwd,{configuration:e});Ke.telemetry?.reportProject(u.cwd),await u.setupResolutions(),await u.setupWorkspaces(),Ke.telemetry?.reportWorkspaceCount(u.workspaces.length),Ke.telemetry?.reportDependencyCount(u.workspaces.reduce((C,R)=>C+R.manifest.dependencies.size+R.manifest.devDependencies.size,0));let A=u.tryWorkspaceByCwd(o);if(A)return{project:u,workspace:A,locator:A.anchoredLocator};let p=await u.findLocatorForLocation(`${o}/`,{strict:!0});if(p)return{project:u,locator:p,workspace:null};let h=Ot(e,u.cwd,yt.PATH),E=Ot(e,K.relative(u.cwd,o),yt.PATH),I=`- If ${h} isn't intended to be a project, remove any yarn.lock and/or package.json file there.`,v=`- If ${h} is intended to be a project, it might be that you forgot to list ${E} in its workspace configuration.`,x=`- Finally, if ${h} is fine and you intend ${E} to be treated as a completely separate project (not even a workspace), create an empty yarn.lock file in it.`;throw new st(`The nearest package directory (${Ot(e,o,yt.PATH)}) doesn't seem to be part of the project declared in ${Ot(e,u.cwd,yt.PATH)}. + +${[I,v,x].join(` +`)}`)}async setupResolutions(){this.storedResolutions=new Map,this.storedDescriptors=new Map,this.storedPackages=new Map,this.lockFileChecksum=null;let e=K.join(this.cwd,dr.lockfile),r=this.configuration.get("defaultLanguageName");if(oe.existsSync(e)){let o=await oe.readFilePromise(e,"utf8");this.lockFileChecksum=$pe(o);let a=Ki(o);if(a.__metadata){let n=a.__metadata.version,u=a.__metadata.cacheKey;this.lockfileLastVersion=n,this.lockfileNeedsRefresh=n<Gx;for(let A of Object.keys(a)){if(A==="__metadata")continue;let p=a[A];if(typeof p.resolution>"u")throw new Error(`Assertion failed: Expected the lockfile entry to have a resolution field (${A})`);let h=Sf(p.resolution,!0),E=new Ut;E.load(p,{yamlCompatibilityMode:!0});let I=E.version,v=E.languageName||r,x=p.linkType.toUpperCase(),C=p.conditions??null,R=E.dependencies,L=E.peerDependencies,U=E.dependenciesMeta,z=E.peerDependenciesMeta,te=E.bin;if(p.checksum!=null){let le=typeof u<"u"&&!p.checksum.includes("/")?`${u}/${p.checksum}`:p.checksum;this.storedChecksums.set(h.locatorHash,le)}let ae={...h,version:I,languageName:v,linkType:x,conditions:C,dependencies:R,peerDependencies:L,dependenciesMeta:U,peerDependenciesMeta:z,bin:te};this.originalPackages.set(ae.locatorHash,ae);for(let le of A.split(kAt)){let ce=rh(le);n<=6&&(ce=this.configuration.normalizeDependency(ce),ce=In(ce,ce.range.replace(/^patch:[^@]+@(?!npm(:|%3A))/,"$1npm%3A"))),this.storedDescriptors.set(ce.descriptorHash,ce),this.storedResolutions.set(ce.descriptorHash,h.locatorHash)}}}else o.includes("yarn lockfile v1")&&(this.lockfileLastVersion=-1)}}async setupWorkspaces(){this.workspaces=[],this.workspacesByCwd=new Map,this.workspacesByIdent=new Map;let e=new Set,r=(0,jx.default)(4),o=async(a,n)=>{if(e.has(n))return a;e.add(n);let u=new My(n,{project:this});await r(()=>u.setup());let A=a.then(()=>{this.addWorkspace(u)});return Array.from(u.workspacesCwds).reduce(o,A)};await o(Promise.resolve(),this.cwd)}addWorkspace(e){let r=this.workspacesByIdent.get(e.anchoredLocator.identHash);if(typeof r<"u")throw new Error(`Duplicate workspace name ${Oi(this.configuration,e.anchoredLocator)}: ${ue.fromPortablePath(e.cwd)} conflicts with ${ue.fromPortablePath(r.cwd)}`);this.workspaces.push(e),this.workspacesByCwd.set(e.cwd,e),this.workspacesByIdent.set(e.anchoredLocator.identHash,e)}get topLevelWorkspace(){return this.getWorkspaceByCwd(this.cwd)}tryWorkspaceByCwd(e){K.isAbsolute(e)||(e=K.resolve(this.cwd,e)),e=K.normalize(e).replace(/\/+$/,"");let r=this.workspacesByCwd.get(e);return r||null}getWorkspaceByCwd(e){let r=this.tryWorkspaceByCwd(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByFilePath(e){let r=null;for(let o of this.workspaces)K.relative(o.cwd,e).startsWith("../")||r&&r.cwd.length>=o.cwd.length||(r=o);return r||null}getWorkspaceByFilePath(e){let r=this.tryWorkspaceByFilePath(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByIdent(e){let r=this.workspacesByIdent.get(e.identHash);return typeof r>"u"?null:r}getWorkspaceByIdent(e){let r=this.tryWorkspaceByIdent(e);if(!r)throw new Error(`Workspace not found (${Oi(this.configuration,e)})`);return r}tryWorkspaceByDescriptor(e){if(e.range.startsWith(ei.protocol)){let o=e.range.slice(ei.protocol.length);if(o!=="^"&&o!=="~"&&o!=="*"&&!Qa(o))return this.tryWorkspaceByCwd(o)}let r=this.tryWorkspaceByIdent(e);return r===null||(Pf(e)&&(e=UI(e)),!r.accepts(e.range))?null:r}getWorkspaceByDescriptor(e){let r=this.tryWorkspaceByDescriptor(e);if(r===null)throw new Error(`Workspace not found (${jn(this.configuration,e)})`);return r}tryWorkspaceByLocator(e){let r=this.tryWorkspaceByIdent(e);return r===null||(Gc(e)&&(e=_I(e)),r.anchoredLocator.locatorHash!==e.locatorHash)?null:r}getWorkspaceByLocator(e){let r=this.tryWorkspaceByLocator(e);if(!r)throw new Error(`Workspace not found (${qr(this.configuration,e)})`);return r}deleteDescriptor(e){this.storedResolutions.delete(e),this.storedDescriptors.delete(e)}deleteLocator(e){this.originalPackages.delete(e),this.storedPackages.delete(e),this.accessibleLocators.delete(e)}forgetResolution(e){if("descriptorHash"in e){let r=this.storedResolutions.get(e.descriptorHash);this.deleteDescriptor(e.descriptorHash);let o=new Set(this.storedResolutions.values());typeof r<"u"&&!o.has(r)&&this.deleteLocator(r)}if("locatorHash"in e){this.deleteLocator(e.locatorHash);for(let[r,o]of this.storedResolutions)o===e.locatorHash&&this.deleteDescriptor(r)}}forgetTransientResolutions(){let e=this.configuration.makeResolver(),r=new Map;for(let[o,a]of this.storedResolutions.entries()){let n=r.get(a);n||r.set(a,n=new Set),n.add(o)}for(let o of this.originalPackages.values()){let a;try{a=e.shouldPersistResolution(o,{project:this,resolver:e})}catch{a=!1}if(!a){this.deleteLocator(o.locatorHash);let n=r.get(o.locatorHash);if(n){r.delete(o.locatorHash);for(let u of n)this.deleteDescriptor(u)}}}}forgetVirtualResolutions(){for(let e of this.storedPackages.values())for(let[r,o]of e.dependencies)Pf(o)&&e.dependencies.set(r,UI(o))}getDependencyMeta(e,r){let o={},n=this.topLevelWorkspace.manifest.dependenciesMeta.get(rn(e));if(!n)return o;let u=n.get(null);if(u&&Object.assign(o,u),r===null||!ehe.default.valid(r))return o;for(let[A,p]of n)A!==null&&A===r&&Object.assign(o,p);return o}async findLocatorForLocation(e,{strict:r=!1}={}){let o=new ki,a=this.configuration.getLinkers(),n={project:this,report:o};for(let u of a){let A=await u.findPackageLocator(e,n);if(A){if(r&&(await u.findPackageLocation(A,n)).replace(Zpe,"")!==e.replace(Zpe,""))continue;return A}}return null}async loadUserConfig(){let e=K.join(this.cwd,".pnp.cjs");await oe.existsPromise(e)&&vf(e).setup();let r=K.join(this.cwd,"yarn.config.cjs");return await oe.existsPromise(r)?vf(r):null}async preparePackage(e,{resolver:r,resolveOptions:o}){let a=await this.configuration.getPackageExtensions(),n=this.configuration.normalizePackage(e,{packageExtensions:a});for(let[u,A]of n.dependencies){let p=await this.configuration.reduceHook(E=>E.reduceDependency,A,this,n,A,{resolver:r,resolveOptions:o});if(!HI(A,p))throw new Error("Assertion failed: The descriptor ident cannot be changed through aliases");let h=r.bindDescriptor(p,n,o);n.dependencies.set(u,h)}return n}async resolveEverything(e){if(!this.workspacesByCwd||!this.workspacesByIdent)throw new Error("Workspaces must have been setup before calling this function");this.forgetVirtualResolutions();let r=new Map(this.originalPackages),o=[];e.lockfileOnly||this.forgetTransientResolutions();let a=e.resolver||this.configuration.makeResolver(),n=new Ty(a);await n.setup(this,{report:e.report});let u=e.lockfileOnly?[new _x(a)]:[n,a],A=new yg([new Ny(a),...u]),p=new yg([...u]),h=this.configuration.makeFetcher(),E=e.lockfileOnly?{project:this,report:e.report,resolver:A}:{project:this,report:e.report,resolver:A,fetchOptions:{project:this,cache:e.cache,checksums:this.storedChecksums,report:e.report,fetcher:h,cacheOptions:{mirrorWriteOnly:!0}}},I=new Map,v=new Map,x=new Map,C=new Map,R=new Map,L=new Map,U=this.topLevelWorkspace.anchoredLocator,z=new Set,te=[],ae=k4(),le=this.configuration.getSupportedArchitectures();await e.report.startProgressPromise(Zs.progressViaTitle(),async ne=>{let Z=async rt=>{let Te=await xm(async()=>await A.resolve(rt,E),Se=>`${qr(this.configuration,rt)}: ${Se}`);if(!qI(rt,Te))throw new Error(`Assertion failed: The locator cannot be changed by the resolver (went from ${qr(this.configuration,rt)} to ${qr(this.configuration,Te)})`);C.set(Te.locatorHash,Te),!r.delete(Te.locatorHash)&&!this.tryWorkspaceByLocator(Te)&&o.push(Te);let ke=await this.preparePackage(Te,{resolver:A,resolveOptions:E}),Ye=_c([...ke.dependencies.values()].map(Se=>H(Se)));return te.push(Ye),Ye.catch(()=>{}),v.set(ke.locatorHash,ke),ke},xe=async rt=>{let Te=R.get(rt.locatorHash);if(typeof Te<"u")return Te;let Fe=Promise.resolve().then(()=>Z(rt));return R.set(rt.locatorHash,Fe),Fe},Ne=async(rt,Te)=>{let Fe=await H(Te);return I.set(rt.descriptorHash,rt),x.set(rt.descriptorHash,Fe.locatorHash),Fe},ht=async rt=>{ne.setTitle(jn(this.configuration,rt));let Te=this.resolutionAliases.get(rt.descriptorHash);if(typeof Te<"u")return Ne(rt,this.storedDescriptors.get(Te));let Fe=A.getResolutionDependencies(rt,E),ke=Object.fromEntries(await _c(Object.entries(Fe).map(async([et,Ue])=>{let b=A.bindDescriptor(Ue,U,E),w=await H(b);return z.add(w.locatorHash),[et,w]}))),Se=(await xm(async()=>await A.getCandidates(rt,ke,E),et=>`${jn(this.configuration,rt)}: ${et}`))[0];if(typeof Se>"u")throw new Jt(82,`${jn(this.configuration,rt)}: No candidates found`);if(e.checkResolutions){let{locators:et}=await p.getSatisfying(rt,ke,[Se],{...E,resolver:p});if(!et.find(Ue=>Ue.locatorHash===Se.locatorHash))throw new Jt(78,`Invalid resolution ${NI(this.configuration,rt,Se)}`)}return I.set(rt.descriptorHash,rt),x.set(rt.descriptorHash,Se.locatorHash),xe(Se)},H=rt=>{let Te=L.get(rt.descriptorHash);if(typeof Te<"u")return Te;I.set(rt.descriptorHash,rt);let Fe=Promise.resolve().then(()=>ht(rt));return L.set(rt.descriptorHash,Fe),Fe};for(let rt of this.workspaces){let Te=rt.anchoredDescriptor;te.push(H(Te))}for(;te.length>0;){let rt=[...te];te.length=0,await _c(rt)}});let ce=ol(r.values(),ne=>this.tryWorkspaceByLocator(ne)?ol.skip:ne);if(o.length>0||ce.length>0){let ne=new Set(this.workspaces.flatMap(rt=>{let Te=v.get(rt.anchoredLocator.locatorHash);if(!Te)throw new Error("Assertion failed: The workspace should have been resolved");return Array.from(Te.dependencies.values(),Fe=>{let ke=x.get(Fe.descriptorHash);if(!ke)throw new Error("Assertion failed: The resolution should have been registered");return ke})})),Z=rt=>ne.has(rt.locatorHash)?"0":"1",xe=rt=>ka(rt),Ne=Fs(o,[Z,xe]),ht=Fs(ce,[Z,xe]),H=e.report.getRecommendedLength();Ne.length>0&&e.report.reportInfo(85,`${Ot(this.configuration,"+",yt.ADDED)} ${zP(this.configuration,Ne,H)}`),ht.length>0&&e.report.reportInfo(85,`${Ot(this.configuration,"-",yt.REMOVED)} ${zP(this.configuration,ht,H)}`)}let Ce=new Set(this.resolutionAliases.values()),de=new Set(v.keys()),Be=new Set,Ee=new Map,g=[],me=new Map;TAt({project:this,accessibleLocators:Be,volatileDescriptors:Ce,optionalBuilds:de,peerRequirements:Ee,peerWarnings:g,peerRequirementNodes:me,allDescriptors:I,allResolutions:x,allPackages:v});for(let ne of z)de.delete(ne);for(let ne of Ce)I.delete(ne),x.delete(ne);let we=new Set,Ae=new Set;for(let ne of v.values())ne.conditions!=null&&de.has(ne.locatorHash)&&(bS(ne,le)||(bS(ne,ae)&&e.report.reportWarningOnce(77,`${qr(this.configuration,ne)}: Your current architecture (${process.platform}-${process.arch}) is supported by this package, but is missing from the ${Ot(this.configuration,"supportedArchitectures",yt.SETTING)} setting`),Ae.add(ne.locatorHash)),we.add(ne.locatorHash));this.storedResolutions=x,this.storedDescriptors=I,this.storedPackages=v,this.accessibleLocators=Be,this.conditionalLocators=we,this.disabledLocators=Ae,this.originalPackages=C,this.optionalBuilds=de,this.peerRequirements=Ee,this.peerWarnings=g,this.peerRequirementNodes=me}async fetchEverything({cache:e,report:r,fetcher:o,mode:a,persistProject:n=!0}){let u={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators},A=o||this.configuration.makeFetcher(),p={checksums:this.storedChecksums,project:this,cache:e,fetcher:A,report:r,cacheOptions:u},h=Array.from(new Set(Fs(this.storedResolutions.values(),[C=>{let R=this.storedPackages.get(C);if(!R)throw new Error("Assertion failed: The locator should have been registered");return ka(R)}])));a==="update-lockfile"&&(h=h.filter(C=>!this.storedChecksums.has(C)));let E=!1,I=Zs.progressViaCounter(h.length);await r.reportProgress(I);let v=(0,jx.default)(QAt);if(await _c(h.map(C=>v(async()=>{let R=this.storedPackages.get(C);if(!R)throw new Error("Assertion failed: The locator should have been registered");if(Gc(R))return;let L;try{L=await A.fetch(R,p)}catch(U){U.message=`${qr(this.configuration,R)}: ${U.message}`,r.reportExceptionOnce(U),E=U;return}L.checksum!=null?this.storedChecksums.set(R.locatorHash,L.checksum):this.storedChecksums.delete(R.locatorHash),L.releaseFs&&L.releaseFs()}).finally(()=>{I.tick()}))),E)throw E;let x=n&&a!=="update-lockfile"?await this.cacheCleanup({cache:e,report:r}):null;if(r.cacheMisses.size>0||x){let R=(await Promise.all([...r.cacheMisses].map(async ce=>{let Ce=this.storedPackages.get(ce),de=this.storedChecksums.get(ce)??null,Be=e.getLocatorPath(Ce,de);return(await oe.statPromise(Be)).size}))).reduce((ce,Ce)=>ce+Ce,0)-(x?.size??0),L=r.cacheMisses.size,U=x?.count??0,z=`${jP(L,{zero:"No new packages",one:"A package was",more:`${Ot(this.configuration,L,yt.NUMBER)} packages were`})} added to the project`,te=`${jP(U,{zero:"none were",one:"one was",more:`${Ot(this.configuration,U,yt.NUMBER)} were`})} removed`,ae=R!==0?` (${Ot(this.configuration,R,yt.SIZE_DIFF)})`:"",le=U>0?L>0?`${z}, and ${te}${ae}.`:`${z}, but ${te}${ae}.`:`${z}${ae}.`;r.reportInfo(13,le)}}async linkEverything({cache:e,report:r,fetcher:o,mode:a}){let n={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators,skipIntegrityCheck:!0},u=o||this.configuration.makeFetcher(),A={checksums:this.storedChecksums,project:this,cache:e,fetcher:u,report:r,cacheOptions:n},p=this.configuration.getLinkers(),h={project:this,report:r},E=new Map(p.map(we=>{let Ae=we.makeInstaller(h),ne=we.getCustomDataKey(),Z=this.linkersCustomData.get(ne);return typeof Z<"u"&&Ae.attachCustomData(Z),[we,Ae]})),I=new Map,v=new Map,x=new Map,C=new Map(await _c([...this.accessibleLocators].map(async we=>{let Ae=this.storedPackages.get(we);if(!Ae)throw new Error("Assertion failed: The locator should have been registered");return[we,await u.fetch(Ae,A)]}))),R=[],L=new Set,U=[];for(let we of this.accessibleLocators){let Ae=this.storedPackages.get(we);if(typeof Ae>"u")throw new Error("Assertion failed: The locator should have been registered");let ne=C.get(Ae.locatorHash);if(typeof ne>"u")throw new Error("Assertion failed: The fetch result should have been registered");let Z=[],xe=ht=>{Z.push(ht)},Ne=this.tryWorkspaceByLocator(Ae);if(Ne!==null){let ht=[],{scripts:H}=Ne.manifest;for(let Te of["preinstall","install","postinstall"])H.has(Te)&&ht.push({type:0,script:Te});try{for(let[Te,Fe]of E)if(Te.supportsPackage(Ae,h)&&(await Fe.installPackage(Ae,ne,{holdFetchResult:xe})).buildRequest!==null)throw new Error("Assertion failed: Linkers can't return build directives for workspaces; this responsibility befalls to the Yarn core")}finally{Z.length===0?ne.releaseFs?.():R.push(_c(Z).catch(()=>{}).then(()=>{ne.releaseFs?.()}))}let rt=K.join(ne.packageFs.getRealPath(),ne.prefixPath);v.set(Ae.locatorHash,rt),!Gc(Ae)&&ht.length>0&&x.set(Ae.locatorHash,{buildDirectives:ht,buildLocations:[rt]})}else{let ht=p.find(Te=>Te.supportsPackage(Ae,h));if(!ht)throw new Jt(12,`${qr(this.configuration,Ae)} isn't supported by any available linker`);let H=E.get(ht);if(!H)throw new Error("Assertion failed: The installer should have been registered");let rt;try{rt=await H.installPackage(Ae,ne,{holdFetchResult:xe})}finally{Z.length===0?ne.releaseFs?.():R.push(_c(Z).then(()=>{}).then(()=>{ne.releaseFs?.()}))}I.set(Ae.locatorHash,ht),v.set(Ae.locatorHash,rt.packageLocation),rt.buildRequest&&rt.packageLocation&&(rt.buildRequest.skipped?(L.add(Ae.locatorHash),this.skippedBuilds.has(Ae.locatorHash)||U.push([Ae,rt.buildRequest.explain])):x.set(Ae.locatorHash,{buildDirectives:rt.buildRequest.directives,buildLocations:[rt.packageLocation]}))}}let z=new Map;for(let we of this.accessibleLocators){let Ae=this.storedPackages.get(we);if(!Ae)throw new Error("Assertion failed: The locator should have been registered");let ne=this.tryWorkspaceByLocator(Ae)!==null,Z=async(xe,Ne)=>{let ht=v.get(Ae.locatorHash);if(typeof ht>"u")throw new Error(`Assertion failed: The package (${qr(this.configuration,Ae)}) should have been registered`);let H=[];for(let rt of Ae.dependencies.values()){let Te=this.storedResolutions.get(rt.descriptorHash);if(typeof Te>"u")throw new Error(`Assertion failed: The resolution (${jn(this.configuration,rt)}, from ${qr(this.configuration,Ae)})should have been registered`);let Fe=this.storedPackages.get(Te);if(typeof Fe>"u")throw new Error(`Assertion failed: The package (${Te}, resolved from ${jn(this.configuration,rt)}) should have been registered`);let ke=this.tryWorkspaceByLocator(Fe)===null?I.get(Te):null;if(typeof ke>"u")throw new Error(`Assertion failed: The package (${Te}, resolved from ${jn(this.configuration,rt)}) should have been registered`);ke===xe||ke===null?v.get(Fe.locatorHash)!==null&&H.push([rt,Fe]):!ne&&ht!==null&&xI(z,Te).push(ht)}ht!==null&&await Ne.attachInternalDependencies(Ae,H)};if(ne)for(let[xe,Ne]of E)xe.supportsPackage(Ae,h)&&await Z(xe,Ne);else{let xe=I.get(Ae.locatorHash);if(!xe)throw new Error("Assertion failed: The linker should have been found");let Ne=E.get(xe);if(!Ne)throw new Error("Assertion failed: The installer should have been registered");await Z(xe,Ne)}}for(let[we,Ae]of z){let ne=this.storedPackages.get(we);if(!ne)throw new Error("Assertion failed: The package should have been registered");let Z=I.get(ne.locatorHash);if(!Z)throw new Error("Assertion failed: The linker should have been found");let xe=E.get(Z);if(!xe)throw new Error("Assertion failed: The installer should have been registered");await xe.attachExternalDependents(ne,Ae)}let te=new Map;for(let[we,Ae]of E){let ne=await Ae.finalizeInstall();for(let Z of ne?.records??[])Z.buildRequest.skipped?(L.add(Z.locator.locatorHash),this.skippedBuilds.has(Z.locator.locatorHash)||U.push([Z.locator,Z.buildRequest.explain])):x.set(Z.locator.locatorHash,{buildDirectives:Z.buildRequest.directives,buildLocations:Z.buildLocations});typeof ne?.customData<"u"&&te.set(we.getCustomDataKey(),ne.customData)}if(this.linkersCustomData=te,await _c(R),a==="skip-build")return;for(let[,we]of Fs(U,([Ae])=>ka(Ae)))we(r);let ae=new Set(x.keys()),le=(0,Hx.createHash)("sha512");le.update(process.versions.node),await this.configuration.triggerHook(we=>we.globalHashGeneration,this,we=>{le.update("\0"),le.update(we)});let ce=le.digest("hex"),Ce=new Map,de=we=>{let Ae=Ce.get(we.locatorHash);if(typeof Ae<"u")return Ae;let ne=this.storedPackages.get(we.locatorHash);if(typeof ne>"u")throw new Error("Assertion failed: The package should have been registered");let Z=(0,Hx.createHash)("sha512");Z.update(we.locatorHash),Ce.set(we.locatorHash,"<recursive>");for(let xe of ne.dependencies.values()){let Ne=this.storedResolutions.get(xe.descriptorHash);if(typeof Ne>"u")throw new Error(`Assertion failed: The resolution (${jn(this.configuration,xe)}) should have been registered`);let ht=this.storedPackages.get(Ne);if(typeof ht>"u")throw new Error("Assertion failed: The package should have been registered");Z.update(de(ht))}return Ae=Z.digest("hex"),Ce.set(we.locatorHash,Ae),Ae},Be=(we,Ae)=>{let ne=(0,Hx.createHash)("sha512");ne.update(ce),ne.update(de(we));for(let Z of Ae)ne.update(Z);return ne.digest("hex")},Ee=new Map,g=!1,me=we=>{let Ae=new Set([we.locatorHash]);for(let ne of Ae){let Z=this.storedPackages.get(ne);if(!Z)throw new Error("Assertion failed: The package should have been registered");for(let xe of Z.dependencies.values()){let Ne=this.storedResolutions.get(xe.descriptorHash);if(!Ne)throw new Error(`Assertion failed: The resolution (${jn(this.configuration,xe)}) should have been registered`);if(Ne!==we.locatorHash&&ae.has(Ne))return!1;let ht=this.storedPackages.get(Ne);if(!ht)throw new Error("Assertion failed: The package should have been registered");let H=this.tryWorkspaceByLocator(ht);if(H){if(H.anchoredLocator.locatorHash!==we.locatorHash&&ae.has(H.anchoredLocator.locatorHash))return!1;Ae.add(H.anchoredLocator.locatorHash)}Ae.add(Ne)}}return!0};for(;ae.size>0;){let we=ae.size,Ae=[];for(let ne of ae){let Z=this.storedPackages.get(ne);if(!Z)throw new Error("Assertion failed: The package should have been registered");if(!me(Z))continue;let xe=x.get(Z.locatorHash);if(!xe)throw new Error("Assertion failed: The build directive should have been registered");let Ne=Be(Z,xe.buildLocations);if(this.storedBuildState.get(Z.locatorHash)===Ne){Ee.set(Z.locatorHash,Ne),ae.delete(ne);continue}g||(await this.persistInstallStateFile(),g=!0),this.storedBuildState.has(Z.locatorHash)?r.reportInfo(8,`${qr(this.configuration,Z)} must be rebuilt because its dependency tree changed`):r.reportInfo(7,`${qr(this.configuration,Z)} must be built because it never has been before or the last one failed`);let ht=xe.buildLocations.map(async H=>{if(!K.isAbsolute(H))throw new Error(`Assertion failed: Expected the build location to be absolute (not ${H})`);for(let rt of xe.buildDirectives){let Te=`# This file contains the result of Yarn building a package (${ka(Z)}) +`;switch(rt.type){case 0:Te+=`# Script name: ${rt.script} +`;break;case 1:Te+=`# Script code: ${rt.script} +`;break}let Fe=null;if(!await oe.mktempPromise(async Ye=>{let Se=K.join(Ye,"build.log"),{stdout:et,stderr:Ue}=this.configuration.getSubprocessStreams(Se,{header:Te,prefix:qr(this.configuration,Z),report:r}),b;try{switch(rt.type){case 0:b=await Nb(Z,rt.script,[],{cwd:H,project:this,stdin:Fe,stdout:et,stderr:Ue});break;case 1:b=await fU(Z,rt.script,[],{cwd:H,project:this,stdin:Fe,stdout:et,stderr:Ue});break}}catch(y){Ue.write(y.stack),b=1}if(et.end(),Ue.end(),b===0)return!0;oe.detachTemp(Ye);let w=`${qr(this.configuration,Z)} couldn't be built successfully (exit code ${Ot(this.configuration,b,yt.NUMBER)}, logs can be found here: ${Ot(this.configuration,Se,yt.PATH)})`,S=this.optionalBuilds.has(Z.locatorHash);return S?r.reportInfo(9,w):r.reportError(9,w),Zce&&r.reportFold(ue.fromPortablePath(Se),oe.readFileSync(Se,"utf8")),S}))return!1}return!0});Ae.push(...ht,Promise.allSettled(ht).then(H=>{ae.delete(ne),H.every(rt=>rt.status==="fulfilled"&&rt.value===!0)&&Ee.set(Z.locatorHash,Ne)}))}if(await _c(Ae),we===ae.size){let ne=Array.from(ae).map(Z=>{let xe=this.storedPackages.get(Z);if(!xe)throw new Error("Assertion failed: The package should have been registered");return qr(this.configuration,xe)}).join(", ");r.reportError(3,`Some packages have circular dependencies that make their build order unsatisfiable - as a result they won't be built (affected packages are: ${ne})`);break}}this.storedBuildState=Ee,this.skippedBuilds=L}async installWithNewReport(e,r){return(await Rt.start({configuration:this.configuration,json:e.json,stdout:e.stdout,forceSectionAlignment:!0,includeLogs:!e.json&&!e.quiet,includeVersion:!0},async a=>{await this.install({...r,report:a})})).exitCode()}async install(e){let r=this.configuration.get("nodeLinker");Ke.telemetry?.reportInstall(r);let o=!1;if(await e.report.startTimerPromise("Project validation",{skipIfEmpty:!0},async()=>{this.configuration.get("enableOfflineMode")&&e.report.reportWarning(90,"Offline work is enabled; Yarn won't fetch packages from the remote registry if it can avoid it"),await this.configuration.triggerHook(E=>E.validateProject,this,{reportWarning:(E,I)=>{e.report.reportWarning(E,I)},reportError:(E,I)=>{e.report.reportError(E,I),o=!0}})}),o)return;let a=await this.configuration.getPackageExtensions();for(let E of a.values())for(let[,I]of E)for(let v of I)v.status="inactive";let n=K.join(this.cwd,dr.lockfile),u=null;if(e.immutable)try{u=await oe.readFilePromise(n,"utf8")}catch(E){throw E.code==="ENOENT"?new Jt(28,"The lockfile would have been created by this install, which is explicitly forbidden."):E}await e.report.startTimerPromise("Resolution step",async()=>{await this.resolveEverything(e)}),await e.report.startTimerPromise("Post-resolution validation",{skipIfEmpty:!0},async()=>{LAt(this,e.report);for(let[,E]of a)for(let[,I]of E)for(let v of I)if(v.userProvided){let x=Ot(this.configuration,v,yt.PACKAGE_EXTENSION);switch(v.status){case"inactive":e.report.reportWarning(68,`${x}: No matching package in the dependency tree; you may not need this rule anymore.`);break;case"redundant":e.report.reportWarning(69,`${x}: This rule seems redundant when applied on the original package; the extension may have been applied upstream.`);break}}if(u!==null){let E=L0(u,this.generateLockfile());if(E!==u){let I=dpe(n,n,u,E,void 0,void 0,{maxEditLength:100});if(I){e.report.reportSeparator();for(let v of I.hunks){e.report.reportInfo(null,`@@ -${v.oldStart},${v.oldLines} +${v.newStart},${v.newLines} @@`);for(let x of v.lines)x.startsWith("+")?e.report.reportError(28,Ot(this.configuration,x,yt.ADDED)):x.startsWith("-")?e.report.reportError(28,Ot(this.configuration,x,yt.REMOVED)):e.report.reportInfo(null,Ot(this.configuration,x,"grey"))}e.report.reportSeparator()}throw new Jt(28,"The lockfile would have been modified by this install, which is explicitly forbidden.")}}});for(let E of a.values())for(let[,I]of E)for(let v of I)v.userProvided&&v.status==="active"&&Ke.telemetry?.reportPackageExtension(pg(v,yt.PACKAGE_EXTENSION));await e.report.startTimerPromise("Fetch step",async()=>{await this.fetchEverything(e)});let A=e.immutable?[...new Set(this.configuration.get("immutablePatterns"))].sort():[],p=await Promise.all(A.map(async E=>IS(E,{cwd:this.cwd})));(typeof e.persistProject>"u"||e.persistProject)&&await this.persist(),await e.report.startTimerPromise("Link step",async()=>{if(e.mode==="update-lockfile"){e.report.reportWarning(73,`Skipped due to ${Ot(this.configuration,"mode=update-lockfile",yt.CODE)}`);return}await this.linkEverything(e);let E=await Promise.all(A.map(async I=>IS(I,{cwd:this.cwd})));for(let I=0;I<A.length;++I)p[I]!==E[I]&&e.report.reportError(64,`The checksum for ${A[I]} has been modified by this install, which is explicitly forbidden.`)}),await this.persistInstallStateFile();let h=!1;await e.report.startTimerPromise("Post-install validation",{skipIfEmpty:!0},async()=>{await this.configuration.triggerHook(E=>E.validateProjectAfterInstall,this,{reportWarning:(E,I)=>{e.report.reportWarning(E,I)},reportError:(E,I)=>{e.report.reportError(E,I),h=!0}})}),!h&&await this.configuration.triggerHook(E=>E.afterAllInstalled,this,e)}generateLockfile(){let e=new Map;for(let[n,u]of this.storedResolutions.entries()){let A=e.get(u);A||e.set(u,A=new Set),A.add(n)}let r={},{cacheKey:o}=Gr.getCacheKey(this.configuration);r.__metadata={version:Gx,cacheKey:o};for(let[n,u]of e.entries()){let A=this.originalPackages.get(n);if(!A)continue;let p=[];for(let I of u){let v=this.storedDescriptors.get(I);if(!v)throw new Error("Assertion failed: The descriptor should have been registered");p.push(v)}let h=p.map(I=>xa(I)).sort().join(", "),E=new Ut;E.version=A.linkType==="HARD"?A.version:"0.0.0-use.local",E.languageName=A.languageName,E.dependencies=new Map(A.dependencies),E.peerDependencies=new Map(A.peerDependencies),E.dependenciesMeta=new Map(A.dependenciesMeta),E.peerDependenciesMeta=new Map(A.peerDependenciesMeta),E.bin=new Map(A.bin),r[h]={...E.exportTo({},{compatibilityMode:!1}),linkType:A.linkType.toLowerCase(),resolution:ka(A),checksum:this.storedChecksums.get(A.locatorHash),conditions:A.conditions||void 0}}return`${[`# This file is generated by running "yarn install" inside your project. +`,`# Manual changes might be lost - proceed with caution! +`].join("")} +`+Da(r)}async persistLockfile(){let e=K.join(this.cwd,dr.lockfile),r="";try{r=await oe.readFilePromise(e,"utf8")}catch{}let o=this.generateLockfile(),a=L0(r,o);a!==r&&(await oe.writeFilePromise(e,a),this.lockFileChecksum=$pe(a),this.lockfileNeedsRefresh=!1)}async persistInstallStateFile(){let e=[];for(let u of Object.values(w_))e.push(...u);let r=(0,qx.default)(this,e),o=I_.default.serialize(r),a=zi(o);if(this.installStateChecksum===a)return;let n=this.configuration.get("installStatePath");await oe.mkdirPromise(K.dirname(n),{recursive:!0}),await oe.writeFilePromise(n,await FAt(o)),this.installStateChecksum=a}async restoreInstallState({restoreLinkersCustomData:e=!0,restoreResolutions:r=!0,restoreBuildState:o=!0}={}){let a=this.configuration.get("installStatePath"),n;try{let u=await RAt(await oe.readFilePromise(a));n=I_.default.deserialize(u),this.installStateChecksum=zi(u)}catch{r&&await this.applyLightResolution();return}e&&typeof n.linkersCustomData<"u"&&(this.linkersCustomData=n.linkersCustomData),o&&Object.assign(this,(0,qx.default)(n,w_.restoreBuildState)),r&&(n.lockFileChecksum===this.lockFileChecksum?Object.assign(this,(0,qx.default)(n,w_.restoreResolutions)):await this.applyLightResolution())}async applyLightResolution(){await this.resolveEverything({lockfileOnly:!0,report:new ki}),await this.persistInstallStateFile()}async persist(){let e=(0,jx.default)(4);await Promise.all([this.persistLockfile(),...this.workspaces.map(r=>e(()=>r.persistManifest()))])}async cacheCleanup({cache:e,report:r}){if(this.configuration.get("enableGlobalCache"))return null;let o=new Set([".gitignore"]);if(!fO(e.cwd,this.cwd)||!await oe.existsPromise(e.cwd))return null;let a=[];for(let u of await oe.readdirPromise(e.cwd)){if(o.has(u))continue;let A=K.resolve(e.cwd,u);e.markedFiles.has(A)||(e.immutable?r.reportError(56,`${Ot(this.configuration,K.basename(A),"magenta")} appears to be unused and would be marked for deletion, but the cache is immutable`):a.push(oe.lstatPromise(A).then(async p=>(await oe.removePromise(A),p.size))))}if(a.length===0)return null;let n=await Promise.all(a);return{count:a.length,size:n.reduce((u,A)=>u+A,0)}}}});function MAt(t){let o=Math.floor(t.timeNow/864e5),a=t.updateInterval*864e5,n=t.state.lastUpdate??t.timeNow+a+Math.floor(a*t.randomInitialInterval),u=n+a,A=t.state.lastTips??o*864e5,p=A+864e5+8*36e5-t.timeZone,h=u<=t.timeNow,E=p<=t.timeNow,I=null;return(h||E||!t.state.lastUpdate||!t.state.lastTips)&&(I={},I.lastUpdate=h?t.timeNow:n,I.lastTips=A,I.blocks=h?{}:t.state.blocks,I.displayedTips=t.state.displayedTips),{nextState:I,triggerUpdate:h,triggerTips:E,nextTips:E?o*864e5:A}}var Oy,rhe=Et(()=>{Pt();w1();th();Ab();ql();bf();Oy=class{constructor(e,r){this.values=new Map;this.hits=new Map;this.enumerators=new Map;this.nextTips=0;this.displayedTips=[];this.shouldCommitTips=!1;this.configuration=e;let o=this.getRegistryPath();this.isNew=!oe.existsSync(o),this.shouldShowTips=!1,this.sendReport(r),this.startBuffer()}commitTips(){this.shouldShowTips&&(this.shouldCommitTips=!0)}selectTip(e){let r=new Set(this.displayedTips),o=A=>A&&nn?tA(nn,A):!1,a=e.map((A,p)=>p).filter(A=>e[A]&&o(e[A]?.selector));if(a.length===0)return null;let n=a.filter(A=>!r.has(A));if(n.length===0){let A=Math.floor(a.length*.2);this.displayedTips=A>0?this.displayedTips.slice(-A):[],n=a.filter(p=>!r.has(p))}let u=n[Math.floor(Math.random()*n.length)];return this.displayedTips.push(u),this.commitTips(),e[u]}reportVersion(e){this.reportValue("version",e.replace(/-git\..*/,"-git"))}reportCommandName(e){this.reportValue("commandName",e||"<none>")}reportPluginName(e){this.reportValue("pluginName",e)}reportProject(e){this.reportEnumerator("projectCount",e)}reportInstall(e){this.reportHit("installCount",e)}reportPackageExtension(e){this.reportValue("packageExtension",e)}reportWorkspaceCount(e){this.reportValue("workspaceCount",String(e))}reportDependencyCount(e){this.reportValue("dependencyCount",String(e))}reportValue(e,r){bm(this.values,e).add(r)}reportEnumerator(e,r){bm(this.enumerators,e).add(zi(r))}reportHit(e,r="*"){let o=kI(this.hits,e),a=al(o,r,()=>0);o.set(r,a+1)}getRegistryPath(){let e=this.configuration.get("globalFolder");return K.join(e,"telemetry.json")}sendReport(e){let r=this.getRegistryPath(),o;try{o=oe.readJsonSync(r)}catch{o={}}let{nextState:a,triggerUpdate:n,triggerTips:u,nextTips:A}=MAt({state:o,timeNow:Date.now(),timeZone:new Date().getTimezoneOffset()*60*1e3,randomInitialInterval:Math.random(),updateInterval:this.configuration.get("telemetryInterval")});if(this.nextTips=A,this.displayedTips=o.displayedTips??[],a!==null)try{oe.mkdirSync(K.dirname(r),{recursive:!0}),oe.writeJsonSync(r,a)}catch{return!1}if(u&&this.configuration.get("enableTips")&&(this.shouldShowTips=!0),n){let p=o.blocks??{};if(Object.keys(p).length===0){let h=`https://browser-http-intake.logs.datadoghq.eu/v1/input/${e}?ddsource=yarn`,E=I=>x4(h,I,{configuration:this.configuration}).catch(()=>{});for(let[I,v]of Object.entries(o.blocks??{})){if(Object.keys(v).length===0)continue;let x=v;x.userId=I,x.reportType="primary";for(let L of Object.keys(x.enumerators??{}))x.enumerators[L]=x.enumerators[L].length;E(x);let C=new Map,R=20;for(let[L,U]of Object.entries(x.values))U.length>0&&C.set(L,U.slice(0,R));for(;C.size>0;){let L={};L.userId=I,L.reportType="secondary",L.metrics={};for(let[U,z]of C)L.metrics[U]=z.shift(),z.length===0&&C.delete(U);E(L)}}}}return!0}applyChanges(){let e=this.getRegistryPath(),r;try{r=oe.readJsonSync(e)}catch{r={}}let o=this.configuration.get("telemetryUserId")??"*",a=r.blocks=r.blocks??{},n=a[o]=a[o]??{};for(let u of this.hits.keys()){let A=n.hits=n.hits??{},p=A[u]=A[u]??{};for(let[h,E]of this.hits.get(u))p[h]=(p[h]??0)+E}for(let u of["values","enumerators"])for(let A of this[u].keys()){let p=n[u]=n[u]??{};p[A]=[...new Set([...p[A]??[],...this[u].get(A)??[]])]}this.shouldCommitTips&&(r.lastTips=this.nextTips,r.displayedTips=this.displayedTips),oe.mkdirSync(K.dirname(e),{recursive:!0}),oe.writeJsonSync(e,r)}startBuffer(){process.on("exit",()=>{try{this.applyChanges()}catch{}})}}});var Y1={};Vt(Y1,{BuildDirectiveType:()=>Mx,CACHE_CHECKPOINT:()=>r_,CACHE_VERSION:()=>Lx,Cache:()=>Gr,Configuration:()=>Ke,DEFAULT_RC_FILENAME:()=>L4,FormatType:()=>Tle,InstallMode:()=>hl,LEGACY_PLUGINS:()=>l1,LOCKFILE_VERSION:()=>Gx,LegacyMigrationResolver:()=>Ty,LightReport:()=>AA,LinkType:()=>Fm,LockfileResolver:()=>Ny,Manifest:()=>Ut,MessageName:()=>wr,MultiFetcher:()=>Wm,PackageExtensionStatus:()=>pL,PackageExtensionType:()=>fL,PeerWarningType:()=>Yx,Project:()=>kt,Report:()=>Zs,ReportError:()=>Jt,SettingsType:()=>c1,StreamReport:()=>Rt,TAG_REGEXP:()=>ly,TelemetryManager:()=>Oy,ThrowReport:()=>ki,VirtualFetcher:()=>Km,WindowsLinkType:()=>yb,Workspace:()=>My,WorkspaceFetcher:()=>Vm,WorkspaceResolver:()=>ei,YarnVersion:()=>nn,execUtils:()=>Ur,folderUtils:()=>RS,formatUtils:()=>pe,hashUtils:()=>wn,httpUtils:()=>sn,miscUtils:()=>He,nodeUtils:()=>Xi,parseMessageName:()=>ZD,reportOptionDeprecations:()=>uy,scriptUtils:()=>An,semverUtils:()=>Lr,stringifyMessageName:()=>Ku,structUtils:()=>G,tgzUtils:()=>$i,treeUtils:()=>fs});var Ge=Et(()=>{hb();TS();jl();th();Ab();ql();pb();dU();bf();bo();rpe();cpe();n_();u1();u1();Ape();i_();fpe();s_();Gm();$D();tO();the();Wl();I1();rhe();E_();nO();iO();mg();C_();w1();Cne()});var lhe=_(($_t,K1)=>{"use strict";var UAt=process.env.TERM_PROGRAM==="Hyper",_At=process.platform==="win32",she=process.platform==="linux",D_={ballotDisabled:"\u2612",ballotOff:"\u2610",ballotOn:"\u2611",bullet:"\u2022",bulletWhite:"\u25E6",fullBlock:"\u2588",heart:"\u2764",identicalTo:"\u2261",line:"\u2500",mark:"\u203B",middot:"\xB7",minus:"\uFF0D",multiplication:"\xD7",obelus:"\xF7",pencilDownRight:"\u270E",pencilRight:"\u270F",pencilUpRight:"\u2710",percent:"%",pilcrow2:"\u2761",pilcrow:"\xB6",plusMinus:"\xB1",section:"\xA7",starsOff:"\u2606",starsOn:"\u2605",upDownArrow:"\u2195"},ohe=Object.assign({},D_,{check:"\u221A",cross:"\xD7",ellipsisLarge:"...",ellipsis:"...",info:"i",question:"?",questionSmall:"?",pointer:">",pointerSmall:"\xBB",radioOff:"( )",radioOn:"(*)",warning:"\u203C"}),ahe=Object.assign({},D_,{ballotCross:"\u2718",check:"\u2714",cross:"\u2716",ellipsisLarge:"\u22EF",ellipsis:"\u2026",info:"\u2139",question:"?",questionFull:"\uFF1F",questionSmall:"\uFE56",pointer:she?"\u25B8":"\u276F",pointerSmall:she?"\u2023":"\u203A",radioOff:"\u25EF",radioOn:"\u25C9",warning:"\u26A0"});K1.exports=_At&&!UAt?ohe:ahe;Reflect.defineProperty(K1.exports,"common",{enumerable:!1,value:D_});Reflect.defineProperty(K1.exports,"windows",{enumerable:!1,value:ohe});Reflect.defineProperty(K1.exports,"other",{enumerable:!1,value:ahe})});var zc=_((e8t,P_)=>{"use strict";var HAt=t=>t!==null&&typeof t=="object"&&!Array.isArray(t),qAt=/[\u001b\u009b][[\]#;?()]*(?:(?:(?:[^\W_]*;?[^\W_]*)\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g,che=()=>{let t={enabled:!0,visible:!0,styles:{},keys:{}};"FORCE_COLOR"in process.env&&(t.enabled=process.env.FORCE_COLOR!=="0");let e=n=>{let u=n.open=`\x1B[${n.codes[0]}m`,A=n.close=`\x1B[${n.codes[1]}m`,p=n.regex=new RegExp(`\\u001b\\[${n.codes[1]}m`,"g");return n.wrap=(h,E)=>{h.includes(A)&&(h=h.replace(p,A+u));let I=u+h+A;return E?I.replace(/\r*\n/g,`${A}$&${u}`):I},n},r=(n,u,A)=>typeof n=="function"?n(u):n.wrap(u,A),o=(n,u)=>{if(n===""||n==null)return"";if(t.enabled===!1)return n;if(t.visible===!1)return"";let A=""+n,p=A.includes(` +`),h=u.length;for(h>0&&u.includes("unstyle")&&(u=[...new Set(["unstyle",...u])].reverse());h-- >0;)A=r(t.styles[u[h]],A,p);return A},a=(n,u,A)=>{t.styles[n]=e({name:n,codes:u}),(t.keys[A]||(t.keys[A]=[])).push(n),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(h){t.alias(n,h)},get(){let h=E=>o(E,h.stack);return Reflect.setPrototypeOf(h,t),h.stack=this.stack?this.stack.concat(n):[n],h}})};return a("reset",[0,0],"modifier"),a("bold",[1,22],"modifier"),a("dim",[2,22],"modifier"),a("italic",[3,23],"modifier"),a("underline",[4,24],"modifier"),a("inverse",[7,27],"modifier"),a("hidden",[8,28],"modifier"),a("strikethrough",[9,29],"modifier"),a("black",[30,39],"color"),a("red",[31,39],"color"),a("green",[32,39],"color"),a("yellow",[33,39],"color"),a("blue",[34,39],"color"),a("magenta",[35,39],"color"),a("cyan",[36,39],"color"),a("white",[37,39],"color"),a("gray",[90,39],"color"),a("grey",[90,39],"color"),a("bgBlack",[40,49],"bg"),a("bgRed",[41,49],"bg"),a("bgGreen",[42,49],"bg"),a("bgYellow",[43,49],"bg"),a("bgBlue",[44,49],"bg"),a("bgMagenta",[45,49],"bg"),a("bgCyan",[46,49],"bg"),a("bgWhite",[47,49],"bg"),a("blackBright",[90,39],"bright"),a("redBright",[91,39],"bright"),a("greenBright",[92,39],"bright"),a("yellowBright",[93,39],"bright"),a("blueBright",[94,39],"bright"),a("magentaBright",[95,39],"bright"),a("cyanBright",[96,39],"bright"),a("whiteBright",[97,39],"bright"),a("bgBlackBright",[100,49],"bgBright"),a("bgRedBright",[101,49],"bgBright"),a("bgGreenBright",[102,49],"bgBright"),a("bgYellowBright",[103,49],"bgBright"),a("bgBlueBright",[104,49],"bgBright"),a("bgMagentaBright",[105,49],"bgBright"),a("bgCyanBright",[106,49],"bgBright"),a("bgWhiteBright",[107,49],"bgBright"),t.ansiRegex=qAt,t.hasColor=t.hasAnsi=n=>(t.ansiRegex.lastIndex=0,typeof n=="string"&&n!==""&&t.ansiRegex.test(n)),t.alias=(n,u)=>{let A=typeof u=="string"?t[u]:u;if(typeof A!="function")throw new TypeError("Expected alias to be the name of an existing color (string) or a function");A.stack||(Reflect.defineProperty(A,"name",{value:n}),t.styles[n]=A,A.stack=[n]),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(p){t.alias(n,p)},get(){let p=h=>o(h,p.stack);return Reflect.setPrototypeOf(p,t),p.stack=this.stack?this.stack.concat(A.stack):A.stack,p}})},t.theme=n=>{if(!HAt(n))throw new TypeError("Expected theme to be an object");for(let u of Object.keys(n))t.alias(u,n[u]);return t},t.alias("unstyle",n=>typeof n=="string"&&n!==""?(t.ansiRegex.lastIndex=0,n.replace(t.ansiRegex,"")):""),t.alias("noop",n=>n),t.none=t.clear=t.noop,t.stripColor=t.unstyle,t.symbols=lhe(),t.define=a,t};P_.exports=che();P_.exports.create=che});var No=_(on=>{"use strict";var jAt=Object.prototype.toString,rc=zc(),uhe=!1,S_=[],Ahe={yellow:"blue",cyan:"red",green:"magenta",black:"white",blue:"yellow",red:"cyan",magenta:"green",white:"black"};on.longest=(t,e)=>t.reduce((r,o)=>Math.max(r,e?o[e].length:o.length),0);on.hasColor=t=>!!t&&rc.hasColor(t);var Kx=on.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);on.nativeType=t=>jAt.call(t).slice(8,-1).toLowerCase().replace(/\s/g,"");on.isAsyncFn=t=>on.nativeType(t)==="asyncfunction";on.isPrimitive=t=>t!=null&&typeof t!="object"&&typeof t!="function";on.resolve=(t,e,...r)=>typeof e=="function"?e.call(t,...r):e;on.scrollDown=(t=[])=>[...t.slice(1),t[0]];on.scrollUp=(t=[])=>[t.pop(),...t];on.reorder=(t=[])=>{let e=t.slice();return e.sort((r,o)=>r.index>o.index?1:r.index<o.index?-1:0),e};on.swap=(t,e,r)=>{let o=t.length,a=r===o?0:r<0?o-1:r,n=t[e];t[e]=t[a],t[a]=n};on.width=(t,e=80)=>{let r=t&&t.columns?t.columns:e;return t&&typeof t.getWindowSize=="function"&&(r=t.getWindowSize()[0]),process.platform==="win32"?r-1:r};on.height=(t,e=20)=>{let r=t&&t.rows?t.rows:e;return t&&typeof t.getWindowSize=="function"&&(r=t.getWindowSize()[1]),r};on.wordWrap=(t,e={})=>{if(!t)return t;typeof e=="number"&&(e={width:e});let{indent:r="",newline:o=` +`+r,width:a=80}=e,n=(o+r).match(/[^\S\n]/g)||[];a-=n.length;let u=`.{1,${a}}([\\s\\u200B]+|$)|[^\\s\\u200B]+?([\\s\\u200B]+|$)`,A=t.trim(),p=new RegExp(u,"g"),h=A.match(p)||[];return h=h.map(E=>E.replace(/\n$/,"")),e.padEnd&&(h=h.map(E=>E.padEnd(a," "))),e.padStart&&(h=h.map(E=>E.padStart(a," "))),r+h.join(o)};on.unmute=t=>{let e=t.stack.find(o=>rc.keys.color.includes(o));return e?rc[e]:t.stack.find(o=>o.slice(2)==="bg")?rc[e.slice(2)]:o=>o};on.pascal=t=>t?t[0].toUpperCase()+t.slice(1):"";on.inverse=t=>{if(!t||!t.stack)return t;let e=t.stack.find(o=>rc.keys.color.includes(o));if(e){let o=rc["bg"+on.pascal(e)];return o?o.black:t}let r=t.stack.find(o=>o.slice(0,2)==="bg");return r?rc[r.slice(2).toLowerCase()]||t:rc.none};on.complement=t=>{if(!t||!t.stack)return t;let e=t.stack.find(o=>rc.keys.color.includes(o)),r=t.stack.find(o=>o.slice(0,2)==="bg");if(e&&!r)return rc[Ahe[e]||e];if(r){let o=r.slice(2).toLowerCase(),a=Ahe[o];return a&&rc["bg"+on.pascal(a)]||t}return rc.none};on.meridiem=t=>{let e=t.getHours(),r=t.getMinutes(),o=e>=12?"pm":"am";e=e%12;let a=e===0?12:e,n=r<10?"0"+r:r;return a+":"+n+" "+o};on.set=(t={},e="",r)=>e.split(".").reduce((o,a,n,u)=>{let A=u.length-1>n?o[a]||{}:r;return!on.isObject(A)&&n<u.length-1&&(A={}),o[a]=A},t);on.get=(t={},e="",r)=>{let o=t[e]==null?e.split(".").reduce((a,n)=>a&&a[n],t):t[e];return o??r};on.mixin=(t,e)=>{if(!Kx(t))return e;if(!Kx(e))return t;for(let r of Object.keys(e)){let o=Object.getOwnPropertyDescriptor(e,r);if(o.hasOwnProperty("value"))if(t.hasOwnProperty(r)&&Kx(o.value)){let a=Object.getOwnPropertyDescriptor(t,r);Kx(a.value)?t[r]=on.merge({},t[r],e[r]):Reflect.defineProperty(t,r,o)}else Reflect.defineProperty(t,r,o);else Reflect.defineProperty(t,r,o)}return t};on.merge=(...t)=>{let e={};for(let r of t)on.mixin(e,r);return e};on.mixinEmitter=(t,e)=>{let r=e.constructor.prototype;for(let o of Object.keys(r)){let a=r[o];typeof a=="function"?on.define(t,o,a.bind(e)):on.define(t,o,a)}};on.onExit=t=>{let e=(r,o)=>{uhe||(uhe=!0,S_.forEach(a=>a()),r===!0&&process.exit(128+o))};S_.length===0&&(process.once("SIGTERM",e.bind(null,!0,15)),process.once("SIGINT",e.bind(null,!0,2)),process.once("exit",e)),S_.push(t)};on.define=(t,e,r)=>{Reflect.defineProperty(t,e,{value:r})};on.defineExport=(t,e,r)=>{let o;Reflect.defineProperty(t,e,{enumerable:!0,configurable:!0,set(a){o=a},get(){return o?o():r()}})}});var fhe=_(qy=>{"use strict";qy.ctrl={a:"first",b:"backward",c:"cancel",d:"deleteForward",e:"last",f:"forward",g:"reset",i:"tab",k:"cutForward",l:"reset",n:"newItem",m:"cancel",j:"submit",p:"search",r:"remove",s:"save",u:"undo",w:"cutLeft",x:"toggleCursor",v:"paste"};qy.shift={up:"shiftUp",down:"shiftDown",left:"shiftLeft",right:"shiftRight",tab:"prev"};qy.fn={up:"pageUp",down:"pageDown",left:"pageLeft",right:"pageRight",delete:"deleteForward"};qy.option={b:"backward",f:"forward",d:"cutRight",left:"cutLeft",up:"altUp",down:"altDown"};qy.keys={pageup:"pageUp",pagedown:"pageDown",home:"home",end:"end",cancel:"cancel",delete:"deleteForward",backspace:"delete",down:"down",enter:"submit",escape:"cancel",left:"left",space:"space",number:"number",return:"submit",right:"right",tab:"next",up:"up"}});var ghe=_((n8t,hhe)=>{"use strict";var phe=ve("readline"),GAt=fhe(),YAt=/^(?:\x1b)([a-zA-Z0-9])$/,WAt=/^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/,KAt={OP:"f1",OQ:"f2",OR:"f3",OS:"f4","[11~":"f1","[12~":"f2","[13~":"f3","[14~":"f4","[[A":"f1","[[B":"f2","[[C":"f3","[[D":"f4","[[E":"f5","[15~":"f5","[17~":"f6","[18~":"f7","[19~":"f8","[20~":"f9","[21~":"f10","[23~":"f11","[24~":"f12","[A":"up","[B":"down","[C":"right","[D":"left","[E":"clear","[F":"end","[H":"home",OA:"up",OB:"down",OC:"right",OD:"left",OE:"clear",OF:"end",OH:"home","[1~":"home","[2~":"insert","[3~":"delete","[4~":"end","[5~":"pageup","[6~":"pagedown","[[5~":"pageup","[[6~":"pagedown","[7~":"home","[8~":"end","[a":"up","[b":"down","[c":"right","[d":"left","[e":"clear","[2$":"insert","[3$":"delete","[5$":"pageup","[6$":"pagedown","[7$":"home","[8$":"end",Oa:"up",Ob:"down",Oc:"right",Od:"left",Oe:"clear","[2^":"insert","[3^":"delete","[5^":"pageup","[6^":"pagedown","[7^":"home","[8^":"end","[Z":"tab"};function VAt(t){return["[a","[b","[c","[d","[e","[2$","[3$","[5$","[6$","[7$","[8$","[Z"].includes(t)}function zAt(t){return["Oa","Ob","Oc","Od","Oe","[2^","[3^","[5^","[6^","[7^","[8^"].includes(t)}var Vx=(t="",e={})=>{let r,o={name:e.name,ctrl:!1,meta:!1,shift:!1,option:!1,sequence:t,raw:t,...e};if(Buffer.isBuffer(t)?t[0]>127&&t[1]===void 0?(t[0]-=128,t="\x1B"+String(t)):t=String(t):t!==void 0&&typeof t!="string"?t=String(t):t||(t=o.sequence||""),o.sequence=o.sequence||t||o.name,t==="\r")o.raw=void 0,o.name="return";else if(t===` +`)o.name="enter";else if(t===" ")o.name="tab";else if(t==="\b"||t==="\x7F"||t==="\x1B\x7F"||t==="\x1B\b")o.name="backspace",o.meta=t.charAt(0)==="\x1B";else if(t==="\x1B"||t==="\x1B\x1B")o.name="escape",o.meta=t.length===2;else if(t===" "||t==="\x1B ")o.name="space",o.meta=t.length===2;else if(t<="")o.name=String.fromCharCode(t.charCodeAt(0)+97-1),o.ctrl=!0;else if(t.length===1&&t>="0"&&t<="9")o.name="number";else if(t.length===1&&t>="a"&&t<="z")o.name=t;else if(t.length===1&&t>="A"&&t<="Z")o.name=t.toLowerCase(),o.shift=!0;else if(r=YAt.exec(t))o.meta=!0,o.shift=/^[A-Z]$/.test(r[1]);else if(r=WAt.exec(t)){let a=[...t];a[0]==="\x1B"&&a[1]==="\x1B"&&(o.option=!0);let n=[r[1],r[2],r[4],r[6]].filter(Boolean).join(""),u=(r[3]||r[5]||1)-1;o.ctrl=!!(u&4),o.meta=!!(u&10),o.shift=!!(u&1),o.code=n,o.name=KAt[n],o.shift=VAt(n)||o.shift,o.ctrl=zAt(n)||o.ctrl}return o};Vx.listen=(t={},e)=>{let{stdin:r}=t;if(!r||r!==process.stdin&&!r.isTTY)throw new Error("Invalid stream passed");let o=phe.createInterface({terminal:!0,input:r});phe.emitKeypressEvents(r,o);let a=(A,p)=>e(A,Vx(A,p),o),n=r.isRaw;return r.isTTY&&r.setRawMode(!0),r.on("keypress",a),o.resume(),()=>{r.isTTY&&r.setRawMode(n),r.removeListener("keypress",a),o.pause(),o.close()}};Vx.action=(t,e,r)=>{let o={...GAt,...r};return e.ctrl?(e.action=o.ctrl[e.name],e):e.option&&o.option?(e.action=o.option[e.name],e):e.shift?(e.action=o.shift[e.name],e):(e.action=o.keys[e.name],e)};hhe.exports=Vx});var mhe=_((i8t,dhe)=>{"use strict";dhe.exports=t=>{t.timers=t.timers||{};let e=t.options.timers;if(e)for(let r of Object.keys(e)){let o=e[r];typeof o=="number"&&(o={interval:o}),JAt(t,r,o)}};function JAt(t,e,r={}){let o=t.timers[e]={name:e,start:Date.now(),ms:0,tick:0},a=r.interval||120;o.frames=r.frames||[],o.loading=!0;let n=setInterval(()=>{o.ms=Date.now()-o.start,o.tick++,t.render()},a);return o.stop=()=>{o.loading=!1,clearInterval(n)},Reflect.defineProperty(o,"interval",{value:n}),t.once("close",()=>o.stop()),o.stop}});var Ehe=_((s8t,yhe)=>{"use strict";var{define:XAt,width:ZAt}=No(),b_=class{constructor(e){let r=e.options;XAt(this,"_prompt",e),this.type=e.type,this.name=e.name,this.message="",this.header="",this.footer="",this.error="",this.hint="",this.input="",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt="",this.buffer="",this.width=ZAt(r.stdout||process.stdout),Object.assign(this,r),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=e.symbols,this.styles=e.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let e={...this};return e.status=this.status,e.buffer=Buffer.from(e.buffer),delete e.clone,e}set color(e){this._color=e}get color(){let e=this.prompt.styles;if(this.cancelled)return e.cancelled;if(this.submitted)return e.submitted;let r=this._color||e[this.status];return typeof r=="function"?r:e.pending}set loading(e){this._loading=e}get loading(){return typeof this._loading=="boolean"?this._loading:this.loadingChoices?"choices":!1}get status(){return this.cancelled?"cancelled":this.submitted?"submitted":"pending"}};yhe.exports=b_});var whe=_((o8t,Che)=>{"use strict";var x_=No(),eo=zc(),k_={default:eo.noop,noop:eo.noop,set inverse(t){this._inverse=t},get inverse(){return this._inverse||x_.inverse(this.primary)},set complement(t){this._complement=t},get complement(){return this._complement||x_.complement(this.primary)},primary:eo.cyan,success:eo.green,danger:eo.magenta,strong:eo.bold,warning:eo.yellow,muted:eo.dim,disabled:eo.gray,dark:eo.dim.gray,underline:eo.underline,set info(t){this._info=t},get info(){return this._info||this.primary},set em(t){this._em=t},get em(){return this._em||this.primary.underline},set heading(t){this._heading=t},get heading(){return this._heading||this.muted.underline},set pending(t){this._pending=t},get pending(){return this._pending||this.primary},set submitted(t){this._submitted=t},get submitted(){return this._submitted||this.success},set cancelled(t){this._cancelled=t},get cancelled(){return this._cancelled||this.danger},set typing(t){this._typing=t},get typing(){return this._typing||this.dim},set placeholder(t){this._placeholder=t},get placeholder(){return this._placeholder||this.primary.dim},set highlight(t){this._highlight=t},get highlight(){return this._highlight||this.inverse}};k_.merge=(t={})=>{t.styles&&typeof t.styles.enabled=="boolean"&&(eo.enabled=t.styles.enabled),t.styles&&typeof t.styles.visible=="boolean"&&(eo.visible=t.styles.visible);let e=x_.merge({},k_,t.styles);delete e.merge;for(let r of Object.keys(eo))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>eo[r]});for(let r of Object.keys(eo.styles))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>eo[r]});return e};Che.exports=k_});var Bhe=_((a8t,Ihe)=>{"use strict";var Q_=process.platform==="win32",Yf=zc(),$At=No(),F_={...Yf.symbols,upDownDoubleArrow:"\u21D5",upDownDoubleArrow2:"\u2B0D",upDownArrow:"\u2195",asterisk:"*",asterism:"\u2042",bulletWhite:"\u25E6",electricArrow:"\u2301",ellipsisLarge:"\u22EF",ellipsisSmall:"\u2026",fullBlock:"\u2588",identicalTo:"\u2261",indicator:Yf.symbols.check,leftAngle:"\u2039",mark:"\u203B",minus:"\u2212",multiplication:"\xD7",obelus:"\xF7",percent:"%",pilcrow:"\xB6",pilcrow2:"\u2761",pencilUpRight:"\u2710",pencilDownRight:"\u270E",pencilRight:"\u270F",plus:"+",plusMinus:"\xB1",pointRight:"\u261E",rightAngle:"\u203A",section:"\xA7",hexagon:{off:"\u2B21",on:"\u2B22",disabled:"\u2B22"},ballot:{on:"\u2611",off:"\u2610",disabled:"\u2612"},stars:{on:"\u2605",off:"\u2606",disabled:"\u2606"},folder:{on:"\u25BC",off:"\u25B6",disabled:"\u25B6"},prefix:{pending:Yf.symbols.question,submitted:Yf.symbols.check,cancelled:Yf.symbols.cross},separator:{pending:Yf.symbols.pointerSmall,submitted:Yf.symbols.middot,cancelled:Yf.symbols.middot},radio:{off:Q_?"( )":"\u25EF",on:Q_?"(*)":"\u25C9",disabled:Q_?"(|)":"\u24BE"},numbers:["\u24EA","\u2460","\u2461","\u2462","\u2463","\u2464","\u2465","\u2466","\u2467","\u2468","\u2469","\u246A","\u246B","\u246C","\u246D","\u246E","\u246F","\u2470","\u2471","\u2472","\u2473","\u3251","\u3252","\u3253","\u3254","\u3255","\u3256","\u3257","\u3258","\u3259","\u325A","\u325B","\u325C","\u325D","\u325E","\u325F","\u32B1","\u32B2","\u32B3","\u32B4","\u32B5","\u32B6","\u32B7","\u32B8","\u32B9","\u32BA","\u32BB","\u32BC","\u32BD","\u32BE","\u32BF"]};F_.merge=t=>{let e=$At.merge({},Yf.symbols,F_,t.symbols);return delete e.merge,e};Ihe.exports=F_});var Dhe=_((l8t,vhe)=>{"use strict";var eft=whe(),tft=Bhe(),rft=No();vhe.exports=t=>{t.options=rft.merge({},t.options.theme,t.options),t.symbols=tft.merge(t.options),t.styles=eft.merge(t.options)}});var khe=_((bhe,xhe)=>{"use strict";var Phe=process.env.TERM_PROGRAM==="Apple_Terminal",nft=zc(),R_=No(),Jc=xhe.exports=bhe,vi="\x1B[",She="\x07",T_=!1,Dh=Jc.code={bell:She,beep:She,beginning:`${vi}G`,down:`${vi}J`,esc:vi,getPosition:`${vi}6n`,hide:`${vi}?25l`,line:`${vi}2K`,lineEnd:`${vi}K`,lineStart:`${vi}1K`,restorePosition:vi+(Phe?"8":"u"),savePosition:vi+(Phe?"7":"s"),screen:`${vi}2J`,show:`${vi}?25h`,up:`${vi}1J`},Og=Jc.cursor={get hidden(){return T_},hide(){return T_=!0,Dh.hide},show(){return T_=!1,Dh.show},forward:(t=1)=>`${vi}${t}C`,backward:(t=1)=>`${vi}${t}D`,nextLine:(t=1)=>`${vi}E`.repeat(t),prevLine:(t=1)=>`${vi}F`.repeat(t),up:(t=1)=>t?`${vi}${t}A`:"",down:(t=1)=>t?`${vi}${t}B`:"",right:(t=1)=>t?`${vi}${t}C`:"",left:(t=1)=>t?`${vi}${t}D`:"",to(t,e){return e?`${vi}${e+1};${t+1}H`:`${vi}${t+1}G`},move(t=0,e=0){let r="";return r+=t<0?Og.left(-t):t>0?Og.right(t):"",r+=e<0?Og.up(-e):e>0?Og.down(e):"",r},restore(t={}){let{after:e,cursor:r,initial:o,input:a,prompt:n,size:u,value:A}=t;if(o=R_.isPrimitive(o)?String(o):"",a=R_.isPrimitive(a)?String(a):"",A=R_.isPrimitive(A)?String(A):"",u){let p=Jc.cursor.up(u)+Jc.cursor.to(n.length),h=a.length-r;return h>0&&(p+=Jc.cursor.left(h)),p}if(A||e){let p=!a&&o?-o.length:-a.length+r;return e&&(p-=e.length),a===""&&o&&!n.includes(o)&&(p+=o.length),Jc.cursor.move(p)}}},N_=Jc.erase={screen:Dh.screen,up:Dh.up,down:Dh.down,line:Dh.line,lineEnd:Dh.lineEnd,lineStart:Dh.lineStart,lines(t){let e="";for(let r=0;r<t;r++)e+=Jc.erase.line+(r<t-1?Jc.cursor.up(1):"");return t&&(e+=Jc.code.beginning),e}};Jc.clear=(t="",e=process.stdout.columns)=>{if(!e)return N_.line+Og.to(0);let r=n=>[...nft.unstyle(n)].length,o=t.split(/\r?\n/),a=0;for(let n of o)a+=1+Math.floor(Math.max(r(n)-1,0)/e);return(N_.line+Og.prevLine()).repeat(a-1)+N_.line+Og.to(0)}});var jy=_((c8t,Fhe)=>{"use strict";var ift=ve("events"),Qhe=zc(),L_=ghe(),sft=mhe(),oft=Ehe(),aft=Dhe(),Na=No(),Ug=khe(),M_=class t extends ift{constructor(e={}){super(),this.name=e.name,this.type=e.type,this.options=e,aft(this),sft(this),this.state=new oft(this),this.initial=[e.initial,e.default].find(r=>r!=null),this.stdout=e.stdout||process.stdout,this.stdin=e.stdin||process.stdin,this.scale=e.scale||1,this.term=this.options.term||process.env.TERM_PROGRAM,this.margin=cft(this.options.margin),this.setMaxListeners(0),lft(this)}async keypress(e,r={}){this.keypressed=!0;let o=L_.action(e,L_(e,r),this.options.actions);this.state.keypress=o,this.emit("keypress",e,o),this.emit("state",this.state.clone());let a=this.options[o.action]||this[o.action]||this.dispatch;if(typeof a=="function")return await a.call(this,e,o);this.alert()}alert(){delete this.state.alert,this.options.show===!1?this.emit("alert"):this.stdout.write(Ug.code.beep)}cursorHide(){this.stdout.write(Ug.cursor.hide()),Na.onExit(()=>this.cursorShow())}cursorShow(){this.stdout.write(Ug.cursor.show())}write(e){e&&(this.stdout&&this.state.show!==!1&&this.stdout.write(e),this.state.buffer+=e)}clear(e=0){let r=this.state.buffer;this.state.buffer="",!(!r&&!e||this.options.show===!1)&&this.stdout.write(Ug.cursor.down(e)+Ug.clear(r,this.width))}restore(){if(this.state.closed||this.options.show===!1)return;let{prompt:e,after:r,rest:o}=this.sections(),{cursor:a,initial:n="",input:u="",value:A=""}=this,p=this.state.size=o.length,h={after:r,cursor:a,initial:n,input:u,prompt:e,size:p,value:A},E=Ug.cursor.restore(h);E&&this.stdout.write(E)}sections(){let{buffer:e,input:r,prompt:o}=this.state;o=Qhe.unstyle(o);let a=Qhe.unstyle(e),n=a.indexOf(o),u=a.slice(0,n),p=a.slice(n).split(` +`),h=p[0],E=p[p.length-1],v=(o+(r?" "+r:"")).length,x=v<h.length?h.slice(v+1):"";return{header:u,prompt:h,after:x,rest:p.slice(1),last:E}}async submit(){this.state.submitted=!0,this.state.validating=!0,this.options.onSubmit&&await this.options.onSubmit.call(this,this.name,this.value,this);let e=this.state.error||await this.validate(this.value,this.state);if(e!==!0){let r=` +`+this.symbols.pointer+" ";typeof e=="string"?r+=e.trim():r+="Invalid input",this.state.error=` +`+this.styles.danger(r),this.state.submitted=!1,await this.render(),await this.alert(),this.state.validating=!1,this.state.error=void 0;return}this.state.validating=!1,await this.render(),await this.close(),this.value=await this.result(this.value),this.emit("submit",this.value)}async cancel(e){this.state.cancelled=this.state.submitted=!0,await this.render(),await this.close(),typeof this.options.onCancel=="function"&&await this.options.onCancel.call(this,this.name,this.value,this),this.emit("cancel",await this.error(e))}async close(){this.state.closed=!0;try{let e=this.sections(),r=Math.ceil(e.prompt.length/this.width);e.rest&&this.write(Ug.cursor.down(e.rest.length)),this.write(` +`.repeat(r))}catch{}this.emit("close")}start(){!this.stop&&this.options.show!==!1&&(this.stop=L_.listen(this,this.keypress.bind(this)),this.once("close",this.stop))}async skip(){return this.skipped=this.options.skip===!0,typeof this.options.skip=="function"&&(this.skipped=await this.options.skip.call(this,this.name,this.value)),this.skipped}async initialize(){let{format:e,options:r,result:o}=this;if(this.format=()=>e.call(this,this.value),this.result=()=>o.call(this,this.value),typeof r.initial=="function"&&(this.initial=await r.initial.call(this,this)),typeof r.onRun=="function"&&await r.onRun.call(this,this),typeof r.onSubmit=="function"){let a=r.onSubmit.bind(this),n=this.submit.bind(this);delete this.options.onSubmit,this.submit=async()=>(await a(this.name,this.value,this),n())}await this.start(),await this.render()}render(){throw new Error("expected prompt to have a custom render method")}run(){return new Promise(async(e,r)=>{if(this.once("submit",e),this.once("cancel",r),await this.skip())return this.render=()=>{},this.submit();await this.initialize(),this.emit("run")})}async element(e,r,o){let{options:a,state:n,symbols:u,timers:A}=this,p=A&&A[e];n.timer=p;let h=a[e]||n[e]||u[e],E=r&&r[e]!=null?r[e]:await h;if(E==="")return E;let I=await this.resolve(E,n,r,o);return!I&&r&&r[e]?this.resolve(h,n,r,o):I}async prefix(){let e=await this.element("prefix")||this.symbols,r=this.timers&&this.timers.prefix,o=this.state;return o.timer=r,Na.isObject(e)&&(e=e[o.status]||e.pending),Na.hasColor(e)?e:(this.styles[o.status]||this.styles.pending)(e)}async message(){let e=await this.element("message");return Na.hasColor(e)?e:this.styles.strong(e)}async separator(){let e=await this.element("separator")||this.symbols,r=this.timers&&this.timers.separator,o=this.state;o.timer=r;let a=e[o.status]||e.pending||o.separator,n=await this.resolve(a,o);return Na.isObject(n)&&(n=n[o.status]||n.pending),Na.hasColor(n)?n:this.styles.muted(n)}async pointer(e,r){let o=await this.element("pointer",e,r);if(typeof o=="string"&&Na.hasColor(o))return o;if(o){let a=this.styles,n=this.index===r,u=n?a.primary:h=>h,A=await this.resolve(o[n?"on":"off"]||o,this.state),p=Na.hasColor(A)?A:u(A);return n?p:" ".repeat(A.length)}}async indicator(e,r){let o=await this.element("indicator",e,r);if(typeof o=="string"&&Na.hasColor(o))return o;if(o){let a=this.styles,n=e.enabled===!0,u=n?a.success:a.dark,A=o[n?"on":"off"]||o;return Na.hasColor(A)?A:u(A)}return""}body(){return null}footer(){if(this.state.status==="pending")return this.element("footer")}header(){if(this.state.status==="pending")return this.element("header")}async hint(){if(this.state.status==="pending"&&!this.isValue(this.state.input)){let e=await this.element("hint");return Na.hasColor(e)?e:this.styles.muted(e)}}error(e){return this.state.submitted?"":e||this.state.error}format(e){return e}result(e){return e}validate(e){return this.options.required===!0?this.isValue(e):!0}isValue(e){return e!=null&&e!==""}resolve(e,...r){return Na.resolve(this,e,...r)}get base(){return t.prototype}get style(){return this.styles[this.state.status]}get height(){return this.options.rows||Na.height(this.stdout,25)}get width(){return this.options.columns||Na.width(this.stdout,80)}get size(){return{width:this.width,height:this.height}}set cursor(e){this.state.cursor=e}get cursor(){return this.state.cursor}set input(e){this.state.input=e}get input(){return this.state.input}set value(e){this.state.value=e}get value(){let{input:e,value:r}=this.state,o=[r,e].find(this.isValue.bind(this));return this.isValue(o)?o:this.initial}static get prompt(){return e=>new this(e).run()}};function lft(t){let e=a=>t[a]===void 0||typeof t[a]=="function",r=["actions","choices","initial","margin","roles","styles","symbols","theme","timers","value"],o=["body","footer","error","header","hint","indicator","message","prefix","separator","skip"];for(let a of Object.keys(t.options)){if(r.includes(a)||/^on[A-Z]/.test(a))continue;let n=t.options[a];typeof n=="function"&&e(a)?o.includes(a)||(t[a]=n.bind(t)):typeof t[a]!="function"&&(t[a]=n)}}function cft(t){typeof t=="number"&&(t=[t,t,t,t]);let e=[].concat(t||[]),r=a=>a%2===0?` +`:" ",o=[];for(let a=0;a<4;a++){let n=r(a);e[a]?o.push(n.repeat(e[a])):o.push("")}return o}Fhe.exports=M_});var Nhe=_((u8t,The)=>{"use strict";var uft=No(),Rhe={default(t,e){return e},checkbox(t,e){throw new Error("checkbox role is not implemented yet")},editable(t,e){throw new Error("editable role is not implemented yet")},expandable(t,e){throw new Error("expandable role is not implemented yet")},heading(t,e){return e.disabled="",e.indicator=[e.indicator," "].find(r=>r!=null),e.message=e.message||"",e},input(t,e){throw new Error("input role is not implemented yet")},option(t,e){return Rhe.default(t,e)},radio(t,e){throw new Error("radio role is not implemented yet")},separator(t,e){return e.disabled="",e.indicator=[e.indicator," "].find(r=>r!=null),e.message=e.message||t.symbols.line.repeat(5),e},spacer(t,e){return e}};The.exports=(t,e={})=>{let r=uft.merge({},Rhe,e.roles);return r[t]||r.default}});var V1=_((A8t,Ohe)=>{"use strict";var Aft=zc(),fft=jy(),pft=Nhe(),zx=No(),{reorder:O_,scrollUp:hft,scrollDown:gft,isObject:Lhe,swap:dft}=zx,U_=class extends fft{constructor(e){super(e),this.cursorHide(),this.maxSelected=e.maxSelected||1/0,this.multiple=e.multiple||!1,this.initial=e.initial||0,this.delay=e.delay||0,this.longest=0,this.num=""}async initialize(){typeof this.options.initial=="function"&&(this.initial=await this.options.initial.call(this)),await this.reset(!0),await super.initialize()}async reset(){let{choices:e,initial:r,autofocus:o,suggest:a}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(e)),this.choices.forEach(n=>n.enabled=!1),typeof a!="function"&&this.selectable.length===0)throw new Error("At least one choice must be selectable");Lhe(r)&&(r=Object.keys(r)),Array.isArray(r)?(o!=null&&(this.index=this.findIndex(o)),r.forEach(n=>this.enable(this.find(n))),await this.render()):(o!=null&&(r=o),typeof r=="string"&&(r=this.findIndex(r)),typeof r=="number"&&r>-1&&(this.index=Math.max(0,Math.min(r,this.choices.length)),this.enable(this.find(this.index)))),this.isDisabled(this.focused)&&await this.down()}async toChoices(e,r){this.state.loadingChoices=!0;let o=[],a=0,n=async(u,A)=>{typeof u=="function"&&(u=await u.call(this)),u instanceof Promise&&(u=await u);for(let p=0;p<u.length;p++){let h=u[p]=await this.toChoice(u[p],a++,A);o.push(h),h.choices&&await n(h.choices,h)}return o};return n(e,r).then(u=>(this.state.loadingChoices=!1,u))}async toChoice(e,r,o){if(typeof e=="function"&&(e=await e.call(this,this)),e instanceof Promise&&(e=await e),typeof e=="string"&&(e={name:e}),e.normalized)return e;e.normalized=!0;let a=e.value;if(e=pft(e.role,this.options)(this,e),typeof e.disabled=="string"&&!e.hint&&(e.hint=e.disabled,e.disabled=!0),e.disabled===!0&&e.hint==null&&(e.hint="(disabled)"),e.index!=null)return e;e.name=e.name||e.key||e.title||e.value||e.message,e.message=e.message||e.name||"",e.value=[e.value,e.name].find(this.isValue.bind(this)),e.input="",e.index=r,e.cursor=0,zx.define(e,"parent",o),e.level=o?o.level+1:1,e.indent==null&&(e.indent=o?o.indent+" ":e.indent||""),e.path=o?o.path+"."+e.name:e.name,e.enabled=!!(this.multiple&&!this.isDisabled(e)&&(e.enabled||this.isSelected(e))),this.isDisabled(e)||(this.longest=Math.max(this.longest,Aft.unstyle(e.message).length));let u={...e};return e.reset=(A=u.input,p=u.value)=>{for(let h of Object.keys(u))e[h]=u[h];e.input=A,e.value=p},a==null&&typeof e.initial=="function"&&(e.input=await e.initial.call(this,this.state,e,r)),e}async onChoice(e,r){this.emit("choice",e,r,this),typeof e.onChoice=="function"&&await e.onChoice.call(this,this.state,e,r)}async addChoice(e,r,o){let a=await this.toChoice(e,r,o);return this.choices.push(a),this.index=this.choices.length-1,this.limit=this.choices.length,a}async newItem(e,r,o){let a={name:"New choice name?",editable:!0,newChoice:!0,...e},n=await this.addChoice(a,r,o);return n.updateChoice=()=>{delete n.newChoice,n.name=n.message=n.input,n.input="",n.cursor=0},this.render()}indent(e){return e.indent==null?e.level>1?" ".repeat(e.level-1):"":e.indent}dispatch(e,r){if(this.multiple&&this[r.name])return this[r.name]();this.alert()}focus(e,r){return typeof r!="boolean"&&(r=e.enabled),r&&!e.enabled&&this.selected.length>=this.maxSelected?this.alert():(this.index=e.index,e.enabled=r&&!this.isDisabled(e),e)}space(){return this.multiple?(this.toggle(this.focused),this.render()):this.alert()}a(){if(this.maxSelected<this.choices.length)return this.alert();let e=this.selectable.every(r=>r.enabled);return this.choices.forEach(r=>r.enabled=!e),this.render()}i(){return this.choices.length-this.selected.length>this.maxSelected?this.alert():(this.choices.forEach(e=>e.enabled=!e.enabled),this.render())}g(e=this.focused){return this.choices.some(r=>!!r.parent)?(this.toggle(e.parent&&!e.choices?e.parent:e),this.render()):this.a()}toggle(e,r){if(!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();typeof r!="boolean"&&(r=!e.enabled),e.enabled=r,e.choices&&e.choices.forEach(a=>this.toggle(a,r));let o=e.parent;for(;o;){let a=o.choices.filter(n=>this.isDisabled(n));o.enabled=a.every(n=>n.enabled===!0),o=o.parent}return Mhe(this,this.choices),this.emit("toggle",e,this),e}enable(e){return this.selected.length>=this.maxSelected?this.alert():(e.enabled=!this.isDisabled(e),e.choices&&e.choices.forEach(this.enable.bind(this)),e)}disable(e){return e.enabled=!1,e.choices&&e.choices.forEach(this.disable.bind(this)),e}number(e){this.num+=e;let r=o=>{let a=Number(o);if(a>this.choices.length-1)return this.alert();let n=this.focused,u=this.choices.find(A=>a===A.index);if(!u.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(this.visible.indexOf(u)===-1){let A=O_(this.choices),p=A.indexOf(u);if(n.index>p){let h=A.slice(p,p+this.limit),E=A.filter(I=>!h.includes(I));this.choices=h.concat(E)}else{let h=p-this.limit+1;this.choices=A.slice(h).concat(A.slice(0,h))}}return this.index=this.choices.indexOf(u),this.toggle(this.focused),this.render()};return clearTimeout(this.numberTimeout),new Promise(o=>{let a=this.choices.length,n=this.num,u=(A=!1,p)=>{clearTimeout(this.numberTimeout),A&&(p=r(n)),this.num="",o(p)};if(n==="0"||n.length===1&&+(n+"0")>a)return u(!0);if(Number(n)>a)return u(!1,this.alert());this.numberTimeout=setTimeout(()=>u(!0),this.delay)})}home(){return this.choices=O_(this.choices),this.index=0,this.render()}end(){let e=this.choices.length-this.limit,r=O_(this.choices);return this.choices=r.slice(e).concat(r.slice(0,e)),this.index=this.limit-1,this.render()}first(){return this.index=0,this.render()}last(){return this.index=this.visible.length-1,this.render()}prev(){return this.visible.length<=1?this.alert():this.up()}next(){return this.visible.length<=1?this.alert():this.down()}right(){return this.cursor>=this.input.length?this.alert():(this.cursor++,this.render())}left(){return this.cursor<=0?this.alert():(this.cursor--,this.render())}up(){let e=this.choices.length,r=this.visible.length,o=this.index;return this.options.scroll===!1&&o===0?this.alert():e>r&&o===0?this.scrollUp():(this.index=(o-1%e+e)%e,this.isDisabled()?this.up():this.render())}down(){let e=this.choices.length,r=this.visible.length,o=this.index;return this.options.scroll===!1&&o===r-1?this.alert():e>r&&o===r-1?this.scrollDown():(this.index=(o+1)%e,this.isDisabled()?this.down():this.render())}scrollUp(e=0){return this.choices=hft(this.choices),this.index=e,this.isDisabled()?this.up():this.render()}scrollDown(e=this.visible.length-1){return this.choices=gft(this.choices),this.index=e,this.isDisabled()?this.down():this.render()}async shiftUp(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index-1),await this.up(),this.sorting=!1;return}return this.scrollUp(this.index)}async shiftDown(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index+1),await this.down(),this.sorting=!1;return}return this.scrollDown(this.index)}pageUp(){return this.visible.length<=1?this.alert():(this.limit=Math.max(this.limit-1,0),this.index=Math.min(this.limit-1,this.index),this._limit=this.limit,this.isDisabled()?this.up():this.render())}pageDown(){return this.visible.length>=this.choices.length?this.alert():(this.index=Math.max(0,this.index),this.limit=Math.min(this.limit+1,this.choices.length),this._limit=this.limit,this.isDisabled()?this.down():this.render())}swap(e){dft(this.choices,this.index,e)}isDisabled(e=this.focused){return e&&["disabled","collapsed","hidden","completing","readonly"].some(o=>e[o]===!0)?!0:e&&e.role==="heading"}isEnabled(e=this.focused){if(Array.isArray(e))return e.every(r=>this.isEnabled(r));if(e.choices){let r=e.choices.filter(o=>!this.isDisabled(o));return e.enabled&&r.every(o=>this.isEnabled(o))}return e.enabled&&!this.isDisabled(e)}isChoice(e,r){return e.name===r||e.index===Number(r)}isSelected(e){return Array.isArray(this.initial)?this.initial.some(r=>this.isChoice(e,r)):this.isChoice(e,this.initial)}map(e=[],r="value"){return[].concat(e||[]).reduce((o,a)=>(o[a]=this.find(a,r),o),{})}filter(e,r){let a=typeof e=="function"?e:(A,p)=>[A.name,p].includes(e),u=(this.options.multiple?this.state._choices:this.choices).filter(a);return r?u.map(A=>A[r]):u}find(e,r){if(Lhe(e))return r?e[r]:e;let a=typeof e=="function"?e:(u,A)=>[u.name,A].includes(e),n=this.choices.find(a);if(n)return r?n[r]:n}findIndex(e){return this.choices.indexOf(this.find(e))}async submit(){let e=this.focused;if(!e)return this.alert();if(e.newChoice)return e.input?(e.updateChoice(),this.render()):this.alert();if(this.choices.some(u=>u.newChoice))return this.alert();let{reorder:r,sort:o}=this.options,a=this.multiple===!0,n=this.selected;return n===void 0?this.alert():(Array.isArray(n)&&r!==!1&&o!==!0&&(n=zx.reorder(n)),this.value=a?n.map(u=>u.name):n.name,super.submit())}set choices(e=[]){this.state._choices=this.state._choices||[],this.state.choices=e;for(let r of e)this.state._choices.some(o=>o.name===r.name)||this.state._choices.push(r);if(!this._initial&&this.options.initial){this._initial=!0;let r=this.initial;if(typeof r=="string"||typeof r=="number"){let o=this.find(r);o&&(this.initial=o.index,this.focus(o,!0))}}}get choices(){return Mhe(this,this.state.choices||[])}set visible(e){this.state.visible=e}get visible(){return(this.state.visible||this.choices).slice(0,this.limit)}set limit(e){this.state.limit=e}get limit(){let{state:e,options:r,choices:o}=this,a=e.limit||this._limit||r.limit||o.length;return Math.min(a,this.height)}set value(e){super.value=e}get value(){return typeof super.value!="string"&&super.value===this.initial?this.input:super.value}set index(e){this.state.index=e}get index(){return Math.max(0,this.state?this.state.index:0)}get enabled(){return this.filter(this.isEnabled.bind(this))}get focused(){let e=this.choices[this.index];return e&&this.state.submitted&&this.multiple!==!0&&(e.enabled=!0),e}get selectable(){return this.choices.filter(e=>!this.isDisabled(e))}get selected(){return this.multiple?this.enabled:this.focused}};function Mhe(t,e){if(e instanceof Promise)return e;if(typeof e=="function"){if(zx.isAsyncFn(e))return e;e=e.call(t,t)}for(let r of e){if(Array.isArray(r.choices)){let o=r.choices.filter(a=>!t.isDisabled(a));r.enabled=o.every(a=>a.enabled===!0)}t.isDisabled(r)===!0&&delete r.enabled}return e}Ohe.exports=U_});var Ph=_((f8t,Uhe)=>{"use strict";var mft=V1(),__=No(),H_=class extends mft{constructor(e){super(e),this.emptyError=this.options.emptyError||"No items were selected"}async dispatch(e,r){if(this.multiple)return this[r.name]?await this[r.name](e,r):await super.dispatch(e,r);this.alert()}separator(){if(this.options.separator)return super.separator();let e=this.styles.muted(this.symbols.ellipsis);return this.state.submitted?super.separator():e}pointer(e,r){return!this.multiple||this.options.pointer?super.pointer(e,r):""}indicator(e,r){return this.multiple?super.indicator(e,r):""}choiceMessage(e,r){let o=this.resolve(e.message,this.state,e,r);return e.role==="heading"&&!__.hasColor(o)&&(o=this.styles.strong(o)),this.resolve(o,this.state,e,r)}choiceSeparator(){return":"}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=await this.pointer(e,r),n=await this.indicator(e,r)+(e.pad||""),u=await this.resolve(e.hint,this.state,e,r);u&&!__.hasColor(u)&&(u=this.styles.muted(u));let A=this.indent(e),p=await this.choiceMessage(e,r),h=()=>[this.margin[3],A+a+n,p,this.margin[1],u].filter(Boolean).join(" ");return e.role==="heading"?h():e.disabled?(__.hasColor(p)||(p=this.styles.disabled(p)),h()):(o&&(p=this.styles.em(p)),h())}async renderChoices(){if(this.state.loading==="choices")return this.styles.warning("Loading choices");if(this.state.submitted)return"";let e=this.visible.map(async(n,u)=>await this.renderChoice(n,u)),r=await Promise.all(e);r.length||r.push(this.styles.danger("No matching choices"));let o=this.margin[0]+r.join(` +`),a;return this.options.choicesHeader&&(a=await this.resolve(this.options.choicesHeader,this.state)),[a,o].filter(Boolean).join(` +`)}format(){return!this.state.submitted||this.state.cancelled?"":Array.isArray(this.selected)?this.selected.map(e=>this.styles.primary(e.name)).join(", "):this.styles.primary(this.selected.name)}async render(){let{submitted:e,size:r}=this.state,o="",a=await this.header(),n=await this.prefix(),u=await this.separator(),A=await this.message();this.options.promptLine!==!1&&(o=[n,A,u,""].join(" "),this.state.prompt=o);let p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),I=await this.footer();p&&(o+=p),h&&!o.includes(h)&&(o+=" "+h),e&&!p&&!E.trim()&&this.multiple&&this.emptyError!=null&&(o+=this.styles.danger(this.emptyError)),this.clear(r),this.write([a,o,E,I].filter(Boolean).join(` +`)),this.write(this.margin[2]),this.restore()}};Uhe.exports=H_});var Hhe=_((p8t,_he)=>{"use strict";var yft=Ph(),Eft=(t,e)=>{let r=t.toLowerCase();return o=>{let n=o.toLowerCase().indexOf(r),u=e(o.slice(n,n+r.length));return n>=0?o.slice(0,n)+u+o.slice(n+r.length):o}},q_=class extends yft{constructor(e){super(e),this.cursorShow()}moveCursor(e){this.state.cursor+=e}dispatch(e){return this.append(e)}space(e){return this.options.multiple?super.space(e):this.append(e)}append(e){let{cursor:r,input:o}=this.state;return this.input=o.slice(0,r)+e+o.slice(r),this.moveCursor(1),this.complete()}delete(){let{cursor:e,input:r}=this.state;return r?(this.input=r.slice(0,e-1)+r.slice(e),this.moveCursor(-1),this.complete()):this.alert()}deleteForward(){let{cursor:e,input:r}=this.state;return r[e]===void 0?this.alert():(this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.complete())}number(e){return this.append(e)}async complete(){this.completing=!0,this.choices=await this.suggest(this.input,this.state._choices),this.state.limit=void 0,this.index=Math.min(Math.max(this.visible.length-1,0),this.index),await this.render(),this.completing=!1}suggest(e=this.input,r=this.state._choices){if(typeof this.options.suggest=="function")return this.options.suggest.call(this,e,r);let o=e.toLowerCase();return r.filter(a=>a.message.toLowerCase().includes(o))}pointer(){return""}format(){if(!this.focused)return this.input;if(this.options.multiple&&this.state.submitted)return this.selected.map(e=>this.styles.primary(e.message)).join(", ");if(this.state.submitted){let e=this.value=this.input=this.focused.value;return this.styles.primary(e)}return this.input}async render(){if(this.state.status!=="pending")return super.render();let e=this.options.highlight?this.options.highlight.bind(this):this.styles.placeholder,r=Eft(this.input,e),o=this.choices;this.choices=o.map(a=>({...a,message:r(a.message)})),await super.render(),this.choices=o}submit(){return this.options.multiple&&(this.value=this.selected.map(e=>e.name)),super.submit()}};_he.exports=q_});var G_=_((h8t,qhe)=>{"use strict";var j_=No();qhe.exports=(t,e={})=>{t.cursorHide();let{input:r="",initial:o="",pos:a,showCursor:n=!0,color:u}=e,A=u||t.styles.placeholder,p=j_.inverse(t.styles.primary),h=R=>p(t.styles.black(R)),E=r,I=" ",v=h(I);if(t.blink&&t.blink.off===!0&&(h=R=>R,v=""),n&&a===0&&o===""&&r==="")return h(I);if(n&&a===0&&(r===o||r===""))return h(o[0])+A(o.slice(1));o=j_.isPrimitive(o)?`${o}`:"",r=j_.isPrimitive(r)?`${r}`:"";let x=o&&o.startsWith(r)&&o!==r,C=x?h(o[r.length]):v;if(a!==r.length&&n===!0&&(E=r.slice(0,a)+h(r[a])+r.slice(a+1),C=""),n===!1&&(C=""),x){let R=t.styles.unstyle(E+C);return E+C+A(o.slice(R.length))}return E+C}});var Jx=_((g8t,jhe)=>{"use strict";var Cft=zc(),wft=Ph(),Ift=G_(),Y_=class extends wft{constructor(e){super({...e,multiple:!0}),this.type="form",this.initial=this.options.initial,this.align=[this.options.align,"right"].find(r=>r!=null),this.emptyError="",this.values={}}async reset(e){return await super.reset(),e===!0&&(this._index=this.index),this.index=this._index,this.values={},this.choices.forEach(r=>r.reset&&r.reset()),this.render()}dispatch(e){return!!e&&this.append(e)}append(e){let r=this.focused;if(!r)return this.alert();let{cursor:o,input:a}=r;return r.value=r.input=a.slice(0,o)+e+a.slice(o),r.cursor++,this.render()}delete(){let e=this.focused;if(!e||e.cursor<=0)return this.alert();let{cursor:r,input:o}=e;return e.value=e.input=o.slice(0,r-1)+o.slice(r),e.cursor--,this.render()}deleteForward(){let e=this.focused;if(!e)return this.alert();let{cursor:r,input:o}=e;if(o[r]===void 0)return this.alert();let a=`${o}`.slice(0,r)+`${o}`.slice(r+1);return e.value=e.input=a,this.render()}right(){let e=this.focused;return e?e.cursor>=e.input.length?this.alert():(e.cursor++,this.render()):this.alert()}left(){let e=this.focused;return e?e.cursor<=0?this.alert():(e.cursor--,this.render()):this.alert()}space(e,r){return this.dispatch(e,r)}number(e,r){return this.dispatch(e,r)}next(){let e=this.focused;if(!e)return this.alert();let{initial:r,input:o}=e;return r&&r.startsWith(o)&&o!==r?(e.value=e.input=r,e.cursor=e.value.length,this.render()):super.next()}prev(){let e=this.focused;return e?e.cursor===0?super.prev():(e.value=e.input="",e.cursor=0,this.render()):this.alert()}separator(){return""}format(e){return this.state.submitted?"":super.format(e)}pointer(){return""}indicator(e){return e.input?"\u29BF":"\u2299"}async choiceSeparator(e,r){let o=await this.resolve(e.separator,this.state,e,r)||":";return o?" "+this.styles.disabled(o):""}async renderChoice(e,r){await this.onChoice(e,r);let{state:o,styles:a}=this,{cursor:n,initial:u="",name:A,hint:p,input:h=""}=e,{muted:E,submitted:I,primary:v,danger:x}=a,C=p,R=this.index===r,L=e.validate||(()=>!0),U=await this.choiceSeparator(e,r),z=e.message;this.align==="right"&&(z=z.padStart(this.longest+1," ")),this.align==="left"&&(z=z.padEnd(this.longest+1," "));let te=this.values[A]=h||u,ae=h?"success":"dark";await L.call(e,te,this.state)!==!0&&(ae="danger");let le=a[ae],ce=le(await this.indicator(e,r))+(e.pad||""),Ce=this.indent(e),de=()=>[Ce,ce,z+U,h,C].filter(Boolean).join(" ");if(o.submitted)return z=Cft.unstyle(z),h=I(h),C="",de();if(e.format)h=await e.format.call(this,h,e,r);else{let Be=this.styles.muted;h=Ift(this,{input:h,initial:u,pos:n,showCursor:R,color:Be})}return this.isValue(h)||(h=this.styles.muted(this.symbols.ellipsis)),e.result&&(this.values[A]=await e.result.call(this,te,e,r)),R&&(z=v(z)),e.error?h+=(h?" ":"")+x(e.error.trim()):e.hint&&(h+=(h?" ":"")+E(e.hint.trim())),de()}async submit(){return this.value=this.values,super.base.submit.call(this)}};jhe.exports=Y_});var W_=_((d8t,Yhe)=>{"use strict";var Bft=Jx(),vft=()=>{throw new Error("expected prompt to have a custom authenticate method")},Ghe=(t=vft)=>{class e extends Bft{constructor(o){super(o)}async submit(){this.value=await t.call(this,this.values,this.state),super.base.submit.call(this)}static create(o){return Ghe(o)}}return e};Yhe.exports=Ghe()});var Vhe=_((m8t,Khe)=>{"use strict";var Dft=W_();function Pft(t,e){return t.username===this.options.username&&t.password===this.options.password}var Whe=(t=Pft)=>{let e=[{name:"username",message:"username"},{name:"password",message:"password",format(o){return this.options.showPassword?o:(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(o.length))}}];class r extends Dft.create(t){constructor(a){super({...a,choices:e})}static create(a){return Whe(a)}}return r};Khe.exports=Whe()});var Xx=_((y8t,zhe)=>{"use strict";var Sft=jy(),{isPrimitive:bft,hasColor:xft}=No(),K_=class extends Sft{constructor(e){super(e),this.cursorHide()}async initialize(){let e=await this.resolve(this.initial,this.state);this.input=await this.cast(e),await super.initialize()}dispatch(e){return this.isValue(e)?(this.input=e,this.submit()):this.alert()}format(e){let{styles:r,state:o}=this;return o.submitted?r.success(e):r.primary(e)}cast(e){return this.isTrue(e)}isTrue(e){return/^[ty1]/i.test(e)}isFalse(e){return/^[fn0]/i.test(e)}isValue(e){return bft(e)&&(this.isTrue(e)||this.isFalse(e))}async hint(){if(this.state.status==="pending"){let e=await this.element("hint");return xft(e)?e:this.styles.muted(e)}}async render(){let{input:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=this.styles.muted(this.default),A=[o,n,u,a].filter(Boolean).join(" ");this.state.prompt=A;let p=await this.header(),h=this.value=this.cast(e),E=await this.format(h),I=await this.error()||await this.hint(),v=await this.footer();I&&!A.includes(I)&&(E+=" "+I),A+=" "+E,this.clear(r),this.write([p,A,v].filter(Boolean).join(` +`)),this.restore()}set value(e){super.value=e}get value(){return this.cast(super.value)}};zhe.exports=K_});var Xhe=_((E8t,Jhe)=>{"use strict";var kft=Xx(),V_=class extends kft{constructor(e){super(e),this.default=this.options.default||(this.initial?"(Y/n)":"(y/N)")}};Jhe.exports=V_});var $he=_((C8t,Zhe)=>{"use strict";var Qft=Ph(),Fft=Jx(),Gy=Fft.prototype,z_=class extends Qft{constructor(e){super({...e,multiple:!0}),this.align=[this.options.align,"left"].find(r=>r!=null),this.emptyError="",this.values={}}dispatch(e,r){let o=this.focused,a=o.parent||{};return!o.editable&&!a.editable&&(e==="a"||e==="i")?super[e]():Gy.dispatch.call(this,e,r)}append(e,r){return Gy.append.call(this,e,r)}delete(e,r){return Gy.delete.call(this,e,r)}space(e){return this.focused.editable?this.append(e):super.space()}number(e){return this.focused.editable?this.append(e):super.number(e)}next(){return this.focused.editable?Gy.next.call(this):super.next()}prev(){return this.focused.editable?Gy.prev.call(this):super.prev()}async indicator(e,r){let o=e.indicator||"",a=e.editable?o:super.indicator(e,r);return await this.resolve(a,this.state,e,r)||""}indent(e){return e.role==="heading"?"":e.editable?" ":" "}async renderChoice(e,r){return e.indent="",e.editable?Gy.renderChoice.call(this,e,r):super.renderChoice(e,r)}error(){return""}footer(){return this.state.error}async validate(){let e=!0;for(let r of this.choices){if(typeof r.validate!="function"||r.role==="heading")continue;let o=r.parent?this.value[r.parent.name]:this.value;if(r.editable?o=r.value===r.name?r.initial||"":r.value:this.isDisabled(r)||(o=r.enabled===!0),e=await r.validate(o,this.state),e!==!0)break}return e!==!0&&(this.state.error=typeof e=="string"?e:"Invalid Input"),e}submit(){if(this.focused.newChoice===!0)return super.submit();if(this.choices.some(e=>e.newChoice))return this.alert();this.value={};for(let e of this.choices){let r=e.parent?this.value[e.parent.name]:this.value;if(e.role==="heading"){this.value[e.name]={};continue}e.editable?r[e.name]=e.value===e.name?e.initial||"":e.value:this.isDisabled(e)||(r[e.name]=e.enabled===!0)}return this.base.submit.call(this)}};Zhe.exports=z_});var _g=_((w8t,e0e)=>{"use strict";var Rft=jy(),Tft=G_(),{isPrimitive:Nft}=No(),J_=class extends Rft{constructor(e){super(e),this.initial=Nft(this.initial)?String(this.initial):"",this.initial&&this.cursorHide(),this.state.prevCursor=0,this.state.clipboard=[]}async keypress(e,r={}){let o=this.state.prevKeypress;return this.state.prevKeypress=r,this.options.multiline===!0&&r.name==="return"&&(!o||o.name!=="return")?this.append(` +`,r):super.keypress(e,r)}moveCursor(e){this.cursor+=e}reset(){return this.input=this.value="",this.cursor=0,this.render()}dispatch(e,r){if(!e||r.ctrl||r.code)return this.alert();this.append(e)}append(e){let{cursor:r,input:o}=this.state;this.input=`${o}`.slice(0,r)+e+`${o}`.slice(r),this.moveCursor(String(e).length),this.render()}insert(e){this.append(e)}delete(){let{cursor:e,input:r}=this.state;if(e<=0)return this.alert();this.input=`${r}`.slice(0,e-1)+`${r}`.slice(e),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:e,input:r}=this.state;if(r[e]===void 0)return this.alert();this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.render()}cutForward(){let e=this.cursor;if(this.input.length<=e)return this.alert();this.state.clipboard.push(this.input.slice(e)),this.input=this.input.slice(0,e),this.render()}cutLeft(){let e=this.cursor;if(e===0)return this.alert();let r=this.input.slice(0,e),o=this.input.slice(e),a=r.split(" ");this.state.clipboard.push(a.pop()),this.input=a.join(" "),this.cursor=this.input.length,this.input+=o,this.render()}paste(){if(!this.state.clipboard.length)return this.alert();this.insert(this.state.clipboard.pop()),this.render()}toggleCursor(){this.state.prevCursor?(this.cursor=this.state.prevCursor,this.state.prevCursor=0):(this.state.prevCursor=this.cursor,this.cursor=0),this.render()}first(){this.cursor=0,this.render()}last(){this.cursor=this.input.length-1,this.render()}next(){let e=this.initial!=null?String(this.initial):"";if(!e||!e.startsWith(this.input))return this.alert();this.input=this.initial,this.cursor=this.initial.length,this.render()}prev(){if(!this.input)return this.alert();this.reset()}backward(){return this.left()}forward(){return this.right()}right(){return this.cursor>=this.input.length?this.alert():(this.moveCursor(1),this.render())}left(){return this.cursor<=0?this.alert():(this.moveCursor(-1),this.render())}isValue(e){return!!e}async format(e=this.value){let r=await this.resolve(this.initial,this.state);return this.state.submitted?this.styles.submitted(e||r):Tft(this,{input:e,initial:r,pos:this.cursor})}async render(){let e=this.state.size,r=await this.prefix(),o=await this.separator(),a=await this.message(),n=[r,a,o].filter(Boolean).join(" ");this.state.prompt=n;let u=await this.header(),A=await this.format(),p=await this.error()||await this.hint(),h=await this.footer();p&&!A.includes(p)&&(A+=" "+p),n+=" "+A,this.clear(e),this.write([u,n,h].filter(Boolean).join(` +`)),this.restore()}};e0e.exports=J_});var r0e=_((I8t,t0e)=>{"use strict";var Lft=t=>t.filter((e,r)=>t.lastIndexOf(e)===r),Zx=t=>Lft(t).filter(Boolean);t0e.exports=(t,e={},r="")=>{let{past:o=[],present:a=""}=e,n,u;switch(t){case"prev":case"undo":return n=o.slice(0,o.length-1),u=o[o.length-1]||"",{past:Zx([r,...n]),present:u};case"next":case"redo":return n=o.slice(1),u=o[0]||"",{past:Zx([...n,r]),present:u};case"save":return{past:Zx([...o,r]),present:""};case"remove":return u=Zx(o.filter(A=>A!==r)),a="",u.length&&(a=u.pop()),{past:u,present:a};default:throw new Error(`Invalid action: "${t}"`)}}});var Z_=_((B8t,i0e)=>{"use strict";var Mft=_g(),n0e=r0e(),X_=class extends Mft{constructor(e){super(e);let r=this.options.history;if(r&&r.store){let o=r.values||this.initial;this.autosave=!!r.autosave,this.store=r.store,this.data=this.store.get("values")||{past:[],present:o},this.initial=this.data.present||this.data.past[this.data.past.length-1]}}completion(e){return this.store?(this.data=n0e(e,this.data,this.input),this.data.present?(this.input=this.data.present,this.cursor=this.input.length,this.render()):this.alert()):this.alert()}altUp(){return this.completion("prev")}altDown(){return this.completion("next")}prev(){return this.save(),super.prev()}save(){this.store&&(this.data=n0e("save",this.data,this.input),this.store.set("values",this.data))}submit(){return this.store&&this.autosave===!0&&this.save(),super.submit()}};i0e.exports=X_});var o0e=_((v8t,s0e)=>{"use strict";var Oft=_g(),$_=class extends Oft{format(){return""}};s0e.exports=$_});var l0e=_((D8t,a0e)=>{"use strict";var Uft=_g(),e8=class extends Uft{constructor(e={}){super(e),this.sep=this.options.separator||/, */,this.initial=e.initial||""}split(e=this.value){return e?String(e).split(this.sep):[]}format(){let e=this.state.submitted?this.styles.primary:r=>r;return this.list.map(e).join(", ")}async submit(e){let r=this.state.error||await this.validate(this.list,this.state);return r!==!0?(this.state.error=r,super.submit()):(this.value=this.list,super.submit())}get list(){return this.split()}};a0e.exports=e8});var u0e=_((P8t,c0e)=>{"use strict";var _ft=Ph(),t8=class extends _ft{constructor(e){super({...e,multiple:!0})}};c0e.exports=t8});var n8=_((S8t,A0e)=>{"use strict";var Hft=_g(),r8=class extends Hft{constructor(e={}){super({style:"number",...e}),this.min=this.isValue(e.min)?this.toNumber(e.min):-1/0,this.max=this.isValue(e.max)?this.toNumber(e.max):1/0,this.delay=e.delay!=null?e.delay:1e3,this.float=e.float!==!1,this.round=e.round===!0||e.float===!1,this.major=e.major||10,this.minor=e.minor||1,this.initial=e.initial!=null?e.initial:"",this.input=String(this.initial),this.cursor=this.input.length,this.cursorShow()}append(e){return!/[-+.]/.test(e)||e==="."&&this.input.includes(".")?this.alert("invalid number"):super.append(e)}number(e){return super.append(e)}next(){return this.input&&this.input!==this.initial?this.alert():this.isValue(this.initial)?(this.input=this.initial,this.cursor=String(this.initial).length,this.render()):this.alert()}up(e){let r=e||this.minor,o=this.toNumber(this.input);return o>this.max+r?this.alert():(this.input=`${o+r}`,this.render())}down(e){let r=e||this.minor,o=this.toNumber(this.input);return o<this.min-r?this.alert():(this.input=`${o-r}`,this.render())}shiftDown(){return this.down(this.major)}shiftUp(){return this.up(this.major)}format(e=this.input){return typeof this.options.format=="function"?this.options.format.call(this,e):this.styles.info(e)}toNumber(e=""){return this.float?+e:Math.round(+e)}isValue(e){return/^[-+]?[0-9]+((\.)|(\.[0-9]+))?$/.test(e)}submit(){let e=[this.input,this.initial].find(r=>this.isValue(r));return this.value=this.toNumber(e||0),super.submit()}};A0e.exports=r8});var p0e=_((b8t,f0e)=>{f0e.exports=n8()});var g0e=_((x8t,h0e)=>{"use strict";var qft=_g(),i8=class extends qft{constructor(e){super(e),this.cursorShow()}format(e=this.input){return this.keypressed?(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(e.length)):""}};h0e.exports=i8});var y0e=_((k8t,m0e)=>{"use strict";var jft=zc(),Gft=V1(),d0e=No(),s8=class extends Gft{constructor(e={}){super(e),this.widths=[].concat(e.messageWidth||50),this.align=[].concat(e.align||"left"),this.linebreak=e.linebreak||!1,this.edgeLength=e.edgeLength||3,this.newline=e.newline||` + `;let r=e.startNumber||1;typeof this.scale=="number"&&(this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((o,a)=>({name:a+r})))}async reset(){return this.tableized=!1,await super.reset(),this.render()}tableize(){if(this.tableized===!0)return;this.tableized=!0;let e=0;for(let r of this.choices){e=Math.max(e,r.message.length),r.scaleIndex=r.initial||2,r.scale=[];for(let o=0;o<this.scale.length;o++)r.scale.push({index:o})}this.widths[0]=Math.min(this.widths[0],e+3)}async dispatch(e,r){if(this.multiple)return this[r.name]?await this[r.name](e,r):await super.dispatch(e,r);this.alert()}heading(e,r,o){return this.styles.strong(e)}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIndex>=this.scale.length-1?this.alert():(e.scaleIndex++,this.render())}left(){let e=this.focused;return e.scaleIndex<=0?this.alert():(e.scaleIndex--,this.render())}indent(){return""}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.index)).join(", "):""}pointer(){return""}renderScaleKey(){return this.scaleKey===!1||this.state.submitted?"":["",...this.scale.map(o=>` ${o.name} - ${o.message}`)].map(o=>this.styles.muted(o)).join(` +`)}renderScaleHeading(e){let r=this.scale.map(p=>p.name);typeof this.options.renderScaleHeading=="function"&&(r=this.options.renderScaleHeading.call(this,e));let o=this.scaleLength-r.join("").length,a=Math.round(o/(r.length-1)),u=r.map(p=>this.styles.strong(p)).join(" ".repeat(a)),A=" ".repeat(this.widths[0]);return this.margin[3]+A+this.margin[1]+u}scaleIndicator(e,r,o){if(typeof this.options.scaleIndicator=="function")return this.options.scaleIndicator.call(this,e,r,o);let a=e.scaleIndex===r.index;return r.disabled?this.styles.hint(this.symbols.radio.disabled):a?this.styles.success(this.symbols.radio.on):this.symbols.radio.off}renderScale(e,r){let o=e.scale.map(n=>this.scaleIndicator(e,n,r)),a=this.term==="Hyper"?"":" ";return o.join(a+this.symbols.line.repeat(this.edgeLength))}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=await this.pointer(e,r),n=await e.hint;n&&!d0e.hasColor(n)&&(n=this.styles.muted(n));let u=C=>this.margin[3]+C.replace(/\s+$/,"").padEnd(this.widths[0]," "),A=this.newline,p=this.indent(e),h=await this.resolve(e.message,this.state,e,r),E=await this.renderScale(e,r),I=this.margin[1]+this.margin[3];this.scaleLength=jft.unstyle(E).length,this.widths[0]=Math.min(this.widths[0],this.width-this.scaleLength-I.length);let x=d0e.wordWrap(h,{width:this.widths[0],newline:A}).split(` +`).map(C=>u(C)+this.margin[1]);return o&&(E=this.styles.info(E),x=x.map(C=>this.styles.info(C))),x[0]+=E,this.linebreak&&x.push(""),[p+a,x.join(` +`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return"";this.tableize();let e=this.visible.map(async(a,n)=>await this.renderChoice(a,n)),r=await Promise.all(e),o=await this.renderScaleHeading();return this.margin[0]+[o,...r.map(a=>a.join(" "))].join(` +`)}async render(){let{submitted:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u="";this.options.promptLine!==!1&&(u=[o,n,a,""].join(" "),this.state.prompt=u);let A=await this.header(),p=await this.format(),h=await this.renderScaleKey(),E=await this.error()||await this.hint(),I=await this.renderChoices(),v=await this.footer(),x=this.emptyError;p&&(u+=p),E&&!u.includes(E)&&(u+=" "+E),e&&!p&&!I.trim()&&this.multiple&&x!=null&&(u+=this.styles.danger(x)),this.clear(r),this.write([A,u,h,I,v].filter(Boolean).join(` +`)),this.state.submitted||this.write(this.margin[2]),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIndex;return this.base.submit.call(this)}};m0e.exports=s8});var w0e=_((Q8t,C0e)=>{"use strict";var E0e=zc(),Yft=(t="")=>typeof t=="string"?t.replace(/^['"]|['"]$/g,""):"",a8=class{constructor(e){this.name=e.key,this.field=e.field||{},this.value=Yft(e.initial||this.field.initial||""),this.message=e.message||this.name,this.cursor=0,this.input="",this.lines=[]}},Wft=async(t={},e={},r=o=>o)=>{let o=new Set,a=t.fields||[],n=t.template,u=[],A=[],p=[],h=1;typeof n=="function"&&(n=await n());let E=-1,I=()=>n[++E],v=()=>n[E+1],x=C=>{C.line=h,u.push(C)};for(x({type:"bos",value:""});E<n.length-1;){let C=I();if(/^[^\S\n ]$/.test(C)){x({type:"text",value:C});continue}if(C===` +`){x({type:"newline",value:C}),h++;continue}if(C==="\\"){C+=I(),x({type:"text",value:C});continue}if((C==="$"||C==="#"||C==="{")&&v()==="{"){let L=I();C+=L;let U={type:"template",open:C,inner:"",close:"",value:C},z;for(;z=I();){if(z==="}"){v()==="}"&&(z+=I()),U.value+=z,U.close=z;break}z===":"?(U.initial="",U.key=U.inner):U.initial!==void 0&&(U.initial+=z),U.value+=z,U.inner+=z}U.template=U.open+(U.initial||U.inner)+U.close,U.key=U.key||U.inner,e.hasOwnProperty(U.key)&&(U.initial=e[U.key]),U=r(U),x(U),p.push(U.key),o.add(U.key);let te=A.find(ae=>ae.name===U.key);U.field=a.find(ae=>ae.name===U.key),te||(te=new a8(U),A.push(te)),te.lines.push(U.line-1);continue}let R=u[u.length-1];R.type==="text"&&R.line===h?R.value+=C:x({type:"text",value:C})}return x({type:"eos",value:""}),{input:n,tabstops:u,unique:o,keys:p,items:A}};C0e.exports=async t=>{let e=t.options,r=new Set(e.required===!0?[]:e.required||[]),o={...e.values,...e.initial},{tabstops:a,items:n,keys:u}=await Wft(e,o),A=o8("result",t,e),p=o8("format",t,e),h=o8("validate",t,e,!0),E=t.isValue.bind(t);return async(I={},v=!1)=>{let x=0;I.required=r,I.items=n,I.keys=u,I.output="";let C=async(z,te,ae,le)=>{let ce=await h(z,te,ae,le);return ce===!1?"Invalid field "+ae.name:ce};for(let z of a){let te=z.value,ae=z.key;if(z.type!=="template"){te&&(I.output+=te);continue}if(z.type==="template"){let le=n.find(Ee=>Ee.name===ae);e.required===!0&&I.required.add(le.name);let ce=[le.input,I.values[le.value],le.value,te].find(E),de=(le.field||{}).message||z.inner;if(v){let Ee=await C(I.values[ae],I,le,x);if(Ee&&typeof Ee=="string"||Ee===!1){I.invalid.set(ae,Ee);continue}I.invalid.delete(ae);let g=await A(I.values[ae],I,le,x);I.output+=E0e.unstyle(g);continue}le.placeholder=!1;let Be=te;te=await p(te,I,le,x),ce!==te?(I.values[ae]=ce,te=t.styles.typing(ce),I.missing.delete(de)):(I.values[ae]=void 0,ce=`<${de}>`,te=t.styles.primary(ce),le.placeholder=!0,I.required.has(ae)&&I.missing.add(de)),I.missing.has(de)&&I.validating&&(te=t.styles.warning(ce)),I.invalid.has(ae)&&I.validating&&(te=t.styles.danger(ce)),x===I.index&&(Be!==te?te=t.styles.underline(te):te=t.styles.heading(E0e.unstyle(te))),x++}te&&(I.output+=te)}let R=I.output.split(` +`).map(z=>" "+z),L=n.length,U=0;for(let z of n)I.invalid.has(z.name)&&z.lines.forEach(te=>{R[te][0]===" "&&(R[te]=I.styles.danger(I.symbols.bullet)+R[te].slice(1))}),t.isValue(I.values[z.name])&&U++;return I.completed=(U/L*100).toFixed(0),I.output=R.join(` +`),I.output}};function o8(t,e,r,o){return(a,n,u,A)=>typeof u.field[t]=="function"?u.field[t].call(e,a,n,u,A):[o,a].find(p=>e.isValue(p))}});var B0e=_((F8t,I0e)=>{"use strict";var Kft=zc(),Vft=w0e(),zft=jy(),l8=class extends zft{constructor(e){super(e),this.cursorHide(),this.reset(!0)}async initialize(){this.interpolate=await Vft(this),await super.initialize()}async reset(e){this.state.keys=[],this.state.invalid=new Map,this.state.missing=new Set,this.state.completed=0,this.state.values={},e!==!0&&(await this.initialize(),await this.render())}moveCursor(e){let r=this.getItem();this.cursor+=e,r.cursor+=e}dispatch(e,r){if(!r.code&&!r.ctrl&&e!=null&&this.getItem()){this.append(e,r);return}this.alert()}append(e,r){let o=this.getItem(),a=o.input.slice(0,this.cursor),n=o.input.slice(this.cursor);this.input=o.input=`${a}${e}${n}`,this.moveCursor(1),this.render()}delete(){let e=this.getItem();if(this.cursor<=0||!e.input)return this.alert();let r=e.input.slice(this.cursor),o=e.input.slice(0,this.cursor-1);this.input=e.input=`${o}${r}`,this.moveCursor(-1),this.render()}increment(e){return e>=this.state.keys.length-1?0:e+1}decrement(e){return e<=0?this.state.keys.length-1:e-1}first(){this.state.index=0,this.render()}last(){this.state.index=this.state.keys.length-1,this.render()}right(){if(this.cursor>=this.input.length)return this.alert();this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();this.moveCursor(-1),this.render()}prev(){this.state.index=this.decrement(this.state.index),this.getItem(),this.render()}next(){this.state.index=this.increment(this.state.index),this.getItem(),this.render()}up(){this.prev()}down(){this.next()}format(e){let r=this.state.completed<100?this.styles.warning:this.styles.success;return this.state.submitted===!0&&this.state.completed!==100&&(r=this.styles.danger),r(`${this.state.completed}% completed`)}async render(){let{index:e,keys:r=[],submitted:o,size:a}=this.state,n=[this.options.newline,` +`].find(z=>z!=null),u=await this.prefix(),A=await this.separator(),p=await this.message(),h=[u,p,A].filter(Boolean).join(" ");this.state.prompt=h;let E=await this.header(),I=await this.error()||"",v=await this.hint()||"",x=o?"":await this.interpolate(this.state),C=this.state.key=r[e]||"",R=await this.format(C),L=await this.footer();R&&(h+=" "+R),v&&!R&&this.state.completed===0&&(h+=" "+v),this.clear(a);let U=[E,h,x,L,I.trim()];this.write(U.filter(Boolean).join(n)),this.restore()}getItem(e){let{items:r,keys:o,index:a}=this.state,n=r.find(u=>u.name===o[a]);return n&&n.input!=null&&(this.input=n.input,this.cursor=n.cursor),n}async submit(){typeof this.interpolate!="function"&&await this.initialize(),await this.interpolate(this.state,!0);let{invalid:e,missing:r,output:o,values:a}=this.state;if(e.size){let A="";for(let[p,h]of e)A+=`Invalid ${p}: ${h} +`;return this.state.error=A,super.submit()}if(r.size)return this.state.error="Required: "+[...r.keys()].join(", "),super.submit();let u=Kft.unstyle(o).split(` +`).map(A=>A.slice(1)).join(` +`);return this.value={values:a,result:u},super.submit()}};I0e.exports=l8});var D0e=_((R8t,v0e)=>{"use strict";var Jft="(Use <shift>+<up/down> to sort)",Xft=Ph(),c8=class extends Xft{constructor(e){super({...e,reorder:!1,sort:!0,multiple:!0}),this.state.hint=[this.options.hint,Jft].find(this.isValue.bind(this))}indicator(){return""}async renderChoice(e,r){let o=await super.renderChoice(e,r),a=this.symbols.identicalTo+" ",n=this.index===r&&this.sorting?this.styles.muted(a):" ";return this.options.drag===!1&&(n=""),this.options.numbered===!0?n+`${r+1} - `+o:n+o}get selected(){return this.choices}submit(){return this.value=this.choices.map(e=>e.value),super.submit()}};v0e.exports=c8});var S0e=_((T8t,P0e)=>{"use strict";var Zft=V1(),u8=class extends Zft{constructor(e={}){if(super(e),this.emptyError=e.emptyError||"No items were selected",this.term=process.env.TERM_PROGRAM,!this.options.header){let r=["","4 - Strongly Agree","3 - Agree","2 - Neutral","1 - Disagree","0 - Strongly Disagree",""];r=r.map(o=>this.styles.muted(o)),this.state.header=r.join(` + `)}}async toChoices(...e){if(this.createdScales)return!1;this.createdScales=!0;let r=await super.toChoices(...e);for(let o of r)o.scale=$ft(5,this.options),o.scaleIdx=2;return r}dispatch(){this.alert()}space(){let e=this.focused,r=e.scale[e.scaleIdx],o=r.selected;return e.scale.forEach(a=>a.selected=!1),r.selected=!o,this.render()}indicator(){return""}pointer(){return""}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIdx>=e.scale.length-1?this.alert():(e.scaleIdx++,this.render())}left(){let e=this.focused;return e.scaleIdx<=0?this.alert():(e.scaleIdx--,this.render())}indent(){return" "}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=this.term==="Hyper",n=a?9:8,u=a?"":" ",A=this.symbols.line.repeat(n),p=" ".repeat(n+(a?0:1)),h=te=>(te?this.styles.success("\u25C9"):"\u25EF")+u,E=r+1+".",I=o?this.styles.heading:this.styles.noop,v=await this.resolve(e.message,this.state,e,r),x=this.indent(e),C=x+e.scale.map((te,ae)=>h(ae===e.scaleIdx)).join(A),R=te=>te===e.scaleIdx?I(te):te,L=x+e.scale.map((te,ae)=>R(ae)).join(p),U=()=>[E,v].filter(Boolean).join(" "),z=()=>[U(),C,L," "].filter(Boolean).join(` +`);return o&&(C=this.styles.cyan(C),L=this.styles.cyan(L)),z()}async renderChoices(){if(this.state.submitted)return"";let e=this.visible.map(async(o,a)=>await this.renderChoice(o,a)),r=await Promise.all(e);return r.length||r.push(this.styles.danger("No matching choices")),r.join(` +`)}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.scaleIdx)).join(", "):""}async render(){let{submitted:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=[o,n,a].filter(Boolean).join(" ");this.state.prompt=u;let A=await this.header(),p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),I=await this.footer();(p||!h)&&(u+=" "+p),h&&!u.includes(h)&&(u+=" "+h),e&&!p&&!E&&this.multiple&&this.type!=="form"&&(u+=this.styles.danger(this.emptyError)),this.clear(r),this.write([u,A,E,I].filter(Boolean).join(` +`)),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIdx;return this.base.submit.call(this)}};function $ft(t,e={}){if(Array.isArray(e.scale))return e.scale.map(o=>({...o}));let r=[];for(let o=1;o<t+1;o++)r.push({i:o,selected:!1});return r}P0e.exports=u8});var x0e=_((N8t,b0e)=>{b0e.exports=Z_()});var Q0e=_((L8t,k0e)=>{"use strict";var ept=Xx(),A8=class extends ept{async initialize(){await super.initialize(),this.value=this.initial=!!this.options.initial,this.disabled=this.options.disabled||"no",this.enabled=this.options.enabled||"yes",await this.render()}reset(){this.value=this.initial,this.render()}delete(){this.alert()}toggle(){this.value=!this.value,this.render()}enable(){if(this.value===!0)return this.alert();this.value=!0,this.render()}disable(){if(this.value===!1)return this.alert();this.value=!1,this.render()}up(){this.toggle()}down(){this.toggle()}right(){this.toggle()}left(){this.toggle()}next(){this.toggle()}prev(){this.toggle()}dispatch(e="",r){switch(e.toLowerCase()){case" ":return this.toggle();case"1":case"y":case"t":return this.enable();case"0":case"n":case"f":return this.disable();default:return this.alert()}}format(){let e=o=>this.styles.primary.underline(o);return[this.value?this.disabled:e(this.disabled),this.value?e(this.enabled):this.enabled].join(this.styles.muted(" / "))}async render(){let{size:e}=this.state,r=await this.header(),o=await this.prefix(),a=await this.separator(),n=await this.message(),u=await this.format(),A=await this.error()||await this.hint(),p=await this.footer(),h=[o,n,a,u].join(" ");this.state.prompt=h,A&&!h.includes(A)&&(h+=" "+A),this.clear(e),this.write([r,h,p].filter(Boolean).join(` +`)),this.write(this.margin[2]),this.restore()}};k0e.exports=A8});var R0e=_((M8t,F0e)=>{"use strict";var tpt=Ph(),f8=class extends tpt{constructor(e){if(super(e),typeof this.options.correctChoice!="number"||this.options.correctChoice<0)throw new Error("Please specify the index of the correct answer from the list of choices")}async toChoices(e,r){let o=await super.toChoices(e,r);if(o.length<2)throw new Error("Please give at least two choices to the user");if(this.options.correctChoice>o.length)throw new Error("Please specify the index of the correct answer from the list of choices");return o}check(e){return e.index===this.options.correctChoice}async result(e){return{selectedAnswer:e,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}};F0e.exports=f8});var N0e=_(p8=>{"use strict";var T0e=No(),ps=(t,e)=>{T0e.defineExport(p8,t,e),T0e.defineExport(p8,t.toLowerCase(),e)};ps("AutoComplete",()=>Hhe());ps("BasicAuth",()=>Vhe());ps("Confirm",()=>Xhe());ps("Editable",()=>$he());ps("Form",()=>Jx());ps("Input",()=>Z_());ps("Invisible",()=>o0e());ps("List",()=>l0e());ps("MultiSelect",()=>u0e());ps("Numeral",()=>p0e());ps("Password",()=>g0e());ps("Scale",()=>y0e());ps("Select",()=>Ph());ps("Snippet",()=>B0e());ps("Sort",()=>D0e());ps("Survey",()=>S0e());ps("Text",()=>x0e());ps("Toggle",()=>Q0e());ps("Quiz",()=>R0e())});var M0e=_((U8t,L0e)=>{L0e.exports={ArrayPrompt:V1(),AuthPrompt:W_(),BooleanPrompt:Xx(),NumberPrompt:n8(),StringPrompt:_g()}});var J1=_((_8t,U0e)=>{"use strict";var O0e=ve("assert"),g8=ve("events"),Sh=No(),Xc=class extends g8{constructor(e,r){super(),this.options=Sh.merge({},e),this.answers={...r}}register(e,r){if(Sh.isObject(e)){for(let a of Object.keys(e))this.register(a,e[a]);return this}O0e.equal(typeof r,"function","expected a function");let o=e.toLowerCase();return r.prototype instanceof this.Prompt?this.prompts[o]=r:this.prompts[o]=r(this.Prompt,this),this}async prompt(e=[]){for(let r of[].concat(e))try{typeof r=="function"&&(r=await r.call(this)),await this.ask(Sh.merge({},this.options,r))}catch(o){return Promise.reject(o)}return this.answers}async ask(e){typeof e=="function"&&(e=await e.call(this));let r=Sh.merge({},this.options,e),{type:o,name:a}=e,{set:n,get:u}=Sh;if(typeof o=="function"&&(o=await o.call(this,e,this.answers)),!o)return this.answers[a];O0e(this.prompts[o],`Prompt "${o}" is not registered`);let A=new this.prompts[o](r),p=u(this.answers,a);A.state.answers=this.answers,A.enquirer=this,a&&A.on("submit",E=>{this.emit("answer",a,E,A),n(this.answers,a,E)});let h=A.emit.bind(A);return A.emit=(...E)=>(this.emit.call(this,...E),h(...E)),this.emit("prompt",A,this),r.autofill&&p!=null?(A.value=A.input=p,r.autofill==="show"&&await A.submit()):p=A.value=await A.run(),p}use(e){return e.call(this,this),this}set Prompt(e){this._Prompt=e}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(e){this._Prompt=e}static get Prompt(){return this._Prompt||jy()}static get prompts(){return N0e()}static get types(){return M0e()}static get prompt(){let e=(r,...o)=>{let a=new this(...o),n=a.emit.bind(a);return a.emit=(...u)=>(e.emit(...u),n(...u)),a.prompt(r)};return Sh.mixinEmitter(e,new g8),e}};Sh.mixinEmitter(Xc,new g8);var h8=Xc.prompts;for(let t of Object.keys(h8)){let e=t.toLowerCase(),r=o=>new h8[t](o).run();Xc.prompt[e]=r,Xc[e]=r,Xc[t]||Reflect.defineProperty(Xc,t,{get:()=>h8[t]})}var z1=t=>{Sh.defineExport(Xc,t,()=>Xc.types[t])};z1("ArrayPrompt");z1("AuthPrompt");z1("BooleanPrompt");z1("NumberPrompt");z1("StringPrompt");U0e.exports=Xc});var e2=_((IHt,W0e)=>{var apt=Ux();function lpt(t,e,r){var o=t==null?void 0:apt(t,e);return o===void 0?r:o}W0e.exports=lpt});var z0e=_((bHt,V0e)=>{function cpt(t,e){for(var r=-1,o=t==null?0:t.length;++r<o&&e(t[r],r,t)!==!1;);return t}V0e.exports=cpt});var X0e=_((xHt,J0e)=>{var upt=Ag(),Apt=LP();function fpt(t,e){return t&&upt(e,Apt(e),t)}J0e.exports=fpt});var $0e=_((kHt,Z0e)=>{var ppt=Ag(),hpt=Sm();function gpt(t,e){return t&&ppt(e,hpt(e),t)}Z0e.exports=gpt});var tge=_((QHt,ege)=>{var dpt=Ag(),mpt=kP();function ypt(t,e){return dpt(t,mpt(t),e)}ege.exports=ypt});var w8=_((FHt,rge)=>{var Ept=xP(),Cpt=HP(),wpt=kP(),Ipt=MN(),Bpt=Object.getOwnPropertySymbols,vpt=Bpt?function(t){for(var e=[];t;)Ept(e,wpt(t)),t=Cpt(t);return e}:Ipt;rge.exports=vpt});var ige=_((RHt,nge)=>{var Dpt=Ag(),Ppt=w8();function Spt(t,e){return Dpt(t,Ppt(t),e)}nge.exports=Spt});var I8=_((THt,sge)=>{var bpt=LN(),xpt=w8(),kpt=Sm();function Qpt(t){return bpt(t,kpt,xpt)}sge.exports=Qpt});var age=_((NHt,oge)=>{var Fpt=Object.prototype,Rpt=Fpt.hasOwnProperty;function Tpt(t){var e=t.length,r=new t.constructor(e);return e&&typeof t[0]=="string"&&Rpt.call(t,"index")&&(r.index=t.index,r.input=t.input),r}oge.exports=Tpt});var cge=_((LHt,lge)=>{var Npt=UP();function Lpt(t,e){var r=e?Npt(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.byteLength)}lge.exports=Lpt});var Age=_((MHt,uge)=>{var Mpt=/\w*$/;function Opt(t){var e=new t.constructor(t.source,Mpt.exec(t));return e.lastIndex=t.lastIndex,e}uge.exports=Opt});var dge=_((OHt,gge)=>{var fge=lg(),pge=fge?fge.prototype:void 0,hge=pge?pge.valueOf:void 0;function Upt(t){return hge?Object(hge.call(t)):{}}gge.exports=Upt});var yge=_((UHt,mge)=>{var _pt=UP(),Hpt=cge(),qpt=Age(),jpt=dge(),Gpt=XN(),Ypt="[object Boolean]",Wpt="[object Date]",Kpt="[object Map]",Vpt="[object Number]",zpt="[object RegExp]",Jpt="[object Set]",Xpt="[object String]",Zpt="[object Symbol]",$pt="[object ArrayBuffer]",eht="[object DataView]",tht="[object Float32Array]",rht="[object Float64Array]",nht="[object Int8Array]",iht="[object Int16Array]",sht="[object Int32Array]",oht="[object Uint8Array]",aht="[object Uint8ClampedArray]",lht="[object Uint16Array]",cht="[object Uint32Array]";function uht(t,e,r){var o=t.constructor;switch(e){case $pt:return _pt(t);case Ypt:case Wpt:return new o(+t);case eht:return Hpt(t,r);case tht:case rht:case nht:case iht:case sht:case oht:case aht:case lht:case cht:return Gpt(t,r);case Kpt:return new o;case Vpt:case Xpt:return new o(t);case zpt:return qpt(t);case Jpt:return new o;case Zpt:return jpt(t)}}mge.exports=uht});var Cge=_((_Ht,Ege)=>{var Aht=PI(),fht=Ju(),pht="[object Map]";function hht(t){return fht(t)&&Aht(t)==pht}Ege.exports=hht});var vge=_((HHt,Bge)=>{var ght=Cge(),dht=FP(),wge=RP(),Ige=wge&&wge.isMap,mht=Ige?dht(Ige):ght;Bge.exports=mht});var Pge=_((qHt,Dge)=>{var yht=PI(),Eht=Ju(),Cht="[object Set]";function wht(t){return Eht(t)&&yht(t)==Cht}Dge.exports=wht});var kge=_((jHt,xge)=>{var Iht=Pge(),Bht=FP(),Sge=RP(),bge=Sge&&Sge.isSet,vht=bge?Bht(bge):Iht;xge.exports=vht});var B8=_((GHt,Tge)=>{var Dht=SP(),Pht=z0e(),Sht=qP(),bht=X0e(),xht=$0e(),kht=JN(),Qht=_P(),Fht=tge(),Rht=ige(),Tht=HN(),Nht=I8(),Lht=PI(),Mht=age(),Oht=yge(),Uht=ZN(),_ht=Hl(),Hht=wI(),qht=vge(),jht=sl(),Ght=kge(),Yht=LP(),Wht=Sm(),Kht=1,Vht=2,zht=4,Qge="[object Arguments]",Jht="[object Array]",Xht="[object Boolean]",Zht="[object Date]",$ht="[object Error]",Fge="[object Function]",e0t="[object GeneratorFunction]",t0t="[object Map]",r0t="[object Number]",Rge="[object Object]",n0t="[object RegExp]",i0t="[object Set]",s0t="[object String]",o0t="[object Symbol]",a0t="[object WeakMap]",l0t="[object ArrayBuffer]",c0t="[object DataView]",u0t="[object Float32Array]",A0t="[object Float64Array]",f0t="[object Int8Array]",p0t="[object Int16Array]",h0t="[object Int32Array]",g0t="[object Uint8Array]",d0t="[object Uint8ClampedArray]",m0t="[object Uint16Array]",y0t="[object Uint32Array]",ri={};ri[Qge]=ri[Jht]=ri[l0t]=ri[c0t]=ri[Xht]=ri[Zht]=ri[u0t]=ri[A0t]=ri[f0t]=ri[p0t]=ri[h0t]=ri[t0t]=ri[r0t]=ri[Rge]=ri[n0t]=ri[i0t]=ri[s0t]=ri[o0t]=ri[g0t]=ri[d0t]=ri[m0t]=ri[y0t]=!0;ri[$ht]=ri[Fge]=ri[a0t]=!1;function ek(t,e,r,o,a,n){var u,A=e&Kht,p=e&Vht,h=e&zht;if(r&&(u=a?r(t,o,a,n):r(t)),u!==void 0)return u;if(!jht(t))return t;var E=_ht(t);if(E){if(u=Mht(t),!A)return Qht(t,u)}else{var I=Lht(t),v=I==Fge||I==e0t;if(Hht(t))return kht(t,A);if(I==Rge||I==Qge||v&&!a){if(u=p||v?{}:Uht(t),!A)return p?Rht(t,xht(u,t)):Fht(t,bht(u,t))}else{if(!ri[I])return a?t:{};u=Oht(t,I,A)}}n||(n=new Dht);var x=n.get(t);if(x)return x;n.set(t,u),Ght(t)?t.forEach(function(L){u.add(ek(L,e,r,L,t,n))}):qht(t)&&t.forEach(function(L,U){u.set(U,ek(L,e,r,U,t,n))});var C=h?p?Nht:Tht:p?Wht:Yht,R=E?void 0:C(t);return Pht(R||t,function(L,U){R&&(U=L,L=t[U]),Sht(u,U,ek(L,e,r,U,t,n))}),u}Tge.exports=ek});var v8=_((YHt,Nge)=>{var E0t=B8(),C0t=1,w0t=4;function I0t(t){return E0t(t,C0t|w0t)}Nge.exports=I0t});var D8=_((WHt,Lge)=>{var B0t=g_();function v0t(t,e,r){return t==null?t:B0t(t,e,r)}Lge.exports=v0t});var Hge=_((ZHt,_ge)=>{var D0t=Object.prototype,P0t=D0t.hasOwnProperty;function S0t(t,e){return t!=null&&P0t.call(t,e)}_ge.exports=S0t});var jge=_(($Ht,qge)=>{var b0t=Hge(),x0t=d_();function k0t(t,e){return t!=null&&x0t(t,e,b0t)}qge.exports=k0t});var Yge=_((e6t,Gge)=>{function Q0t(t){var e=t==null?0:t.length;return e?t[e-1]:void 0}Gge.exports=Q0t});var Kge=_((t6t,Wge)=>{var F0t=Ux(),R0t=oU();function T0t(t,e){return e.length<2?t:F0t(t,R0t(e,0,-1))}Wge.exports=T0t});var S8=_((r6t,Vge)=>{var N0t=Mg(),L0t=Yge(),M0t=Kge(),O0t=Ly();function U0t(t,e){return e=N0t(e,t),t=M0t(t,e),t==null||delete t[O0t(L0t(e))]}Vge.exports=U0t});var b8=_((n6t,zge)=>{var _0t=S8();function H0t(t,e){return t==null?!0:_0t(t,e)}zge.exports=H0t});var ede=_((F6t,G0t)=>{G0t.exports={name:"@yarnpkg/cli",version:"4.4.0",license:"BSD-2-Clause",main:"./sources/index.ts",exports:{".":"./sources/index.ts","./polyfills":"./sources/polyfills.ts","./package.json":"./package.json"},dependencies:{"@yarnpkg/core":"workspace:^","@yarnpkg/fslib":"workspace:^","@yarnpkg/libzip":"workspace:^","@yarnpkg/parsers":"workspace:^","@yarnpkg/plugin-compat":"workspace:^","@yarnpkg/plugin-constraints":"workspace:^","@yarnpkg/plugin-dlx":"workspace:^","@yarnpkg/plugin-essentials":"workspace:^","@yarnpkg/plugin-exec":"workspace:^","@yarnpkg/plugin-file":"workspace:^","@yarnpkg/plugin-git":"workspace:^","@yarnpkg/plugin-github":"workspace:^","@yarnpkg/plugin-http":"workspace:^","@yarnpkg/plugin-init":"workspace:^","@yarnpkg/plugin-interactive-tools":"workspace:^","@yarnpkg/plugin-link":"workspace:^","@yarnpkg/plugin-nm":"workspace:^","@yarnpkg/plugin-npm":"workspace:^","@yarnpkg/plugin-npm-cli":"workspace:^","@yarnpkg/plugin-pack":"workspace:^","@yarnpkg/plugin-patch":"workspace:^","@yarnpkg/plugin-pnp":"workspace:^","@yarnpkg/plugin-pnpm":"workspace:^","@yarnpkg/plugin-stage":"workspace:^","@yarnpkg/plugin-typescript":"workspace:^","@yarnpkg/plugin-version":"workspace:^","@yarnpkg/plugin-workspace-tools":"workspace:^","@yarnpkg/shell":"workspace:^","ci-info":"^4.0.0",clipanion:"^4.0.0-rc.2",semver:"^7.1.2",tslib:"^2.4.0",typanion:"^3.14.0"},devDependencies:{"@types/semver":"^7.1.0","@yarnpkg/builder":"workspace:^","@yarnpkg/monorepo":"workspace:^","@yarnpkg/pnpify":"workspace:^"},peerDependencies:{"@yarnpkg/core":"workspace:^"},scripts:{postpack:"rm -rf lib",prepack:'run build:compile "$(pwd)"',"build:cli+hook":"run build:pnp:hook && builder build bundle","build:cli":"builder build bundle","run:cli":"builder run","update-local":"run build:cli --no-git-hash && rsync -a --delete bundles/ bin/"},publishConfig:{main:"./lib/index.js",bin:null,exports:{".":"./lib/index.js","./package.json":"./package.json"}},files:["/lib/**/*","!/lib/pluginConfiguration.*","!/lib/cli.*"],"@yarnpkg/builder":{bundles:{standard:["@yarnpkg/plugin-essentials","@yarnpkg/plugin-compat","@yarnpkg/plugin-constraints","@yarnpkg/plugin-dlx","@yarnpkg/plugin-exec","@yarnpkg/plugin-file","@yarnpkg/plugin-git","@yarnpkg/plugin-github","@yarnpkg/plugin-http","@yarnpkg/plugin-init","@yarnpkg/plugin-interactive-tools","@yarnpkg/plugin-link","@yarnpkg/plugin-nm","@yarnpkg/plugin-npm","@yarnpkg/plugin-npm-cli","@yarnpkg/plugin-pack","@yarnpkg/plugin-patch","@yarnpkg/plugin-pnp","@yarnpkg/plugin-pnpm","@yarnpkg/plugin-stage","@yarnpkg/plugin-typescript","@yarnpkg/plugin-version","@yarnpkg/plugin-workspace-tools"]}},repository:{type:"git",url:"ssh://git@github.com/yarnpkg/berry.git",directory:"packages/yarnpkg-cli"},engines:{node:">=18.12.0"}}});var M8=_((cGt,fde)=>{"use strict";fde.exports=function(e,r){r===!0&&(r=0);var o="";if(typeof e=="string")try{o=new URL(e).protocol}catch{}else e&&e.constructor===URL&&(o=e.protocol);var a=o.split(/\:|\+/).filter(Boolean);return typeof r=="number"?a[r]:a}});var hde=_((uGt,pde)=>{"use strict";var ugt=M8();function Agt(t){var e={protocols:[],protocol:null,port:null,resource:"",host:"",user:"",password:"",pathname:"",hash:"",search:"",href:t,query:{},parse_failed:!1};try{var r=new URL(t);e.protocols=ugt(r),e.protocol=e.protocols[0],e.port=r.port,e.resource=r.hostname,e.host=r.host,e.user=r.username||"",e.password=r.password||"",e.pathname=r.pathname,e.hash=r.hash.slice(1),e.search=r.search.slice(1),e.href=r.href,e.query=Object.fromEntries(r.searchParams)}catch{e.protocols=["file"],e.protocol=e.protocols[0],e.port="",e.resource="",e.user="",e.pathname="",e.hash="",e.search="",e.href=t,e.query={},e.parse_failed=!0}return e}pde.exports=Agt});var mde=_((AGt,dde)=>{"use strict";var fgt=hde();function pgt(t){return t&&typeof t=="object"&&"default"in t?t:{default:t}}var hgt=pgt(fgt),ggt="text/plain",dgt="us-ascii",gde=(t,e)=>e.some(r=>r instanceof RegExp?r.test(t):r===t),mgt=(t,{stripHash:e})=>{let r=/^data:(?<type>[^,]*?),(?<data>[^#]*?)(?:#(?<hash>.*))?$/.exec(t);if(!r)throw new Error(`Invalid URL: ${t}`);let{type:o,data:a,hash:n}=r.groups,u=o.split(";");n=e?"":n;let A=!1;u[u.length-1]==="base64"&&(u.pop(),A=!0);let p=(u.shift()||"").toLowerCase(),E=[...u.map(I=>{let[v,x=""]=I.split("=").map(C=>C.trim());return v==="charset"&&(x=x.toLowerCase(),x===dgt)?"":`${v}${x?`=${x}`:""}`}).filter(Boolean)];return A&&E.push("base64"),(E.length>0||p&&p!==ggt)&&E.unshift(p),`data:${E.join(";")},${A?a.trim():a}${n?`#${n}`:""}`};function ygt(t,e){if(e={defaultProtocol:"http:",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripTextFragment:!0,stripWWW:!0,removeQueryParameters:[/^utm_\w+/i],removeTrailingSlash:!0,removeSingleSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...e},t=t.trim(),/^data:/i.test(t))return mgt(t,e);if(/^view-source:/i.test(t))throw new Error("`view-source:` is not supported as it is a non-standard protocol");let r=t.startsWith("//");!r&&/^\.*\//.test(t)||(t=t.replace(/^(?!(?:\w+:)?\/\/)|^\/\//,e.defaultProtocol));let a=new URL(t);if(e.forceHttp&&e.forceHttps)throw new Error("The `forceHttp` and `forceHttps` options cannot be used together");if(e.forceHttp&&a.protocol==="https:"&&(a.protocol="http:"),e.forceHttps&&a.protocol==="http:"&&(a.protocol="https:"),e.stripAuthentication&&(a.username="",a.password=""),e.stripHash?a.hash="":e.stripTextFragment&&(a.hash=a.hash.replace(/#?:~:text.*?$/i,"")),a.pathname){let u=/\b[a-z][a-z\d+\-.]{1,50}:\/\//g,A=0,p="";for(;;){let E=u.exec(a.pathname);if(!E)break;let I=E[0],v=E.index,x=a.pathname.slice(A,v);p+=x.replace(/\/{2,}/g,"/"),p+=I,A=v+I.length}let h=a.pathname.slice(A,a.pathname.length);p+=h.replace(/\/{2,}/g,"/"),a.pathname=p}if(a.pathname)try{a.pathname=decodeURI(a.pathname)}catch{}if(e.removeDirectoryIndex===!0&&(e.removeDirectoryIndex=[/^index\.[a-z]+$/]),Array.isArray(e.removeDirectoryIndex)&&e.removeDirectoryIndex.length>0){let u=a.pathname.split("/"),A=u[u.length-1];gde(A,e.removeDirectoryIndex)&&(u=u.slice(0,-1),a.pathname=u.slice(1).join("/")+"/")}if(a.hostname&&(a.hostname=a.hostname.replace(/\.$/,""),e.stripWWW&&/^www\.(?!www\.)[a-z\-\d]{1,63}\.[a-z.\-\d]{2,63}$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\./,""))),Array.isArray(e.removeQueryParameters))for(let u of[...a.searchParams.keys()])gde(u,e.removeQueryParameters)&&a.searchParams.delete(u);if(e.removeQueryParameters===!0&&(a.search=""),e.sortQueryParameters){a.searchParams.sort();try{a.search=decodeURIComponent(a.search)}catch{}}e.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\/$/,""));let n=t;return t=a.toString(),!e.removeSingleSlash&&a.pathname==="/"&&!n.endsWith("/")&&a.hash===""&&(t=t.replace(/\/$/,"")),(e.removeTrailingSlash||a.pathname==="/")&&a.hash===""&&e.removeSingleSlash&&(t=t.replace(/\/$/,"")),r&&!e.normalizeProtocol&&(t=t.replace(/^http:\/\//,"//")),e.stripProtocol&&(t=t.replace(/^(?:https?:)?\/\//,"")),t}var O8=(t,e=!1)=>{let r=/^(?:([a-z_][a-z0-9_-]{0,31})@|https?:\/\/)([\w\.\-@]+)[\/:]([\~,\.\w,\-,\_,\/]+?(?:\.git|\/)?)$/,o=n=>{let u=new Error(n);throw u.subject_url=t,u};(typeof t!="string"||!t.trim())&&o("Invalid url."),t.length>O8.MAX_INPUT_LENGTH&&o("Input exceeds maximum length. If needed, change the value of parseUrl.MAX_INPUT_LENGTH."),e&&(typeof e!="object"&&(e={stripHash:!1}),t=ygt(t,e));let a=hgt.default(t);if(a.parse_failed){let n=a.href.match(r);n?(a.protocols=["ssh"],a.protocol="ssh",a.resource=n[2],a.host=n[2],a.user=n[1],a.pathname=`/${n[3]}`,a.parse_failed=!1):o("URL parsing failed.")}return a};O8.MAX_INPUT_LENGTH=2048;dde.exports=O8});var Cde=_((fGt,Ede)=>{"use strict";var Egt=M8();function yde(t){if(Array.isArray(t))return t.indexOf("ssh")!==-1||t.indexOf("rsync")!==-1;if(typeof t!="string")return!1;var e=Egt(t);if(t=t.substring(t.indexOf("://")+3),yde(e))return!0;var r=new RegExp(".([a-zA-Z\\d]+):(\\d+)/");return!t.match(r)&&t.indexOf("@")<t.indexOf(":")}Ede.exports=yde});var Bde=_((pGt,Ide)=>{"use strict";var Cgt=mde(),wde=Cde();function wgt(t){var e=Cgt(t);return e.token="",e.password==="x-oauth-basic"?e.token=e.user:e.user==="x-token-auth"&&(e.token=e.password),wde(e.protocols)||e.protocols.length===0&&wde(t)?e.protocol="ssh":e.protocols.length?e.protocol=e.protocols[0]:(e.protocol="file",e.protocols=["file"]),e.href=e.href.replace(/\/$/,""),e}Ide.exports=wgt});var Dde=_((hGt,vde)=>{"use strict";var Igt=Bde();function U8(t){if(typeof t!="string")throw new Error("The url must be a string.");var e=/^([a-z\d-]{1,39})\/([-\.\w]{1,100})$/i;e.test(t)&&(t="https://github.com/"+t);var r=Igt(t),o=r.resource.split("."),a=null;switch(r.toString=function(L){return U8.stringify(this,L)},r.source=o.length>2?o.slice(1-o.length).join("."):r.source=r.resource,r.git_suffix=/\.git$/.test(r.pathname),r.name=decodeURIComponent((r.pathname||r.href).replace(/(^\/)|(\/$)/g,"").replace(/\.git$/,"")),r.owner=decodeURIComponent(r.user),r.source){case"git.cloudforge.com":r.owner=r.user,r.organization=o[0],r.source="cloudforge.com";break;case"visualstudio.com":if(r.resource==="vs-ssh.visualstudio.com"){a=r.name.split("/"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3],r.full_name=a[2]+"/"+a[3]);break}else{a=r.name.split("/"),a.length===2?(r.owner=a[1],r.name=a[1],r.full_name="_git/"+r.name):a.length===3?(r.name=a[2],a[0]==="DefaultCollection"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+"/_git/"+r.name):(r.owner=a[0],r.full_name=r.owner+"/_git/"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+"/"+r.owner+"/_git/"+r.name);break}case"dev.azure.com":case"azure.com":if(r.resource==="ssh.dev.azure.com"){a=r.name.split("/"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3]);break}else{a=r.name.split("/"),a.length===5?(r.organization=a[0],r.owner=a[1],r.name=a[4],r.full_name="_git/"+r.name):a.length===3?(r.name=a[2],a[0]==="DefaultCollection"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+"/_git/"+r.name):(r.owner=a[0],r.full_name=r.owner+"/_git/"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+"/"+r.owner+"/_git/"+r.name),r.query&&r.query.path&&(r.filepath=r.query.path.replace(/^\/+/g,"")),r.query&&r.query.version&&(r.ref=r.query.version.replace(/^GB/,""));break}default:a=r.name.split("/");var n=a.length-1;if(a.length>=2){var u=a.indexOf("-",2),A=a.indexOf("blob",2),p=a.indexOf("tree",2),h=a.indexOf("commit",2),E=a.indexOf("src",2),I=a.indexOf("raw",2),v=a.indexOf("edit",2);n=u>0?u-1:A>0?A-1:p>0?p-1:h>0?h-1:E>0?E-1:I>0?I-1:v>0?v-1:n,r.owner=a.slice(0,n).join("/"),r.name=a[n],h&&(r.commit=a[n+2])}r.ref="",r.filepathtype="",r.filepath="";var x=a.length>n&&a[n+1]==="-"?n+1:n;a.length>x+2&&["raw","src","blob","tree","edit"].indexOf(a[x+1])>=0&&(r.filepathtype=a[x+1],r.ref=a[x+2],a.length>x+3&&(r.filepath=a.slice(x+3).join("/"))),r.organization=r.owner;break}r.full_name||(r.full_name=r.owner,r.name&&(r.full_name&&(r.full_name+="/"),r.full_name+=r.name)),r.owner.startsWith("scm/")&&(r.source="bitbucket-server",r.owner=r.owner.replace("scm/",""),r.organization=r.owner,r.full_name=r.owner+"/"+r.name);var C=/(projects|users)\/(.*?)\/repos\/(.*?)((\/.*$)|$)/,R=C.exec(r.pathname);return R!=null&&(r.source="bitbucket-server",R[1]==="users"?r.owner="~"+R[2]:r.owner=R[2],r.organization=r.owner,r.name=R[3],a=R[4].split("/"),a.length>1&&(["raw","browse"].indexOf(a[1])>=0?(r.filepathtype=a[1],a.length>2&&(r.filepath=a.slice(2).join("/"))):a[1]==="commits"&&a.length>2&&(r.commit=a[2])),r.full_name=r.owner+"/"+r.name,r.query.at?r.ref=r.query.at:r.ref=""),r}U8.stringify=function(t,e){e=e||(t.protocols&&t.protocols.length?t.protocols.join("+"):t.protocol);var r=t.port?":"+t.port:"",o=t.user||"git",a=t.git_suffix?".git":"";switch(e){case"ssh":return r?"ssh://"+o+"@"+t.resource+r+"/"+t.full_name+a:o+"@"+t.resource+":"+t.full_name+a;case"git+ssh":case"ssh+git":case"ftp":case"ftps":return e+"://"+o+"@"+t.resource+r+"/"+t.full_name+a;case"http":case"https":var n=t.token?Bgt(t):t.user&&(t.protocols.includes("http")||t.protocols.includes("https"))?t.user+"@":"";return e+"://"+n+t.resource+r+"/"+vgt(t)+a;default:return t.href}};function Bgt(t){switch(t.source){case"bitbucket.org":return"x-token-auth:"+t.token+"@";default:return t.token+"@"}}function vgt(t){switch(t.source){case"bitbucket-server":return"scm/"+t.full_name;default:return""+t.full_name}}vde.exports=U8});var Hde=_((K9t,_de)=>{var Ngt=kb(),Lgt=_P(),Mgt=Hl(),Ogt=Ym(),Ugt=h_(),_gt=Ly(),Hgt=C1();function qgt(t){return Mgt(t)?Ngt(t,_gt):Ogt(t)?[t]:Lgt(Ugt(Hgt(t)))}_de.exports=qgt});function Wgt(t,e){return e===1&&Ygt.has(t[0])}function a2(t){let e=Array.isArray(t)?t:(0,Gde.default)(t);return e.map((o,a)=>jgt.test(o)?`[${o}]`:Ggt.test(o)&&!Wgt(e,a)?`.${o}`:`[${JSON.stringify(o)}]`).join("").replace(/^\./,"")}function Kgt(t,e){let r=[];if(e.methodName!==null&&r.push(pe.pretty(t,e.methodName,pe.Type.CODE)),e.file!==null){let o=[];o.push(pe.pretty(t,e.file,pe.Type.PATH)),e.line!==null&&(o.push(pe.pretty(t,e.line,pe.Type.NUMBER)),e.column!==null&&o.push(pe.pretty(t,e.column,pe.Type.NUMBER))),r.push(`(${o.join(pe.pretty(t,":","grey"))})`)}return r.join(" ")}function ik(t,{manifestUpdates:e,reportedErrors:r},{fix:o}={}){let a=new Map,n=new Map,u=[...r.keys()].map(A=>[A,new Map]);for(let[A,p]of[...u,...e]){let h=r.get(A)?.map(x=>({text:x,fixable:!1}))??[],E=!1,I=t.getWorkspaceByCwd(A),v=I.manifest.exportTo({});for(let[x,C]of p){if(C.size>1){let R=[...C].map(([L,U])=>{let z=pe.pretty(t.configuration,L,pe.Type.INSPECT),te=U.size>0?Kgt(t.configuration,U.values().next().value):null;return te!==null?` +${z} at ${te}`:` +${z}`}).join("");h.push({text:`Conflict detected in constraint targeting ${pe.pretty(t.configuration,x,pe.Type.CODE)}; conflicting values are:${R}`,fixable:!1})}else{let[[R]]=C,L=(0,qde.default)(v,x);if(JSON.stringify(L)===JSON.stringify(R))continue;if(!o){let U=typeof L>"u"?`Missing field ${pe.pretty(t.configuration,x,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,R,pe.Type.INSPECT)}`:typeof R>"u"?`Extraneous field ${pe.pretty(t.configuration,x,pe.Type.CODE)} currently set to ${pe.pretty(t.configuration,L,pe.Type.INSPECT)}`:`Invalid field ${pe.pretty(t.configuration,x,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,R,pe.Type.INSPECT)}, found ${pe.pretty(t.configuration,L,pe.Type.INSPECT)}`;h.push({text:U,fixable:!0});continue}typeof R>"u"?(0,Yde.default)(v,x):(0,jde.default)(v,x,R),E=!0}E&&a.set(I,v)}h.length>0&&n.set(I,h)}return{changedWorkspaces:a,remainingErrors:n}}function Wde(t,{configuration:e}){let r={children:[]};for(let[o,a]of t){let n=[];for(let A of a){let p=A.text.split(/\n/);A.fixable&&(p[0]=`${pe.pretty(e,"\u2699","gray")} ${p[0]}`),n.push({value:pe.tuple(pe.Type.NO_HINT,p[0]),children:p.slice(1).map(h=>({value:pe.tuple(pe.Type.NO_HINT,h)}))})}let u={value:pe.tuple(pe.Type.LOCATOR,o.anchoredLocator),children:He.sortMap(n,A=>A.value[1])};r.children.push(u)}return r.children=He.sortMap(r.children,o=>o.value[1]),r}var qde,jde,Gde,Yde,QE,jgt,Ggt,Ygt,l2=Et(()=>{Ge();qde=Ze(e2()),jde=Ze(D8()),Gde=Ze(Hde()),Yde=Ze(b8()),QE=class{constructor(e){this.indexedFields=e;this.items=[];this.indexes={};this.clear()}clear(){this.items=[];for(let e of this.indexedFields)this.indexes[e]=new Map}insert(e){this.items.push(e);for(let r of this.indexedFields){let o=Object.hasOwn(e,r)?e[r]:void 0;if(typeof o>"u")continue;He.getArrayWithDefault(this.indexes[r],o).push(e)}return e}find(e){if(typeof e>"u")return this.items;let r=Object.entries(e);if(r.length===0)return this.items;let o=[],a;for(let[u,A]of r){let p=u,h=Object.hasOwn(this.indexes,p)?this.indexes[p]:void 0;if(typeof h>"u"){o.push([p,A]);continue}let E=new Set(h.get(A)??[]);if(E.size===0)return[];if(typeof a>"u")a=E;else for(let I of a)E.has(I)||a.delete(I);if(a.size===0)break}let n=[...a??[]];return o.length>0&&(n=n.filter(u=>{for(let[A,p]of o)if(!(typeof p<"u"?Object.hasOwn(u,A)&&u[A]===p:Object.hasOwn(u,A)===!1))return!1;return!0})),n}},jgt=/^[0-9]+$/,Ggt=/^[a-zA-Z0-9_]+$/,Ygt=new Set(["scripts",...Ut.allDependencies])});var Kde=_((s7t,$8)=>{var Vgt;(function(t){var e=function(){return{"append/2":[new t.type.Rule(new t.type.Term("append",[new t.type.Var("X"),new t.type.Var("L")]),new t.type.Term("foldl",[new t.type.Term("append",[]),new t.type.Var("X"),new t.type.Term("[]",[]),new t.type.Var("L")]))],"append/3":[new t.type.Rule(new t.type.Term("append",[new t.type.Term("[]",[]),new t.type.Var("X"),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("append",[new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("S")])]),new t.type.Term("append",[new t.type.Var("T"),new t.type.Var("X"),new t.type.Var("S")]))],"member/2":[new t.type.Rule(new t.type.Term("member",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("_")])]),null),new t.type.Rule(new t.type.Term("member",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("Xs")])]),new t.type.Term("member",[new t.type.Var("X"),new t.type.Var("Xs")]))],"permutation/2":[new t.type.Rule(new t.type.Term("permutation",[new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("permutation",[new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("permutation",[new t.type.Var("T"),new t.type.Var("P")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("P")]),new t.type.Term("append",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("Y")]),new t.type.Var("S")])])]))],"maplist/2":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("X")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("Xs")])]))],"maplist/3":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs")])]))],"maplist/4":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs")])]))],"maplist/5":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds")])]))],"maplist/6":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")]),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Es")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D"),new t.type.Var("E")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds"),new t.type.Var("Es")])]))],"maplist/7":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")]),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Es")]),new t.type.Term(".",[new t.type.Var("F"),new t.type.Var("Fs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D"),new t.type.Var("E"),new t.type.Var("F")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds"),new t.type.Var("Es"),new t.type.Var("Fs")])]))],"maplist/8":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")]),new t.type.Term(".",[new t.type.Var("C"),new t.type.Var("Cs")]),new t.type.Term(".",[new t.type.Var("D"),new t.type.Var("Ds")]),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Es")]),new t.type.Term(".",[new t.type.Var("F"),new t.type.Var("Fs")]),new t.type.Term(".",[new t.type.Var("G"),new t.type.Var("Gs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B"),new t.type.Var("C"),new t.type.Var("D"),new t.type.Var("E"),new t.type.Var("F"),new t.type.Var("G")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs"),new t.type.Var("Cs"),new t.type.Var("Ds"),new t.type.Var("Es"),new t.type.Var("Fs"),new t.type.Var("Gs")])]))],"include/3":[new t.type.Rule(new t.type.Term("include",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("include",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("L")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P"),new t.type.Var("A")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("A"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Term("[]",[])]),new t.type.Var("B")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("F"),new t.type.Var("B")]),new t.type.Term(",",[new t.type.Term(";",[new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("F")]),new t.type.Term(",",[new t.type.Term("=",[new t.type.Var("L"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("S")])]),new t.type.Term("!",[])])]),new t.type.Term("=",[new t.type.Var("L"),new t.type.Var("S")])]),new t.type.Term("include",[new t.type.Var("P"),new t.type.Var("T"),new t.type.Var("S")])])])])]))],"exclude/3":[new t.type.Rule(new t.type.Term("exclude",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("exclude",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("exclude",[new t.type.Var("P"),new t.type.Var("T"),new t.type.Var("E")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P"),new t.type.Var("L")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("L"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Term("[]",[])]),new t.type.Var("Q")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("R"),new t.type.Var("Q")]),new t.type.Term(";",[new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("R")]),new t.type.Term(",",[new t.type.Term("!",[]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("E")])])]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("E")])])])])])])]))],"foldl/4":[new t.type.Rule(new t.type.Term("foldl",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Var("I"),new t.type.Var("I")]),null),new t.type.Rule(new t.type.Term("foldl",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("I"),new t.type.Var("R")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P"),new t.type.Var("L")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("L"),new t.type.Term(".",[new t.type.Var("I"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])])])]),new t.type.Var("L2")]),new t.type.Term(",",[new t.type.Term("=..",[new t.type.Var("P2"),new t.type.Var("L2")]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P2")]),new t.type.Term("foldl",[new t.type.Var("P"),new t.type.Var("T"),new t.type.Var("X"),new t.type.Var("R")])])])])]))],"select/3":[new t.type.Rule(new t.type.Term("select",[new t.type.Var("E"),new t.type.Term(".",[new t.type.Var("E"),new t.type.Var("Xs")]),new t.type.Var("Xs")]),null),new t.type.Rule(new t.type.Term("select",[new t.type.Var("E"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Ys")])]),new t.type.Term("select",[new t.type.Var("E"),new t.type.Var("Xs"),new t.type.Var("Ys")]))],"sum_list/2":[new t.type.Rule(new t.type.Term("sum_list",[new t.type.Term("[]",[]),new t.type.Num(0,!1)]),null),new t.type.Rule(new t.type.Term("sum_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("sum_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term("is",[new t.type.Var("S"),new t.type.Term("+",[new t.type.Var("X"),new t.type.Var("Y")])])]))],"max_list/2":[new t.type.Rule(new t.type.Term("max_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])]),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("max_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("max_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term(";",[new t.type.Term(",",[new t.type.Term(">=",[new t.type.Var("X"),new t.type.Var("Y")]),new t.type.Term(",",[new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("X")]),new t.type.Term("!",[])])]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("Y")])])]))],"min_list/2":[new t.type.Rule(new t.type.Term("min_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])]),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("min_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("min_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term(";",[new t.type.Term(",",[new t.type.Term("=<",[new t.type.Var("X"),new t.type.Var("Y")]),new t.type.Term(",",[new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("X")]),new t.type.Term("!",[])])]),new t.type.Term("=",[new t.type.Var("S"),new t.type.Var("Y")])])]))],"prod_list/2":[new t.type.Rule(new t.type.Term("prod_list",[new t.type.Term("[]",[]),new t.type.Num(1,!1)]),null),new t.type.Rule(new t.type.Term("prod_list",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("prod_list",[new t.type.Var("Xs"),new t.type.Var("Y")]),new t.type.Term("is",[new t.type.Var("S"),new t.type.Term("*",[new t.type.Var("X"),new t.type.Var("Y")])])]))],"last/2":[new t.type.Rule(new t.type.Term("last",[new t.type.Term(".",[new t.type.Var("X"),new t.type.Term("[]",[])]),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("last",[new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("Xs")]),new t.type.Var("X")]),new t.type.Term("last",[new t.type.Var("Xs"),new t.type.Var("X")]))],"prefix/2":[new t.type.Rule(new t.type.Term("prefix",[new t.type.Var("Part"),new t.type.Var("Whole")]),new t.type.Term("append",[new t.type.Var("Part"),new t.type.Var("_"),new t.type.Var("Whole")]))],"nth0/3":[new t.type.Rule(new t.type.Term("nth0",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")])]),new t.type.Term(",",[new t.type.Term(">=",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")]),new t.type.Term("!",[])])])]))],"nth1/3":[new t.type.Rule(new t.type.Term("nth1",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")])]),new t.type.Term(",",[new t.type.Term(">",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("_")]),new t.type.Term("!",[])])])]))],"nth0/4":[new t.type.Rule(new t.type.Term("nth0",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")])]),new t.type.Term(",",[new t.type.Term(">=",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(0,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term("!",[])])])]))],"nth1/4":[new t.type.Rule(new t.type.Term("nth1",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term(";",[new t.type.Term("->",[new t.type.Term("var",[new t.type.Var("X")]),new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")])]),new t.type.Term(",",[new t.type.Term(">",[new t.type.Var("X"),new t.type.Num(0,!1)]),new t.type.Term(",",[new t.type.Term("nth",[new t.type.Num(1,!1),new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("Z"),new t.type.Var("W")]),new t.type.Term("!",[])])])]))],"nth/5":[new t.type.Rule(new t.type.Term("nth",[new t.type.Var("N"),new t.type.Var("N"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("X"),new t.type.Var("Xs")]),null),new t.type.Rule(new t.type.Term("nth",[new t.type.Var("N"),new t.type.Var("O"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")]),new t.type.Var("Y"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Ys")])]),new t.type.Term(",",[new t.type.Term("is",[new t.type.Var("M"),new t.type.Term("+",[new t.type.Var("N"),new t.type.Num(1,!1)])]),new t.type.Term("nth",[new t.type.Var("M"),new t.type.Var("O"),new t.type.Var("Xs"),new t.type.Var("Y"),new t.type.Var("Ys")])]))],"length/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(!t.type.is_variable(A)&&!t.type.is_integer(A))o.throw_error(t.error.type("integer",A,n.indicator));else if(t.type.is_integer(A)&&A.value<0)o.throw_error(t.error.domain("not_less_than_zero",A,n.indicator));else{var p=new t.type.Term("length",[u,new t.type.Num(0,!1),A]);t.type.is_integer(A)&&(p=new t.type.Term(",",[p,new t.type.Term("!",[])])),o.prepend([new t.type.State(a.goal.replace(p),a.substitution,a)])}},"length/3":[new t.type.Rule(new t.type.Term("length",[new t.type.Term("[]",[]),new t.type.Var("N"),new t.type.Var("N")]),null),new t.type.Rule(new t.type.Term("length",[new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("X")]),new t.type.Var("A"),new t.type.Var("N")]),new t.type.Term(",",[new t.type.Term("succ",[new t.type.Var("A"),new t.type.Var("B")]),new t.type.Term("length",[new t.type.Var("X"),new t.type.Var("B"),new t.type.Var("N")])]))],"replicate/3":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_integer(A))o.throw_error(t.error.type("integer",A,n.indicator));else if(A.value<0)o.throw_error(t.error.domain("not_less_than_zero",A,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type("list",p,n.indicator));else{for(var h=new t.type.Term("[]"),E=0;E<A.value;E++)h=new t.type.Term(".",[u,h]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[h,p])),a.substitution,a)])}},"sort/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else{for(var p=[],h=u;h.indicator==="./2";)p.push(h.args[0]),h=h.args[1];if(t.type.is_variable(h))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(h))o.throw_error(t.error.type("list",u,n.indicator));else{for(var E=p.sort(t.compare),I=E.length-1;I>0;I--)E[I].equals(E[I-1])&&E.splice(I,1);for(var v=new t.type.Term("[]"),I=E.length-1;I>=0;I--)v=new t.type.Term(".",[E[I],v]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[v,A])),a.substitution,a)])}}},"msort/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else{for(var p=[],h=u;h.indicator==="./2";)p.push(h.args[0]),h=h.args[1];if(t.type.is_variable(h))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(h))o.throw_error(t.error.type("list",u,n.indicator));else{for(var E=p.sort(t.compare),I=new t.type.Term("[]"),v=E.length-1;v>=0;v--)I=new t.type.Term(".",[E[v],I]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[I,A])),a.substitution,a)])}}},"keysort/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else{for(var p=[],h,E=u;E.indicator==="./2";){if(h=E.args[0],t.type.is_variable(h)){o.throw_error(t.error.instantiation(n.indicator));return}else if(!t.type.is_term(h)||h.indicator!=="-/2"){o.throw_error(t.error.type("pair",h,n.indicator));return}h.args[0].pair=h.args[1],p.push(h.args[0]),E=E.args[1]}if(t.type.is_variable(E))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(E))o.throw_error(t.error.type("list",u,n.indicator));else{for(var I=p.sort(t.compare),v=new t.type.Term("[]"),x=I.length-1;x>=0;x--)v=new t.type.Term(".",[new t.type.Term("-",[I[x],I[x].pair]),v]),delete I[x].pair;o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[v,A])),a.substitution,a)])}}},"take/3":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A)||t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_list(A))o.throw_error(t.error.type("list",A,n.indicator));else if(!t.type.is_integer(u))o.throw_error(t.error.type("integer",u,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type("list",p,n.indicator));else{for(var h=u.value,E=[],I=A;h>0&&I.indicator==="./2";)E.push(I.args[0]),I=I.args[1],h--;if(h===0){for(var v=new t.type.Term("[]"),h=E.length-1;h>=0;h--)v=new t.type.Term(".",[E[h],v]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[v,p])),a.substitution,a)])}}},"drop/3":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A)||t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_list(A))o.throw_error(t.error.type("list",A,n.indicator));else if(!t.type.is_integer(u))o.throw_error(t.error.type("integer",u,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type("list",p,n.indicator));else{for(var h=u.value,E=[],I=A;h>0&&I.indicator==="./2";)E.push(I.args[0]),I=I.args[1],h--;h===0&&o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[I,p])),a.substitution,a)])}},"reverse/2":function(o,a,n){var u=n.args[0],A=n.args[1],p=t.type.is_instantiated_list(u),h=t.type.is_instantiated_list(A);if(t.type.is_variable(u)&&t.type.is_variable(A))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(u)&&!t.type.is_fully_list(u))o.throw_error(t.error.type("list",u,n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type("list",A,n.indicator));else if(!p&&!h)o.throw_error(t.error.instantiation(n.indicator));else{for(var E=p?u:A,I=new t.type.Term("[]",[]);E.indicator==="./2";)I=new t.type.Term(".",[E.args[0],I]),E=E.args[1];o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[I,p?A:u])),a.substitution,a)])}},"list_to_set/2":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else{for(var p=u,h=[];p.indicator==="./2";)h.push(p.args[0]),p=p.args[1];if(t.type.is_variable(p))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_term(p)||p.indicator!=="[]/0")o.throw_error(t.error.type("list",u,n.indicator));else{for(var E=[],I=new t.type.Term("[]",[]),v,x=0;x<h.length;x++){v=!1;for(var C=0;C<E.length&&!v;C++)v=t.compare(h[x],E[C])===0;v||E.push(h[x])}for(x=E.length-1;x>=0;x--)I=new t.type.Term(".",[E[x],I]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term("=",[A,I])),a.substitution,a)])}}}}},r=["append/2","append/3","member/2","permutation/2","maplist/2","maplist/3","maplist/4","maplist/5","maplist/6","maplist/7","maplist/8","include/3","exclude/3","foldl/4","sum_list/2","max_list/2","min_list/2","prod_list/2","last/2","prefix/2","nth0/3","nth1/3","nth0/4","nth1/4","length/2","replicate/3","select/3","sort/2","msort/2","keysort/2","take/3","drop/3","reverse/2","list_to_set/2"];typeof $8<"u"?$8.exports=function(o){t=o,new t.type.Module("lists",e(),r)}:new t.type.Module("lists",e(),r)})(Vgt)});var lme=_(Wr=>{"use strict";var jg=process.platform==="win32",eH="aes-256-cbc",zgt="sha256",Jde="The current environment doesn't support interactive reading from TTY.",Yn=ve("fs"),Vde=process.binding("tty_wrap").TTY,rH=ve("child_process"),kh=ve("path"),nH={prompt:"> ",hideEchoBack:!1,mask:"*",limit:[],limitMessage:"Input another, please.$<( [)limit(])>",defaultInput:"",trueValue:[],falseValue:[],caseSensitive:!1,keepWhitespace:!1,encoding:"utf8",bufferSize:1024,print:void 0,history:!0,cd:!1,phContent:void 0,preCheck:void 0},Wf="none",$c,RE,zde=!1,xh,ok,tH,Jgt=0,lH="",qg=[],ak,Xde=!1,iH=!1,c2=!1;function Zde(t){function e(r){return r.replace(/[^\w\u0080-\uFFFF]/g,function(o){return"#"+o.charCodeAt(0)+";"})}return ok.concat(function(r){var o=[];return Object.keys(r).forEach(function(a){r[a]==="boolean"?t[a]&&o.push("--"+a):r[a]==="string"&&t[a]&&o.push("--"+a,e(t[a]))}),o}({display:"string",displayOnly:"boolean",keyIn:"boolean",hideEchoBack:"boolean",mask:"string",limit:"string",caseSensitive:"boolean"}))}function Xgt(t,e){function r(U){var z,te="",ae;for(tH=tH||ve("os").tmpdir();;){z=kh.join(tH,U+te);try{ae=Yn.openSync(z,"wx")}catch(le){if(le.code==="EEXIST"){te++;continue}else throw le}Yn.closeSync(ae);break}return z}var o,a,n,u={},A,p,h=r("readline-sync.stdout"),E=r("readline-sync.stderr"),I=r("readline-sync.exit"),v=r("readline-sync.done"),x=ve("crypto"),C,R,L;C=x.createHash(zgt),C.update(""+process.pid+Jgt+++Math.random()),L=C.digest("hex"),R=x.createDecipher(eH,L),o=Zde(t),jg?(a=process.env.ComSpec||"cmd.exe",process.env.Q='"',n=["/V:ON","/S","/C","(%Q%"+a+"%Q% /V:ON /S /C %Q%%Q%"+xh+"%Q%"+o.map(function(U){return" %Q%"+U+"%Q%"}).join("")+" & (echo !ERRORLEVEL!)>%Q%"+I+"%Q%%Q%) 2>%Q%"+E+"%Q% |%Q%"+process.execPath+"%Q% %Q%"+__dirname+"\\encrypt.js%Q% %Q%"+eH+"%Q% %Q%"+L+"%Q% >%Q%"+h+"%Q% & (echo 1)>%Q%"+v+"%Q%"]):(a="/bin/sh",n=["-c",'("'+xh+'"'+o.map(function(U){return" '"+U.replace(/'/g,"'\\''")+"'"}).join("")+'; echo $?>"'+I+'") 2>"'+E+'" |"'+process.execPath+'" "'+__dirname+'/encrypt.js" "'+eH+'" "'+L+'" >"'+h+'"; echo 1 >"'+v+'"']),c2&&c2("_execFileSync",o);try{rH.spawn(a,n,e)}catch(U){u.error=new Error(U.message),u.error.method="_execFileSync - spawn",u.error.program=a,u.error.args=n}for(;Yn.readFileSync(v,{encoding:t.encoding}).trim()!=="1";);return(A=Yn.readFileSync(I,{encoding:t.encoding}).trim())==="0"?u.input=R.update(Yn.readFileSync(h,{encoding:"binary"}),"hex",t.encoding)+R.final(t.encoding):(p=Yn.readFileSync(E,{encoding:t.encoding}).trim(),u.error=new Error(Jde+(p?` +`+p:"")),u.error.method="_execFileSync",u.error.program=a,u.error.args=n,u.error.extMessage=p,u.error.exitCode=+A),Yn.unlinkSync(h),Yn.unlinkSync(E),Yn.unlinkSync(I),Yn.unlinkSync(v),u}function Zgt(t){var e,r={},o,a={env:process.env,encoding:t.encoding};if(xh||(jg?process.env.PSModulePath?(xh="powershell.exe",ok=["-ExecutionPolicy","Bypass","-File",__dirname+"\\read.ps1"]):(xh="cscript.exe",ok=["//nologo",__dirname+"\\read.cs.js"]):(xh="/bin/sh",ok=[__dirname+"/read.sh"])),jg&&!process.env.PSModulePath&&(a.stdio=[process.stdin]),rH.execFileSync){e=Zde(t),c2&&c2("execFileSync",e);try{r.input=rH.execFileSync(xh,e,a)}catch(n){o=n.stderr?(n.stderr+"").trim():"",r.error=new Error(Jde+(o?` +`+o:"")),r.error.method="execFileSync",r.error.program=xh,r.error.args=e,r.error.extMessage=o,r.error.exitCode=n.status,r.error.code=n.code,r.error.signal=n.signal}}else r=Xgt(t,a);return r.error||(r.input=r.input.replace(/^\s*'|'\s*$/g,""),t.display=""),r}function sH(t){var e="",r=t.display,o=!t.display&&t.keyIn&&t.hideEchoBack&&!t.mask;function a(){var n=Zgt(t);if(n.error)throw n.error;return n.input}return iH&&iH(t),function(){var n,u,A;function p(){return n||(n=process.binding("fs"),u=process.binding("constants")),n}if(typeof Wf=="string")if(Wf=null,jg){if(A=function(h){var E=h.replace(/^\D+/,"").split("."),I=0;return(E[0]=+E[0])&&(I+=E[0]*1e4),(E[1]=+E[1])&&(I+=E[1]*100),(E[2]=+E[2])&&(I+=E[2]),I}(process.version),!(A>=20302&&A<40204||A>=5e4&&A<50100||A>=50600&&A<60200)&&process.stdin.isTTY)process.stdin.pause(),Wf=process.stdin.fd,RE=process.stdin._handle;else try{Wf=p().open("CONIN$",u.O_RDWR,parseInt("0666",8)),RE=new Vde(Wf,!0)}catch{}if(process.stdout.isTTY)$c=process.stdout.fd;else{try{$c=Yn.openSync("\\\\.\\CON","w")}catch{}if(typeof $c!="number")try{$c=p().open("CONOUT$",u.O_RDWR,parseInt("0666",8))}catch{}}}else{if(process.stdin.isTTY){process.stdin.pause();try{Wf=Yn.openSync("/dev/tty","r"),RE=process.stdin._handle}catch{}}else try{Wf=Yn.openSync("/dev/tty","r"),RE=new Vde(Wf,!1)}catch{}if(process.stdout.isTTY)$c=process.stdout.fd;else try{$c=Yn.openSync("/dev/tty","w")}catch{}}}(),function(){var n,u,A=!t.hideEchoBack&&!t.keyIn,p,h,E,I,v;ak="";function x(C){return C===zde?!0:RE.setRawMode(C)!==0?!1:(zde=C,!0)}if(Xde||!RE||typeof $c!="number"&&(t.display||!A)){e=a();return}if(t.display&&(Yn.writeSync($c,t.display),t.display=""),!t.displayOnly){if(!x(!A)){e=a();return}for(h=t.keyIn?1:t.bufferSize,p=Buffer.allocUnsafe&&Buffer.alloc?Buffer.alloc(h):new Buffer(h),t.keyIn&&t.limit&&(u=new RegExp("[^"+t.limit+"]","g"+(t.caseSensitive?"":"i")));;){E=0;try{E=Yn.readSync(Wf,p,0,h)}catch(C){if(C.code!=="EOF"){x(!1),e+=a();return}}if(E>0?(I=p.toString(t.encoding,0,E),ak+=I):(I=` +`,ak+="\0"),I&&typeof(v=(I.match(/^(.*?)[\r\n]/)||[])[1])=="string"&&(I=v,n=!0),I&&(I=I.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")),I&&u&&(I=I.replace(u,"")),I&&(A||(t.hideEchoBack?t.mask&&Yn.writeSync($c,new Array(I.length+1).join(t.mask)):Yn.writeSync($c,I)),e+=I),!t.keyIn&&n||t.keyIn&&e.length>=h)break}!A&&!o&&Yn.writeSync($c,` +`),x(!1)}}(),t.print&&!o&&t.print(r+(t.displayOnly?"":(t.hideEchoBack?new Array(e.length+1).join(t.mask):e)+` +`),t.encoding),t.displayOnly?"":lH=t.keepWhitespace||t.keyIn?e:e.trim()}function $gt(t,e){var r=[];function o(a){a!=null&&(Array.isArray(a)?a.forEach(o):(!e||e(a))&&r.push(a))}return o(t),r}function cH(t){return t.replace(/[\x00-\x7f]/g,function(e){return"\\x"+("00"+e.charCodeAt().toString(16)).substr(-2)})}function Ns(){var t=Array.prototype.slice.call(arguments),e,r;return t.length&&typeof t[0]=="boolean"&&(r=t.shift(),r&&(e=Object.keys(nH),t.unshift(nH))),t.reduce(function(o,a){return a==null||(a.hasOwnProperty("noEchoBack")&&!a.hasOwnProperty("hideEchoBack")&&(a.hideEchoBack=a.noEchoBack,delete a.noEchoBack),a.hasOwnProperty("noTrim")&&!a.hasOwnProperty("keepWhitespace")&&(a.keepWhitespace=a.noTrim,delete a.noTrim),r||(e=Object.keys(a)),e.forEach(function(n){var u;if(a.hasOwnProperty(n))switch(u=a[n],n){case"mask":case"limitMessage":case"defaultInput":case"encoding":u=u!=null?u+"":"",u&&n!=="limitMessage"&&(u=u.replace(/[\r\n]/g,"")),o[n]=u;break;case"bufferSize":!isNaN(u=parseInt(u,10))&&typeof u=="number"&&(o[n]=u);break;case"displayOnly":case"keyIn":case"hideEchoBack":case"caseSensitive":case"keepWhitespace":case"history":case"cd":o[n]=!!u;break;case"limit":case"trueValue":case"falseValue":o[n]=$gt(u,function(A){var p=typeof A;return p==="string"||p==="number"||p==="function"||A instanceof RegExp}).map(function(A){return typeof A=="string"?A.replace(/[\r\n]/g,""):A});break;case"print":case"phContent":case"preCheck":o[n]=typeof u=="function"?u:void 0;break;case"prompt":case"display":o[n]=u??"";break}})),o},{})}function oH(t,e,r){return e.some(function(o){var a=typeof o;return a==="string"?r?t===o:t.toLowerCase()===o.toLowerCase():a==="number"?parseFloat(t)===o:a==="function"?o(t):o instanceof RegExp?o.test(t):!1})}function uH(t,e){var r=kh.normalize(jg?(process.env.HOMEDRIVE||"")+(process.env.HOMEPATH||""):process.env.HOME||"").replace(/[\/\\]+$/,"");return t=kh.normalize(t),e?t.replace(/^~(?=\/|\\|$)/,r):t.replace(new RegExp("^"+cH(r)+"(?=\\/|\\\\|$)",jg?"i":""),"~")}function TE(t,e){var r="(?:\\(([\\s\\S]*?)\\))?(\\w+|.-.)(?:\\(([\\s\\S]*?)\\))?",o=new RegExp("(\\$)?(\\$<"+r+">)","g"),a=new RegExp("(\\$)?(\\$\\{"+r+"\\})","g");function n(u,A,p,h,E,I){var v;return A||typeof(v=e(E))!="string"?p:v?(h||"")+v+(I||""):""}return t.replace(o,n).replace(a,n)}function $de(t,e,r){var o,a=[],n=-1,u=0,A="",p;function h(E,I){return I.length>3?(E.push(I[0]+"..."+I[I.length-1]),p=!0):I.length&&(E=E.concat(I)),E}return o=t.reduce(function(E,I){return E.concat((I+"").split(""))},[]).reduce(function(E,I){var v,x;return e||(I=I.toLowerCase()),v=/^\d$/.test(I)?1:/^[A-Z]$/.test(I)?2:/^[a-z]$/.test(I)?3:0,r&&v===0?A+=I:(x=I.charCodeAt(0),v&&v===n&&x===u+1?a.push(I):(E=h(E,a),a=[I],n=v),u=x),E},[]),o=h(o,a),A&&(o.push(A),p=!0),{values:o,suppressed:p}}function eme(t,e){return t.join(t.length>2?", ":e?" / ":"/")}function tme(t,e){var r,o,a={},n;if(e.phContent&&(r=e.phContent(t,e)),typeof r!="string")switch(t){case"hideEchoBack":case"mask":case"defaultInput":case"caseSensitive":case"keepWhitespace":case"encoding":case"bufferSize":case"history":case"cd":r=e.hasOwnProperty(t)?typeof e[t]=="boolean"?e[t]?"on":"off":e[t]+"":"";break;case"limit":case"trueValue":case"falseValue":o=e[e.hasOwnProperty(t+"Src")?t+"Src":t],e.keyIn?(a=$de(o,e.caseSensitive),o=a.values):o=o.filter(function(u){var A=typeof u;return A==="string"||A==="number"}),r=eme(o,a.suppressed);break;case"limitCount":case"limitCountNotZero":r=e[e.hasOwnProperty("limitSrc")?"limitSrc":"limit"].length,r=r||t!=="limitCountNotZero"?r+"":"";break;case"lastInput":r=lH;break;case"cwd":case"CWD":case"cwdHome":r=process.cwd(),t==="CWD"?r=kh.basename(r):t==="cwdHome"&&(r=uH(r));break;case"date":case"time":case"localeDate":case"localeTime":r=new Date()["to"+t.replace(/^./,function(u){return u.toUpperCase()})+"String"]();break;default:typeof(n=(t.match(/^history_m(\d+)$/)||[])[1])=="string"&&(r=qg[qg.length-n]||"")}return r}function rme(t){var e=/^(.)-(.)$/.exec(t),r="",o,a,n,u;if(!e)return null;for(o=e[1].charCodeAt(0),a=e[2].charCodeAt(0),u=o<a?1:-1,n=o;n!==a+u;n+=u)r+=String.fromCharCode(n);return r}function aH(t){var e=new RegExp(/(\s*)(?:("|')(.*?)(?:\2|$)|(\S+))/g),r,o="",a=[],n;for(t=t.trim();r=e.exec(t);)n=r[3]||r[4]||"",r[1]&&(a.push(o),o=""),o+=n;return o&&a.push(o),a}function nme(t,e){return e.trueValue.length&&oH(t,e.trueValue,e.caseSensitive)?!0:e.falseValue.length&&oH(t,e.falseValue,e.caseSensitive)?!1:t}function ime(t){var e,r,o,a,n,u,A;function p(E){return tme(E,t)}function h(E){t.display+=(/[^\r\n]$/.test(t.display)?` +`:"")+E}for(t.limitSrc=t.limit,t.displaySrc=t.display,t.limit="",t.display=TE(t.display+"",p);;){if(e=sH(t),r=!1,o="",t.defaultInput&&!e&&(e=t.defaultInput),t.history&&((a=/^\s*\!(?:\!|-1)(:p)?\s*$/.exec(e))?(n=qg[0]||"",a[1]?r=!0:e=n,h(n+` +`),r||(t.displayOnly=!0,sH(t),t.displayOnly=!1)):e&&e!==qg[qg.length-1]&&(qg=[e])),!r&&t.cd&&e)switch(u=aH(e),u[0].toLowerCase()){case"cd":if(u[1])try{process.chdir(uH(u[1],!0))}catch(E){h(E+"")}r=!0;break;case"pwd":h(process.cwd()),r=!0;break}if(!r&&t.preCheck&&(A=t.preCheck(e,t),e=A.res,A.forceNext&&(r=!0)),!r){if(!t.limitSrc.length||oH(e,t.limitSrc,t.caseSensitive))break;t.limitMessage&&(o=TE(t.limitMessage,p))}h((o?o+` +`:"")+TE(t.displaySrc+"",p))}return nme(e,t)}Wr._DBG_set_useExt=function(t){Xde=t};Wr._DBG_set_checkOptions=function(t){iH=t};Wr._DBG_set_checkMethod=function(t){c2=t};Wr._DBG_clearHistory=function(){lH="",qg=[]};Wr.setDefaultOptions=function(t){return nH=Ns(!0,t),Ns(!0)};Wr.question=function(t,e){return ime(Ns(Ns(!0,e),{display:t}))};Wr.prompt=function(t){var e=Ns(!0,t);return e.display=e.prompt,ime(e)};Wr.keyIn=function(t,e){var r=Ns(Ns(!0,e),{display:t,keyIn:!0,keepWhitespace:!0});return r.limitSrc=r.limit.filter(function(o){var a=typeof o;return a==="string"||a==="number"}).map(function(o){return TE(o+"",rme)}),r.limit=cH(r.limitSrc.join("")),["trueValue","falseValue"].forEach(function(o){r[o]=r[o].reduce(function(a,n){var u=typeof n;return u==="string"||u==="number"?a=a.concat((n+"").split("")):a.push(n),a},[])}),r.display=TE(r.display+"",function(o){return tme(o,r)}),nme(sH(r),r)};Wr.questionEMail=function(t,e){return t==null&&(t="Input e-mail address: "),Wr.question(t,Ns({hideEchoBack:!1,limit:/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,limitMessage:"Input valid e-mail address, please.",trueValue:null,falseValue:null},e,{keepWhitespace:!1,cd:!1}))};Wr.questionNewPassword=function(t,e){var r,o,a,n=Ns({hideEchoBack:!0,mask:"*",limitMessage:`It can include: $<charlist> +And the length must be: $<length>`,trueValue:null,falseValue:null,caseSensitive:!0},e,{history:!1,cd:!1,phContent:function(x){return x==="charlist"?r.text:x==="length"?o+"..."+a:null}}),u,A,p,h,E,I,v;for(e=e||{},u=TE(e.charlist?e.charlist+"":"$<!-~>",rme),(isNaN(o=parseInt(e.min,10))||typeof o!="number")&&(o=12),(isNaN(a=parseInt(e.max,10))||typeof a!="number")&&(a=24),h=new RegExp("^["+cH(u)+"]{"+o+","+a+"}$"),r=$de([u],n.caseSensitive,!0),r.text=eme(r.values,r.suppressed),A=e.confirmMessage!=null?e.confirmMessage:"Reinput a same one to confirm it: ",p=e.unmatchMessage!=null?e.unmatchMessage:"It differs from first one. Hit only the Enter key if you want to retry from first one.",t==null&&(t="Input new password: "),E=n.limitMessage;!v;)n.limit=h,n.limitMessage=E,I=Wr.question(t,n),n.limit=[I,""],n.limitMessage=p,v=Wr.question(A,n);return I};function sme(t,e,r){var o;function a(n){return o=r(n),!isNaN(o)&&typeof o=="number"}return Wr.question(t,Ns({limitMessage:"Input valid number, please."},e,{limit:a,cd:!1})),o}Wr.questionInt=function(t,e){return sme(t,e,function(r){return parseInt(r,10)})};Wr.questionFloat=function(t,e){return sme(t,e,parseFloat)};Wr.questionPath=function(t,e){var r,o="",a=Ns({hideEchoBack:!1,limitMessage:`$<error( +)>Input valid path, please.$<( Min:)min>$<( Max:)max>`,history:!0,cd:!0},e,{keepWhitespace:!1,limit:function(n){var u,A,p;n=uH(n,!0),o="";function h(E){E.split(/\/|\\/).reduce(function(I,v){var x=kh.resolve(I+=v+kh.sep);if(!Yn.existsSync(x))Yn.mkdirSync(x);else if(!Yn.statSync(x).isDirectory())throw new Error("Non directory already exists: "+x);return I},"")}try{if(u=Yn.existsSync(n),r=u?Yn.realpathSync(n):kh.resolve(n),!e.hasOwnProperty("exists")&&!u||typeof e.exists=="boolean"&&e.exists!==u)return o=(u?"Already exists":"No such file or directory")+": "+r,!1;if(!u&&e.create&&(e.isDirectory?h(r):(h(kh.dirname(r)),Yn.closeSync(Yn.openSync(r,"w"))),r=Yn.realpathSync(r)),u&&(e.min||e.max||e.isFile||e.isDirectory)){if(A=Yn.statSync(r),e.isFile&&!A.isFile())return o="Not file: "+r,!1;if(e.isDirectory&&!A.isDirectory())return o="Not directory: "+r,!1;if(e.min&&A.size<+e.min||e.max&&A.size>+e.max)return o="Size "+A.size+" is out of range: "+r,!1}if(typeof e.validate=="function"&&(p=e.validate(r))!==!0)return typeof p=="string"&&(o=p),!1}catch(E){return o=E+"",!1}return!0},phContent:function(n){return n==="error"?o:n!=="min"&&n!=="max"?null:e.hasOwnProperty(n)?e[n]+"":""}});return e=e||{},t==null&&(t='Input path (you can "cd" and "pwd"): '),Wr.question(t,a),r};function ome(t,e){var r={},o={};return typeof t=="object"?(Object.keys(t).forEach(function(a){typeof t[a]=="function"&&(o[e.caseSensitive?a:a.toLowerCase()]=t[a])}),r.preCheck=function(a){var n;return r.args=aH(a),n=r.args[0]||"",e.caseSensitive||(n=n.toLowerCase()),r.hRes=n!=="_"&&o.hasOwnProperty(n)?o[n].apply(a,r.args.slice(1)):o.hasOwnProperty("_")?o._.apply(a,r.args):null,{res:a,forceNext:!1}},o.hasOwnProperty("_")||(r.limit=function(){var a=r.args[0]||"";return e.caseSensitive||(a=a.toLowerCase()),o.hasOwnProperty(a)})):r.preCheck=function(a){return r.args=aH(a),r.hRes=typeof t=="function"?t.apply(a,r.args):!0,{res:a,forceNext:!1}},r}Wr.promptCL=function(t,e){var r=Ns({hideEchoBack:!1,limitMessage:"Requested command is not available.",caseSensitive:!1,history:!0},e),o=ome(t,r);return r.limit=o.limit,r.preCheck=o.preCheck,Wr.prompt(r),o.args};Wr.promptLoop=function(t,e){for(var r=Ns({hideEchoBack:!1,trueValue:null,falseValue:null,caseSensitive:!1,history:!0},e);!t(Wr.prompt(r)););};Wr.promptCLLoop=function(t,e){var r=Ns({hideEchoBack:!1,limitMessage:"Requested command is not available.",caseSensitive:!1,history:!0},e),o=ome(t,r);for(r.limit=o.limit,r.preCheck=o.preCheck;Wr.prompt(r),!o.hRes;);};Wr.promptSimShell=function(t){return Wr.prompt(Ns({hideEchoBack:!1,history:!0},t,{prompt:function(){return jg?"$<cwd>>":(process.env.USER||"")+(process.env.HOSTNAME?"@"+process.env.HOSTNAME.replace(/\..*$/,""):"")+":$<cwdHome>$ "}()}))};function ame(t,e,r){var o;return t==null&&(t="Are you sure? "),(!e||e.guide!==!1)&&(t+="")&&(t=t.replace(/\s*:?\s*$/,"")+" [y/n]: "),o=Wr.keyIn(t,Ns(e,{hideEchoBack:!1,limit:r,trueValue:"y",falseValue:"n",caseSensitive:!1})),typeof o=="boolean"?o:""}Wr.keyInYN=function(t,e){return ame(t,e)};Wr.keyInYNStrict=function(t,e){return ame(t,e,"yn")};Wr.keyInPause=function(t,e){t==null&&(t="Continue..."),(!e||e.guide!==!1)&&(t+="")&&(t=t.replace(/\s+$/,"")+" (Hit any key)"),Wr.keyIn(t,Ns({limit:null},e,{hideEchoBack:!0,mask:""}))};Wr.keyInSelect=function(t,e,r){var o=Ns({hideEchoBack:!1},r,{trueValue:null,falseValue:null,caseSensitive:!1,phContent:function(p){return p==="itemsCount"?t.length+"":p==="firstItem"?(t[0]+"").trim():p==="lastItem"?(t[t.length-1]+"").trim():null}}),a="",n={},u=49,A=` +`;if(!Array.isArray(t)||!t.length||t.length>35)throw"`items` must be Array (max length: 35).";return t.forEach(function(p,h){var E=String.fromCharCode(u);a+=E,n[E]=h,A+="["+E+"] "+(p+"").trim()+` +`,u=u===57?97:u+1}),(!r||r.cancel!==!1)&&(a+="0",n[0]=-1,A+="[0] "+(r&&r.cancel!=null&&typeof r.cancel!="boolean"?(r.cancel+"").trim():"CANCEL")+` +`),o.limit=a,A+=` +`,e==null&&(e="Choose one from list: "),(e+="")&&((!r||r.guide!==!1)&&(e=e.replace(/\s*:?\s*$/,"")+" [$<limit>]: "),A+=e),n[Wr.keyIn(A,o).toLowerCase()]};Wr.getRawInput=function(){return ak};function u2(t,e){var r;return e.length&&(r={},r[t]=e[0]),Wr.setDefaultOptions(r)[t]}Wr.setPrint=function(){return u2("print",arguments)};Wr.setPrompt=function(){return u2("prompt",arguments)};Wr.setEncoding=function(){return u2("encoding",arguments)};Wr.setMask=function(){return u2("mask",arguments)};Wr.setBufferSize=function(){return u2("bufferSize",arguments)}});var AH=_((a7t,gl)=>{(function(){var t={major:0,minor:2,patch:66,status:"beta"};tau_file_system={files:{},open:function(w,S,y){var F=tau_file_system.files[w];if(!F){if(y==="read")return null;F={path:w,text:"",type:S,get:function(J,X){return X===this.text.length||X>this.text.length?"end_of_file":this.text.substring(X,X+J)},put:function(J,X){return X==="end_of_file"?(this.text+=J,!0):X==="past_end_of_file"?null:(this.text=this.text.substring(0,X)+J+this.text.substring(X+J.length),!0)},get_byte:function(J){if(J==="end_of_stream")return-1;var X=Math.floor(J/2);if(this.text.length<=X)return-1;var $=n(this.text[Math.floor(J/2)],0);return J%2===0?$&255:$/256>>>0},put_byte:function(J,X){var $=X==="end_of_stream"?this.text.length:Math.floor(X/2);if(this.text.length<$)return null;var ie=this.text.length===$?-1:n(this.text[Math.floor(X/2)],0);return X%2===0?(ie=ie/256>>>0,ie=(ie&255)<<8|J&255):(ie=ie&255,ie=(J&255)<<8|ie&255),this.text.length===$?this.text+=u(ie):this.text=this.text.substring(0,$)+u(ie)+this.text.substring($+1),!0},flush:function(){return!0},close:function(){var J=tau_file_system.files[this.path];return J?!0:null}},tau_file_system.files[w]=F}return y==="write"&&(F.text=""),F}},tau_user_input={buffer:"",get:function(w,S){for(var y;tau_user_input.buffer.length<w;)y=window.prompt(),y&&(tau_user_input.buffer+=y);return y=tau_user_input.buffer.substr(0,w),tau_user_input.buffer=tau_user_input.buffer.substr(w),y}},tau_user_output={put:function(w,S){return console.log(w),!0},flush:function(){return!0}},nodejs_file_system={open:function(w,S,y){var F=ve("fs"),J=F.openSync(w,y[0]);return y==="read"&&!F.existsSync(w)?null:{get:function(X,$){var ie=new Buffer(X);return F.readSync(J,ie,0,X,$),ie.toString()},put:function(X,$){var ie=Buffer.from(X);if($==="end_of_file")F.writeSync(J,ie);else{if($==="past_end_of_file")return null;F.writeSync(J,ie,0,ie.length,$)}return!0},get_byte:function(X){return null},put_byte:function(X,$){return null},flush:function(){return!0},close:function(){return F.closeSync(J),!0}}}},nodejs_user_input={buffer:"",get:function(w,S){for(var y,F=lme();nodejs_user_input.buffer.length<w;)nodejs_user_input.buffer+=F.question();return y=nodejs_user_input.buffer.substr(0,w),nodejs_user_input.buffer=nodejs_user_input.buffer.substr(w),y}},nodejs_user_output={put:function(w,S){return process.stdout.write(w),!0},flush:function(){return!0}};var e;Array.prototype.indexOf?e=function(w,S){return w.indexOf(S)}:e=function(w,S){for(var y=w.length,F=0;F<y;F++)if(S===w[F])return F;return-1};var r=function(w,S){if(w.length!==0){for(var y=w[0],F=w.length,J=1;J<F;J++)y=S(y,w[J]);return y}},o;Array.prototype.map?o=function(w,S){return w.map(S)}:o=function(w,S){for(var y=[],F=w.length,J=0;J<F;J++)y.push(S(w[J]));return y};var a;Array.prototype.filter?a=function(w,S){return w.filter(S)}:a=function(w,S){for(var y=[],F=w.length,J=0;J<F;J++)S(w[J])&&y.push(w[J]);return y};var n;String.prototype.codePointAt?n=function(w,S){return w.codePointAt(S)}:n=function(w,S){return w.charCodeAt(S)};var u;String.fromCodePoint?u=function(){return String.fromCodePoint.apply(null,arguments)}:u=function(){return String.fromCharCode.apply(null,arguments)};var A=0,p=1,h=/(\\a)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\v)|\\x([0-9a-fA-F]+)\\|\\([0-7]+)\\|(\\\\)|(\\')|('')|(\\")|(\\`)|(\\.)|(.)/g,E={"\\a":7,"\\b":8,"\\f":12,"\\n":10,"\\r":13,"\\t":9,"\\v":11};function I(w){var S=[],y=!1;return w.replace(h,function(F,J,X,$,ie,be,Re,at,dt,jt,tr,St,ln,kr,mr,br,Kr){switch(!0){case dt!==void 0:return S.push(parseInt(dt,16)),"";case jt!==void 0:return S.push(parseInt(jt,8)),"";case tr!==void 0:case St!==void 0:case ln!==void 0:case kr!==void 0:case mr!==void 0:return S.push(n(F.substr(1),0)),"";case Kr!==void 0:return S.push(n(Kr,0)),"";case br!==void 0:y=!0;default:return S.push(E[F]),""}}),y?null:S}function v(w,S){var y="";if(w.length<2)return w;try{w=w.replace(/\\([0-7]+)\\/g,function($,ie){return u(parseInt(ie,8))}),w=w.replace(/\\x([0-9a-fA-F]+)\\/g,function($,ie){return u(parseInt(ie,16))})}catch{return null}for(var F=0;F<w.length;F++){var J=w.charAt(F),X=w.charAt(F+1);if(J===S&&X===S)F++,y+=S;else if(J==="\\")if(["a","b","f","n","r","t","v","'",'"',"\\","a","\b","\f",` +`,"\r"," ","\v"].indexOf(X)!==-1)switch(F+=1,X){case"a":y+="a";break;case"b":y+="\b";break;case"f":y+="\f";break;case"n":y+=` +`;break;case"r":y+="\r";break;case"t":y+=" ";break;case"v":y+="\v";break;case"'":y+="'";break;case'"':y+='"';break;case"\\":y+="\\";break}else return null;else y+=J}return y}function x(w){for(var S="",y=0;y<w.length;y++)switch(w.charAt(y)){case"'":S+="\\'";break;case"\\":S+="\\\\";break;case"\b":S+="\\b";break;case"\f":S+="\\f";break;case` +`:S+="\\n";break;case"\r":S+="\\r";break;case" ":S+="\\t";break;case"\v":S+="\\v";break;default:S+=w.charAt(y);break}return S}function C(w){var S=w.substr(2);switch(w.substr(0,2).toLowerCase()){case"0x":return parseInt(S,16);case"0b":return parseInt(S,2);case"0o":return parseInt(S,8);case"0'":return I(S)[0];default:return parseFloat(w)}}var R={whitespace:/^\s*(?:(?:%.*)|(?:\/\*(?:\n|\r|.)*?\*\/)|(?:\s+))\s*/,variable:/^(?:[A-Z_][a-zA-Z0-9_]*)/,atom:/^(\!|,|;|[a-z][0-9a-zA-Z_]*|[#\$\&\*\+\-\.\/\:\<\=\>\?\@\^\~\\]+|'(?:[^']*?(?:\\(?:x?\d+)?\\)*(?:'')*(?:\\')*)*')/,number:/^(?:0o[0-7]+|0x[0-9a-fA-F]+|0b[01]+|0'(?:''|\\[abfnrtv\\'"`]|\\x?\d+\\|[^\\])|\d+(?:\.\d+(?:[eE][+-]?\d+)?)?)/,string:/^(?:"([^"]|""|\\")*"|`([^`]|``|\\`)*`)/,l_brace:/^(?:\[)/,r_brace:/^(?:\])/,l_bracket:/^(?:\{)/,r_bracket:/^(?:\})/,bar:/^(?:\|)/,l_paren:/^(?:\()/,r_paren:/^(?:\))/};function L(w,S){return w.get_flag("char_conversion").id==="on"?S.replace(/./g,function(y){return w.get_char_conversion(y)}):S}function U(w){this.thread=w,this.text="",this.tokens=[]}U.prototype.set_last_tokens=function(w){return this.tokens=w},U.prototype.new_text=function(w){this.text=w,this.tokens=[]},U.prototype.get_tokens=function(w){var S,y=0,F=0,J=0,X=[],$=!1;if(w){var ie=this.tokens[w-1];y=ie.len,S=L(this.thread,this.text.substr(ie.len)),F=ie.line,J=ie.start}else S=this.text;if(/^\s*$/.test(S))return null;for(;S!=="";){var be=[],Re=!1;if(/^\n/.exec(S)!==null){F++,J=0,y++,S=S.replace(/\n/,""),$=!0;continue}for(var at in R)if(R.hasOwnProperty(at)){var dt=R[at].exec(S);dt&&be.push({value:dt[0],name:at,matches:dt})}if(!be.length)return this.set_last_tokens([{value:S,matches:[],name:"lexical",line:F,start:J}]);var ie=r(be,function(kr,mr){return kr.value.length>=mr.value.length?kr:mr});switch(ie.start=J,ie.line=F,S=S.replace(ie.value,""),J+=ie.value.length,y+=ie.value.length,ie.name){case"atom":ie.raw=ie.value,ie.value.charAt(0)==="'"&&(ie.value=v(ie.value.substr(1,ie.value.length-2),"'"),ie.value===null&&(ie.name="lexical",ie.value="unknown escape sequence"));break;case"number":ie.float=ie.value.substring(0,2)!=="0x"&&ie.value.match(/[.eE]/)!==null&&ie.value!=="0'.",ie.value=C(ie.value),ie.blank=Re;break;case"string":var jt=ie.value.charAt(0);ie.value=v(ie.value.substr(1,ie.value.length-2),jt),ie.value===null&&(ie.name="lexical",ie.value="unknown escape sequence");break;case"whitespace":var tr=X[X.length-1];tr&&(tr.space=!0),Re=!0;continue;case"r_bracket":X.length>0&&X[X.length-1].name==="l_bracket"&&(ie=X.pop(),ie.name="atom",ie.value="{}",ie.raw="{}",ie.space=!1);break;case"r_brace":X.length>0&&X[X.length-1].name==="l_brace"&&(ie=X.pop(),ie.name="atom",ie.value="[]",ie.raw="[]",ie.space=!1);break}ie.len=y,X.push(ie),Re=!1}var St=this.set_last_tokens(X);return St.length===0?null:St};function z(w,S,y,F,J){if(!S[y])return{type:A,value:b.error.syntax(S[y-1],"expression expected",!0)};var X;if(F==="0"){var $=S[y];switch($.name){case"number":return{type:p,len:y+1,value:new b.type.Num($.value,$.float)};case"variable":return{type:p,len:y+1,value:new b.type.Var($.value)};case"string":var ie;switch(w.get_flag("double_quotes").id){case"atom":ie=new H($.value,[]);break;case"codes":ie=new H("[]",[]);for(var be=$.value.length-1;be>=0;be--)ie=new H(".",[new b.type.Num(n($.value,be),!1),ie]);break;case"chars":ie=new H("[]",[]);for(var be=$.value.length-1;be>=0;be--)ie=new H(".",[new b.type.Term($.value.charAt(be),[]),ie]);break}return{type:p,len:y+1,value:ie};case"l_paren":var St=z(w,S,y+1,w.__get_max_priority(),!0);return St.type!==p?St:S[St.len]&&S[St.len].name==="r_paren"?(St.len++,St):{type:A,derived:!0,value:b.error.syntax(S[St.len]?S[St.len]:S[St.len-1],") or operator expected",!S[St.len])};case"l_bracket":var St=z(w,S,y+1,w.__get_max_priority(),!0);return St.type!==p?St:S[St.len]&&S[St.len].name==="r_bracket"?(St.len++,St.value=new H("{}",[St.value]),St):{type:A,derived:!0,value:b.error.syntax(S[St.len]?S[St.len]:S[St.len-1],"} or operator expected",!S[St.len])}}var Re=te(w,S,y,J);return Re.type===p||Re.derived||(Re=ae(w,S,y),Re.type===p||Re.derived)?Re:{type:A,derived:!1,value:b.error.syntax(S[y],"unexpected token")}}var at=w.__get_max_priority(),dt=w.__get_next_priority(F),jt=y;if(S[y].name==="atom"&&S[y+1]&&(S[y].space||S[y+1].name!=="l_paren")){var $=S[y++],tr=w.__lookup_operator_classes(F,$.value);if(tr&&tr.indexOf("fy")>-1){var St=z(w,S,y,F,J);if(St.type!==A)return $.value==="-"&&!$.space&&b.type.is_number(St.value)?{value:new b.type.Num(-St.value.value,St.value.is_float),len:St.len,type:p}:{value:new b.type.Term($.value,[St.value]),len:St.len,type:p};X=St}else if(tr&&tr.indexOf("fx")>-1){var St=z(w,S,y,dt,J);if(St.type!==A)return{value:new b.type.Term($.value,[St.value]),len:St.len,type:p};X=St}}y=jt;var St=z(w,S,y,dt,J);if(St.type===p){y=St.len;var $=S[y];if(S[y]&&(S[y].name==="atom"&&w.__lookup_operator_classes(F,$.value)||S[y].name==="bar"&&w.__lookup_operator_classes(F,"|"))){var ln=dt,kr=F,tr=w.__lookup_operator_classes(F,$.value);if(tr.indexOf("xf")>-1)return{value:new b.type.Term($.value,[St.value]),len:++St.len,type:p};if(tr.indexOf("xfx")>-1){var mr=z(w,S,y+1,ln,J);return mr.type===p?{value:new b.type.Term($.value,[St.value,mr.value]),len:mr.len,type:p}:(mr.derived=!0,mr)}else if(tr.indexOf("xfy")>-1){var mr=z(w,S,y+1,kr,J);return mr.type===p?{value:new b.type.Term($.value,[St.value,mr.value]),len:mr.len,type:p}:(mr.derived=!0,mr)}else if(St.type!==A)for(;;){y=St.len;var $=S[y];if($&&$.name==="atom"&&w.__lookup_operator_classes(F,$.value)){var tr=w.__lookup_operator_classes(F,$.value);if(tr.indexOf("yf")>-1)St={value:new b.type.Term($.value,[St.value]),len:++y,type:p};else if(tr.indexOf("yfx")>-1){var mr=z(w,S,++y,ln,J);if(mr.type===A)return mr.derived=!0,mr;y=mr.len,St={value:new b.type.Term($.value,[St.value,mr.value]),len:y,type:p}}else break}else break}}else X={type:A,value:b.error.syntax(S[St.len-1],"operator expected")};return St}return St}function te(w,S,y,F){if(!S[y]||S[y].name==="atom"&&S[y].raw==="."&&!F&&(S[y].space||!S[y+1]||S[y+1].name!=="l_paren"))return{type:A,derived:!1,value:b.error.syntax(S[y-1],"unfounded token")};var J=S[y],X=[];if(S[y].name==="atom"&&S[y].raw!==","){if(y++,S[y-1].space)return{type:p,len:y,value:new b.type.Term(J.value,X)};if(S[y]&&S[y].name==="l_paren"){if(S[y+1]&&S[y+1].name==="r_paren")return{type:A,derived:!0,value:b.error.syntax(S[y+1],"argument expected")};var $=z(w,S,++y,"999",!0);if($.type===A)return $.derived?$:{type:A,derived:!0,value:b.error.syntax(S[y]?S[y]:S[y-1],"argument expected",!S[y])};for(X.push($.value),y=$.len;S[y]&&S[y].name==="atom"&&S[y].value===",";){if($=z(w,S,y+1,"999",!0),$.type===A)return $.derived?$:{type:A,derived:!0,value:b.error.syntax(S[y+1]?S[y+1]:S[y],"argument expected",!S[y+1])};X.push($.value),y=$.len}if(S[y]&&S[y].name==="r_paren")y++;else return{type:A,derived:!0,value:b.error.syntax(S[y]?S[y]:S[y-1],", or ) expected",!S[y])}}return{type:p,len:y,value:new b.type.Term(J.value,X)}}return{type:A,derived:!1,value:b.error.syntax(S[y],"term expected")}}function ae(w,S,y){if(!S[y])return{type:A,derived:!1,value:b.error.syntax(S[y-1],"[ expected")};if(S[y]&&S[y].name==="l_brace"){var F=z(w,S,++y,"999",!0),J=[F.value],X=void 0;if(F.type===A)return S[y]&&S[y].name==="r_brace"?{type:p,len:y+1,value:new b.type.Term("[]",[])}:{type:A,derived:!0,value:b.error.syntax(S[y],"] expected")};for(y=F.len;S[y]&&S[y].name==="atom"&&S[y].value===",";){if(F=z(w,S,y+1,"999",!0),F.type===A)return F.derived?F:{type:A,derived:!0,value:b.error.syntax(S[y+1]?S[y+1]:S[y],"argument expected",!S[y+1])};J.push(F.value),y=F.len}var $=!1;if(S[y]&&S[y].name==="bar"){if($=!0,F=z(w,S,y+1,"999",!0),F.type===A)return F.derived?F:{type:A,derived:!0,value:b.error.syntax(S[y+1]?S[y+1]:S[y],"argument expected",!S[y+1])};X=F.value,y=F.len}return S[y]&&S[y].name==="r_brace"?{type:p,len:y+1,value:g(J,X)}:{type:A,derived:!0,value:b.error.syntax(S[y]?S[y]:S[y-1],$?"] expected":", or | or ] expected",!S[y])}}return{type:A,derived:!1,value:b.error.syntax(S[y],"list expected")}}function le(w,S,y){var F=S[y].line,J=z(w,S,y,w.__get_max_priority(),!1),X=null,$;if(J.type!==A)if(y=J.len,S[y]&&S[y].name==="atom"&&S[y].raw===".")if(y++,b.type.is_term(J.value)){if(J.value.indicator===":-/2"?(X=new b.type.Rule(J.value.args[0],Ee(J.value.args[1])),$={value:X,len:y,type:p}):J.value.indicator==="-->/2"?(X=de(new b.type.Rule(J.value.args[0],J.value.args[1]),w),X.body=Ee(X.body),$={value:X,len:y,type:b.type.is_rule(X)?p:A}):(X=new b.type.Rule(J.value,null),$={value:X,len:y,type:p}),X){var ie=X.singleton_variables();ie.length>0&&w.throw_warning(b.warning.singleton(ie,X.head.indicator,F))}return $}else return{type:A,value:b.error.syntax(S[y],"callable expected")};else return{type:A,value:b.error.syntax(S[y]?S[y]:S[y-1],". or operator expected")};return J}function ce(w,S,y){y=y||{},y.from=y.from?y.from:"$tau-js",y.reconsult=y.reconsult!==void 0?y.reconsult:!0;var F=new U(w),J={},X;F.new_text(S);var $=0,ie=F.get_tokens($);do{if(ie===null||!ie[$])break;var be=le(w,ie,$);if(be.type===A)return new H("throw",[be.value]);if(be.value.body===null&&be.value.head.indicator==="?-/1"){var Re=new et(w.session);Re.add_goal(be.value.head.args[0]),Re.answer(function(dt){b.type.is_error(dt)?w.throw_warning(dt.args[0]):(dt===!1||dt===null)&&w.throw_warning(b.warning.failed_goal(be.value.head.args[0],be.len))}),$=be.len;var at=!0}else if(be.value.body===null&&be.value.head.indicator===":-/1"){var at=w.run_directive(be.value.head.args[0]);$=be.len,be.value.head.args[0].indicator==="char_conversion/2"&&(ie=F.get_tokens($),$=0)}else{X=be.value.head.indicator,y.reconsult!==!1&&J[X]!==!0&&!w.is_multifile_predicate(X)&&(w.session.rules[X]=a(w.session.rules[X]||[],function(jt){return jt.dynamic}),J[X]=!0);var at=w.add_rule(be.value,y);$=be.len}if(!at)return at}while(!0);return!0}function Ce(w,S){var y=new U(w);y.new_text(S);var F=0;do{var J=y.get_tokens(F);if(J===null)break;var X=z(w,J,0,w.__get_max_priority(),!1);if(X.type!==A){var $=X.len,ie=$;if(J[$]&&J[$].name==="atom"&&J[$].raw===".")w.add_goal(Ee(X.value));else{var be=J[$];return new H("throw",[b.error.syntax(be||J[$-1],". or operator expected",!be)])}F=X.len+1}else return new H("throw",[X.value])}while(!0);return!0}function de(w,S){w=w.rename(S);var y=S.next_free_variable(),F=Be(w.body,y,S);return F.error?F.value:(w.body=F.value,w.head.args=w.head.args.concat([y,F.variable]),w.head=new H(w.head.id,w.head.args),w)}function Be(w,S,y){var F;if(b.type.is_term(w)&&w.indicator==="!/0")return{value:w,variable:S,error:!1};if(b.type.is_term(w)&&w.indicator===",/2"){var J=Be(w.args[0],S,y);if(J.error)return J;var X=Be(w.args[1],J.variable,y);return X.error?X:{value:new H(",",[J.value,X.value]),variable:X.variable,error:!1}}else{if(b.type.is_term(w)&&w.indicator==="{}/1")return{value:w.args[0],variable:S,error:!1};if(b.type.is_empty_list(w))return{value:new H("true",[]),variable:S,error:!1};if(b.type.is_list(w)){F=y.next_free_variable();for(var $=w,ie;$.indicator==="./2";)ie=$,$=$.args[1];return b.type.is_variable($)?{value:b.error.instantiation("DCG"),variable:S,error:!0}:b.type.is_empty_list($)?(ie.args[1]=F,{value:new H("=",[S,w]),variable:F,error:!1}):{value:b.error.type("list",w,"DCG"),variable:S,error:!0}}else return b.type.is_callable(w)?(F=y.next_free_variable(),w.args=w.args.concat([S,F]),w=new H(w.id,w.args),{value:w,variable:F,error:!1}):{value:b.error.type("callable",w,"DCG"),variable:S,error:!0}}}function Ee(w){return b.type.is_variable(w)?new H("call",[w]):b.type.is_term(w)&&[",/2",";/2","->/2"].indexOf(w.indicator)!==-1?new H(w.id,[Ee(w.args[0]),Ee(w.args[1])]):w}function g(w,S){for(var y=S||new b.type.Term("[]",[]),F=w.length-1;F>=0;F--)y=new b.type.Term(".",[w[F],y]);return y}function me(w,S){for(var y=w.length-1;y>=0;y--)w[y]===S&&w.splice(y,1)}function we(w){for(var S={},y=[],F=0;F<w.length;F++)w[F]in S||(y.push(w[F]),S[w[F]]=!0);return y}function Ae(w,S,y,F){if(w.session.rules[y]!==null){for(var J=0;J<w.session.rules[y].length;J++)if(w.session.rules[y][J]===F){w.session.rules[y].splice(J,1),w.success(S);break}}}function ne(w){return function(S,y,F){var J=F.args[0],X=F.args.slice(1,w);if(b.type.is_variable(J))S.throw_error(b.error.instantiation(S.level));else if(!b.type.is_callable(J))S.throw_error(b.error.type("callable",J,S.level));else{var $=new H(J.id,J.args.concat(X));S.prepend([new ke(y.goal.replace($),y.substitution,y)])}}}function Z(w){for(var S=w.length-1;S>=0;S--)if(w.charAt(S)==="/")return new H("/",[new H(w.substring(0,S)),new Ne(parseInt(w.substring(S+1)),!1)])}function xe(w){this.id=w}function Ne(w,S){this.is_float=S!==void 0?S:parseInt(w)!==w,this.value=this.is_float?w:parseInt(w)}var ht=0;function H(w,S,y){this.ref=y||++ht,this.id=w,this.args=S||[],this.indicator=w+"/"+this.args.length}var rt=0;function Te(w,S,y,F,J,X){this.id=rt++,this.stream=w,this.mode=S,this.alias=y,this.type=F!==void 0?F:"text",this.reposition=J!==void 0?J:!0,this.eof_action=X!==void 0?X:"eof_code",this.position=this.mode==="append"?"end_of_stream":0,this.output=this.mode==="write"||this.mode==="append",this.input=this.mode==="read"}function Fe(w){w=w||{},this.links=w}function ke(w,S,y){S=S||new Fe,y=y||null,this.goal=w,this.substitution=S,this.parent=y}function Ye(w,S,y){this.head=w,this.body=S,this.dynamic=y||!1}function Se(w){w=w===void 0||w<=0?1e3:w,this.rules={},this.src_predicates={},this.rename=0,this.modules=[],this.thread=new et(this),this.total_threads=1,this.renamed_variables={},this.public_predicates={},this.multifile_predicates={},this.limit=w,this.streams={user_input:new Te(typeof gl<"u"&&gl.exports?nodejs_user_input:tau_user_input,"read","user_input","text",!1,"reset"),user_output:new Te(typeof gl<"u"&&gl.exports?nodejs_user_output:tau_user_output,"write","user_output","text",!1,"eof_code")},this.file_system=typeof gl<"u"&&gl.exports?nodejs_file_system:tau_file_system,this.standard_input=this.streams.user_input,this.standard_output=this.streams.user_output,this.current_input=this.streams.user_input,this.current_output=this.streams.user_output,this.format_success=function(S){return S.substitution},this.format_error=function(S){return S.goal},this.flag={bounded:b.flag.bounded.value,max_integer:b.flag.max_integer.value,min_integer:b.flag.min_integer.value,integer_rounding_function:b.flag.integer_rounding_function.value,char_conversion:b.flag.char_conversion.value,debug:b.flag.debug.value,max_arity:b.flag.max_arity.value,unknown:b.flag.unknown.value,double_quotes:b.flag.double_quotes.value,occurs_check:b.flag.occurs_check.value,dialect:b.flag.dialect.value,version_data:b.flag.version_data.value,nodejs:b.flag.nodejs.value},this.__loaded_modules=[],this.__char_conversion={},this.__operators={1200:{":-":["fx","xfx"],"-->":["xfx"],"?-":["fx"]},1100:{";":["xfy"]},1050:{"->":["xfy"]},1e3:{",":["xfy"]},900:{"\\+":["fy"]},700:{"=":["xfx"],"\\=":["xfx"],"==":["xfx"],"\\==":["xfx"],"@<":["xfx"],"@=<":["xfx"],"@>":["xfx"],"@>=":["xfx"],"=..":["xfx"],is:["xfx"],"=:=":["xfx"],"=\\=":["xfx"],"<":["xfx"],"=<":["xfx"],">":["xfx"],">=":["xfx"]},600:{":":["xfy"]},500:{"+":["yfx"],"-":["yfx"],"/\\":["yfx"],"\\/":["yfx"]},400:{"*":["yfx"],"/":["yfx"],"//":["yfx"],rem:["yfx"],mod:["yfx"],"<<":["yfx"],">>":["yfx"]},200:{"**":["xfx"],"^":["xfy"],"-":["fy"],"+":["fy"],"\\":["fy"]}}}function et(w){this.epoch=Date.now(),this.session=w,this.session.total_threads++,this.total_steps=0,this.cpu_time=0,this.cpu_time_last=0,this.points=[],this.debugger=!1,this.debugger_states=[],this.level="top_level/0",this.__calls=[],this.current_limit=this.session.limit,this.warnings=[]}function Ue(w,S,y){this.id=w,this.rules=S,this.exports=y,b.module[w]=this}Ue.prototype.exports_predicate=function(w){return this.exports.indexOf(w)!==-1},xe.prototype.unify=function(w,S){if(S&&e(w.variables(),this.id)!==-1&&!b.type.is_variable(w))return null;var y={};return y[this.id]=w,new Fe(y)},Ne.prototype.unify=function(w,S){return b.type.is_number(w)&&this.value===w.value&&this.is_float===w.is_float?new Fe:null},H.prototype.unify=function(w,S){if(b.type.is_term(w)&&this.indicator===w.indicator){for(var y=new Fe,F=0;F<this.args.length;F++){var J=b.unify(this.args[F].apply(y),w.args[F].apply(y),S);if(J===null)return null;for(var X in J.links)y.links[X]=J.links[X];y=y.apply(J)}return y}return null},Te.prototype.unify=function(w,S){return b.type.is_stream(w)&&this.id===w.id?new Fe:null},xe.prototype.toString=function(w){return this.id},Ne.prototype.toString=function(w){return this.is_float&&e(this.value.toString(),".")===-1?this.value+".0":this.value.toString()},H.prototype.toString=function(w,S,y){if(w=w||{},w.quoted=w.quoted===void 0?!0:w.quoted,w.ignore_ops=w.ignore_ops===void 0?!1:w.ignore_ops,w.numbervars=w.numbervars===void 0?!1:w.numbervars,S=S===void 0?1200:S,y=y===void 0?"":y,w.numbervars&&this.indicator==="$VAR/1"&&b.type.is_integer(this.args[0])&&this.args[0].value>=0){var F=this.args[0].value,J=Math.floor(F/26),X=F%26;return"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[X]+(J!==0?J:"")}switch(this.indicator){case"[]/0":case"{}/0":case"!/0":return this.id;case"{}/1":return"{"+this.args[0].toString(w)+"}";case"./2":for(var $="["+this.args[0].toString(w),ie=this.args[1];ie.indicator==="./2";)$+=", "+ie.args[0].toString(w),ie=ie.args[1];return ie.indicator!=="[]/0"&&($+="|"+ie.toString(w)),$+="]",$;case",/2":return"("+this.args[0].toString(w)+", "+this.args[1].toString(w)+")";default:var be=this.id,Re=w.session?w.session.lookup_operator(this.id,this.args.length):null;if(w.session===void 0||w.ignore_ops||Re===null)return w.quoted&&!/^(!|,|;|[a-z][0-9a-zA-Z_]*)$/.test(be)&&be!=="{}"&&be!=="[]"&&(be="'"+x(be)+"'"),be+(this.args.length?"("+o(this.args,function(tr){return tr.toString(w)}).join(", ")+")":"");var at=Re.priority>S.priority||Re.priority===S.priority&&(Re.class==="xfy"&&this.indicator!==S.indicator||Re.class==="yfx"&&this.indicator!==S.indicator||this.indicator===S.indicator&&Re.class==="yfx"&&y==="right"||this.indicator===S.indicator&&Re.class==="xfy"&&y==="left");Re.indicator=this.indicator;var dt=at?"(":"",jt=at?")":"";return this.args.length===0?"("+this.id+")":["fy","fx"].indexOf(Re.class)!==-1?dt+be+" "+this.args[0].toString(w,Re)+jt:["yf","xf"].indexOf(Re.class)!==-1?dt+this.args[0].toString(w,Re)+" "+be+jt:dt+this.args[0].toString(w,Re,"left")+" "+this.id+" "+this.args[1].toString(w,Re,"right")+jt}},Te.prototype.toString=function(w){return"<stream>("+this.id+")"},Fe.prototype.toString=function(w){var S="{";for(var y in this.links)this.links.hasOwnProperty(y)&&(S!=="{"&&(S+=", "),S+=y+"/"+this.links[y].toString(w));return S+="}",S},ke.prototype.toString=function(w){return this.goal===null?"<"+this.substitution.toString(w)+">":"<"+this.goal.toString(w)+", "+this.substitution.toString(w)+">"},Ye.prototype.toString=function(w){return this.body?this.head.toString(w)+" :- "+this.body.toString(w)+".":this.head.toString(w)+"."},Se.prototype.toString=function(w){for(var S="",y=0;y<this.modules.length;y++)S+=":- use_module(library("+this.modules[y]+`)). +`;S+=` +`;for(key in this.rules)for(y=0;y<this.rules[key].length;y++)S+=this.rules[key][y].toString(w),S+=` +`;return S},xe.prototype.clone=function(){return new xe(this.id)},Ne.prototype.clone=function(){return new Ne(this.value,this.is_float)},H.prototype.clone=function(){return new H(this.id,o(this.args,function(w){return w.clone()}))},Te.prototype.clone=function(){return new Stram(this.stream,this.mode,this.alias,this.type,this.reposition,this.eof_action)},Fe.prototype.clone=function(){var w={};for(var S in this.links)this.links.hasOwnProperty(S)&&(w[S]=this.links[S].clone());return new Fe(w)},ke.prototype.clone=function(){return new ke(this.goal.clone(),this.substitution.clone(),this.parent)},Ye.prototype.clone=function(){return new Ye(this.head.clone(),this.body!==null?this.body.clone():null)},xe.prototype.equals=function(w){return b.type.is_variable(w)&&this.id===w.id},Ne.prototype.equals=function(w){return b.type.is_number(w)&&this.value===w.value&&this.is_float===w.is_float},H.prototype.equals=function(w){if(!b.type.is_term(w)||this.indicator!==w.indicator)return!1;for(var S=0;S<this.args.length;S++)if(!this.args[S].equals(w.args[S]))return!1;return!0},Te.prototype.equals=function(w){return b.type.is_stream(w)&&this.id===w.id},Fe.prototype.equals=function(w){var S;if(!b.type.is_substitution(w))return!1;for(S in this.links)if(this.links.hasOwnProperty(S)&&(!w.links[S]||!this.links[S].equals(w.links[S])))return!1;for(S in w.links)if(w.links.hasOwnProperty(S)&&!this.links[S])return!1;return!0},ke.prototype.equals=function(w){return b.type.is_state(w)&&this.goal.equals(w.goal)&&this.substitution.equals(w.substitution)&&this.parent===w.parent},Ye.prototype.equals=function(w){return b.type.is_rule(w)&&this.head.equals(w.head)&&(this.body===null&&w.body===null||this.body!==null&&this.body.equals(w.body))},xe.prototype.rename=function(w){return w.get_free_variable(this)},Ne.prototype.rename=function(w){return this},H.prototype.rename=function(w){return new H(this.id,o(this.args,function(S){return S.rename(w)}))},Te.prototype.rename=function(w){return this},Ye.prototype.rename=function(w){return new Ye(this.head.rename(w),this.body!==null?this.body.rename(w):null)},xe.prototype.variables=function(){return[this.id]},Ne.prototype.variables=function(){return[]},H.prototype.variables=function(){return[].concat.apply([],o(this.args,function(w){return w.variables()}))},Te.prototype.variables=function(){return[]},Ye.prototype.variables=function(){return this.body===null?this.head.variables():this.head.variables().concat(this.body.variables())},xe.prototype.apply=function(w){return w.lookup(this.id)?w.lookup(this.id):this},Ne.prototype.apply=function(w){return this},H.prototype.apply=function(w){if(this.indicator==="./2"){for(var S=[],y=this;y.indicator==="./2";)S.push(y.args[0].apply(w)),y=y.args[1];for(var F=y.apply(w),J=S.length-1;J>=0;J--)F=new H(".",[S[J],F]);return F}return new H(this.id,o(this.args,function(X){return X.apply(w)}),this.ref)},Te.prototype.apply=function(w){return this},Ye.prototype.apply=function(w){return new Ye(this.head.apply(w),this.body!==null?this.body.apply(w):null)},Fe.prototype.apply=function(w){var S,y={};for(S in this.links)this.links.hasOwnProperty(S)&&(y[S]=this.links[S].apply(w));return new Fe(y)},H.prototype.select=function(){for(var w=this;w.indicator===",/2";)w=w.args[0];return w},H.prototype.replace=function(w){return this.indicator===",/2"?this.args[0].indicator===",/2"?new H(",",[this.args[0].replace(w),this.args[1]]):w===null?this.args[1]:new H(",",[w,this.args[1]]):w},H.prototype.search=function(w){if(b.type.is_term(w)&&w.ref!==void 0&&this.ref===w.ref)return!0;for(var S=0;S<this.args.length;S++)if(b.type.is_term(this.args[S])&&this.args[S].search(w))return!0;return!1},Se.prototype.get_current_input=function(){return this.current_input},et.prototype.get_current_input=function(){return this.session.get_current_input()},Se.prototype.get_current_output=function(){return this.current_output},et.prototype.get_current_output=function(){return this.session.get_current_output()},Se.prototype.set_current_input=function(w){this.current_input=w},et.prototype.set_current_input=function(w){return this.session.set_current_input(w)},Se.prototype.set_current_output=function(w){this.current_input=w},et.prototype.set_current_output=function(w){return this.session.set_current_output(w)},Se.prototype.get_stream_by_alias=function(w){return this.streams[w]},et.prototype.get_stream_by_alias=function(w){return this.session.get_stream_by_alias(w)},Se.prototype.file_system_open=function(w,S,y){return this.file_system.open(w,S,y)},et.prototype.file_system_open=function(w,S,y){return this.session.file_system_open(w,S,y)},Se.prototype.get_char_conversion=function(w){return this.__char_conversion[w]||w},et.prototype.get_char_conversion=function(w){return this.session.get_char_conversion(w)},Se.prototype.parse=function(w){return this.thread.parse(w)},et.prototype.parse=function(w){var S=new U(this);S.new_text(w);var y=S.get_tokens();if(y===null)return!1;var F=z(this,y,0,this.__get_max_priority(),!1);return F.len!==y.length?!1:{value:F.value,expr:F,tokens:y}},Se.prototype.get_flag=function(w){return this.flag[w]},et.prototype.get_flag=function(w){return this.session.get_flag(w)},Se.prototype.add_rule=function(w,S){return S=S||{},S.from=S.from?S.from:"$tau-js",this.src_predicates[w.head.indicator]=S.from,this.rules[w.head.indicator]||(this.rules[w.head.indicator]=[]),this.rules[w.head.indicator].push(w),this.public_predicates.hasOwnProperty(w.head.indicator)||(this.public_predicates[w.head.indicator]=!1),!0},et.prototype.add_rule=function(w,S){return this.session.add_rule(w,S)},Se.prototype.run_directive=function(w){this.thread.run_directive(w)},et.prototype.run_directive=function(w){return b.type.is_directive(w)?(b.directive[w.indicator](this,w),!0):!1},Se.prototype.__get_max_priority=function(){return"1200"},et.prototype.__get_max_priority=function(){return this.session.__get_max_priority()},Se.prototype.__get_next_priority=function(w){var S=0;w=parseInt(w);for(var y in this.__operators)if(this.__operators.hasOwnProperty(y)){var F=parseInt(y);F>S&&F<w&&(S=F)}return S.toString()},et.prototype.__get_next_priority=function(w){return this.session.__get_next_priority(w)},Se.prototype.__lookup_operator_classes=function(w,S){return this.__operators.hasOwnProperty(w)&&this.__operators[w][S]instanceof Array&&this.__operators[w][S]||!1},et.prototype.__lookup_operator_classes=function(w,S){return this.session.__lookup_operator_classes(w,S)},Se.prototype.lookup_operator=function(w,S){for(var y in this.__operators)if(this.__operators[y][w]){for(var F=0;F<this.__operators[y][w].length;F++)if(S===0||this.__operators[y][w][F].length===S+1)return{priority:y,class:this.__operators[y][w][F]}}return null},et.prototype.lookup_operator=function(w,S){return this.session.lookup_operator(w,S)},Se.prototype.throw_warning=function(w){this.thread.throw_warning(w)},et.prototype.throw_warning=function(w){this.warnings.push(w)},Se.prototype.get_warnings=function(){return this.thread.get_warnings()},et.prototype.get_warnings=function(){return this.warnings},Se.prototype.add_goal=function(w,S){this.thread.add_goal(w,S)},et.prototype.add_goal=function(w,S,y){y=y||null,S===!0&&(this.points=[]);for(var F=w.variables(),J={},X=0;X<F.length;X++)J[F[X]]=new xe(F[X]);this.points.push(new ke(w,new Fe(J),y))},Se.prototype.consult=function(w,S){return this.thread.consult(w,S)},et.prototype.consult=function(w,S){var y="";if(typeof w=="string"){y=w;var F=y.length;if(y.substring(F-3,F)===".pl"&&document.getElementById(y)){var J=document.getElementById(y),X=J.getAttribute("type");X!==null&&X.replace(/ /g,"").toLowerCase()==="text/prolog"&&(y=J.text)}}else if(w.nodeName)switch(w.nodeName.toLowerCase()){case"input":case"textarea":y=w.value;break;default:y=w.innerHTML;break}else return!1;return this.warnings=[],ce(this,y,S)},Se.prototype.query=function(w){return this.thread.query(w)},et.prototype.query=function(w){return this.points=[],this.debugger_points=[],Ce(this,w)},Se.prototype.head_point=function(){return this.thread.head_point()},et.prototype.head_point=function(){return this.points[this.points.length-1]},Se.prototype.get_free_variable=function(w){return this.thread.get_free_variable(w)},et.prototype.get_free_variable=function(w){var S=[];if(w.id==="_"||this.session.renamed_variables[w.id]===void 0){for(this.session.rename++,this.points.length>0&&(S=this.head_point().substitution.domain());e(S,b.format_variable(this.session.rename))!==-1;)this.session.rename++;if(w.id==="_")return new xe(b.format_variable(this.session.rename));this.session.renamed_variables[w.id]=b.format_variable(this.session.rename)}return new xe(this.session.renamed_variables[w.id])},Se.prototype.next_free_variable=function(){return this.thread.next_free_variable()},et.prototype.next_free_variable=function(){this.session.rename++;var w=[];for(this.points.length>0&&(w=this.head_point().substitution.domain());e(w,b.format_variable(this.session.rename))!==-1;)this.session.rename++;return new xe(b.format_variable(this.session.rename))},Se.prototype.is_public_predicate=function(w){return!this.public_predicates.hasOwnProperty(w)||this.public_predicates[w]===!0},et.prototype.is_public_predicate=function(w){return this.session.is_public_predicate(w)},Se.prototype.is_multifile_predicate=function(w){return this.multifile_predicates.hasOwnProperty(w)&&this.multifile_predicates[w]===!0},et.prototype.is_multifile_predicate=function(w){return this.session.is_multifile_predicate(w)},Se.prototype.prepend=function(w){return this.thread.prepend(w)},et.prototype.prepend=function(w){for(var S=w.length-1;S>=0;S--)this.points.push(w[S])},Se.prototype.success=function(w,S){return this.thread.success(w,S)},et.prototype.success=function(w,y){var y=typeof y>"u"?w:y;this.prepend([new ke(w.goal.replace(null),w.substitution,y)])},Se.prototype.throw_error=function(w){return this.thread.throw_error(w)},et.prototype.throw_error=function(w){this.prepend([new ke(new H("throw",[w]),new Fe,null,null)])},Se.prototype.step_rule=function(w,S){return this.thread.step_rule(w,S)},et.prototype.step_rule=function(w,S){var y=S.indicator;if(w==="user"&&(w=null),w===null&&this.session.rules.hasOwnProperty(y))return this.session.rules[y];for(var F=w===null?this.session.modules:e(this.session.modules,w)===-1?[]:[w],J=0;J<F.length;J++){var X=b.module[F[J]];if(X.rules.hasOwnProperty(y)&&(X.rules.hasOwnProperty(this.level)||X.exports_predicate(y)))return b.module[F[J]].rules[y]}return null},Se.prototype.step=function(){return this.thread.step()},et.prototype.step=function(){if(this.points.length!==0){var w=!1,S=this.points.pop();if(this.debugger&&this.debugger_states.push(S),b.type.is_term(S.goal)){var y=S.goal.select(),F=null,J=[];if(y!==null){this.total_steps++;for(var X=S;X.parent!==null&&X.parent.goal.search(y);)X=X.parent;if(this.level=X.parent===null?"top_level/0":X.parent.goal.select().indicator,b.type.is_term(y)&&y.indicator===":/2"&&(F=y.args[0].id,y=y.args[1]),F===null&&b.type.is_builtin(y))this.__call_indicator=y.indicator,w=b.predicate[y.indicator](this,S,y);else{var $=this.step_rule(F,y);if($===null)this.session.rules.hasOwnProperty(y.indicator)||(this.get_flag("unknown").id==="error"?this.throw_error(b.error.existence("procedure",y.indicator,this.level)):this.get_flag("unknown").id==="warning"&&this.throw_warning("unknown procedure "+y.indicator+" (from "+this.level+")"));else if($ instanceof Function)w=$(this,S,y);else{for(var ie in $)if($.hasOwnProperty(ie)){var be=$[ie];this.session.renamed_variables={},be=be.rename(this);var Re=this.get_flag("occurs_check").indicator==="true/0",at=new ke,dt=b.unify(y,be.head,Re);dt!==null&&(at.goal=S.goal.replace(be.body),at.goal!==null&&(at.goal=at.goal.apply(dt)),at.substitution=S.substitution.apply(dt),at.parent=S,J.push(at))}this.prepend(J)}}}}else b.type.is_variable(S.goal)?this.throw_error(b.error.instantiation(this.level)):this.throw_error(b.error.type("callable",S.goal,this.level));return w}},Se.prototype.answer=function(w){return this.thread.answer(w)},et.prototype.answer=function(w){w=w||function(S){},this.__calls.push(w),!(this.__calls.length>1)&&this.again()},Se.prototype.answers=function(w,S,y){return this.thread.answers(w,S,y)},et.prototype.answers=function(w,S,y){var F=S||1e3,J=this;if(S<=0){y&&y();return}this.answer(function(X){w(X),X!==!1?setTimeout(function(){J.answers(w,S-1,y)},1):y&&y()})},Se.prototype.again=function(w){return this.thread.again(w)},et.prototype.again=function(w){for(var S,y=Date.now();this.__calls.length>0;){for(this.warnings=[],w!==!1&&(this.current_limit=this.session.limit);this.current_limit>0&&this.points.length>0&&this.head_point().goal!==null&&!b.type.is_error(this.head_point().goal);)if(this.current_limit--,this.step()===!0)return;var F=Date.now();this.cpu_time_last=F-y,this.cpu_time+=this.cpu_time_last;var J=this.__calls.shift();this.current_limit<=0?J(null):this.points.length===0?J(!1):b.type.is_error(this.head_point().goal)?(S=this.session.format_error(this.points.pop()),this.points=[],J(S)):(this.debugger&&this.debugger_states.push(this.head_point()),S=this.session.format_success(this.points.pop()),J(S))}},Se.prototype.unfold=function(w){if(w.body===null)return!1;var S=w.head,y=w.body,F=y.select(),J=new et(this),X=[];J.add_goal(F),J.step();for(var $=J.points.length-1;$>=0;$--){var ie=J.points[$],be=S.apply(ie.substitution),Re=y.replace(ie.goal);Re!==null&&(Re=Re.apply(ie.substitution)),X.push(new Ye(be,Re))}var at=this.rules[S.indicator],dt=e(at,w);return X.length>0&&dt!==-1?(at.splice.apply(at,[dt,1].concat(X)),!0):!1},et.prototype.unfold=function(w){return this.session.unfold(w)},xe.prototype.interpret=function(w){return b.error.instantiation(w.level)},Ne.prototype.interpret=function(w){return this},H.prototype.interpret=function(w){return b.type.is_unitary_list(this)?this.args[0].interpret(w):b.operate(w,this)},xe.prototype.compare=function(w){return this.id<w.id?-1:this.id>w.id?1:0},Ne.prototype.compare=function(w){if(this.value===w.value&&this.is_float===w.is_float)return 0;if(this.value<w.value||this.value===w.value&&this.is_float&&!w.is_float)return-1;if(this.value>w.value)return 1},H.prototype.compare=function(w){if(this.args.length<w.args.length||this.args.length===w.args.length&&this.id<w.id)return-1;if(this.args.length>w.args.length||this.args.length===w.args.length&&this.id>w.id)return 1;for(var S=0;S<this.args.length;S++){var y=b.compare(this.args[S],w.args[S]);if(y!==0)return y}return 0},Fe.prototype.lookup=function(w){return this.links[w]?this.links[w]:null},Fe.prototype.filter=function(w){var S={};for(var y in this.links)if(this.links.hasOwnProperty(y)){var F=this.links[y];w(y,F)&&(S[y]=F)}return new Fe(S)},Fe.prototype.exclude=function(w){var S={};for(var y in this.links)this.links.hasOwnProperty(y)&&e(w,y)===-1&&(S[y]=this.links[y]);return new Fe(S)},Fe.prototype.add=function(w,S){this.links[w]=S},Fe.prototype.domain=function(w){var S=w===!0?function(J){return J}:function(J){return new xe(J)},y=[];for(var F in this.links)y.push(S(F));return y},xe.prototype.compile=function(){return'new pl.type.Var("'+this.id.toString()+'")'},Ne.prototype.compile=function(){return"new pl.type.Num("+this.value.toString()+", "+this.is_float.toString()+")"},H.prototype.compile=function(){return'new pl.type.Term("'+this.id.replace(/"/g,'\\"')+'", ['+o(this.args,function(w){return w.compile()})+"])"},Ye.prototype.compile=function(){return"new pl.type.Rule("+this.head.compile()+", "+(this.body===null?"null":this.body.compile())+")"},Se.prototype.compile=function(){var w,S=[],y;for(var F in this.rules)if(this.rules.hasOwnProperty(F)){var J=this.rules[F];y=[],w='"'+F+'": [';for(var X=0;X<J.length;X++)y.push(J[X].compile());w+=y.join(),w+="]",S.push(w)}return"{"+S.join()+"};"},xe.prototype.toJavaScript=function(){},Ne.prototype.toJavaScript=function(){return this.value},H.prototype.toJavaScript=function(){if(this.args.length===0&&this.indicator!=="[]/0")return this.id;if(b.type.is_list(this)){for(var w=[],S=this,y;S.indicator==="./2";){if(y=S.args[0].toJavaScript(),y===void 0)return;w.push(y),S=S.args[1]}if(S.indicator==="[]/0")return w}},Ye.prototype.singleton_variables=function(){var w=this.head.variables(),S={},y=[];this.body!==null&&(w=w.concat(this.body.variables()));for(var F=0;F<w.length;F++)S[w[F]]===void 0&&(S[w[F]]=0),S[w[F]]++;for(var J in S)J!=="_"&&S[J]===1&&y.push(J);return y};var b={__env:typeof gl<"u"&&gl.exports?global:window,module:{},version:t,parser:{tokenizer:U,expression:z},utils:{str_indicator:Z,codePointAt:n,fromCodePoint:u},statistics:{getCountTerms:function(){return ht}},fromJavaScript:{test:{boolean:function(w){return w===!0||w===!1},number:function(w){return typeof w=="number"},string:function(w){return typeof w=="string"},list:function(w){return w instanceof Array},variable:function(w){return w===void 0},any:function(w){return!0}},conversion:{boolean:function(w){return new H(w?"true":"false",[])},number:function(w){return new Ne(w,w%1!==0)},string:function(w){return new H(w,[])},list:function(w){for(var S=[],y,F=0;F<w.length;F++){if(y=b.fromJavaScript.apply(w[F]),y===void 0)return;S.push(y)}return g(S)},variable:function(w){return new xe("_")},any:function(w){}},apply:function(w){for(var S in b.fromJavaScript.test)if(S!=="any"&&b.fromJavaScript.test[S](w))return b.fromJavaScript.conversion[S](w);return b.fromJavaScript.conversion.any(w)}},type:{Var:xe,Num:Ne,Term:H,Rule:Ye,State:ke,Stream:Te,Module:Ue,Thread:et,Session:Se,Substitution:Fe,order:[xe,Ne,H,Te],compare:function(w,S){var y=e(b.type.order,w.constructor),F=e(b.type.order,S.constructor);if(y<F)return-1;if(y>F)return 1;if(w.constructor===Ne){if(w.is_float&&S.is_float)return 0;if(w.is_float)return-1;if(S.is_float)return 1}return 0},is_substitution:function(w){return w instanceof Fe},is_state:function(w){return w instanceof ke},is_rule:function(w){return w instanceof Ye},is_variable:function(w){return w instanceof xe},is_stream:function(w){return w instanceof Te},is_anonymous_var:function(w){return w instanceof xe&&w.id==="_"},is_callable:function(w){return w instanceof H},is_number:function(w){return w instanceof Ne},is_integer:function(w){return w instanceof Ne&&!w.is_float},is_float:function(w){return w instanceof Ne&&w.is_float},is_term:function(w){return w instanceof H},is_atom:function(w){return w instanceof H&&w.args.length===0},is_ground:function(w){if(w instanceof xe)return!1;if(w instanceof H){for(var S=0;S<w.args.length;S++)if(!b.type.is_ground(w.args[S]))return!1}return!0},is_atomic:function(w){return w instanceof H&&w.args.length===0||w instanceof Ne},is_compound:function(w){return w instanceof H&&w.args.length>0},is_list:function(w){return w instanceof H&&(w.indicator==="[]/0"||w.indicator==="./2")},is_empty_list:function(w){return w instanceof H&&w.indicator==="[]/0"},is_non_empty_list:function(w){return w instanceof H&&w.indicator==="./2"},is_fully_list:function(w){for(;w instanceof H&&w.indicator==="./2";)w=w.args[1];return w instanceof xe||w instanceof H&&w.indicator==="[]/0"},is_instantiated_list:function(w){for(;w instanceof H&&w.indicator==="./2";)w=w.args[1];return w instanceof H&&w.indicator==="[]/0"},is_unitary_list:function(w){return w instanceof H&&w.indicator==="./2"&&w.args[1]instanceof H&&w.args[1].indicator==="[]/0"},is_character:function(w){return w instanceof H&&(w.id.length===1||w.id.length>0&&w.id.length<=2&&n(w.id,0)>=65536)},is_character_code:function(w){return w instanceof Ne&&!w.is_float&&w.value>=0&&w.value<=1114111},is_byte:function(w){return w instanceof Ne&&!w.is_float&&w.value>=0&&w.value<=255},is_operator:function(w){return w instanceof H&&b.arithmetic.evaluation[w.indicator]},is_directive:function(w){return w instanceof H&&b.directive[w.indicator]!==void 0},is_builtin:function(w){return w instanceof H&&b.predicate[w.indicator]!==void 0},is_error:function(w){return w instanceof H&&w.indicator==="throw/1"},is_predicate_indicator:function(w){return w instanceof H&&w.indicator==="//2"&&w.args[0]instanceof H&&w.args[0].args.length===0&&w.args[1]instanceof Ne&&w.args[1].is_float===!1},is_flag:function(w){return w instanceof H&&w.args.length===0&&b.flag[w.id]!==void 0},is_value_flag:function(w,S){if(!b.type.is_flag(w))return!1;for(var y in b.flag[w.id].allowed)if(b.flag[w.id].allowed.hasOwnProperty(y)&&b.flag[w.id].allowed[y].equals(S))return!0;return!1},is_io_mode:function(w){return b.type.is_atom(w)&&["read","write","append"].indexOf(w.id)!==-1},is_stream_option:function(w){return b.type.is_term(w)&&(w.indicator==="alias/1"&&b.type.is_atom(w.args[0])||w.indicator==="reposition/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")||w.indicator==="type/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="text"||w.args[0].id==="binary")||w.indicator==="eof_action/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="error"||w.args[0].id==="eof_code"||w.args[0].id==="reset"))},is_stream_position:function(w){return b.type.is_integer(w)&&w.value>=0||b.type.is_atom(w)&&(w.id==="end_of_stream"||w.id==="past_end_of_stream")},is_stream_property:function(w){return b.type.is_term(w)&&(w.indicator==="input/0"||w.indicator==="output/0"||w.indicator==="alias/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0]))||w.indicator==="file_name/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0]))||w.indicator==="position/1"&&(b.type.is_variable(w.args[0])||b.type.is_stream_position(w.args[0]))||w.indicator==="reposition/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false"))||w.indicator==="type/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="text"||w.args[0].id==="binary"))||w.indicator==="mode/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="read"||w.args[0].id==="write"||w.args[0].id==="append"))||w.indicator==="eof_action/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="error"||w.args[0].id==="eof_code"||w.args[0].id==="reset"))||w.indicator==="end_of_stream/1"&&(b.type.is_variable(w.args[0])||b.type.is_atom(w.args[0])&&(w.args[0].id==="at"||w.args[0].id==="past"||w.args[0].id==="not")))},is_streamable:function(w){return w.__proto__.stream!==void 0},is_read_option:function(w){return b.type.is_term(w)&&["variables/1","variable_names/1","singletons/1"].indexOf(w.indicator)!==-1},is_write_option:function(w){return b.type.is_term(w)&&(w.indicator==="quoted/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")||w.indicator==="ignore_ops/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")||w.indicator==="numbervars/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false"))},is_close_option:function(w){return b.type.is_term(w)&&w.indicator==="force/1"&&b.type.is_atom(w.args[0])&&(w.args[0].id==="true"||w.args[0].id==="false")},is_modifiable_flag:function(w){return b.type.is_flag(w)&&b.flag[w.id].changeable},is_module:function(w){return w instanceof H&&w.indicator==="library/1"&&w.args[0]instanceof H&&w.args[0].args.length===0&&b.module[w.args[0].id]!==void 0}},arithmetic:{evaluation:{"e/0":{type_args:null,type_result:!0,fn:function(w){return Math.E}},"pi/0":{type_args:null,type_result:!0,fn:function(w){return Math.PI}},"tau/0":{type_args:null,type_result:!0,fn:function(w){return 2*Math.PI}},"epsilon/0":{type_args:null,type_result:!0,fn:function(w){return Number.EPSILON}},"+/1":{type_args:null,type_result:null,fn:function(w,S){return w}},"-/1":{type_args:null,type_result:null,fn:function(w,S){return-w}},"\\/1":{type_args:!1,type_result:!1,fn:function(w,S){return~w}},"abs/1":{type_args:null,type_result:null,fn:function(w,S){return Math.abs(w)}},"sign/1":{type_args:null,type_result:null,fn:function(w,S){return Math.sign(w)}},"float_integer_part/1":{type_args:!0,type_result:!1,fn:function(w,S){return parseInt(w)}},"float_fractional_part/1":{type_args:!0,type_result:!0,fn:function(w,S){return w-parseInt(w)}},"float/1":{type_args:null,type_result:!0,fn:function(w,S){return parseFloat(w)}},"floor/1":{type_args:!0,type_result:!1,fn:function(w,S){return Math.floor(w)}},"truncate/1":{type_args:!0,type_result:!1,fn:function(w,S){return parseInt(w)}},"round/1":{type_args:!0,type_result:!1,fn:function(w,S){return Math.round(w)}},"ceiling/1":{type_args:!0,type_result:!1,fn:function(w,S){return Math.ceil(w)}},"sin/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.sin(w)}},"cos/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.cos(w)}},"tan/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.tan(w)}},"asin/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.asin(w)}},"acos/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.acos(w)}},"atan/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.atan(w)}},"atan2/2":{type_args:null,type_result:!0,fn:function(w,S,y){return Math.atan2(w,S)}},"exp/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.exp(w)}},"sqrt/1":{type_args:null,type_result:!0,fn:function(w,S){return Math.sqrt(w)}},"log/1":{type_args:null,type_result:!0,fn:function(w,S){return w>0?Math.log(w):b.error.evaluation("undefined",S.__call_indicator)}},"+/2":{type_args:null,type_result:null,fn:function(w,S,y){return w+S}},"-/2":{type_args:null,type_result:null,fn:function(w,S,y){return w-S}},"*/2":{type_args:null,type_result:null,fn:function(w,S,y){return w*S}},"//2":{type_args:null,type_result:!0,fn:function(w,S,y){return S?w/S:b.error.evaluation("zero_division",y.__call_indicator)}},"///2":{type_args:!1,type_result:!1,fn:function(w,S,y){return S?parseInt(w/S):b.error.evaluation("zero_division",y.__call_indicator)}},"**/2":{type_args:null,type_result:!0,fn:function(w,S,y){return Math.pow(w,S)}},"^/2":{type_args:null,type_result:null,fn:function(w,S,y){return Math.pow(w,S)}},"<</2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w<<S}},">>/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w>>S}},"/\\/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w&S}},"\\//2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w|S}},"xor/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return w^S}},"rem/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return S?w%S:b.error.evaluation("zero_division",y.__call_indicator)}},"mod/2":{type_args:!1,type_result:!1,fn:function(w,S,y){return S?w-parseInt(w/S)*S:b.error.evaluation("zero_division",y.__call_indicator)}},"max/2":{type_args:null,type_result:null,fn:function(w,S,y){return Math.max(w,S)}},"min/2":{type_args:null,type_result:null,fn:function(w,S,y){return Math.min(w,S)}}}},directive:{"dynamic/1":function(w,S){var y=S.args[0];if(b.type.is_variable(y))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_compound(y)||y.indicator!=="//2")w.throw_error(b.error.type("predicate_indicator",y,S.indicator));else if(b.type.is_variable(y.args[0])||b.type.is_variable(y.args[1]))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_atom(y.args[0]))w.throw_error(b.error.type("atom",y.args[0],S.indicator));else if(!b.type.is_integer(y.args[1]))w.throw_error(b.error.type("integer",y.args[1],S.indicator));else{var F=S.args[0].args[0].id+"/"+S.args[0].args[1].value;w.session.public_predicates[F]=!0,w.session.rules[F]||(w.session.rules[F]=[])}},"multifile/1":function(w,S){var y=S.args[0];b.type.is_variable(y)?w.throw_error(b.error.instantiation(S.indicator)):!b.type.is_compound(y)||y.indicator!=="//2"?w.throw_error(b.error.type("predicate_indicator",y,S.indicator)):b.type.is_variable(y.args[0])||b.type.is_variable(y.args[1])?w.throw_error(b.error.instantiation(S.indicator)):b.type.is_atom(y.args[0])?b.type.is_integer(y.args[1])?w.session.multifile_predicates[S.args[0].args[0].id+"/"+S.args[0].args[1].value]=!0:w.throw_error(b.error.type("integer",y.args[1],S.indicator)):w.throw_error(b.error.type("atom",y.args[0],S.indicator))},"set_prolog_flag/2":function(w,S){var y=S.args[0],F=S.args[1];b.type.is_variable(y)||b.type.is_variable(F)?w.throw_error(b.error.instantiation(S.indicator)):b.type.is_atom(y)?b.type.is_flag(y)?b.type.is_value_flag(y,F)?b.type.is_modifiable_flag(y)?w.session.flag[y.id]=F:w.throw_error(b.error.permission("modify","flag",y)):w.throw_error(b.error.domain("flag_value",new H("+",[y,F]),S.indicator)):w.throw_error(b.error.domain("prolog_flag",y,S.indicator)):w.throw_error(b.error.type("atom",y,S.indicator))},"use_module/1":function(w,S){var y=S.args[0];if(b.type.is_variable(y))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_term(y))w.throw_error(b.error.type("term",y,S.indicator));else if(b.type.is_module(y)){var F=y.args[0].id;e(w.session.modules,F)===-1&&w.session.modules.push(F)}},"char_conversion/2":function(w,S){var y=S.args[0],F=S.args[1];b.type.is_variable(y)||b.type.is_variable(F)?w.throw_error(b.error.instantiation(S.indicator)):b.type.is_character(y)?b.type.is_character(F)?y.id===F.id?delete w.session.__char_conversion[y.id]:w.session.__char_conversion[y.id]=F.id:w.throw_error(b.error.type("character",F,S.indicator)):w.throw_error(b.error.type("character",y,S.indicator))},"op/3":function(w,S){var y=S.args[0],F=S.args[1],J=S.args[2];if(b.type.is_variable(y)||b.type.is_variable(F)||b.type.is_variable(J))w.throw_error(b.error.instantiation(S.indicator));else if(!b.type.is_integer(y))w.throw_error(b.error.type("integer",y,S.indicator));else if(!b.type.is_atom(F))w.throw_error(b.error.type("atom",F,S.indicator));else if(!b.type.is_atom(J))w.throw_error(b.error.type("atom",J,S.indicator));else if(y.value<0||y.value>1200)w.throw_error(b.error.domain("operator_priority",y,S.indicator));else if(J.id===",")w.throw_error(b.error.permission("modify","operator",J,S.indicator));else if(J.id==="|"&&(y.value<1001||F.id.length!==3))w.throw_error(b.error.permission("modify","operator",J,S.indicator));else if(["fy","fx","yf","xf","xfx","yfx","xfy"].indexOf(F.id)===-1)w.throw_error(b.error.domain("operator_specifier",F,S.indicator));else{var X={prefix:null,infix:null,postfix:null};for(var $ in w.session.__operators)if(w.session.__operators.hasOwnProperty($)){var ie=w.session.__operators[$][J.id];ie&&(e(ie,"fx")!==-1&&(X.prefix={priority:$,type:"fx"}),e(ie,"fy")!==-1&&(X.prefix={priority:$,type:"fy"}),e(ie,"xf")!==-1&&(X.postfix={priority:$,type:"xf"}),e(ie,"yf")!==-1&&(X.postfix={priority:$,type:"yf"}),e(ie,"xfx")!==-1&&(X.infix={priority:$,type:"xfx"}),e(ie,"xfy")!==-1&&(X.infix={priority:$,type:"xfy"}),e(ie,"yfx")!==-1&&(X.infix={priority:$,type:"yfx"}))}var be;switch(F.id){case"fy":case"fx":be="prefix";break;case"yf":case"xf":be="postfix";break;default:be="infix";break}if(((X.prefix&&be==="prefix"||X.postfix&&be==="postfix"||X.infix&&be==="infix")&&X[be].type!==F.id||X.infix&&be==="postfix"||X.postfix&&be==="infix")&&y.value!==0)w.throw_error(b.error.permission("create","operator",J,S.indicator));else return X[be]&&(me(w.session.__operators[X[be].priority][J.id],F.id),w.session.__operators[X[be].priority][J.id].length===0&&delete w.session.__operators[X[be].priority][J.id]),y.value>0&&(w.session.__operators[y.value]||(w.session.__operators[y.value.toString()]={}),w.session.__operators[y.value][J.id]||(w.session.__operators[y.value][J.id]=[]),w.session.__operators[y.value][J.id].push(F.id)),!0}}},predicate:{"op/3":function(w,S,y){b.directive["op/3"](w,y)&&w.success(S)},"current_op/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2],$=[];for(var ie in w.session.__operators)for(var be in w.session.__operators[ie])for(var Re=0;Re<w.session.__operators[ie][be].length;Re++)$.push(new ke(S.goal.replace(new H(",",[new H("=",[new Ne(ie,!1),F]),new H(",",[new H("=",[new H(w.session.__operators[ie][be][Re],[]),J]),new H("=",[new H(be,[]),X])])])),S.substitution,S));w.prepend($)},";/2":function(w,S,y){if(b.type.is_term(y.args[0])&&y.args[0].indicator==="->/2"){var F=w.points,J=w.session.format_success,X=w.session.format_error;w.session.format_success=function(Re){return Re.substitution},w.session.format_error=function(Re){return Re.goal},w.points=[new ke(y.args[0].args[0],S.substitution,S)];var $=function(Re){w.points=F,w.session.format_success=J,w.session.format_error=X,Re===!1?w.prepend([new ke(S.goal.replace(y.args[1]),S.substitution,S)]):b.type.is_error(Re)?w.throw_error(Re.args[0]):Re===null?(w.prepend([S]),w.__calls.shift()(null)):w.prepend([new ke(S.goal.replace(y.args[0].args[1]).apply(Re),S.substitution.apply(Re),S)])};w.__calls.unshift($)}else{var ie=new ke(S.goal.replace(y.args[0]),S.substitution,S),be=new ke(S.goal.replace(y.args[1]),S.substitution,S);w.prepend([ie,be])}},"!/0":function(w,S,y){var F,J,X=[];for(F=S,J=null;F.parent!==null&&F.parent.goal.search(y);)if(J=F,F=F.parent,F.goal!==null){var $=F.goal.select();if($&&$.id==="call"&&$.search(y)){F=J;break}}for(var ie=w.points.length-1;ie>=0;ie--){for(var be=w.points[ie],Re=be.parent;Re!==null&&Re!==F.parent;)Re=Re.parent;Re===null&&Re!==F.parent&&X.push(be)}w.points=X.reverse(),w.success(S)},"\\+/1":function(w,S,y){var F=y.args[0];b.type.is_variable(F)?w.throw_error(b.error.instantiation(w.level)):b.type.is_callable(F)?w.prepend([new ke(S.goal.replace(new H(",",[new H(",",[new H("call",[F]),new H("!",[])]),new H("fail",[])])),S.substitution,S),new ke(S.goal.replace(null),S.substitution,S)]):w.throw_error(b.error.type("callable",F,w.level))},"->/2":function(w,S,y){var F=S.goal.replace(new H(",",[y.args[0],new H(",",[new H("!"),y.args[1]])]));w.prepend([new ke(F,S.substitution,S)])},"fail/0":function(w,S,y){},"false/0":function(w,S,y){},"true/0":function(w,S,y){w.success(S)},"call/1":ne(1),"call/2":ne(2),"call/3":ne(3),"call/4":ne(4),"call/5":ne(5),"call/6":ne(6),"call/7":ne(7),"call/8":ne(8),"once/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("call",[F]),new H("!",[])])),S.substitution,S)])},"forall/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H("\\+",[new H(",",[new H("call",[F]),new H("\\+",[new H("call",[J])])])])),S.substitution,S)])},"repeat/0":function(w,S,y){w.prepend([new ke(S.goal.replace(null),S.substitution,S),S])},"throw/1":function(w,S,y){b.type.is_variable(y.args[0])?w.throw_error(b.error.instantiation(w.level)):w.throw_error(y.args[0])},"catch/3":function(w,S,y){var F=w.points;w.points=[],w.prepend([new ke(y.args[0],S.substitution,S)]);var J=w.session.format_success,X=w.session.format_error;w.session.format_success=function(ie){return ie.substitution},w.session.format_error=function(ie){return ie.goal};var $=function(ie){var be=w.points;if(w.points=F,w.session.format_success=J,w.session.format_error=X,b.type.is_error(ie)){for(var Re=[],at=w.points.length-1;at>=0;at--){for(var tr=w.points[at],dt=tr.parent;dt!==null&&dt!==S.parent;)dt=dt.parent;dt===null&&dt!==S.parent&&Re.push(tr)}w.points=Re;var jt=w.get_flag("occurs_check").indicator==="true/0",tr=new ke,St=b.unify(ie.args[0],y.args[1],jt);St!==null?(tr.substitution=S.substitution.apply(St),tr.goal=S.goal.replace(y.args[2]).apply(St),tr.parent=S,w.prepend([tr])):w.throw_error(ie.args[0])}else if(ie!==!1){for(var ln=ie===null?[]:[new ke(S.goal.apply(ie).replace(null),S.substitution.apply(ie),S)],kr=[],at=be.length-1;at>=0;at--){kr.push(be[at]);var mr=be[at].goal!==null?be[at].goal.select():null;if(b.type.is_term(mr)&&mr.indicator==="!/0")break}var br=o(kr,function(Kr){return Kr.goal===null&&(Kr.goal=new H("true",[])),Kr=new ke(S.goal.replace(new H("catch",[Kr.goal,y.args[1],y.args[2]])),S.substitution.apply(Kr.substitution),Kr.parent),Kr.exclude=y.args[0].variables(),Kr}).reverse();w.prepend(br),w.prepend(ln),ie===null&&(this.current_limit=0,w.__calls.shift()(null))}};w.__calls.unshift($)},"=/2":function(w,S,y){var F=w.get_flag("occurs_check").indicator==="true/0",J=new ke,X=b.unify(y.args[0],y.args[1],F);X!==null&&(J.goal=S.goal.apply(X).replace(null),J.substitution=S.substitution.apply(X),J.parent=S,w.prepend([J]))},"unify_with_occurs_check/2":function(w,S,y){var F=new ke,J=b.unify(y.args[0],y.args[1],!0);J!==null&&(F.goal=S.goal.apply(J).replace(null),F.substitution=S.substitution.apply(J),F.parent=S,w.prepend([F]))},"\\=/2":function(w,S,y){var F=w.get_flag("occurs_check").indicator==="true/0",J=b.unify(y.args[0],y.args[1],F);J===null&&w.success(S)},"subsumes_term/2":function(w,S,y){var F=w.get_flag("occurs_check").indicator==="true/0",J=b.unify(y.args[1],y.args[0],F);J!==null&&y.args[1].apply(J).equals(y.args[1])&&w.success(S)},"findall/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2];if(b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(J))w.throw_error(b.error.type("callable",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else{var $=w.next_free_variable(),ie=new H(",",[J,new H("=",[$,F])]),be=w.points,Re=w.session.limit,at=w.session.format_success;w.session.format_success=function(tr){return tr.substitution},w.add_goal(ie,!0,S);var dt=[],jt=function(tr){if(tr!==!1&&tr!==null&&!b.type.is_error(tr))w.__calls.unshift(jt),dt.push(tr.links[$.id]),w.session.limit=w.current_limit;else if(w.points=be,w.session.limit=Re,w.session.format_success=at,b.type.is_error(tr))w.throw_error(tr.args[0]);else if(w.current_limit>0){for(var St=new H("[]"),ln=dt.length-1;ln>=0;ln--)St=new H(".",[dt[ln],St]);w.prepend([new ke(S.goal.replace(new H("=",[X,St])),S.substitution,S)])}};w.__calls.unshift(jt)}},"bagof/3":function(w,S,y){var F,J=y.args[0],X=y.args[1],$=y.args[2];if(b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(X))w.throw_error(b.error.type("callable",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_list($))w.throw_error(b.error.type("list",$,y.indicator));else{var ie=w.next_free_variable(),be;X.indicator==="^/2"?(be=X.args[0].variables(),X=X.args[1]):be=[],be=be.concat(J.variables());for(var Re=X.variables().filter(function(br){return e(be,br)===-1}),at=new H("[]"),dt=Re.length-1;dt>=0;dt--)at=new H(".",[new xe(Re[dt]),at]);var jt=new H(",",[X,new H("=",[ie,new H(",",[at,J])])]),tr=w.points,St=w.session.limit,ln=w.session.format_success;w.session.format_success=function(br){return br.substitution},w.add_goal(jt,!0,S);var kr=[],mr=function(br){if(br!==!1&&br!==null&&!b.type.is_error(br)){w.__calls.unshift(mr);var Kr=!1,Kn=br.links[ie.id].args[0],Ms=br.links[ie.id].args[1];for(var Ri in kr)if(kr.hasOwnProperty(Ri)){var gs=kr[Ri];if(gs.variables.equals(Kn)){gs.answers.push(Ms),Kr=!0;break}}Kr||kr.push({variables:Kn,answers:[Ms]}),w.session.limit=w.current_limit}else if(w.points=tr,w.session.limit=St,w.session.format_success=ln,b.type.is_error(br))w.throw_error(br.args[0]);else if(w.current_limit>0){for(var io=[],Pi=0;Pi<kr.length;Pi++){br=kr[Pi].answers;for(var Os=new H("[]"),so=br.length-1;so>=0;so--)Os=new H(".",[br[so],Os]);io.push(new ke(S.goal.replace(new H(",",[new H("=",[at,kr[Pi].variables]),new H("=",[$,Os])])),S.substitution,S))}w.prepend(io)}};w.__calls.unshift(mr)}},"setof/3":function(w,S,y){var F,J=y.args[0],X=y.args[1],$=y.args[2];if(b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(X))w.throw_error(b.error.type("callable",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_list($))w.throw_error(b.error.type("list",$,y.indicator));else{var ie=w.next_free_variable(),be;X.indicator==="^/2"?(be=X.args[0].variables(),X=X.args[1]):be=[],be=be.concat(J.variables());for(var Re=X.variables().filter(function(br){return e(be,br)===-1}),at=new H("[]"),dt=Re.length-1;dt>=0;dt--)at=new H(".",[new xe(Re[dt]),at]);var jt=new H(",",[X,new H("=",[ie,new H(",",[at,J])])]),tr=w.points,St=w.session.limit,ln=w.session.format_success;w.session.format_success=function(br){return br.substitution},w.add_goal(jt,!0,S);var kr=[],mr=function(br){if(br!==!1&&br!==null&&!b.type.is_error(br)){w.__calls.unshift(mr);var Kr=!1,Kn=br.links[ie.id].args[0],Ms=br.links[ie.id].args[1];for(var Ri in kr)if(kr.hasOwnProperty(Ri)){var gs=kr[Ri];if(gs.variables.equals(Kn)){gs.answers.push(Ms),Kr=!0;break}}Kr||kr.push({variables:Kn,answers:[Ms]}),w.session.limit=w.current_limit}else if(w.points=tr,w.session.limit=St,w.session.format_success=ln,b.type.is_error(br))w.throw_error(br.args[0]);else if(w.current_limit>0){for(var io=[],Pi=0;Pi<kr.length;Pi++){br=kr[Pi].answers.sort(b.compare);for(var Os=new H("[]"),so=br.length-1;so>=0;so--)Os=new H(".",[br[so],Os]);io.push(new ke(S.goal.replace(new H(",",[new H("=",[at,kr[Pi].variables]),new H("=",[$,Os])])),S.substitution,S))}w.prepend(io)}};w.__calls.unshift(mr)}},"functor/3":function(w,S,y){var F,J=y.args[0],X=y.args[1],$=y.args[2];if(b.type.is_variable(J)&&(b.type.is_variable(X)||b.type.is_variable($)))w.throw_error(b.error.instantiation("functor/3"));else if(!b.type.is_variable($)&&!b.type.is_integer($))w.throw_error(b.error.type("integer",y.args[2],"functor/3"));else if(!b.type.is_variable(X)&&!b.type.is_atomic(X))w.throw_error(b.error.type("atomic",y.args[1],"functor/3"));else if(b.type.is_integer(X)&&b.type.is_integer($)&&$.value!==0)w.throw_error(b.error.type("atom",y.args[1],"functor/3"));else if(b.type.is_variable(J)){if(y.args[2].value>=0){for(var ie=[],be=0;be<$.value;be++)ie.push(w.next_free_variable());var Re=b.type.is_integer(X)?X:new H(X.id,ie);w.prepend([new ke(S.goal.replace(new H("=",[J,Re])),S.substitution,S)])}}else{var at=b.type.is_integer(J)?J:new H(J.id,[]),dt=b.type.is_integer(J)?new Ne(0,!1):new Ne(J.args.length,!1),jt=new H(",",[new H("=",[at,X]),new H("=",[dt,$])]);w.prepend([new ke(S.goal.replace(jt),S.substitution,S)])}},"arg/3":function(w,S,y){if(b.type.is_variable(y.args[0])||b.type.is_variable(y.args[1]))w.throw_error(b.error.instantiation(y.indicator));else if(y.args[0].value<0)w.throw_error(b.error.domain("not_less_than_zero",y.args[0],y.indicator));else if(!b.type.is_compound(y.args[1]))w.throw_error(b.error.type("compound",y.args[1],y.indicator));else{var F=y.args[0].value;if(F>0&&F<=y.args[1].args.length){var J=new H("=",[y.args[1].args[F-1],y.args[2]]);w.prepend([new ke(S.goal.replace(J),S.substitution,S)])}}},"=../2":function(w,S,y){var F;if(b.type.is_variable(y.args[0])&&(b.type.is_variable(y.args[1])||b.type.is_non_empty_list(y.args[1])&&b.type.is_variable(y.args[1].args[0])))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_fully_list(y.args[1]))w.throw_error(b.error.type("list",y.args[1],y.indicator));else if(b.type.is_variable(y.args[0])){if(!b.type.is_variable(y.args[1])){var X=[];for(F=y.args[1].args[1];F.indicator==="./2";)X.push(F.args[0]),F=F.args[1];b.type.is_variable(y.args[0])&&b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):X.length===0&&b.type.is_compound(y.args[1].args[0])?w.throw_error(b.error.type("atomic",y.args[1].args[0],y.indicator)):X.length>0&&(b.type.is_compound(y.args[1].args[0])||b.type.is_number(y.args[1].args[0]))?w.throw_error(b.error.type("atom",y.args[1].args[0],y.indicator)):X.length===0?w.prepend([new ke(S.goal.replace(new H("=",[y.args[1].args[0],y.args[0]],S)),S.substitution,S)]):w.prepend([new ke(S.goal.replace(new H("=",[new H(y.args[1].args[0].id,X),y.args[0]])),S.substitution,S)])}}else{if(b.type.is_atomic(y.args[0]))F=new H(".",[y.args[0],new H("[]")]);else{F=new H("[]");for(var J=y.args[0].args.length-1;J>=0;J--)F=new H(".",[y.args[0].args[J],F]);F=new H(".",[new H(y.args[0].id),F])}w.prepend([new ke(S.goal.replace(new H("=",[F,y.args[1]])),S.substitution,S)])}},"copy_term/2":function(w,S,y){var F=y.args[0].rename(w);w.prepend([new ke(S.goal.replace(new H("=",[F,y.args[1]])),S.substitution,S.parent)])},"term_variables/2":function(w,S,y){var F=y.args[0],J=y.args[1];if(!b.type.is_fully_list(J))w.throw_error(b.error.type("list",J,y.indicator));else{var X=g(o(we(F.variables()),function($){return new xe($)}));w.prepend([new ke(S.goal.replace(new H("=",[J,X])),S.substitution,S)])}},"clause/2":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else if(!b.type.is_variable(y.args[1])&&!b.type.is_callable(y.args[1]))w.throw_error(b.error.type("callable",y.args[1],y.indicator));else if(w.session.rules[y.args[0].indicator]!==void 0)if(w.is_public_predicate(y.args[0].indicator)){var F=[];for(var J in w.session.rules[y.args[0].indicator])if(w.session.rules[y.args[0].indicator].hasOwnProperty(J)){var X=w.session.rules[y.args[0].indicator][J];w.session.renamed_variables={},X=X.rename(w),X.body===null&&(X.body=new H("true"));var $=new H(",",[new H("=",[X.head,y.args[0]]),new H("=",[X.body,y.args[1]])]);F.push(new ke(S.goal.replace($),S.substitution,S))}w.prepend(F)}else w.throw_error(b.error.permission("access","private_procedure",y.args[0].indicator,y.indicator))},"current_predicate/1":function(w,S,y){var F=y.args[0];if(!b.type.is_variable(F)&&(!b.type.is_compound(F)||F.indicator!=="//2"))w.throw_error(b.error.type("predicate_indicator",F,y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_variable(F.args[0])&&!b.type.is_atom(F.args[0]))w.throw_error(b.error.type("atom",F.args[0],y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_variable(F.args[1])&&!b.type.is_integer(F.args[1]))w.throw_error(b.error.type("integer",F.args[1],y.indicator));else{var J=[];for(var X in w.session.rules)if(w.session.rules.hasOwnProperty(X)){var $=X.lastIndexOf("/"),ie=X.substr(0,$),be=parseInt(X.substr($+1,X.length-($+1))),Re=new H("/",[new H(ie),new Ne(be,!1)]),at=new H("=",[Re,F]);J.push(new ke(S.goal.replace(at),S.substitution,S))}w.prepend(J)}},"asserta/1":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else{var F,J;y.args[0].indicator===":-/2"?(F=y.args[0].args[0],J=Ee(y.args[0].args[1])):(F=y.args[0],J=null),b.type.is_callable(F)?J!==null&&!b.type.is_callable(J)?w.throw_error(b.error.type("callable",J,y.indicator)):w.is_public_predicate(F.indicator)?(w.session.rules[F.indicator]===void 0&&(w.session.rules[F.indicator]=[]),w.session.public_predicates[F.indicator]=!0,w.session.rules[F.indicator]=[new Ye(F,J,!0)].concat(w.session.rules[F.indicator]),w.success(S)):w.throw_error(b.error.permission("modify","static_procedure",F.indicator,y.indicator)):w.throw_error(b.error.type("callable",F,y.indicator))}},"assertz/1":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else{var F,J;y.args[0].indicator===":-/2"?(F=y.args[0].args[0],J=Ee(y.args[0].args[1])):(F=y.args[0],J=null),b.type.is_callable(F)?J!==null&&!b.type.is_callable(J)?w.throw_error(b.error.type("callable",J,y.indicator)):w.is_public_predicate(F.indicator)?(w.session.rules[F.indicator]===void 0&&(w.session.rules[F.indicator]=[]),w.session.public_predicates[F.indicator]=!0,w.session.rules[F.indicator].push(new Ye(F,J,!0)),w.success(S)):w.throw_error(b.error.permission("modify","static_procedure",F.indicator,y.indicator)):w.throw_error(b.error.type("callable",F,y.indicator))}},"retract/1":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_callable(y.args[0]))w.throw_error(b.error.type("callable",y.args[0],y.indicator));else{var F,J;if(y.args[0].indicator===":-/2"?(F=y.args[0].args[0],J=y.args[0].args[1]):(F=y.args[0],J=new H("true")),typeof S.retract>"u")if(w.is_public_predicate(F.indicator)){if(w.session.rules[F.indicator]!==void 0){for(var X=[],$=0;$<w.session.rules[F.indicator].length;$++){w.session.renamed_variables={};var ie=w.session.rules[F.indicator][$],be=ie.rename(w);be.body===null&&(be.body=new H("true",[]));var Re=w.get_flag("occurs_check").indicator==="true/0",at=b.unify(new H(",",[F,J]),new H(",",[be.head,be.body]),Re);if(at!==null){var dt=new ke(S.goal.replace(new H(",",[new H("retract",[new H(":-",[F,J])]),new H(",",[new H("=",[F,be.head]),new H("=",[J,be.body])])])),S.substitution,S);dt.retract=ie,X.push(dt)}}w.prepend(X)}}else w.throw_error(b.error.permission("modify","static_procedure",F.indicator,y.indicator));else Ae(w,S,F.indicator,S.retract)}},"retractall/1":function(w,S,y){var F=y.args[0];b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_callable(F)?w.prepend([new ke(S.goal.replace(new H(",",[new H("retract",[new b.type.Term(":-",[F,new xe("_")])]),new H("fail",[])])),S.substitution,S),new ke(S.goal.replace(null),S.substitution,S)]):w.throw_error(b.error.type("callable",F,y.indicator))},"abolish/1":function(w,S,y){if(b.type.is_variable(y.args[0])||b.type.is_term(y.args[0])&&y.args[0].indicator==="//2"&&(b.type.is_variable(y.args[0].args[0])||b.type.is_variable(y.args[0].args[1])))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_term(y.args[0])||y.args[0].indicator!=="//2")w.throw_error(b.error.type("predicate_indicator",y.args[0],y.indicator));else if(!b.type.is_atom(y.args[0].args[0]))w.throw_error(b.error.type("atom",y.args[0].args[0],y.indicator));else if(!b.type.is_integer(y.args[0].args[1]))w.throw_error(b.error.type("integer",y.args[0].args[1],y.indicator));else if(y.args[0].args[1].value<0)w.throw_error(b.error.domain("not_less_than_zero",y.args[0].args[1],y.indicator));else if(b.type.is_number(w.get_flag("max_arity"))&&y.args[0].args[1].value>w.get_flag("max_arity").value)w.throw_error(b.error.representation("max_arity",y.indicator));else{var F=y.args[0].args[0].id+"/"+y.args[0].args[1].value;w.is_public_predicate(F)?(delete w.session.rules[F],w.success(S)):w.throw_error(b.error.permission("modify","static_procedure",F,y.indicator))}},"atom_length/2":function(w,S,y){if(b.type.is_variable(y.args[0]))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_atom(y.args[0]))w.throw_error(b.error.type("atom",y.args[0],y.indicator));else if(!b.type.is_variable(y.args[1])&&!b.type.is_integer(y.args[1]))w.throw_error(b.error.type("integer",y.args[1],y.indicator));else if(b.type.is_integer(y.args[1])&&y.args[1].value<0)w.throw_error(b.error.domain("not_less_than_zero",y.args[1],y.indicator));else{var F=new Ne(y.args[0].id.length,!1);w.prepend([new ke(S.goal.replace(new H("=",[F,y.args[1]])),S.substitution,S)])}},"atom_concat/3":function(w,S,y){var F,J,X=y.args[0],$=y.args[1],ie=y.args[2];if(b.type.is_variable(ie)&&(b.type.is_variable(X)||b.type.is_variable($)))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_atom(X))w.throw_error(b.error.type("atom",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_atom($))w.throw_error(b.error.type("atom",$,y.indicator));else if(!b.type.is_variable(ie)&&!b.type.is_atom(ie))w.throw_error(b.error.type("atom",ie,y.indicator));else{var be=b.type.is_variable(X),Re=b.type.is_variable($);if(!be&&!Re)J=new H("=",[ie,new H(X.id+$.id)]),w.prepend([new ke(S.goal.replace(J),S.substitution,S)]);else if(be&&!Re)F=ie.id.substr(0,ie.id.length-$.id.length),F+$.id===ie.id&&(J=new H("=",[X,new H(F)]),w.prepend([new ke(S.goal.replace(J),S.substitution,S)]));else if(Re&&!be)F=ie.id.substr(X.id.length),X.id+F===ie.id&&(J=new H("=",[$,new H(F)]),w.prepend([new ke(S.goal.replace(J),S.substitution,S)]));else{for(var at=[],dt=0;dt<=ie.id.length;dt++){var jt=new H(ie.id.substr(0,dt)),tr=new H(ie.id.substr(dt));J=new H(",",[new H("=",[jt,X]),new H("=",[tr,$])]),at.push(new ke(S.goal.replace(J),S.substitution,S))}w.prepend(at)}}},"sub_atom/5":function(w,S,y){var F,J=y.args[0],X=y.args[1],$=y.args[2],ie=y.args[3],be=y.args[4];if(b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_integer(X))w.throw_error(b.error.type("integer",X,y.indicator));else if(!b.type.is_variable($)&&!b.type.is_integer($))w.throw_error(b.error.type("integer",$,y.indicator));else if(!b.type.is_variable(ie)&&!b.type.is_integer(ie))w.throw_error(b.error.type("integer",ie,y.indicator));else if(b.type.is_integer(X)&&X.value<0)w.throw_error(b.error.domain("not_less_than_zero",X,y.indicator));else if(b.type.is_integer($)&&$.value<0)w.throw_error(b.error.domain("not_less_than_zero",$,y.indicator));else if(b.type.is_integer(ie)&&ie.value<0)w.throw_error(b.error.domain("not_less_than_zero",ie,y.indicator));else{var Re=[],at=[],dt=[];if(b.type.is_variable(X))for(F=0;F<=J.id.length;F++)Re.push(F);else Re.push(X.value);if(b.type.is_variable($))for(F=0;F<=J.id.length;F++)at.push(F);else at.push($.value);if(b.type.is_variable(ie))for(F=0;F<=J.id.length;F++)dt.push(F);else dt.push(ie.value);var jt=[];for(var tr in Re)if(Re.hasOwnProperty(tr)){F=Re[tr];for(var St in at)if(at.hasOwnProperty(St)){var ln=at[St],kr=J.id.length-F-ln;if(e(dt,kr)!==-1&&F+ln+kr===J.id.length){var mr=J.id.substr(F,ln);if(J.id===J.id.substr(0,F)+mr+J.id.substr(F+ln,kr)){var br=new H("=",[new H(mr),be]),Kr=new H("=",[X,new Ne(F)]),Kn=new H("=",[$,new Ne(ln)]),Ms=new H("=",[ie,new Ne(kr)]),Ri=new H(",",[new H(",",[new H(",",[Kr,Kn]),Ms]),br]);jt.push(new ke(S.goal.replace(Ri),S.substitution,S))}}}}w.prepend(jt)}},"atom_chars/2":function(w,S,y){var F=y.args[0],J=y.args[1];if(b.type.is_variable(F)&&b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_atom(F))w.throw_error(b.error.type("atom",F,y.indicator));else if(b.type.is_variable(F)){for(var ie=J,be=b.type.is_variable(F),Re="";ie.indicator==="./2";){if(b.type.is_character(ie.args[0]))Re+=ie.args[0].id;else if(b.type.is_variable(ie.args[0])&&be){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_variable(ie.args[0])){w.throw_error(b.error.type("character",ie.args[0],y.indicator));return}ie=ie.args[1]}b.type.is_variable(ie)&&be?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_empty_list(ie)&&!b.type.is_variable(ie)?w.throw_error(b.error.type("list",J,y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[new H(Re),F])),S.substitution,S)])}else{for(var X=new H("[]"),$=F.id.length-1;$>=0;$--)X=new H(".",[new H(F.id.charAt($)),X]);w.prepend([new ke(S.goal.replace(new H("=",[J,X])),S.substitution,S)])}},"atom_codes/2":function(w,S,y){var F=y.args[0],J=y.args[1];if(b.type.is_variable(F)&&b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_atom(F))w.throw_error(b.error.type("atom",F,y.indicator));else if(b.type.is_variable(F)){for(var ie=J,be=b.type.is_variable(F),Re="";ie.indicator==="./2";){if(b.type.is_character_code(ie.args[0]))Re+=u(ie.args[0].value);else if(b.type.is_variable(ie.args[0])&&be){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_variable(ie.args[0])){w.throw_error(b.error.representation("character_code",y.indicator));return}ie=ie.args[1]}b.type.is_variable(ie)&&be?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_empty_list(ie)&&!b.type.is_variable(ie)?w.throw_error(b.error.type("list",J,y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[new H(Re),F])),S.substitution,S)])}else{for(var X=new H("[]"),$=F.id.length-1;$>=0;$--)X=new H(".",[new Ne(n(F.id,$),!1),X]);w.prepend([new ke(S.goal.replace(new H("=",[J,X])),S.substitution,S)])}},"char_code/2":function(w,S,y){var F=y.args[0],J=y.args[1];if(b.type.is_variable(F)&&b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_character(F))w.throw_error(b.error.type("character",F,y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_integer(J))w.throw_error(b.error.type("integer",J,y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_character_code(J))w.throw_error(b.error.representation("character_code",y.indicator));else if(b.type.is_variable(J)){var X=new Ne(n(F.id,0),!1);w.prepend([new ke(S.goal.replace(new H("=",[X,J])),S.substitution,S)])}else{var $=new H(u(J.value));w.prepend([new ke(S.goal.replace(new H("=",[$,F])),S.substitution,S)])}},"number_chars/2":function(w,S,y){var F,J=y.args[0],X=y.args[1];if(b.type.is_variable(J)&&b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_number(J))w.throw_error(b.error.type("number",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else{var $=b.type.is_variable(J);if(!b.type.is_variable(X)){var ie=X,be=!0;for(F="";ie.indicator==="./2";){if(b.type.is_character(ie.args[0]))F+=ie.args[0].id;else if(b.type.is_variable(ie.args[0]))be=!1;else if(!b.type.is_variable(ie.args[0])){w.throw_error(b.error.type("character",ie.args[0],y.indicator));return}ie=ie.args[1]}if(be=be&&b.type.is_empty_list(ie),!b.type.is_empty_list(ie)&&!b.type.is_variable(ie)){w.throw_error(b.error.type("list",X,y.indicator));return}if(!be&&$){w.throw_error(b.error.instantiation(y.indicator));return}else if(be)if(b.type.is_variable(ie)&&$){w.throw_error(b.error.instantiation(y.indicator));return}else{var Re=w.parse(F),at=Re.value;!b.type.is_number(at)||Re.tokens[Re.tokens.length-1].space?w.throw_error(b.error.syntax_by_predicate("parseable_number",y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[J,at])),S.substitution,S)]);return}}if(!$){F=J.toString();for(var dt=new H("[]"),jt=F.length-1;jt>=0;jt--)dt=new H(".",[new H(F.charAt(jt)),dt]);w.prepend([new ke(S.goal.replace(new H("=",[X,dt])),S.substitution,S)])}}},"number_codes/2":function(w,S,y){var F,J=y.args[0],X=y.args[1];if(b.type.is_variable(J)&&b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_number(J))w.throw_error(b.error.type("number",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else{var $=b.type.is_variable(J);if(!b.type.is_variable(X)){var ie=X,be=!0;for(F="";ie.indicator==="./2";){if(b.type.is_character_code(ie.args[0]))F+=u(ie.args[0].value);else if(b.type.is_variable(ie.args[0]))be=!1;else if(!b.type.is_variable(ie.args[0])){w.throw_error(b.error.type("character_code",ie.args[0],y.indicator));return}ie=ie.args[1]}if(be=be&&b.type.is_empty_list(ie),!b.type.is_empty_list(ie)&&!b.type.is_variable(ie)){w.throw_error(b.error.type("list",X,y.indicator));return}if(!be&&$){w.throw_error(b.error.instantiation(y.indicator));return}else if(be)if(b.type.is_variable(ie)&&$){w.throw_error(b.error.instantiation(y.indicator));return}else{var Re=w.parse(F),at=Re.value;!b.type.is_number(at)||Re.tokens[Re.tokens.length-1].space?w.throw_error(b.error.syntax_by_predicate("parseable_number",y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[J,at])),S.substitution,S)]);return}}if(!$){F=J.toString();for(var dt=new H("[]"),jt=F.length-1;jt>=0;jt--)dt=new H(".",[new Ne(n(F,jt),!1),dt]);w.prepend([new ke(S.goal.replace(new H("=",[X,dt])),S.substitution,S)])}}},"upcase_atom/2":function(w,S,y){var F=y.args[0],J=y.args[1];b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_atom(F)?!b.type.is_variable(J)&&!b.type.is_atom(J)?w.throw_error(b.error.type("atom",J,y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[J,new H(F.id.toUpperCase(),[])])),S.substitution,S)]):w.throw_error(b.error.type("atom",F,y.indicator))},"downcase_atom/2":function(w,S,y){var F=y.args[0],J=y.args[1];b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_atom(F)?!b.type.is_variable(J)&&!b.type.is_atom(J)?w.throw_error(b.error.type("atom",J,y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[J,new H(F.id.toLowerCase(),[])])),S.substitution,S)]):w.throw_error(b.error.type("atom",F,y.indicator))},"atomic_list_concat/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H("atomic_list_concat",[F,new H("",[]),J])),S.substitution,S)])},"atomic_list_concat/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2];if(b.type.is_variable(J)||b.type.is_variable(F)&&b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_list(F))w.throw_error(b.error.type("list",F,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_atom(X))w.throw_error(b.error.type("atom",X,y.indicator));else if(b.type.is_variable(X)){for(var ie="",be=F;b.type.is_term(be)&&be.indicator==="./2";){if(!b.type.is_atom(be.args[0])&&!b.type.is_number(be.args[0])){w.throw_error(b.error.type("atomic",be.args[0],y.indicator));return}ie!==""&&(ie+=J.id),b.type.is_atom(be.args[0])?ie+=be.args[0].id:ie+=""+be.args[0].value,be=be.args[1]}ie=new H(ie,[]),b.type.is_variable(be)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_term(be)||be.indicator!=="[]/0"?w.throw_error(b.error.type("list",F,y.indicator)):w.prepend([new ke(S.goal.replace(new H("=",[ie,X])),S.substitution,S)])}else{var $=g(o(X.id.split(J.id),function(Re){return new H(Re,[])}));w.prepend([new ke(S.goal.replace(new H("=",[$,F])),S.substitution,S)])}},"@=</2":function(w,S,y){b.compare(y.args[0],y.args[1])<=0&&w.success(S)},"==/2":function(w,S,y){b.compare(y.args[0],y.args[1])===0&&w.success(S)},"\\==/2":function(w,S,y){b.compare(y.args[0],y.args[1])!==0&&w.success(S)},"@</2":function(w,S,y){b.compare(y.args[0],y.args[1])<0&&w.success(S)},"@>/2":function(w,S,y){b.compare(y.args[0],y.args[1])>0&&w.success(S)},"@>=/2":function(w,S,y){b.compare(y.args[0],y.args[1])>=0&&w.success(S)},"compare/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2];if(!b.type.is_variable(F)&&!b.type.is_atom(F))w.throw_error(b.error.type("atom",F,y.indicator));else if(b.type.is_atom(F)&&["<",">","="].indexOf(F.id)===-1)w.throw_error(b.type.domain("order",F,y.indicator));else{var $=b.compare(J,X);$=$===0?"=":$===-1?"<":">",w.prepend([new ke(S.goal.replace(new H("=",[F,new H($,[])])),S.substitution,S)])}},"is/2":function(w,S,y){var F=y.args[1].interpret(w);b.type.is_number(F)?w.prepend([new ke(S.goal.replace(new H("=",[y.args[0],F],w.level)),S.substitution,S)]):w.throw_error(F)},"between/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2];if(b.type.is_variable(F)||b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_integer(F))w.throw_error(b.error.type("integer",F,y.indicator));else if(!b.type.is_integer(J))w.throw_error(b.error.type("integer",J,y.indicator));else if(!b.type.is_variable(X)&&!b.type.is_integer(X))w.throw_error(b.error.type("integer",X,y.indicator));else if(b.type.is_variable(X)){var $=[new ke(S.goal.replace(new H("=",[X,F])),S.substitution,S)];F.value<J.value&&$.push(new ke(S.goal.replace(new H("between",[new Ne(F.value+1,!1),J,X])),S.substitution,S)),w.prepend($)}else F.value<=X.value&&J.value>=X.value&&w.success(S)},"succ/2":function(w,S,y){var F=y.args[0],J=y.args[1];b.type.is_variable(F)&&b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_variable(F)&&!b.type.is_integer(F)?w.throw_error(b.error.type("integer",F,y.indicator)):!b.type.is_variable(J)&&!b.type.is_integer(J)?w.throw_error(b.error.type("integer",J,y.indicator)):!b.type.is_variable(F)&&F.value<0?w.throw_error(b.error.domain("not_less_than_zero",F,y.indicator)):!b.type.is_variable(J)&&J.value<0?w.throw_error(b.error.domain("not_less_than_zero",J,y.indicator)):(b.type.is_variable(J)||J.value>0)&&(b.type.is_variable(F)?w.prepend([new ke(S.goal.replace(new H("=",[F,new Ne(J.value-1,!1)])),S.substitution,S)]):w.prepend([new ke(S.goal.replace(new H("=",[J,new Ne(F.value+1,!1)])),S.substitution,S)]))},"=:=/2":function(w,S,y){var F=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(F)?w.throw_error(F):F===0&&w.success(S)},"=\\=/2":function(w,S,y){var F=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(F)?w.throw_error(F):F!==0&&w.success(S)},"</2":function(w,S,y){var F=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(F)?w.throw_error(F):F<0&&w.success(S)},"=</2":function(w,S,y){var F=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(F)?w.throw_error(F):F<=0&&w.success(S)},">/2":function(w,S,y){var F=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(F)?w.throw_error(F):F>0&&w.success(S)},">=/2":function(w,S,y){var F=b.arithmetic_compare(w,y.args[0],y.args[1]);b.type.is_term(F)?w.throw_error(F):F>=0&&w.success(S)},"var/1":function(w,S,y){b.type.is_variable(y.args[0])&&w.success(S)},"atom/1":function(w,S,y){b.type.is_atom(y.args[0])&&w.success(S)},"atomic/1":function(w,S,y){b.type.is_atomic(y.args[0])&&w.success(S)},"compound/1":function(w,S,y){b.type.is_compound(y.args[0])&&w.success(S)},"integer/1":function(w,S,y){b.type.is_integer(y.args[0])&&w.success(S)},"float/1":function(w,S,y){b.type.is_float(y.args[0])&&w.success(S)},"number/1":function(w,S,y){b.type.is_number(y.args[0])&&w.success(S)},"nonvar/1":function(w,S,y){b.type.is_variable(y.args[0])||w.success(S)},"ground/1":function(w,S,y){y.variables().length===0&&w.success(S)},"acyclic_term/1":function(w,S,y){for(var F=S.substitution.apply(S.substitution),J=y.args[0].variables(),X=0;X<J.length;X++)if(S.substitution.links[J[X]]!==void 0&&!S.substitution.links[J[X]].equals(F.links[J[X]]))return;w.success(S)},"callable/1":function(w,S,y){b.type.is_callable(y.args[0])&&w.success(S)},"is_list/1":function(w,S,y){for(var F=y.args[0];b.type.is_term(F)&&F.indicator==="./2";)F=F.args[1];b.type.is_term(F)&&F.indicator==="[]/0"&&w.success(S)},"current_input/1":function(w,S,y){var F=y.args[0];!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream",F,y.indicator)):(b.type.is_atom(F)&&w.get_stream_by_alias(F.id)&&(F=w.get_stream_by_alias(F.id)),w.prepend([new ke(S.goal.replace(new H("=",[F,w.get_current_input()])),S.substitution,S)]))},"current_output/1":function(w,S,y){var F=y.args[0];!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):(b.type.is_atom(F)&&w.get_stream_by_alias(F.id)&&(F=w.get_stream_by_alias(F.id)),w.prepend([new ke(S.goal.replace(new H("=",[F,w.get_current_output()])),S.substitution,S)]))},"set_input/1":function(w,S,y){var F=y.args[0],J=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):b.type.is_stream(J)?J.output===!0?w.throw_error(b.error.permission("input","stream",F,y.indicator)):(w.set_current_input(J),w.success(S)):w.throw_error(b.error.existence("stream",F,y.indicator))},"set_output/1":function(w,S,y){var F=y.args[0],J=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):b.type.is_stream(J)?J.input===!0?w.throw_error(b.error.permission("output","stream",F,y.indicator)):(w.set_current_output(J),w.success(S)):w.throw_error(b.error.existence("stream",F,y.indicator))},"open/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2];w.prepend([new ke(S.goal.replace(new H("open",[F,J,X,new H("[]",[])])),S.substitution,S)])},"open/4":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2],$=y.args[3];if(b.type.is_variable(F)||b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_atom(J))w.throw_error(b.error.type("atom",J,y.indicator));else if(!b.type.is_list($))w.throw_error(b.error.type("list",$,y.indicator));else if(!b.type.is_variable(X))w.throw_error(b.error.type("variable",X,y.indicator));else if(!b.type.is_atom(F)&&!b.type.is_streamable(F))w.throw_error(b.error.domain("source_sink",F,y.indicator));else if(!b.type.is_io_mode(J))w.throw_error(b.error.domain("io_mode",J,y.indicator));else{for(var ie={},be=$,Re;b.type.is_term(be)&&be.indicator==="./2";){if(Re=be.args[0],b.type.is_variable(Re)){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_stream_option(Re)){w.throw_error(b.error.domain("stream_option",Re,y.indicator));return}ie[Re.id]=Re.args[0].id,be=be.args[1]}if(be.indicator!=="[]/0"){b.type.is_variable(be)?w.throw_error(b.error.instantiation(y.indicator)):w.throw_error(b.error.type("list",$,y.indicator));return}else{var at=ie.alias;if(at&&w.get_stream_by_alias(at)){w.throw_error(b.error.permission("open","source_sink",new H("alias",[new H(at,[])]),y.indicator));return}ie.type||(ie.type="text");var dt;if(b.type.is_atom(F)?dt=w.file_system_open(F.id,ie.type,J.id):dt=F.stream(ie.type,J.id),dt===!1){w.throw_error(b.error.permission("open","source_sink",F,y.indicator));return}else if(dt===null){w.throw_error(b.error.existence("source_sink",F,y.indicator));return}var jt=new Te(dt,J.id,ie.alias,ie.type,ie.reposition==="true",ie.eof_action);at?w.session.streams[at]=jt:w.session.streams[jt.id]=jt,w.prepend([new ke(S.goal.replace(new H("=",[X,jt])),S.substitution,S)])}}},"close/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H("close",[F,new H("[]",[])])),S.substitution,S)])},"close/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F)||b.type.is_variable(J))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_list(J))w.throw_error(b.error.type("list",J,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else{for(var $={},ie=J,be;b.type.is_term(ie)&&ie.indicator==="./2";){if(be=ie.args[0],b.type.is_variable(be)){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_close_option(be)){w.throw_error(b.error.domain("close_option",be,y.indicator));return}$[be.id]=be.args[0].id==="true",ie=ie.args[1]}if(ie.indicator!=="[]/0"){b.type.is_variable(ie)?w.throw_error(b.error.instantiation(y.indicator)):w.throw_error(b.error.type("list",J,y.indicator));return}else{if(X===w.session.standard_input||X===w.session.standard_output){w.success(S);return}else X===w.session.current_input?w.session.current_input=w.session.standard_input:X===w.session.current_output&&(w.session.current_output=w.session.current_output);X.alias!==null?delete w.session.streams[X.alias]:delete w.session.streams[X.id],X.output&&X.stream.flush();var Re=X.stream.close();X.stream=null,($.force===!0||Re===!0)&&w.success(S)}}},"flush_output/0":function(w,S,y){w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("flush_output",[new xe("S")])])),S.substitution,S)])},"flush_output/1":function(w,S,y){var F=y.args[0],J=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):!b.type.is_stream(J)||J.stream===null?w.throw_error(b.error.existence("stream",F,y.indicator)):F.input===!0?w.throw_error(b.error.permission("output","stream",output,y.indicator)):(J.stream.flush(),w.success(S))},"stream_property/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_variable(F)&&(!b.type.is_stream(X)||X.stream===null))w.throw_error(b.error.existence("stream",F,y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_stream_property(J))w.throw_error(b.error.domain("stream_property",J,y.indicator));else{var $=[],ie=[];if(!b.type.is_variable(F))$.push(X);else for(var be in w.session.streams)$.push(w.session.streams[be]);for(var Re=0;Re<$.length;Re++){var at=[];$[Re].filename&&at.push(new H("file_name",[new H($[Re].file_name,[])])),at.push(new H("mode",[new H($[Re].mode,[])])),at.push(new H($[Re].input?"input":"output",[])),$[Re].alias&&at.push(new H("alias",[new H($[Re].alias,[])])),at.push(new H("position",[typeof $[Re].position=="number"?new Ne($[Re].position,!1):new H($[Re].position,[])])),at.push(new H("end_of_stream",[new H($[Re].position==="end_of_stream"?"at":$[Re].position==="past_end_of_stream"?"past":"not",[])])),at.push(new H("eof_action",[new H($[Re].eof_action,[])])),at.push(new H("reposition",[new H($[Re].reposition?"true":"false",[])])),at.push(new H("type",[new H($[Re].type,[])]));for(var dt=0;dt<at.length;dt++)ie.push(new ke(S.goal.replace(new H(",",[new H("=",[b.type.is_variable(F)?F:X,$[Re]]),new H("=",[J,at[dt]])])),S.substitution,S))}w.prepend(ie)}},"at_end_of_stream/0":function(w,S,y){w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H(",",[new H("stream_property",[new xe("S"),new H("end_of_stream",[new xe("E")])]),new H(",",[new H("!",[]),new H(";",[new H("=",[new xe("E"),new H("at",[])]),new H("=",[new xe("E"),new H("past",[])])])])])])),S.substitution,S)])},"at_end_of_stream/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("stream_property",[F,new H("end_of_stream",[new xe("E")])]),new H(",",[new H("!",[]),new H(";",[new H("=",[new xe("E"),new H("at",[])]),new H("=",[new xe("E"),new H("past",[])])])])])),S.substitution,S)])},"set_stream_position/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)||b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):!b.type.is_stream(X)||X.stream===null?w.throw_error(b.error.existence("stream",F,y.indicator)):b.type.is_stream_position(J)?X.reposition===!1?w.throw_error(b.error.permission("reposition","stream",F,y.indicator)):(b.type.is_integer(J)?X.position=J.value:X.position=J.id,w.success(S)):w.throw_error(b.error.domain("stream_position",J,y.indicator))},"get_char/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("get_char",[new xe("S"),F])])),S.substitution,S)])},"get_char/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_character(J))w.throw_error(b.error.type("in_character",J,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if(X.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if(X.type==="binary")w.throw_error(b.error.permission("input","binary_stream",F,y.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{var $;if(X.position==="end_of_stream")$="end_of_file",X.position="past_end_of_stream";else{if($=X.stream.get(1,X.position),$===null){w.throw_error(b.error.representation("character",y.indicator));return}X.position++}w.prepend([new ke(S.goal.replace(new H("=",[new H($,[]),J])),S.substitution,S)])}},"get_code/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("get_code",[new xe("S"),F])])),S.substitution,S)])},"get_code/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_integer(J))w.throw_error(b.error.type("integer",char,y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if(X.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if(X.type==="binary")w.throw_error(b.error.permission("input","binary_stream",F,y.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{var $;if(X.position==="end_of_stream")$=-1,X.position="past_end_of_stream";else{if($=X.stream.get(1,X.position),$===null){w.throw_error(b.error.representation("character",y.indicator));return}$=n($,0),X.position++}w.prepend([new ke(S.goal.replace(new H("=",[new Ne($,!1),J])),S.substitution,S)])}},"peek_char/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("peek_char",[new xe("S"),F])])),S.substitution,S)])},"peek_char/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_character(J))w.throw_error(b.error.type("in_character",J,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if(X.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if(X.type==="binary")w.throw_error(b.error.permission("input","binary_stream",F,y.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{var $;if(X.position==="end_of_stream")$="end_of_file",X.position="past_end_of_stream";else if($=X.stream.get(1,X.position),$===null){w.throw_error(b.error.representation("character",y.indicator));return}w.prepend([new ke(S.goal.replace(new H("=",[new H($,[]),J])),S.substitution,S)])}},"peek_code/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("peek_code",[new xe("S"),F])])),S.substitution,S)])},"peek_code/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_integer(J))w.throw_error(b.error.type("integer",char,y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if(X.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if(X.type==="binary")w.throw_error(b.error.permission("input","binary_stream",F,y.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{var $;if(X.position==="end_of_stream")$=-1,X.position="past_end_of_stream";else{if($=X.stream.get(1,X.position),$===null){w.throw_error(b.error.representation("character",y.indicator));return}$=n($,0)}w.prepend([new ke(S.goal.replace(new H("=",[new Ne($,!1),J])),S.substitution,S)])}},"put_char/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("put_char",[new xe("S"),F])])),S.substitution,S)])},"put_char/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)||b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_character(J)?!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):!b.type.is_stream(X)||X.stream===null?w.throw_error(b.error.existence("stream",F,y.indicator)):X.input?w.throw_error(b.error.permission("output","stream",F,y.indicator)):X.type==="binary"?w.throw_error(b.error.permission("output","binary_stream",F,y.indicator)):X.stream.put(J.id,X.position)&&(typeof X.position=="number"&&X.position++,w.success(S)):w.throw_error(b.error.type("character",J,y.indicator))},"put_code/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("put_code",[new xe("S"),F])])),S.substitution,S)])},"put_code/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)||b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_integer(J)?b.type.is_character_code(J)?!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):!b.type.is_stream(X)||X.stream===null?w.throw_error(b.error.existence("stream",F,y.indicator)):X.input?w.throw_error(b.error.permission("output","stream",F,y.indicator)):X.type==="binary"?w.throw_error(b.error.permission("output","binary_stream",F,y.indicator)):X.stream.put_char(u(J.value),X.position)&&(typeof X.position=="number"&&X.position++,w.success(S)):w.throw_error(b.error.representation("character_code",y.indicator)):w.throw_error(b.error.type("integer",J,y.indicator))},"nl/0":function(w,S,y){w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("put_char",[new xe("S"),new H(` +`,[])])])),S.substitution,S)])},"nl/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H("put_char",[F,new H(` +`,[])])),S.substitution,S)])},"get_byte/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("get_byte",[new xe("S"),F])])),S.substitution,S)])},"get_byte/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_byte(J))w.throw_error(b.error.type("in_byte",char,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if(X.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if(X.type==="text")w.throw_error(b.error.permission("input","text_stream",F,y.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{var $;if(X.position==="end_of_stream")$="end_of_file",X.position="past_end_of_stream";else{if($=X.stream.get_byte(X.position),$===null){w.throw_error(b.error.representation("byte",y.indicator));return}X.position++}w.prepend([new ke(S.goal.replace(new H("=",[new Ne($,!1),J])),S.substitution,S)])}},"peek_byte/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("peek_byte",[new xe("S"),F])])),S.substitution,S)])},"peek_byte/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_variable(J)&&!b.type.is_byte(J))w.throw_error(b.error.type("in_byte",char,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream(X)||X.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if(X.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if(X.type==="text")w.throw_error(b.error.permission("input","text_stream",F,y.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{var $;if(X.position==="end_of_stream")$="end_of_file",X.position="past_end_of_stream";else if($=X.stream.get_byte(X.position),$===null){w.throw_error(b.error.representation("byte",y.indicator));return}w.prepend([new ke(S.goal.replace(new H("=",[new Ne($,!1),J])),S.substitution,S)])}},"put_byte/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("put_byte",[new xe("S"),F])])),S.substitution,S)])},"put_byte/2":function(w,S,y){var F=y.args[0],J=y.args[1],X=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);b.type.is_variable(F)||b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_byte(J)?!b.type.is_variable(F)&&!b.type.is_stream(F)&&!b.type.is_atom(F)?w.throw_error(b.error.domain("stream_or_alias",F,y.indicator)):!b.type.is_stream(X)||X.stream===null?w.throw_error(b.error.existence("stream",F,y.indicator)):X.input?w.throw_error(b.error.permission("output","stream",F,y.indicator)):X.type==="text"?w.throw_error(b.error.permission("output","text_stream",F,y.indicator)):X.stream.put_byte(J.value,X.position)&&(typeof X.position=="number"&&X.position++,w.success(S)):w.throw_error(b.error.type("byte",J,y.indicator))},"read/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("read_term",[new xe("S"),F,new H("[]",[])])])),S.substitution,S)])},"read/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H("read_term",[F,J,new H("[]",[])])),S.substitution,S)])},"read_term/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_input",[new xe("S")]),new H("read_term",[new xe("S"),F,J])])),S.substitution,S)])},"read_term/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2],$=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F)||b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream($)||$.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if($.output)w.throw_error(b.error.permission("input","stream",F,y.indicator));else if($.type==="binary")w.throw_error(b.error.permission("input","binary_stream",F,y.indicator));else if($.position==="past_end_of_stream"&&$.eof_action==="error")w.throw_error(b.error.permission("input","past_end_of_stream",F,y.indicator));else{for(var ie={},be=X,Re;b.type.is_term(be)&&be.indicator==="./2";){if(Re=be.args[0],b.type.is_variable(Re)){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_read_option(Re)){w.throw_error(b.error.domain("read_option",Re,y.indicator));return}ie[Re.id]=Re.args[0],be=be.args[1]}if(be.indicator!=="[]/0"){b.type.is_variable(be)?w.throw_error(b.error.instantiation(y.indicator)):w.throw_error(b.error.type("list",X,y.indicator));return}else{for(var at,dt,jt,tr="",St=[],ln=null;ln===null||ln.name!=="atom"||ln.value!=="."||jt.type===A&&b.flatten_error(new H("throw",[jt.value])).found==="token_not_found";){if(at=$.stream.get(1,$.position),at===null){w.throw_error(b.error.representation("character",y.indicator));return}if(at==="end_of_file"||at==="past_end_of_file"){jt?w.throw_error(b.error.syntax(St[jt.len-1],". or expression expected",!1)):w.throw_error(b.error.syntax(null,"token not found",!0));return}$.position++,tr+=at,dt=new U(w),dt.new_text(tr),St=dt.get_tokens(),ln=St!==null&&St.length>0?St[St.length-1]:null,St!==null&&(jt=z(w,St,0,w.__get_max_priority(),!1))}if(jt.type===p&&jt.len===St.length-1&&ln.value==="."){jt=jt.value.rename(w);var kr=new H("=",[J,jt]);if(ie.variables){var mr=g(o(we(jt.variables()),function(br){return new xe(br)}));kr=new H(",",[kr,new H("=",[ie.variables,mr])])}if(ie.variable_names){var mr=g(o(we(jt.variables()),function(Kr){var Kn;for(Kn in w.session.renamed_variables)if(w.session.renamed_variables.hasOwnProperty(Kn)&&w.session.renamed_variables[Kn]===Kr)break;return new H("=",[new H(Kn,[]),new xe(Kr)])}));kr=new H(",",[kr,new H("=",[ie.variable_names,mr])])}if(ie.singletons){var mr=g(o(new Ye(jt,null).singleton_variables(),function(Kr){var Kn;for(Kn in w.session.renamed_variables)if(w.session.renamed_variables.hasOwnProperty(Kn)&&w.session.renamed_variables[Kn]===Kr)break;return new H("=",[new H(Kn,[]),new xe(Kr)])}));kr=new H(",",[kr,new H("=",[ie.singletons,mr])])}w.prepend([new ke(S.goal.replace(kr),S.substitution,S)])}else jt.type===p?w.throw_error(b.error.syntax(St[jt.len],"unexpected token",!1)):w.throw_error(jt.value)}}},"write/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("write",[new xe("S"),F])])),S.substitution,S)])},"write/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H("write_term",[F,J,new H(".",[new H("quoted",[new H("false",[])]),new H(".",[new H("ignore_ops",[new H("false")]),new H(".",[new H("numbervars",[new H("true")]),new H("[]",[])])])])])),S.substitution,S)])},"writeq/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("writeq",[new xe("S"),F])])),S.substitution,S)])},"writeq/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H("write_term",[F,J,new H(".",[new H("quoted",[new H("true",[])]),new H(".",[new H("ignore_ops",[new H("false")]),new H(".",[new H("numbervars",[new H("true")]),new H("[]",[])])])])])),S.substitution,S)])},"write_canonical/1":function(w,S,y){var F=y.args[0];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("write_canonical",[new xe("S"),F])])),S.substitution,S)])},"write_canonical/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H("write_term",[F,J,new H(".",[new H("quoted",[new H("true",[])]),new H(".",[new H("ignore_ops",[new H("true")]),new H(".",[new H("numbervars",[new H("false")]),new H("[]",[])])])])])),S.substitution,S)])},"write_term/2":function(w,S,y){var F=y.args[0],J=y.args[1];w.prepend([new ke(S.goal.replace(new H(",",[new H("current_output",[new xe("S")]),new H("write_term",[new xe("S"),F,J])])),S.substitution,S)])},"write_term/3":function(w,S,y){var F=y.args[0],J=y.args[1],X=y.args[2],$=b.type.is_stream(F)?F:w.get_stream_by_alias(F.id);if(b.type.is_variable(F)||b.type.is_variable(X))w.throw_error(b.error.instantiation(y.indicator));else if(!b.type.is_list(X))w.throw_error(b.error.type("list",X,y.indicator));else if(!b.type.is_stream(F)&&!b.type.is_atom(F))w.throw_error(b.error.domain("stream_or_alias",F,y.indicator));else if(!b.type.is_stream($)||$.stream===null)w.throw_error(b.error.existence("stream",F,y.indicator));else if($.input)w.throw_error(b.error.permission("output","stream",F,y.indicator));else if($.type==="binary")w.throw_error(b.error.permission("output","binary_stream",F,y.indicator));else if($.position==="past_end_of_stream"&&$.eof_action==="error")w.throw_error(b.error.permission("output","past_end_of_stream",F,y.indicator));else{for(var ie={},be=X,Re;b.type.is_term(be)&&be.indicator==="./2";){if(Re=be.args[0],b.type.is_variable(Re)){w.throw_error(b.error.instantiation(y.indicator));return}else if(!b.type.is_write_option(Re)){w.throw_error(b.error.domain("write_option",Re,y.indicator));return}ie[Re.id]=Re.args[0].id==="true",be=be.args[1]}if(be.indicator!=="[]/0"){b.type.is_variable(be)?w.throw_error(b.error.instantiation(y.indicator)):w.throw_error(b.error.type("list",X,y.indicator));return}else{ie.session=w.session;var at=J.toString(ie);$.stream.put(at,$.position),typeof $.position=="number"&&($.position+=at.length),w.success(S)}}},"halt/0":function(w,S,y){w.points=[]},"halt/1":function(w,S,y){var F=y.args[0];b.type.is_variable(F)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_integer(F)?w.points=[]:w.throw_error(b.error.type("integer",F,y.indicator))},"current_prolog_flag/2":function(w,S,y){var F=y.args[0],J=y.args[1];if(!b.type.is_variable(F)&&!b.type.is_atom(F))w.throw_error(b.error.type("atom",F,y.indicator));else if(!b.type.is_variable(F)&&!b.type.is_flag(F))w.throw_error(b.error.domain("prolog_flag",F,y.indicator));else{var X=[];for(var $ in b.flag)if(b.flag.hasOwnProperty($)){var ie=new H(",",[new H("=",[new H($),F]),new H("=",[w.get_flag($),J])]);X.push(new ke(S.goal.replace(ie),S.substitution,S))}w.prepend(X)}},"set_prolog_flag/2":function(w,S,y){var F=y.args[0],J=y.args[1];b.type.is_variable(F)||b.type.is_variable(J)?w.throw_error(b.error.instantiation(y.indicator)):b.type.is_atom(F)?b.type.is_flag(F)?b.type.is_value_flag(F,J)?b.type.is_modifiable_flag(F)?(w.session.flag[F.id]=J,w.success(S)):w.throw_error(b.error.permission("modify","flag",F)):w.throw_error(b.error.domain("flag_value",new H("+",[F,J]),y.indicator)):w.throw_error(b.error.domain("prolog_flag",F,y.indicator)):w.throw_error(b.error.type("atom",F,y.indicator))}},flag:{bounded:{allowed:[new H("true"),new H("false")],value:new H("true"),changeable:!1},max_integer:{allowed:[new Ne(Number.MAX_SAFE_INTEGER)],value:new Ne(Number.MAX_SAFE_INTEGER),changeable:!1},min_integer:{allowed:[new Ne(Number.MIN_SAFE_INTEGER)],value:new Ne(Number.MIN_SAFE_INTEGER),changeable:!1},integer_rounding_function:{allowed:[new H("down"),new H("toward_zero")],value:new H("toward_zero"),changeable:!1},char_conversion:{allowed:[new H("on"),new H("off")],value:new H("on"),changeable:!0},debug:{allowed:[new H("on"),new H("off")],value:new H("off"),changeable:!0},max_arity:{allowed:[new H("unbounded")],value:new H("unbounded"),changeable:!1},unknown:{allowed:[new H("error"),new H("fail"),new H("warning")],value:new H("error"),changeable:!0},double_quotes:{allowed:[new H("chars"),new H("codes"),new H("atom")],value:new H("codes"),changeable:!0},occurs_check:{allowed:[new H("false"),new H("true")],value:new H("false"),changeable:!0},dialect:{allowed:[new H("tau")],value:new H("tau"),changeable:!1},version_data:{allowed:[new H("tau",[new Ne(t.major,!1),new Ne(t.minor,!1),new Ne(t.patch,!1),new H(t.status)])],value:new H("tau",[new Ne(t.major,!1),new Ne(t.minor,!1),new Ne(t.patch,!1),new H(t.status)]),changeable:!1},nodejs:{allowed:[new H("yes"),new H("no")],value:new H(typeof gl<"u"&&gl.exports?"yes":"no"),changeable:!1}},unify:function(w,S,y){y=y===void 0?!1:y;for(var F=[{left:w,right:S}],J={};F.length!==0;){var X=F.pop();if(w=X.left,S=X.right,b.type.is_term(w)&&b.type.is_term(S)){if(w.indicator!==S.indicator)return null;for(var $=0;$<w.args.length;$++)F.push({left:w.args[$],right:S.args[$]})}else if(b.type.is_number(w)&&b.type.is_number(S)){if(w.value!==S.value||w.is_float!==S.is_float)return null}else if(b.type.is_variable(w)){if(b.type.is_variable(S)&&w.id===S.id)continue;if(y===!0&&S.variables().indexOf(w.id)!==-1)return null;if(w.id!=="_"){var ie=new Fe;ie.add(w.id,S);for(var $=0;$<F.length;$++)F[$].left=F[$].left.apply(ie),F[$].right=F[$].right.apply(ie);for(var $ in J)J[$]=J[$].apply(ie);J[w.id]=S}}else if(b.type.is_variable(S))F.push({left:S,right:w});else if(w.unify!==void 0){if(!w.unify(S))return null}else return null}return new Fe(J)},compare:function(w,S){var y=b.type.compare(w,S);return y!==0?y:w.compare(S)},arithmetic_compare:function(w,S,y){var F=S.interpret(w);if(b.type.is_number(F)){var J=y.interpret(w);return b.type.is_number(J)?F.value<J.value?-1:F.value>J.value?1:0:J}else return F},operate:function(w,S){if(b.type.is_operator(S)){for(var y=b.type.is_operator(S),F=[],J,X=!1,$=0;$<S.args.length;$++){if(J=S.args[$].interpret(w),b.type.is_number(J)){if(y.type_args!==null&&J.is_float!==y.type_args)return b.error.type(y.type_args?"float":"integer",J,w.__call_indicator);F.push(J.value)}else return J;X=X||J.is_float}return F.push(w),J=b.arithmetic.evaluation[S.indicator].fn.apply(this,F),X=y.type_result===null?X:y.type_result,b.type.is_term(J)?J:J===Number.POSITIVE_INFINITY||J===Number.NEGATIVE_INFINITY?b.error.evaluation("overflow",w.__call_indicator):X===!1&&w.get_flag("bounded").id==="true"&&(J>w.get_flag("max_integer").value||J<w.get_flag("min_integer").value)?b.error.evaluation("int_overflow",w.__call_indicator):new Ne(J,X)}else return b.error.type("evaluable",S.indicator,w.__call_indicator)},error:{existence:function(w,S,y){return typeof S=="string"&&(S=Z(S)),new H("error",[new H("existence_error",[new H(w),S]),Z(y)])},type:function(w,S,y){return new H("error",[new H("type_error",[new H(w),S]),Z(y)])},instantiation:function(w){return new H("error",[new H("instantiation_error"),Z(w)])},domain:function(w,S,y){return new H("error",[new H("domain_error",[new H(w),S]),Z(y)])},representation:function(w,S){return new H("error",[new H("representation_error",[new H(w)]),Z(S)])},permission:function(w,S,y,F){return new H("error",[new H("permission_error",[new H(w),new H(S),y]),Z(F)])},evaluation:function(w,S){return new H("error",[new H("evaluation_error",[new H(w)]),Z(S)])},syntax:function(w,S,y){w=w||{value:"",line:0,column:0,matches:[""],start:0};var F=y&&w.matches.length>0?w.start+w.matches[0].length:w.start,J=y?new H("token_not_found"):new H("found",[new H(w.value.toString())]),X=new H(".",[new H("line",[new Ne(w.line+1)]),new H(".",[new H("column",[new Ne(F+1)]),new H(".",[J,new H("[]",[])])])]);return new H("error",[new H("syntax_error",[new H(S)]),X])},syntax_by_predicate:function(w,S){return new H("error",[new H("syntax_error",[new H(w)]),Z(S)])}},warning:{singleton:function(w,S,y){for(var F=new H("[]"),J=w.length-1;J>=0;J--)F=new H(".",[new xe(w[J]),F]);return new H("warning",[new H("singleton_variables",[F,Z(S)]),new H(".",[new H("line",[new Ne(y,!1)]),new H("[]")])])},failed_goal:function(w,S){return new H("warning",[new H("failed_goal",[w]),new H(".",[new H("line",[new Ne(S,!1)]),new H("[]")])])}},format_variable:function(w){return"_"+w},format_answer:function(w,S,F){S instanceof Se&&(S=S.thread);var F=F||{};if(F.session=S?S.session:void 0,b.type.is_error(w))return"uncaught exception: "+w.args[0].toString();if(w===!1)return"false.";if(w===null)return"limit exceeded ;";var J=0,X="";if(b.type.is_substitution(w)){var $=w.domain(!0);w=w.filter(function(Re,at){return!b.type.is_variable(at)||$.indexOf(at.id)!==-1&&Re!==at.id})}for(var ie in w.links)w.links.hasOwnProperty(ie)&&(J++,X!==""&&(X+=", "),X+=ie.toString(F)+" = "+w.links[ie].toString(F));var be=typeof S>"u"||S.points.length>0?" ;":".";return J===0?"true"+be:X+be},flatten_error:function(w){if(!b.type.is_error(w))return null;w=w.args[0];var S={};return S.type=w.args[0].id,S.thrown=S.type==="syntax_error"?null:w.args[1].id,S.expected=null,S.found=null,S.representation=null,S.existence=null,S.existence_type=null,S.line=null,S.column=null,S.permission_operation=null,S.permission_type=null,S.evaluation_type=null,S.type==="type_error"||S.type==="domain_error"?(S.expected=w.args[0].args[0].id,S.found=w.args[0].args[1].toString()):S.type==="syntax_error"?w.args[1].indicator==="./2"?(S.expected=w.args[0].args[0].id,S.found=w.args[1].args[1].args[1].args[0],S.found=S.found.id==="token_not_found"?S.found.id:S.found.args[0].id,S.line=w.args[1].args[0].args[0].value,S.column=w.args[1].args[1].args[0].args[0].value):S.thrown=w.args[1].id:S.type==="permission_error"?(S.found=w.args[0].args[2].toString(),S.permission_operation=w.args[0].args[0].id,S.permission_type=w.args[0].args[1].id):S.type==="evaluation_error"?S.evaluation_type=w.args[0].args[0].id:S.type==="representation_error"?S.representation=w.args[0].args[0].id:S.type==="existence_error"&&(S.existence=w.args[0].args[1].toString(),S.existence_type=w.args[0].args[0].id),S},create:function(w){return new b.type.Session(w)}};typeof gl<"u"?gl.exports=b:window.pl=b})()});function cme(t,e,r){t.prepend(r.map(o=>new La.default.type.State(e.goal.replace(o),e.substitution,e)))}function fH(t){let e=Ame.get(t.session);if(e==null)throw new Error("Assertion failed: A project should have been registered for the active session");return e}function fme(t,e){Ame.set(t,e),t.consult(`:- use_module(library(${rdt.id})).`)}var pH,La,ume,Qh,edt,tdt,Ame,rdt,pme=Et(()=>{Ge();pH=Ze(e2()),La=Ze(AH()),ume=Ze(ve("vm")),{is_atom:Qh,is_variable:edt,is_instantiated_list:tdt}=La.default.type;Ame=new WeakMap;rdt=new La.default.type.Module("constraints",{"project_workspaces_by_descriptor/3":(t,e,r)=>{let[o,a,n]=r.args;if(!Qh(o)||!Qh(a)){t.throw_error(La.default.error.instantiation(r.indicator));return}let u=G.parseIdent(o.id),A=G.makeDescriptor(u,a.id),h=fH(t).tryWorkspaceByDescriptor(A);edt(n)&&h!==null&&cme(t,e,[new La.default.type.Term("=",[n,new La.default.type.Term(String(h.relativeCwd))])]),Qh(n)&&h!==null&&h.relativeCwd===n.id&&t.success(e)},"workspace_field/3":(t,e,r)=>{let[o,a,n]=r.args;if(!Qh(o)||!Qh(a)){t.throw_error(La.default.error.instantiation(r.indicator));return}let A=fH(t).tryWorkspaceByCwd(o.id);if(A==null)return;let p=(0,pH.default)(A.manifest.raw,a.id);typeof p>"u"||cme(t,e,[new La.default.type.Term("=",[n,new La.default.type.Term(typeof p=="object"?JSON.stringify(p):p)])])},"workspace_field_test/3":(t,e,r)=>{let[o,a,n]=r.args;t.prepend([new La.default.type.State(e.goal.replace(new La.default.type.Term("workspace_field_test",[o,a,n,new La.default.type.Term("[]",[])])),e.substitution,e)])},"workspace_field_test/4":(t,e,r)=>{let[o,a,n,u]=r.args;if(!Qh(o)||!Qh(a)||!Qh(n)||!tdt(u)){t.throw_error(La.default.error.instantiation(r.indicator));return}let p=fH(t).tryWorkspaceByCwd(o.id);if(p==null)return;let h=(0,pH.default)(p.manifest.raw,a.id);if(typeof h>"u")return;let E={$$:h};for(let[v,x]of u.toJavaScript().entries())E[`$${v}`]=x;ume.default.runInNewContext(n.id,E)&&t.success(e)}},["project_workspaces_by_descriptor/3","workspace_field/3","workspace_field_test/3","workspace_field_test/4"])});var A2={};Vt(A2,{Constraints:()=>gH,DependencyType:()=>mme});function to(t){if(t instanceof NE.default.type.Num)return t.value;if(t instanceof NE.default.type.Term)switch(t.indicator){case"throw/1":return to(t.args[0]);case"error/1":return to(t.args[0]);case"error/2":if(t.args[0]instanceof NE.default.type.Term&&t.args[0].indicator==="syntax_error/1")return Object.assign(to(t.args[0]),...to(t.args[1]));{let e=to(t.args[0]);return e.message+=` (in ${to(t.args[1])})`,e}case"syntax_error/1":return new Jt(43,`Syntax error: ${to(t.args[0])}`);case"existence_error/2":return new Jt(44,`Existence error: ${to(t.args[0])} ${to(t.args[1])} not found`);case"instantiation_error/0":return new Jt(75,"Instantiation error: an argument is variable when an instantiated argument was expected");case"line/1":return{line:to(t.args[0])};case"column/1":return{column:to(t.args[0])};case"found/1":return{found:to(t.args[0])};case"./2":return[to(t.args[0])].concat(to(t.args[1]));case"//2":return`${to(t.args[0])}/${to(t.args[1])}`;default:return t.id}throw`couldn't pretty print because of unsupported node ${t}`}function gme(t){let e;try{e=to(t)}catch(r){throw typeof r=="string"?new Jt(42,`Unknown error: ${t} (note: ${r})`):r}return typeof e.line<"u"&&typeof e.column<"u"&&(e.message+=` at line ${e.line}, column ${e.column}`),e}function Gg(t){return t.id==="null"?null:`${t.toJavaScript()}`}function ndt(t){if(t.id==="null")return null;{let e=t.toJavaScript();if(typeof e!="string")return JSON.stringify(e);try{return JSON.stringify(JSON.parse(e))}catch{return JSON.stringify(e)}}}function Fh(t){return typeof t=="string"?`'${t}'`:"[]"}var dme,NE,mme,hme,hH,gH,f2=Et(()=>{Ge();Ge();Pt();dme=Ze(Kde()),NE=Ze(AH());l2();pme();(0,dme.default)(NE.default);mme=(o=>(o.Dependencies="dependencies",o.DevDependencies="devDependencies",o.PeerDependencies="peerDependencies",o))(mme||{}),hme=["dependencies","devDependencies","peerDependencies"];hH=class{constructor(e,r){let o=1e3*e.workspaces.length;this.session=NE.default.create(o),fme(this.session,e),this.session.consult(":- use_module(library(lists))."),this.session.consult(r)}fetchNextAnswer(){return new Promise(e=>{this.session.answer(r=>{e(r)})})}async*makeQuery(e){let r=this.session.query(e);if(r!==!0)throw gme(r);for(;;){let o=await this.fetchNextAnswer();if(o===null)throw new Jt(79,"Resolution limit exceeded");if(!o)break;if(o.id==="throw")throw gme(o);yield o}}};gH=class t{constructor(e){this.source="";this.project=e;let r=e.configuration.get("constraintsPath");oe.existsSync(r)&&(this.source=oe.readFileSync(r,"utf8"))}static async find(e){return new t(e)}getProjectDatabase(){let e="";for(let r of hme)e+=`dependency_type(${r}). +`;for(let r of this.project.workspacesByCwd.values()){let o=r.relativeCwd;e+=`workspace(${Fh(o)}). +`,e+=`workspace_ident(${Fh(o)}, ${Fh(G.stringifyIdent(r.anchoredLocator))}). +`,e+=`workspace_version(${Fh(o)}, ${Fh(r.manifest.version)}). +`;for(let a of hme)for(let n of r.manifest[a].values())e+=`workspace_has_dependency(${Fh(o)}, ${Fh(G.stringifyIdent(n))}, ${Fh(n.range)}, ${a}). +`}return e+=`workspace(_) :- false. +`,e+=`workspace_ident(_, _) :- false. +`,e+=`workspace_version(_, _) :- false. +`,e+=`workspace_has_dependency(_, _, _, _) :- false. +`,e}getDeclarations(){let e="";return e+=`gen_enforced_dependency(_, _, _, _) :- false. +`,e+=`gen_enforced_field(_, _, _) :- false. +`,e}get fullSource(){return`${this.getProjectDatabase()} +${this.source} +${this.getDeclarations()}`}createSession(){return new hH(this.project,this.fullSource)}async processClassic(){let e=this.createSession();return{enforcedDependencies:await this.genEnforcedDependencies(e),enforcedFields:await this.genEnforcedFields(e)}}async process(){let{enforcedDependencies:e,enforcedFields:r}=await this.processClassic(),o=new Map;for(let{workspace:a,dependencyIdent:n,dependencyRange:u,dependencyType:A}of e){let p=a2([A,G.stringifyIdent(n)]),h=He.getMapWithDefault(o,a.cwd);He.getMapWithDefault(h,p).set(u??void 0,new Set)}for(let{workspace:a,fieldPath:n,fieldValue:u}of r){let A=a2(n),p=He.getMapWithDefault(o,a.cwd);He.getMapWithDefault(p,A).set(JSON.parse(u)??void 0,new Set)}return{manifestUpdates:o,reportedErrors:new Map}}async genEnforcedDependencies(e){let r=[];for await(let o of e.makeQuery("workspace(WorkspaceCwd), dependency_type(DependencyType), gen_enforced_dependency(WorkspaceCwd, DependencyIdent, DependencyRange, DependencyType).")){let a=K.resolve(this.project.cwd,Gg(o.links.WorkspaceCwd)),n=Gg(o.links.DependencyIdent),u=Gg(o.links.DependencyRange),A=Gg(o.links.DependencyType);if(a===null||n===null)throw new Error("Invalid rule");let p=this.project.getWorkspaceByCwd(a),h=G.parseIdent(n);r.push({workspace:p,dependencyIdent:h,dependencyRange:u,dependencyType:A})}return He.sortMap(r,[({dependencyRange:o})=>o!==null?"0":"1",({workspace:o})=>G.stringifyIdent(o.anchoredLocator),({dependencyIdent:o})=>G.stringifyIdent(o)])}async genEnforcedFields(e){let r=[];for await(let o of e.makeQuery("workspace(WorkspaceCwd), gen_enforced_field(WorkspaceCwd, FieldPath, FieldValue).")){let a=K.resolve(this.project.cwd,Gg(o.links.WorkspaceCwd)),n=Gg(o.links.FieldPath),u=ndt(o.links.FieldValue);if(a===null||n===null)throw new Error("Invalid rule");let A=this.project.getWorkspaceByCwd(a);r.push({workspace:A,fieldPath:n,fieldValue:u})}return He.sortMap(r,[({workspace:o})=>G.stringifyIdent(o.anchoredLocator),({fieldPath:o})=>o])}async*query(e){let r=this.createSession();for await(let o of r.makeQuery(e)){let a={};for(let[n,u]of Object.entries(o.links))n!=="_"&&(a[n]=Gg(u));yield a}}}});var Pme=_(Ak=>{"use strict";Object.defineProperty(Ak,"__esModule",{value:!0});function S2(t){let e=[...t.caches],r=e.shift();return r===void 0?Dme():{get(o,a,n={miss:()=>Promise.resolve()}){return r.get(o,a,n).catch(()=>S2({caches:e}).get(o,a,n))},set(o,a){return r.set(o,a).catch(()=>S2({caches:e}).set(o,a))},delete(o){return r.delete(o).catch(()=>S2({caches:e}).delete(o))},clear(){return r.clear().catch(()=>S2({caches:e}).clear())}}}function Dme(){return{get(t,e,r={miss:()=>Promise.resolve()}){return e().then(a=>Promise.all([a,r.miss(a)])).then(([a])=>a)},set(t,e){return Promise.resolve(e)},delete(t){return Promise.resolve()},clear(){return Promise.resolve()}}}Ak.createFallbackableCache=S2;Ak.createNullCache=Dme});var bme=_((MWt,Sme)=>{Sme.exports=Pme()});var xme=_(xH=>{"use strict";Object.defineProperty(xH,"__esModule",{value:!0});function Idt(t={serializable:!0}){let e={};return{get(r,o,a={miss:()=>Promise.resolve()}){let n=JSON.stringify(r);if(n in e)return Promise.resolve(t.serializable?JSON.parse(e[n]):e[n]);let u=o(),A=a&&a.miss||(()=>Promise.resolve());return u.then(p=>A(p)).then(()=>u)},set(r,o){return e[JSON.stringify(r)]=t.serializable?JSON.stringify(o):o,Promise.resolve(o)},delete(r){return delete e[JSON.stringify(r)],Promise.resolve()},clear(){return e={},Promise.resolve()}}}xH.createInMemoryCache=Idt});var Qme=_((UWt,kme)=>{kme.exports=xme()});var Rme=_(eu=>{"use strict";Object.defineProperty(eu,"__esModule",{value:!0});function Bdt(t,e,r){let o={"x-algolia-api-key":r,"x-algolia-application-id":e};return{headers(){return t===kH.WithinHeaders?o:{}},queryParameters(){return t===kH.WithinQueryParameters?o:{}}}}function vdt(t){let e=0,r=()=>(e++,new Promise(o=>{setTimeout(()=>{o(t(r))},Math.min(100*e,1e3))}));return t(r)}function Fme(t,e=(r,o)=>Promise.resolve()){return Object.assign(t,{wait(r){return Fme(t.then(o=>Promise.all([e(o,r),o])).then(o=>o[1]))}})}function Ddt(t){let e=t.length-1;for(e;e>0;e--){let r=Math.floor(Math.random()*(e+1)),o=t[e];t[e]=t[r],t[r]=o}return t}function Pdt(t,e){return e&&Object.keys(e).forEach(r=>{t[r]=e[r](t)}),t}function Sdt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}var bdt="4.22.1",xdt=t=>()=>t.transporter.requester.destroy(),kH={WithinQueryParameters:0,WithinHeaders:1};eu.AuthMode=kH;eu.addMethods=Pdt;eu.createAuth=Bdt;eu.createRetryablePromise=vdt;eu.createWaitablePromise=Fme;eu.destroy=xdt;eu.encode=Sdt;eu.shuffle=Ddt;eu.version=bdt});var b2=_((HWt,Tme)=>{Tme.exports=Rme()});var Nme=_(QH=>{"use strict";Object.defineProperty(QH,"__esModule",{value:!0});var kdt={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};QH.MethodEnum=kdt});var x2=_((jWt,Lme)=>{Lme.exports=Nme()});var Xme=_(Qi=>{"use strict";Object.defineProperty(Qi,"__esModule",{value:!0});var Ome=x2();function FH(t,e){let r=t||{},o=r.data||{};return Object.keys(r).forEach(a=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(a)===-1&&(o[a]=r[a])}),{data:Object.entries(o).length>0?o:void 0,timeout:r.timeout||e,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var k2={Read:1,Write:2,Any:3},YE={Up:1,Down:2,Timeouted:3},Ume=2*60*1e3;function TH(t,e=YE.Up){return{...t,status:e,lastUpdate:Date.now()}}function _me(t){return t.status===YE.Up||Date.now()-t.lastUpdate>Ume}function Hme(t){return t.status===YE.Timeouted&&Date.now()-t.lastUpdate<=Ume}function NH(t){return typeof t=="string"?{protocol:"https",url:t,accept:k2.Any}:{protocol:t.protocol||"https",url:t.url,accept:t.accept||k2.Any}}function Qdt(t,e){return Promise.all(e.map(r=>t.get(r,()=>Promise.resolve(TH(r))))).then(r=>{let o=r.filter(A=>_me(A)),a=r.filter(A=>Hme(A)),n=[...o,...a],u=n.length>0?n.map(A=>NH(A)):e;return{getTimeout(A,p){return(a.length===0&&A===0?1:a.length+3+A)*p},statelessHosts:u}})}var Fdt=({isTimedOut:t,status:e})=>!t&&~~e===0,Rdt=t=>{let e=t.status;return t.isTimedOut||Fdt(t)||~~(e/100)!==2&&~~(e/100)!==4},Tdt=({status:t})=>~~(t/100)===2,Ndt=(t,e)=>Rdt(t)?e.onRetry(t):Tdt(t)?e.onSuccess(t):e.onFail(t);function Mme(t,e,r,o){let a=[],n=Wme(r,o),u=Kme(t,o),A=r.method,p=r.method!==Ome.MethodEnum.Get?{}:{...r.data,...o.data},h={"x-algolia-agent":t.userAgent.value,...t.queryParameters,...p,...o.queryParameters},E=0,I=(v,x)=>{let C=v.pop();if(C===void 0)throw Jme(RH(a));let R={data:n,headers:u,method:A,url:Gme(C,r.path,h),connectTimeout:x(E,t.timeouts.connect),responseTimeout:x(E,o.timeout)},L=z=>{let te={request:R,response:z,host:C,triesLeft:v.length};return a.push(te),te},U={onSuccess:z=>qme(z),onRetry(z){let te=L(z);return z.isTimedOut&&E++,Promise.all([t.logger.info("Retryable failure",LH(te)),t.hostsCache.set(C,TH(C,z.isTimedOut?YE.Timeouted:YE.Down))]).then(()=>I(v,x))},onFail(z){throw L(z),jme(z,RH(a))}};return t.requester.send(R).then(z=>Ndt(z,U))};return Qdt(t.hostsCache,e).then(v=>I([...v.statelessHosts].reverse(),v.getTimeout))}function Ldt(t){let{hostsCache:e,logger:r,requester:o,requestsCache:a,responsesCache:n,timeouts:u,userAgent:A,hosts:p,queryParameters:h,headers:E}=t,I={hostsCache:e,logger:r,requester:o,requestsCache:a,responsesCache:n,timeouts:u,userAgent:A,headers:E,queryParameters:h,hosts:p.map(v=>NH(v)),read(v,x){let C=FH(x,I.timeouts.read),R=()=>Mme(I,I.hosts.filter(z=>(z.accept&k2.Read)!==0),v,C);if((C.cacheable!==void 0?C.cacheable:v.cacheable)!==!0)return R();let U={request:v,mappedRequestOptions:C,transporter:{queryParameters:I.queryParameters,headers:I.headers}};return I.responsesCache.get(U,()=>I.requestsCache.get(U,()=>I.requestsCache.set(U,R()).then(z=>Promise.all([I.requestsCache.delete(U),z]),z=>Promise.all([I.requestsCache.delete(U),Promise.reject(z)])).then(([z,te])=>te)),{miss:z=>I.responsesCache.set(U,z)})},write(v,x){return Mme(I,I.hosts.filter(C=>(C.accept&k2.Write)!==0),v,FH(x,I.timeouts.write))}};return I}function Mdt(t){let e={value:`Algolia for JavaScript (${t})`,add(r){let o=`; ${r.segment}${r.version!==void 0?` (${r.version})`:""}`;return e.value.indexOf(o)===-1&&(e.value=`${e.value}${o}`),e}};return e}function qme(t){try{return JSON.parse(t.content)}catch(e){throw zme(e.message,t)}}function jme({content:t,status:e},r){let o=t;try{o=JSON.parse(t).message}catch{}return Vme(o,e,r)}function Odt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}function Gme(t,e,r){let o=Yme(r),a=`${t.protocol}://${t.url}/${e.charAt(0)==="/"?e.substr(1):e}`;return o.length&&(a+=`?${o}`),a}function Yme(t){let e=r=>Object.prototype.toString.call(r)==="[object Object]"||Object.prototype.toString.call(r)==="[object Array]";return Object.keys(t).map(r=>Odt("%s=%s",r,e(t[r])?JSON.stringify(t[r]):t[r])).join("&")}function Wme(t,e){if(t.method===Ome.MethodEnum.Get||t.data===void 0&&e.data===void 0)return;let r=Array.isArray(t.data)?t.data:{...t.data,...e.data};return JSON.stringify(r)}function Kme(t,e){let r={...t.headers,...e.headers},o={};return Object.keys(r).forEach(a=>{let n=r[a];o[a.toLowerCase()]=n}),o}function RH(t){return t.map(e=>LH(e))}function LH(t){let e=t.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...t,request:{...t.request,headers:{...t.request.headers,...e}}}}function Vme(t,e,r){return{name:"ApiError",message:t,status:e,transporterStackTrace:r}}function zme(t,e){return{name:"DeserializationError",message:t,response:e}}function Jme(t){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:t}}Qi.CallEnum=k2;Qi.HostStatusEnum=YE;Qi.createApiError=Vme;Qi.createDeserializationError=zme;Qi.createMappedRequestOptions=FH;Qi.createRetryError=Jme;Qi.createStatefulHost=TH;Qi.createStatelessHost=NH;Qi.createTransporter=Ldt;Qi.createUserAgent=Mdt;Qi.deserializeFailure=jme;Qi.deserializeSuccess=qme;Qi.isStatefulHostTimeouted=Hme;Qi.isStatefulHostUp=_me;Qi.serializeData=Wme;Qi.serializeHeaders=Kme;Qi.serializeQueryParameters=Yme;Qi.serializeUrl=Gme;Qi.stackFrameWithoutCredentials=LH;Qi.stackTraceWithoutCredentials=RH});var Q2=_((YWt,Zme)=>{Zme.exports=Xme()});var $me=_(Rh=>{"use strict";Object.defineProperty(Rh,"__esModule",{value:!0});var WE=b2(),Udt=Q2(),F2=x2(),_dt=t=>{let e=t.region||"us",r=WE.createAuth(WE.AuthMode.WithinHeaders,t.appId,t.apiKey),o=Udt.createTransporter({hosts:[{url:`analytics.${e}.algolia.com`}],...t,headers:{...r.headers(),"content-type":"application/json",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}}),a=t.appId;return WE.addMethods({appId:a,transporter:o},t.methods)},Hdt=t=>(e,r)=>t.transporter.write({method:F2.MethodEnum.Post,path:"2/abtests",data:e},r),qdt=t=>(e,r)=>t.transporter.write({method:F2.MethodEnum.Delete,path:WE.encode("2/abtests/%s",e)},r),jdt=t=>(e,r)=>t.transporter.read({method:F2.MethodEnum.Get,path:WE.encode("2/abtests/%s",e)},r),Gdt=t=>e=>t.transporter.read({method:F2.MethodEnum.Get,path:"2/abtests"},e),Ydt=t=>(e,r)=>t.transporter.write({method:F2.MethodEnum.Post,path:WE.encode("2/abtests/%s/stop",e)},r);Rh.addABTest=Hdt;Rh.createAnalyticsClient=_dt;Rh.deleteABTest=qdt;Rh.getABTest=jdt;Rh.getABTests=Gdt;Rh.stopABTest=Ydt});var tye=_((KWt,eye)=>{eye.exports=$me()});var nye=_(R2=>{"use strict";Object.defineProperty(R2,"__esModule",{value:!0});var MH=b2(),Wdt=Q2(),rye=x2(),Kdt=t=>{let e=t.region||"us",r=MH.createAuth(MH.AuthMode.WithinHeaders,t.appId,t.apiKey),o=Wdt.createTransporter({hosts:[{url:`personalization.${e}.algolia.com`}],...t,headers:{...r.headers(),"content-type":"application/json",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}});return MH.addMethods({appId:t.appId,transporter:o},t.methods)},Vdt=t=>e=>t.transporter.read({method:rye.MethodEnum.Get,path:"1/strategies/personalization"},e),zdt=t=>(e,r)=>t.transporter.write({method:rye.MethodEnum.Post,path:"1/strategies/personalization",data:e},r);R2.createPersonalizationClient=Kdt;R2.getPersonalizationStrategy=Vdt;R2.setPersonalizationStrategy=zdt});var sye=_((zWt,iye)=>{iye.exports=nye()});var Eye=_(Ft=>{"use strict";Object.defineProperty(Ft,"__esModule",{value:!0});var Gt=b2(),Ma=Q2(),Ir=x2(),Jdt=ve("crypto");function fk(t){let e=r=>t.request(r).then(o=>{if(t.batch!==void 0&&t.batch(o.hits),!t.shouldStop(o))return o.cursor?e({cursor:o.cursor}):e({page:(r.page||0)+1})});return e({})}var Xdt=t=>{let e=t.appId,r=Gt.createAuth(t.authMode!==void 0?t.authMode:Gt.AuthMode.WithinHeaders,e,t.apiKey),o=Ma.createTransporter({hosts:[{url:`${e}-dsn.algolia.net`,accept:Ma.CallEnum.Read},{url:`${e}.algolia.net`,accept:Ma.CallEnum.Write}].concat(Gt.shuffle([{url:`${e}-1.algolianet.com`},{url:`${e}-2.algolianet.com`},{url:`${e}-3.algolianet.com`}])),...t,headers:{...r.headers(),"content-type":"application/x-www-form-urlencoded",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}}),a={transporter:o,appId:e,addAlgoliaAgent(n,u){o.userAgent.add({segment:n,version:u})},clearCache(){return Promise.all([o.requestsCache.clear(),o.responsesCache.clear()]).then(()=>{})}};return Gt.addMethods(a,t.methods)};function oye(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function aye(){return{name:"ObjectNotFoundError",message:"Object not found."}}function lye(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Zdt=t=>(e,r)=>{let{queryParameters:o,...a}=r||{},n={acl:e,...o!==void 0?{queryParameters:o}:{}},u=(A,p)=>Gt.createRetryablePromise(h=>T2(t)(A.key,p).catch(E=>{if(E.status!==404)throw E;return h()}));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:"1/keys",data:n},a),u)},$dt=t=>(e,r,o)=>{let a=Ma.createMappedRequestOptions(o);return a.queryParameters["X-Algolia-User-ID"]=e,t.transporter.write({method:Ir.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:r}},a)},emt=t=>(e,r,o)=>t.transporter.write({method:Ir.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:e,cluster:r}},o),tmt=t=>(e,r)=>Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!0,requests:{action:"addEntry",body:[]}}},r),(o,a)=>KE(t)(o.taskID,a)),pk=t=>(e,r,o)=>{let a=(n,u)=>N2(t)(e,{methods:{waitTask:es}}).waitTask(n.taskID,u);return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/operation",e),data:{operation:"copy",destination:r}},o),a)},rmt=t=>(e,r,o)=>pk(t)(e,r,{...o,scope:[gk.Rules]}),nmt=t=>(e,r,o)=>pk(t)(e,r,{...o,scope:[gk.Settings]}),imt=t=>(e,r,o)=>pk(t)(e,r,{...o,scope:[gk.Synonyms]}),smt=t=>(e,r)=>e.method===Ir.MethodEnum.Get?t.transporter.read(e,r):t.transporter.write(e,r),omt=t=>(e,r)=>{let o=(a,n)=>Gt.createRetryablePromise(u=>T2(t)(e,n).then(u).catch(A=>{if(A.status!==404)throw A}));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Delete,path:Gt.encode("1/keys/%s",e)},r),o)},amt=t=>(e,r,o)=>{let a=r.map(n=>({action:"deleteEntry",body:{objectID:n}}));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!1,requests:a}},o),(n,u)=>KE(t)(n.taskID,u))},lmt=()=>(t,e)=>{let r=Ma.serializeQueryParameters(e),o=Jdt.createHmac("sha256",t).update(r).digest("hex");return Buffer.from(o+r).toString("base64")},T2=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/keys/%s",e)},r),cye=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/task/%s",e.toString())},r),cmt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"/1/dictionaries/*/settings"},e),umt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"1/logs"},e),Amt=()=>t=>{let e=Buffer.from(t,"base64").toString("ascii"),r=/validUntil=(\d+)/,o=e.match(r);if(o===null)throw lye();return parseInt(o[1],10)-Math.round(new Date().getTime()/1e3)},fmt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"1/clusters/mapping/top"},e),pmt=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/clusters/mapping/%s",e)},r),hmt=t=>e=>{let{retrieveMappings:r,...o}=e||{};return r===!0&&(o.getClusters=!0),t.transporter.read({method:Ir.MethodEnum.Get,path:"1/clusters/mapping/pending"},o)},N2=t=>(e,r={})=>{let o={transporter:t.transporter,appId:t.appId,indexName:e};return Gt.addMethods(o,r.methods)},gmt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"1/keys"},e),dmt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"1/clusters"},e),mmt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"1/indexes"},e),ymt=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:"1/clusters/mapping"},e),Emt=t=>(e,r,o)=>{let a=(n,u)=>N2(t)(e,{methods:{waitTask:es}}).waitTask(n.taskID,u);return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/operation",e),data:{operation:"move",destination:r}},o),a)},Cmt=t=>(e,r)=>{let o=(a,n)=>Promise.all(Object.keys(a.taskID).map(u=>N2(t)(u,{methods:{waitTask:es}}).waitTask(a.taskID[u],n)));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:e}},r),o)},wmt=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:e}},r),Imt=t=>(e,r)=>{let o=e.map(a=>({...a,params:Ma.serializeQueryParameters(a.params||{})}));return t.transporter.read({method:Ir.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:o},cacheable:!0},r)},Bmt=t=>(e,r)=>Promise.all(e.map(o=>{let{facetName:a,facetQuery:n,...u}=o.params;return N2(t)(o.indexName,{methods:{searchForFacetValues:dye}}).searchForFacetValues(a,n,{...r,...u})})),vmt=t=>(e,r)=>{let o=Ma.createMappedRequestOptions(r);return o.queryParameters["X-Algolia-User-ID"]=e,t.transporter.write({method:Ir.MethodEnum.Delete,path:"1/clusters/mapping"},o)},Dmt=t=>(e,r,o)=>{let a=r.map(n=>({action:"addEntry",body:n}));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!0,requests:a}},o),(n,u)=>KE(t)(n.taskID,u))},Pmt=t=>(e,r)=>{let o=(a,n)=>Gt.createRetryablePromise(u=>T2(t)(e,n).catch(A=>{if(A.status!==404)throw A;return u()}));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/keys/%s/restore",e)},r),o)},Smt=t=>(e,r,o)=>{let a=r.map(n=>({action:"addEntry",body:n}));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("/1/dictionaries/%s/batch",e),data:{clearExistingDictionaryEntries:!1,requests:a}},o),(n,u)=>KE(t)(n.taskID,u))},bmt=t=>(e,r,o)=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("/1/dictionaries/%s/search",e),data:{query:r},cacheable:!0},o),xmt=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:e}},r),kmt=t=>(e,r)=>Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Put,path:"/1/dictionaries/*/settings",data:e},r),(o,a)=>KE(t)(o.taskID,a)),Qmt=t=>(e,r)=>{let o=Object.assign({},r),{queryParameters:a,...n}=r||{},u=a?{queryParameters:a}:{},A=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],p=E=>Object.keys(o).filter(I=>A.indexOf(I)!==-1).every(I=>{if(Array.isArray(E[I])&&Array.isArray(o[I])){let v=E[I];return v.length===o[I].length&&v.every((x,C)=>x===o[I][C])}else return E[I]===o[I]}),h=(E,I)=>Gt.createRetryablePromise(v=>T2(t)(e,I).then(x=>p(x)?Promise.resolve():v()));return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Put,path:Gt.encode("1/keys/%s",e),data:u},n),h)},KE=t=>(e,r)=>Gt.createRetryablePromise(o=>cye(t)(e,r).then(a=>a.status!=="published"?o():void 0)),uye=t=>(e,r)=>{let o=(a,n)=>es(t)(a.taskID,n);return Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/batch",t.indexName),data:{requests:e}},r),o)},Fmt=t=>e=>fk({shouldStop:r=>r.cursor===void 0,...e,request:r=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/browse",t.indexName),data:r},e)}),Rmt=t=>e=>{let r={hitsPerPage:1e3,...e};return fk({shouldStop:o=>o.hits.length<r.hitsPerPage,...r,request(o){return mye(t)("",{...r,...o}).then(a=>({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},Tmt=t=>e=>{let r={hitsPerPage:1e3,...e};return fk({shouldStop:o=>o.hits.length<r.hitsPerPage,...r,request(o){return yye(t)("",{...r,...o}).then(a=>({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},hk=t=>(e,r,o)=>{let{batchSize:a,...n}=o||{},u={taskIDs:[],objectIDs:[]},A=(p=0)=>{let h=[],E;for(E=p;E<e.length&&(h.push(e[E]),h.length!==(a||1e3));E++);return h.length===0?Promise.resolve(u):uye(t)(h.map(I=>({action:r,body:I})),n).then(I=>(u.objectIDs=u.objectIDs.concat(I.objectIDs),u.taskIDs.push(I.taskID),E++,A(E)))};return Gt.createWaitablePromise(A(),(p,h)=>Promise.all(p.taskIDs.map(E=>es(t)(E,h))))},Nmt=t=>e=>Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/clear",t.indexName)},e),(r,o)=>es(t)(r.taskID,o)),Lmt=t=>e=>{let{forwardToReplicas:r,...o}=e||{},a=Ma.createMappedRequestOptions(o);return r&&(a.queryParameters.forwardToReplicas=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/rules/clear",t.indexName)},a),(n,u)=>es(t)(n.taskID,u))},Mmt=t=>e=>{let{forwardToReplicas:r,...o}=e||{},a=Ma.createMappedRequestOptions(o);return r&&(a.queryParameters.forwardToReplicas=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/synonyms/clear",t.indexName)},a),(n,u)=>es(t)(n.taskID,u))},Omt=t=>(e,r)=>Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/deleteByQuery",t.indexName),data:e},r),(o,a)=>es(t)(o.taskID,a)),Umt=t=>e=>Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Delete,path:Gt.encode("1/indexes/%s",t.indexName)},e),(r,o)=>es(t)(r.taskID,o)),_mt=t=>(e,r)=>Gt.createWaitablePromise(Aye(t)([e],r).then(o=>({taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),Aye=t=>(e,r)=>{let o=e.map(a=>({objectID:a}));return hk(t)(o,Wg.DeleteObject,r)},Hmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Ma.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Delete,path:Gt.encode("1/indexes/%s/rules/%s",t.indexName,e)},n),(u,A)=>es(t)(u.taskID,A))},qmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Ma.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Delete,path:Gt.encode("1/indexes/%s/synonyms/%s",t.indexName,e)},n),(u,A)=>es(t)(u.taskID,A))},jmt=t=>e=>fye(t)(e).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),Gmt=t=>(e,r,o)=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("1/answers/%s/prediction",t.indexName),data:{query:e,queryLanguages:r},cacheable:!0},o),Ymt=t=>(e,r)=>{let{query:o,paginate:a,...n}=r||{},u=0,A=()=>gye(t)(o||"",{...n,page:u}).then(p=>{for(let[h,E]of Object.entries(p.hits))if(e(E))return{object:E,position:parseInt(h,10),page:u};if(u++,a===!1||u>=p.nbPages)throw aye();return A()});return A()},Wmt=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/indexes/%s/%s",t.indexName,e)},r),Kmt=()=>(t,e)=>{for(let[r,o]of Object.entries(t.hits))if(o.objectID===e)return parseInt(r,10);return-1},Vmt=t=>(e,r)=>{let{attributesToRetrieve:o,...a}=r||{},n=e.map(u=>({indexName:t.indexName,objectID:u,...o?{attributesToRetrieve:o}:{}}));return t.transporter.read({method:Ir.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:n}},a)},zmt=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/indexes/%s/rules/%s",t.indexName,e)},r),fye=t=>e=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/indexes/%s/settings",t.indexName),data:{getVersion:2}},e),Jmt=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/indexes/%s/synonyms/%s",t.indexName,e)},r),pye=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Get,path:Gt.encode("1/indexes/%s/task/%s",t.indexName,e.toString())},r),Xmt=t=>(e,r)=>Gt.createWaitablePromise(hye(t)([e],r).then(o=>({objectID:o.objectIDs[0],taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),hye=t=>(e,r)=>{let{createIfNotExists:o,...a}=r||{},n=o?Wg.PartialUpdateObject:Wg.PartialUpdateObjectNoCreate;return hk(t)(e,n,a)},Zmt=t=>(e,r)=>{let{safe:o,autoGenerateObjectIDIfNotExist:a,batchSize:n,...u}=r||{},A=(C,R,L,U)=>Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/operation",C),data:{operation:L,destination:R}},U),(z,te)=>es(t)(z.taskID,te)),p=Math.random().toString(36).substring(7),h=`${t.indexName}_tmp_${p}`,E=OH({appId:t.appId,transporter:t.transporter,indexName:h}),I=[],v=A(t.indexName,h,"copy",{...u,scope:["settings","synonyms","rules"]});I.push(v);let x=(o?v.wait(u):v).then(()=>{let C=E(e,{...u,autoGenerateObjectIDIfNotExist:a,batchSize:n});return I.push(C),o?C.wait(u):C}).then(()=>{let C=A(h,t.indexName,"move",u);return I.push(C),o?C.wait(u):C}).then(()=>Promise.all(I)).then(([C,R,L])=>({objectIDs:R.objectIDs,taskIDs:[C.taskID,...R.taskIDs,L.taskID]}));return Gt.createWaitablePromise(x,(C,R)=>Promise.all(I.map(L=>L.wait(R))))},$mt=t=>(e,r)=>UH(t)(e,{...r,clearExistingRules:!0}),eyt=t=>(e,r)=>_H(t)(e,{...r,clearExistingSynonyms:!0}),tyt=t=>(e,r)=>Gt.createWaitablePromise(OH(t)([e],r).then(o=>({objectID:o.objectIDs[0],taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),OH=t=>(e,r)=>{let{autoGenerateObjectIDIfNotExist:o,...a}=r||{},n=o?Wg.AddObject:Wg.UpdateObject;if(n===Wg.UpdateObject){for(let u of e)if(u.objectID===void 0)return Gt.createWaitablePromise(Promise.reject(oye()))}return hk(t)(e,n,a)},ryt=t=>(e,r)=>UH(t)([e],r),UH=t=>(e,r)=>{let{forwardToReplicas:o,clearExistingRules:a,...n}=r||{},u=Ma.createMappedRequestOptions(n);return o&&(u.queryParameters.forwardToReplicas=1),a&&(u.queryParameters.clearExistingRules=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/rules/batch",t.indexName),data:e},u),(A,p)=>es(t)(A.taskID,p))},nyt=t=>(e,r)=>_H(t)([e],r),_H=t=>(e,r)=>{let{forwardToReplicas:o,clearExistingSynonyms:a,replaceExistingSynonyms:n,...u}=r||{},A=Ma.createMappedRequestOptions(u);return o&&(A.queryParameters.forwardToReplicas=1),(n||a)&&(A.queryParameters.replaceExistingSynonyms=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/synonyms/batch",t.indexName),data:e},A),(p,h)=>es(t)(p.taskID,h))},gye=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/query",t.indexName),data:{query:e},cacheable:!0},r),dye=t=>(e,r,o)=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/facets/%s/query",t.indexName,e),data:{facetQuery:r},cacheable:!0},o),mye=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/rules/search",t.indexName),data:{query:e}},r),yye=t=>(e,r)=>t.transporter.read({method:Ir.MethodEnum.Post,path:Gt.encode("1/indexes/%s/synonyms/search",t.indexName),data:{query:e}},r),iyt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Ma.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Gt.createWaitablePromise(t.transporter.write({method:Ir.MethodEnum.Put,path:Gt.encode("1/indexes/%s/settings",t.indexName),data:e},n),(u,A)=>es(t)(u.taskID,A))},es=t=>(e,r)=>Gt.createRetryablePromise(o=>pye(t)(e,r).then(a=>a.status!=="published"?o():void 0)),syt={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",Inference:"inference",ListIndexes:"listIndexes",Logs:"logs",Personalization:"personalization",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},Wg={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject",DeleteIndex:"delete",ClearIndex:"clear"},gk={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},oyt={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},ayt={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};Ft.ApiKeyACLEnum=syt;Ft.BatchActionEnum=Wg;Ft.ScopeEnum=gk;Ft.StrategyEnum=oyt;Ft.SynonymEnum=ayt;Ft.addApiKey=Zdt;Ft.assignUserID=$dt;Ft.assignUserIDs=emt;Ft.batch=uye;Ft.browseObjects=Fmt;Ft.browseRules=Rmt;Ft.browseSynonyms=Tmt;Ft.chunkedBatch=hk;Ft.clearDictionaryEntries=tmt;Ft.clearObjects=Nmt;Ft.clearRules=Lmt;Ft.clearSynonyms=Mmt;Ft.copyIndex=pk;Ft.copyRules=rmt;Ft.copySettings=nmt;Ft.copySynonyms=imt;Ft.createBrowsablePromise=fk;Ft.createMissingObjectIDError=oye;Ft.createObjectNotFoundError=aye;Ft.createSearchClient=Xdt;Ft.createValidUntilNotFoundError=lye;Ft.customRequest=smt;Ft.deleteApiKey=omt;Ft.deleteBy=Omt;Ft.deleteDictionaryEntries=amt;Ft.deleteIndex=Umt;Ft.deleteObject=_mt;Ft.deleteObjects=Aye;Ft.deleteRule=Hmt;Ft.deleteSynonym=qmt;Ft.exists=jmt;Ft.findAnswers=Gmt;Ft.findObject=Ymt;Ft.generateSecuredApiKey=lmt;Ft.getApiKey=T2;Ft.getAppTask=cye;Ft.getDictionarySettings=cmt;Ft.getLogs=umt;Ft.getObject=Wmt;Ft.getObjectPosition=Kmt;Ft.getObjects=Vmt;Ft.getRule=zmt;Ft.getSecuredApiKeyRemainingValidity=Amt;Ft.getSettings=fye;Ft.getSynonym=Jmt;Ft.getTask=pye;Ft.getTopUserIDs=fmt;Ft.getUserID=pmt;Ft.hasPendingMappings=hmt;Ft.initIndex=N2;Ft.listApiKeys=gmt;Ft.listClusters=dmt;Ft.listIndices=mmt;Ft.listUserIDs=ymt;Ft.moveIndex=Emt;Ft.multipleBatch=Cmt;Ft.multipleGetObjects=wmt;Ft.multipleQueries=Imt;Ft.multipleSearchForFacetValues=Bmt;Ft.partialUpdateObject=Xmt;Ft.partialUpdateObjects=hye;Ft.removeUserID=vmt;Ft.replaceAllObjects=Zmt;Ft.replaceAllRules=$mt;Ft.replaceAllSynonyms=eyt;Ft.replaceDictionaryEntries=Dmt;Ft.restoreApiKey=Pmt;Ft.saveDictionaryEntries=Smt;Ft.saveObject=tyt;Ft.saveObjects=OH;Ft.saveRule=ryt;Ft.saveRules=UH;Ft.saveSynonym=nyt;Ft.saveSynonyms=_H;Ft.search=gye;Ft.searchDictionaryEntries=bmt;Ft.searchForFacetValues=dye;Ft.searchRules=mye;Ft.searchSynonyms=yye;Ft.searchUserIDs=xmt;Ft.setDictionarySettings=kmt;Ft.setSettings=iyt;Ft.updateApiKey=Qmt;Ft.waitAppTask=KE;Ft.waitTask=es});var wye=_((XWt,Cye)=>{Cye.exports=Eye()});var Iye=_(dk=>{"use strict";Object.defineProperty(dk,"__esModule",{value:!0});function lyt(){return{debug(t,e){return Promise.resolve()},info(t,e){return Promise.resolve()},error(t,e){return Promise.resolve()}}}var cyt={Debug:1,Info:2,Error:3};dk.LogLevelEnum=cyt;dk.createNullLogger=lyt});var vye=_(($Wt,Bye)=>{Bye.exports=Iye()});var bye=_(HH=>{"use strict";Object.defineProperty(HH,"__esModule",{value:!0});var Dye=ve("http"),Pye=ve("https"),uyt=ve("url"),Sye={keepAlive:!0},Ayt=new Dye.Agent(Sye),fyt=new Pye.Agent(Sye);function pyt({agent:t,httpAgent:e,httpsAgent:r,requesterOptions:o={}}={}){let a=e||t||Ayt,n=r||t||fyt;return{send(u){return new Promise(A=>{let p=uyt.parse(u.url),h=p.query===null?p.pathname:`${p.pathname}?${p.query}`,E={...o,agent:p.protocol==="https:"?n:a,hostname:p.hostname,path:h,method:u.method,headers:{...o&&o.headers?o.headers:{},...u.headers},...p.port!==void 0?{port:p.port||""}:{}},I=(p.protocol==="https:"?Pye:Dye).request(E,R=>{let L=[];R.on("data",U=>{L=L.concat(U)}),R.on("end",()=>{clearTimeout(x),clearTimeout(C),A({status:R.statusCode||0,content:Buffer.concat(L).toString(),isTimedOut:!1})})}),v=(R,L)=>setTimeout(()=>{I.abort(),A({status:0,content:L,isTimedOut:!0})},R*1e3),x=v(u.connectTimeout,"Connection timeout"),C;I.on("error",R=>{clearTimeout(x),clearTimeout(C),A({status:0,content:R.message,isTimedOut:!1})}),I.once("response",()=>{clearTimeout(x),C=v(u.responseTimeout,"Socket timeout")}),u.data!==void 0&&I.write(u.data),I.end()})},destroy(){return a.destroy(),n.destroy(),Promise.resolve()}}}HH.createNodeHttpRequester=pyt});var kye=_((tKt,xye)=>{xye.exports=bye()});var Tye=_((rKt,Rye)=>{"use strict";var Qye=bme(),hyt=Qme(),VE=tye(),jH=b2(),qH=sye(),_t=wye(),gyt=vye(),dyt=kye(),myt=Q2();function Fye(t,e,r){let o={appId:t,apiKey:e,timeouts:{connect:2,read:5,write:30},requester:dyt.createNodeHttpRequester(),logger:gyt.createNullLogger(),responsesCache:Qye.createNullCache(),requestsCache:Qye.createNullCache(),hostsCache:hyt.createInMemoryCache(),userAgent:myt.createUserAgent(jH.version).add({segment:"Node.js",version:process.versions.node})},a={...o,...r},n=()=>u=>qH.createPersonalizationClient({...o,...u,methods:{getPersonalizationStrategy:qH.getPersonalizationStrategy,setPersonalizationStrategy:qH.setPersonalizationStrategy}});return _t.createSearchClient({...a,methods:{search:_t.multipleQueries,searchForFacetValues:_t.multipleSearchForFacetValues,multipleBatch:_t.multipleBatch,multipleGetObjects:_t.multipleGetObjects,multipleQueries:_t.multipleQueries,copyIndex:_t.copyIndex,copySettings:_t.copySettings,copyRules:_t.copyRules,copySynonyms:_t.copySynonyms,moveIndex:_t.moveIndex,listIndices:_t.listIndices,getLogs:_t.getLogs,listClusters:_t.listClusters,multipleSearchForFacetValues:_t.multipleSearchForFacetValues,getApiKey:_t.getApiKey,addApiKey:_t.addApiKey,listApiKeys:_t.listApiKeys,updateApiKey:_t.updateApiKey,deleteApiKey:_t.deleteApiKey,restoreApiKey:_t.restoreApiKey,assignUserID:_t.assignUserID,assignUserIDs:_t.assignUserIDs,getUserID:_t.getUserID,searchUserIDs:_t.searchUserIDs,listUserIDs:_t.listUserIDs,getTopUserIDs:_t.getTopUserIDs,removeUserID:_t.removeUserID,hasPendingMappings:_t.hasPendingMappings,generateSecuredApiKey:_t.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:_t.getSecuredApiKeyRemainingValidity,destroy:jH.destroy,clearDictionaryEntries:_t.clearDictionaryEntries,deleteDictionaryEntries:_t.deleteDictionaryEntries,getDictionarySettings:_t.getDictionarySettings,getAppTask:_t.getAppTask,replaceDictionaryEntries:_t.replaceDictionaryEntries,saveDictionaryEntries:_t.saveDictionaryEntries,searchDictionaryEntries:_t.searchDictionaryEntries,setDictionarySettings:_t.setDictionarySettings,waitAppTask:_t.waitAppTask,customRequest:_t.customRequest,initIndex:u=>A=>_t.initIndex(u)(A,{methods:{batch:_t.batch,delete:_t.deleteIndex,findAnswers:_t.findAnswers,getObject:_t.getObject,getObjects:_t.getObjects,saveObject:_t.saveObject,saveObjects:_t.saveObjects,search:_t.search,searchForFacetValues:_t.searchForFacetValues,waitTask:_t.waitTask,setSettings:_t.setSettings,getSettings:_t.getSettings,partialUpdateObject:_t.partialUpdateObject,partialUpdateObjects:_t.partialUpdateObjects,deleteObject:_t.deleteObject,deleteObjects:_t.deleteObjects,deleteBy:_t.deleteBy,clearObjects:_t.clearObjects,browseObjects:_t.browseObjects,getObjectPosition:_t.getObjectPosition,findObject:_t.findObject,exists:_t.exists,saveSynonym:_t.saveSynonym,saveSynonyms:_t.saveSynonyms,getSynonym:_t.getSynonym,searchSynonyms:_t.searchSynonyms,browseSynonyms:_t.browseSynonyms,deleteSynonym:_t.deleteSynonym,clearSynonyms:_t.clearSynonyms,replaceAllObjects:_t.replaceAllObjects,replaceAllSynonyms:_t.replaceAllSynonyms,searchRules:_t.searchRules,getRule:_t.getRule,deleteRule:_t.deleteRule,saveRule:_t.saveRule,saveRules:_t.saveRules,replaceAllRules:_t.replaceAllRules,browseRules:_t.browseRules,clearRules:_t.clearRules}}),initAnalytics:()=>u=>VE.createAnalyticsClient({...o,...u,methods:{addABTest:VE.addABTest,getABTest:VE.getABTest,getABTests:VE.getABTests,stopABTest:VE.stopABTest,deleteABTest:VE.deleteABTest}}),initPersonalization:n,initRecommendation:()=>u=>(a.logger.info("The `initRecommendation` method is deprecated. Use `initPersonalization` instead."),n()(u))}})}Fye.version=jH.version;Rye.exports=Fye});var YH=_((nKt,GH)=>{var Nye=Tye();GH.exports=Nye;GH.exports.default=Nye});var VH=_((sKt,Oye)=>{"use strict";var Mye=Object.getOwnPropertySymbols,Eyt=Object.prototype.hasOwnProperty,Cyt=Object.prototype.propertyIsEnumerable;function wyt(t){if(t==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function Iyt(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de",Object.getOwnPropertyNames(t)[0]==="5")return!1;for(var e={},r=0;r<10;r++)e["_"+String.fromCharCode(r)]=r;var o=Object.getOwnPropertyNames(e).map(function(n){return e[n]});if(o.join("")!=="0123456789")return!1;var a={};return"abcdefghijklmnopqrst".split("").forEach(function(n){a[n]=n}),Object.keys(Object.assign({},a)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}Oye.exports=Iyt()?Object.assign:function(t,e){for(var r,o=wyt(t),a,n=1;n<arguments.length;n++){r=Object(arguments[n]);for(var u in r)Eyt.call(r,u)&&(o[u]=r[u]);if(Mye){a=Mye(r);for(var A=0;A<a.length;A++)Cyt.call(r,a[A])&&(o[a[A]]=r[a[A]])}}return o}});var Jye=_(Nn=>{"use strict";var $H=VH(),tu=typeof Symbol=="function"&&Symbol.for,L2=tu?Symbol.for("react.element"):60103,Byt=tu?Symbol.for("react.portal"):60106,vyt=tu?Symbol.for("react.fragment"):60107,Dyt=tu?Symbol.for("react.strict_mode"):60108,Pyt=tu?Symbol.for("react.profiler"):60114,Syt=tu?Symbol.for("react.provider"):60109,byt=tu?Symbol.for("react.context"):60110,xyt=tu?Symbol.for("react.forward_ref"):60112,kyt=tu?Symbol.for("react.suspense"):60113,Qyt=tu?Symbol.for("react.memo"):60115,Fyt=tu?Symbol.for("react.lazy"):60116,Uye=typeof Symbol=="function"&&Symbol.iterator;function M2(t){for(var e="https://reactjs.org/docs/error-decoder.html?invariant="+t,r=1;r<arguments.length;r++)e+="&args[]="+encodeURIComponent(arguments[r]);return"Minified React error #"+t+"; visit "+e+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var _ye={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Hye={};function zE(t,e,r){this.props=t,this.context=e,this.refs=Hye,this.updater=r||_ye}zE.prototype.isReactComponent={};zE.prototype.setState=function(t,e){if(typeof t!="object"&&typeof t!="function"&&t!=null)throw Error(M2(85));this.updater.enqueueSetState(this,t,e,"setState")};zE.prototype.forceUpdate=function(t){this.updater.enqueueForceUpdate(this,t,"forceUpdate")};function qye(){}qye.prototype=zE.prototype;function e6(t,e,r){this.props=t,this.context=e,this.refs=Hye,this.updater=r||_ye}var t6=e6.prototype=new qye;t6.constructor=e6;$H(t6,zE.prototype);t6.isPureReactComponent=!0;var r6={current:null},jye=Object.prototype.hasOwnProperty,Gye={key:!0,ref:!0,__self:!0,__source:!0};function Yye(t,e,r){var o,a={},n=null,u=null;if(e!=null)for(o in e.ref!==void 0&&(u=e.ref),e.key!==void 0&&(n=""+e.key),e)jye.call(e,o)&&!Gye.hasOwnProperty(o)&&(a[o]=e[o]);var A=arguments.length-2;if(A===1)a.children=r;else if(1<A){for(var p=Array(A),h=0;h<A;h++)p[h]=arguments[h+2];a.children=p}if(t&&t.defaultProps)for(o in A=t.defaultProps,A)a[o]===void 0&&(a[o]=A[o]);return{$$typeof:L2,type:t,key:n,ref:u,props:a,_owner:r6.current}}function Ryt(t,e){return{$$typeof:L2,type:t.type,key:e,ref:t.ref,props:t.props,_owner:t._owner}}function n6(t){return typeof t=="object"&&t!==null&&t.$$typeof===L2}function Tyt(t){var e={"=":"=0",":":"=2"};return"$"+(""+t).replace(/[=:]/g,function(r){return e[r]})}var Wye=/\/+/g,mk=[];function Kye(t,e,r,o){if(mk.length){var a=mk.pop();return a.result=t,a.keyPrefix=e,a.func=r,a.context=o,a.count=0,a}return{result:t,keyPrefix:e,func:r,context:o,count:0}}function Vye(t){t.result=null,t.keyPrefix=null,t.func=null,t.context=null,t.count=0,10>mk.length&&mk.push(t)}function JH(t,e,r,o){var a=typeof t;(a==="undefined"||a==="boolean")&&(t=null);var n=!1;if(t===null)n=!0;else switch(a){case"string":case"number":n=!0;break;case"object":switch(t.$$typeof){case L2:case Byt:n=!0}}if(n)return r(o,t,e===""?"."+zH(t,0):e),1;if(n=0,e=e===""?".":e+":",Array.isArray(t))for(var u=0;u<t.length;u++){a=t[u];var A=e+zH(a,u);n+=JH(a,A,r,o)}else if(t===null||typeof t!="object"?A=null:(A=Uye&&t[Uye]||t["@@iterator"],A=typeof A=="function"?A:null),typeof A=="function")for(t=A.call(t),u=0;!(a=t.next()).done;)a=a.value,A=e+zH(a,u++),n+=JH(a,A,r,o);else if(a==="object")throw r=""+t,Error(M2(31,r==="[object Object]"?"object with keys {"+Object.keys(t).join(", ")+"}":r,""));return n}function XH(t,e,r){return t==null?0:JH(t,"",e,r)}function zH(t,e){return typeof t=="object"&&t!==null&&t.key!=null?Tyt(t.key):e.toString(36)}function Nyt(t,e){t.func.call(t.context,e,t.count++)}function Lyt(t,e,r){var o=t.result,a=t.keyPrefix;t=t.func.call(t.context,e,t.count++),Array.isArray(t)?ZH(t,o,r,function(n){return n}):t!=null&&(n6(t)&&(t=Ryt(t,a+(!t.key||e&&e.key===t.key?"":(""+t.key).replace(Wye,"$&/")+"/")+r)),o.push(t))}function ZH(t,e,r,o,a){var n="";r!=null&&(n=(""+r).replace(Wye,"$&/")+"/"),e=Kye(e,n,o,a),XH(t,Lyt,e),Vye(e)}var zye={current:null};function Kf(){var t=zye.current;if(t===null)throw Error(M2(321));return t}var Myt={ReactCurrentDispatcher:zye,ReactCurrentBatchConfig:{suspense:null},ReactCurrentOwner:r6,IsSomeRendererActing:{current:!1},assign:$H};Nn.Children={map:function(t,e,r){if(t==null)return t;var o=[];return ZH(t,o,null,e,r),o},forEach:function(t,e,r){if(t==null)return t;e=Kye(null,null,e,r),XH(t,Nyt,e),Vye(e)},count:function(t){return XH(t,function(){return null},null)},toArray:function(t){var e=[];return ZH(t,e,null,function(r){return r}),e},only:function(t){if(!n6(t))throw Error(M2(143));return t}};Nn.Component=zE;Nn.Fragment=vyt;Nn.Profiler=Pyt;Nn.PureComponent=e6;Nn.StrictMode=Dyt;Nn.Suspense=kyt;Nn.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Myt;Nn.cloneElement=function(t,e,r){if(t==null)throw Error(M2(267,t));var o=$H({},t.props),a=t.key,n=t.ref,u=t._owner;if(e!=null){if(e.ref!==void 0&&(n=e.ref,u=r6.current),e.key!==void 0&&(a=""+e.key),t.type&&t.type.defaultProps)var A=t.type.defaultProps;for(p in e)jye.call(e,p)&&!Gye.hasOwnProperty(p)&&(o[p]=e[p]===void 0&&A!==void 0?A[p]:e[p])}var p=arguments.length-2;if(p===1)o.children=r;else if(1<p){A=Array(p);for(var h=0;h<p;h++)A[h]=arguments[h+2];o.children=A}return{$$typeof:L2,type:t.type,key:a,ref:n,props:o,_owner:u}};Nn.createContext=function(t,e){return e===void 0&&(e=null),t={$$typeof:byt,_calculateChangedBits:e,_currentValue:t,_currentValue2:t,_threadCount:0,Provider:null,Consumer:null},t.Provider={$$typeof:Syt,_context:t},t.Consumer=t};Nn.createElement=Yye;Nn.createFactory=function(t){var e=Yye.bind(null,t);return e.type=t,e};Nn.createRef=function(){return{current:null}};Nn.forwardRef=function(t){return{$$typeof:xyt,render:t}};Nn.isValidElement=n6;Nn.lazy=function(t){return{$$typeof:Fyt,_ctor:t,_status:-1,_result:null}};Nn.memo=function(t,e){return{$$typeof:Qyt,type:t,compare:e===void 0?null:e}};Nn.useCallback=function(t,e){return Kf().useCallback(t,e)};Nn.useContext=function(t,e){return Kf().useContext(t,e)};Nn.useDebugValue=function(){};Nn.useEffect=function(t,e){return Kf().useEffect(t,e)};Nn.useImperativeHandle=function(t,e,r){return Kf().useImperativeHandle(t,e,r)};Nn.useLayoutEffect=function(t,e){return Kf().useLayoutEffect(t,e)};Nn.useMemo=function(t,e){return Kf().useMemo(t,e)};Nn.useReducer=function(t,e,r){return Kf().useReducer(t,e,r)};Nn.useRef=function(t){return Kf().useRef(t)};Nn.useState=function(t){return Kf().useState(t)};Nn.version="16.13.1"});var an=_((aKt,Xye)=>{"use strict";Xye.exports=Jye()});var s6=_((lKt,i6)=>{"use strict";var fn=i6.exports;i6.exports.default=fn;var Ln="\x1B[",O2="\x1B]",JE="\x07",yk=";",Zye=process.env.TERM_PROGRAM==="Apple_Terminal";fn.cursorTo=(t,e)=>{if(typeof t!="number")throw new TypeError("The `x` argument is required");return typeof e!="number"?Ln+(t+1)+"G":Ln+(e+1)+";"+(t+1)+"H"};fn.cursorMove=(t,e)=>{if(typeof t!="number")throw new TypeError("The `x` argument is required");let r="";return t<0?r+=Ln+-t+"D":t>0&&(r+=Ln+t+"C"),e<0?r+=Ln+-e+"A":e>0&&(r+=Ln+e+"B"),r};fn.cursorUp=(t=1)=>Ln+t+"A";fn.cursorDown=(t=1)=>Ln+t+"B";fn.cursorForward=(t=1)=>Ln+t+"C";fn.cursorBackward=(t=1)=>Ln+t+"D";fn.cursorLeft=Ln+"G";fn.cursorSavePosition=Zye?"\x1B7":Ln+"s";fn.cursorRestorePosition=Zye?"\x1B8":Ln+"u";fn.cursorGetPosition=Ln+"6n";fn.cursorNextLine=Ln+"E";fn.cursorPrevLine=Ln+"F";fn.cursorHide=Ln+"?25l";fn.cursorShow=Ln+"?25h";fn.eraseLines=t=>{let e="";for(let r=0;r<t;r++)e+=fn.eraseLine+(r<t-1?fn.cursorUp():"");return t&&(e+=fn.cursorLeft),e};fn.eraseEndLine=Ln+"K";fn.eraseStartLine=Ln+"1K";fn.eraseLine=Ln+"2K";fn.eraseDown=Ln+"J";fn.eraseUp=Ln+"1J";fn.eraseScreen=Ln+"2J";fn.scrollUp=Ln+"S";fn.scrollDown=Ln+"T";fn.clearScreen="\x1Bc";fn.clearTerminal=process.platform==="win32"?`${fn.eraseScreen}${Ln}0f`:`${fn.eraseScreen}${Ln}3J${Ln}H`;fn.beep=JE;fn.link=(t,e)=>[O2,"8",yk,yk,e,JE,t,O2,"8",yk,yk,JE].join("");fn.image=(t,e={})=>{let r=`${O2}1337;File=inline=1`;return e.width&&(r+=`;width=${e.width}`),e.height&&(r+=`;height=${e.height}`),e.preserveAspectRatio===!1&&(r+=";preserveAspectRatio=0"),r+":"+t.toString("base64")+JE};fn.iTerm={setCwd:(t=process.cwd())=>`${O2}50;CurrentDir=${t}${JE}`,annotation:(t,e={})=>{let r=`${O2}1337;`,o=typeof e.x<"u",a=typeof e.y<"u";if((o||a)&&!(o&&a&&typeof e.length<"u"))throw new Error("`x`, `y` and `length` must be defined when `x` or `y` is defined");return t=t.replace(/\|/g,""),r+=e.isHidden?"AddHiddenAnnotation=":"AddAnnotation=",e.length>0?r+=(o?[t,e.length,e.x,e.y]:[e.length,t]).join("|"):r+=t,r+JE}}});var eEe=_((cKt,o6)=>{"use strict";var $ye=(t,e)=>{for(let r of Reflect.ownKeys(e))Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r));return t};o6.exports=$ye;o6.exports.default=$ye});var rEe=_((uKt,Ck)=>{"use strict";var Oyt=eEe(),Ek=new WeakMap,tEe=(t,e={})=>{if(typeof t!="function")throw new TypeError("Expected a function");let r,o=0,a=t.displayName||t.name||"<anonymous>",n=function(...u){if(Ek.set(n,++o),o===1)r=t.apply(this,u),t=null;else if(e.throw===!0)throw new Error(`Function \`${a}\` can only be called once`);return r};return Oyt(n,t),Ek.set(n,o),n};Ck.exports=tEe;Ck.exports.default=tEe;Ck.exports.callCount=t=>{if(!Ek.has(t))throw new Error(`The given function \`${t.name}\` is not wrapped by the \`onetime\` package`);return Ek.get(t)}});var nEe=_((AKt,wk)=>{wk.exports=["SIGABRT","SIGALRM","SIGHUP","SIGINT","SIGTERM"];process.platform!=="win32"&&wk.exports.push("SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&wk.exports.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT","SIGUNUSED")});var c6=_((fKt,$E)=>{var yi=global.process,Kg=function(t){return t&&typeof t=="object"&&typeof t.removeListener=="function"&&typeof t.emit=="function"&&typeof t.reallyExit=="function"&&typeof t.listeners=="function"&&typeof t.kill=="function"&&typeof t.pid=="number"&&typeof t.on=="function"};Kg(yi)?(iEe=ve("assert"),XE=nEe(),sEe=/^win/i.test(yi.platform),U2=ve("events"),typeof U2!="function"&&(U2=U2.EventEmitter),yi.__signal_exit_emitter__?Ls=yi.__signal_exit_emitter__:(Ls=yi.__signal_exit_emitter__=new U2,Ls.count=0,Ls.emitted={}),Ls.infinite||(Ls.setMaxListeners(1/0),Ls.infinite=!0),$E.exports=function(t,e){if(!Kg(global.process))return function(){};iEe.equal(typeof t,"function","a callback must be provided for exit handler"),ZE===!1&&a6();var r="exit";e&&e.alwaysLast&&(r="afterexit");var o=function(){Ls.removeListener(r,t),Ls.listeners("exit").length===0&&Ls.listeners("afterexit").length===0&&Ik()};return Ls.on(r,t),o},Ik=function(){!ZE||!Kg(global.process)||(ZE=!1,XE.forEach(function(e){try{yi.removeListener(e,Bk[e])}catch{}}),yi.emit=vk,yi.reallyExit=l6,Ls.count-=1)},$E.exports.unload=Ik,Vg=function(e,r,o){Ls.emitted[e]||(Ls.emitted[e]=!0,Ls.emit(e,r,o))},Bk={},XE.forEach(function(t){Bk[t]=function(){if(Kg(global.process)){var r=yi.listeners(t);r.length===Ls.count&&(Ik(),Vg("exit",null,t),Vg("afterexit",null,t),sEe&&t==="SIGHUP"&&(t="SIGINT"),yi.kill(yi.pid,t))}}}),$E.exports.signals=function(){return XE},ZE=!1,a6=function(){ZE||!Kg(global.process)||(ZE=!0,Ls.count+=1,XE=XE.filter(function(e){try{return yi.on(e,Bk[e]),!0}catch{return!1}}),yi.emit=aEe,yi.reallyExit=oEe)},$E.exports.load=a6,l6=yi.reallyExit,oEe=function(e){Kg(global.process)&&(yi.exitCode=e||0,Vg("exit",yi.exitCode,null),Vg("afterexit",yi.exitCode,null),l6.call(yi,yi.exitCode))},vk=yi.emit,aEe=function(e,r){if(e==="exit"&&Kg(global.process)){r!==void 0&&(yi.exitCode=r);var o=vk.apply(this,arguments);return Vg("exit",yi.exitCode,null),Vg("afterexit",yi.exitCode,null),o}else return vk.apply(this,arguments)}):$E.exports=function(){return function(){}};var iEe,XE,sEe,U2,Ls,Ik,Vg,Bk,ZE,a6,l6,oEe,vk,aEe});var cEe=_((pKt,lEe)=>{"use strict";var Uyt=rEe(),_yt=c6();lEe.exports=Uyt(()=>{_yt(()=>{process.stderr.write("\x1B[?25h")},{alwaysLast:!0})})});var u6=_(eC=>{"use strict";var Hyt=cEe(),Dk=!1;eC.show=(t=process.stderr)=>{t.isTTY&&(Dk=!1,t.write("\x1B[?25h"))};eC.hide=(t=process.stderr)=>{t.isTTY&&(Hyt(),Dk=!0,t.write("\x1B[?25l"))};eC.toggle=(t,e)=>{t!==void 0&&(Dk=t),Dk?eC.show(e):eC.hide(e)}});var pEe=_(_2=>{"use strict";var fEe=_2&&_2.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(_2,"__esModule",{value:!0});var uEe=fEe(s6()),AEe=fEe(u6()),qyt=(t,{showCursor:e=!1}={})=>{let r=0,o="",a=!1,n=u=>{!e&&!a&&(AEe.default.hide(),a=!0);let A=u+` +`;A!==o&&(o=A,t.write(uEe.default.eraseLines(r)+A),r=A.split(` +`).length)};return n.clear=()=>{t.write(uEe.default.eraseLines(r)),o="",r=0},n.done=()=>{o="",r=0,e||(AEe.default.show(),a=!1)},n};_2.default={create:qyt}});var hEe=_((dKt,jyt)=>{jyt.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY_BUILD_BASE",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}}]});var mEe=_(dl=>{"use strict";var dEe=hEe(),pA=process.env;Object.defineProperty(dl,"_vendors",{value:dEe.map(function(t){return t.constant})});dl.name=null;dl.isPR=null;dEe.forEach(function(t){var e=Array.isArray(t.env)?t.env:[t.env],r=e.every(function(o){return gEe(o)});if(dl[t.constant]=r,r)switch(dl.name=t.name,typeof t.pr){case"string":dl.isPR=!!pA[t.pr];break;case"object":"env"in t.pr?dl.isPR=t.pr.env in pA&&pA[t.pr.env]!==t.pr.ne:"any"in t.pr?dl.isPR=t.pr.any.some(function(o){return!!pA[o]}):dl.isPR=gEe(t.pr);break;default:dl.isPR=null}});dl.isCI=!!(pA.CI||pA.CONTINUOUS_INTEGRATION||pA.BUILD_NUMBER||pA.RUN_ID||dl.name);function gEe(t){return typeof t=="string"?!!pA[t]:Object.keys(t).every(function(e){return pA[e]===t[e]})}});var EEe=_((yKt,yEe)=>{"use strict";yEe.exports=mEe().isCI});var wEe=_((EKt,CEe)=>{"use strict";var Gyt=t=>{let e=new Set;do for(let r of Reflect.ownKeys(t))e.add([t,r]);while((t=Reflect.getPrototypeOf(t))&&t!==Object.prototype);return e};CEe.exports=(t,{include:e,exclude:r}={})=>{let o=a=>{let n=u=>typeof u=="string"?a===u:u.test(a);return e?e.some(n):r?!r.some(n):!0};for(let[a,n]of Gyt(t.constructor.prototype)){if(n==="constructor"||!o(n))continue;let u=Reflect.getOwnPropertyDescriptor(a,n);u&&typeof u.value=="function"&&(t[n]=t[n].bind(t))}return t}});var bEe=_(kn=>{"use strict";Object.defineProperty(kn,"__esModule",{value:!0});var rC,j2,kk,Qk,m6;typeof window>"u"||typeof MessageChannel!="function"?(tC=null,A6=null,f6=function(){if(tC!==null)try{var t=kn.unstable_now();tC(!0,t),tC=null}catch(e){throw setTimeout(f6,0),e}},IEe=Date.now(),kn.unstable_now=function(){return Date.now()-IEe},rC=function(t){tC!==null?setTimeout(rC,0,t):(tC=t,setTimeout(f6,0))},j2=function(t,e){A6=setTimeout(t,e)},kk=function(){clearTimeout(A6)},Qk=function(){return!1},m6=kn.unstable_forceFrameRate=function(){}):(Pk=window.performance,p6=window.Date,BEe=window.setTimeout,vEe=window.clearTimeout,typeof console<"u"&&(DEe=window.cancelAnimationFrame,typeof window.requestAnimationFrame!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),typeof DEe!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")),typeof Pk=="object"&&typeof Pk.now=="function"?kn.unstable_now=function(){return Pk.now()}:(PEe=p6.now(),kn.unstable_now=function(){return p6.now()-PEe}),H2=!1,q2=null,Sk=-1,h6=5,g6=0,Qk=function(){return kn.unstable_now()>=g6},m6=function(){},kn.unstable_forceFrameRate=function(t){0>t||125<t?console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported"):h6=0<t?Math.floor(1e3/t):5},d6=new MessageChannel,bk=d6.port2,d6.port1.onmessage=function(){if(q2!==null){var t=kn.unstable_now();g6=t+h6;try{q2(!0,t)?bk.postMessage(null):(H2=!1,q2=null)}catch(e){throw bk.postMessage(null),e}}else H2=!1},rC=function(t){q2=t,H2||(H2=!0,bk.postMessage(null))},j2=function(t,e){Sk=BEe(function(){t(kn.unstable_now())},e)},kk=function(){vEe(Sk),Sk=-1});var tC,A6,f6,IEe,Pk,p6,BEe,vEe,DEe,PEe,H2,q2,Sk,h6,g6,d6,bk;function y6(t,e){var r=t.length;t.push(e);e:for(;;){var o=Math.floor((r-1)/2),a=t[o];if(a!==void 0&&0<xk(a,e))t[o]=e,t[r]=a,r=o;else break e}}function nc(t){return t=t[0],t===void 0?null:t}function Fk(t){var e=t[0];if(e!==void 0){var r=t.pop();if(r!==e){t[0]=r;e:for(var o=0,a=t.length;o<a;){var n=2*(o+1)-1,u=t[n],A=n+1,p=t[A];if(u!==void 0&&0>xk(u,r))p!==void 0&&0>xk(p,u)?(t[o]=p,t[A]=r,o=A):(t[o]=u,t[n]=r,o=n);else if(p!==void 0&&0>xk(p,r))t[o]=p,t[A]=r,o=A;else break e}}return e}return null}function xk(t,e){var r=t.sortIndex-e.sortIndex;return r!==0?r:t.id-e.id}var ru=[],Th=[],Yyt=1,sa=null,Lo=3,Rk=!1,zg=!1,G2=!1;function Tk(t){for(var e=nc(Th);e!==null;){if(e.callback===null)Fk(Th);else if(e.startTime<=t)Fk(Th),e.sortIndex=e.expirationTime,y6(ru,e);else break;e=nc(Th)}}function E6(t){if(G2=!1,Tk(t),!zg)if(nc(ru)!==null)zg=!0,rC(C6);else{var e=nc(Th);e!==null&&j2(E6,e.startTime-t)}}function C6(t,e){zg=!1,G2&&(G2=!1,kk()),Rk=!0;var r=Lo;try{for(Tk(e),sa=nc(ru);sa!==null&&(!(sa.expirationTime>e)||t&&!Qk());){var o=sa.callback;if(o!==null){sa.callback=null,Lo=sa.priorityLevel;var a=o(sa.expirationTime<=e);e=kn.unstable_now(),typeof a=="function"?sa.callback=a:sa===nc(ru)&&Fk(ru),Tk(e)}else Fk(ru);sa=nc(ru)}if(sa!==null)var n=!0;else{var u=nc(Th);u!==null&&j2(E6,u.startTime-e),n=!1}return n}finally{sa=null,Lo=r,Rk=!1}}function SEe(t){switch(t){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var Wyt=m6;kn.unstable_ImmediatePriority=1;kn.unstable_UserBlockingPriority=2;kn.unstable_NormalPriority=3;kn.unstable_IdlePriority=5;kn.unstable_LowPriority=4;kn.unstable_runWithPriority=function(t,e){switch(t){case 1:case 2:case 3:case 4:case 5:break;default:t=3}var r=Lo;Lo=t;try{return e()}finally{Lo=r}};kn.unstable_next=function(t){switch(Lo){case 1:case 2:case 3:var e=3;break;default:e=Lo}var r=Lo;Lo=e;try{return t()}finally{Lo=r}};kn.unstable_scheduleCallback=function(t,e,r){var o=kn.unstable_now();if(typeof r=="object"&&r!==null){var a=r.delay;a=typeof a=="number"&&0<a?o+a:o,r=typeof r.timeout=="number"?r.timeout:SEe(t)}else r=SEe(t),a=o;return r=a+r,t={id:Yyt++,callback:e,priorityLevel:t,startTime:a,expirationTime:r,sortIndex:-1},a>o?(t.sortIndex=a,y6(Th,t),nc(ru)===null&&t===nc(Th)&&(G2?kk():G2=!0,j2(E6,a-o))):(t.sortIndex=r,y6(ru,t),zg||Rk||(zg=!0,rC(C6))),t};kn.unstable_cancelCallback=function(t){t.callback=null};kn.unstable_wrapCallback=function(t){var e=Lo;return function(){var r=Lo;Lo=e;try{return t.apply(this,arguments)}finally{Lo=r}}};kn.unstable_getCurrentPriorityLevel=function(){return Lo};kn.unstable_shouldYield=function(){var t=kn.unstable_now();Tk(t);var e=nc(ru);return e!==sa&&sa!==null&&e!==null&&e.callback!==null&&e.startTime<=t&&e.expirationTime<sa.expirationTime||Qk()};kn.unstable_requestPaint=Wyt;kn.unstable_continueExecution=function(){zg||Rk||(zg=!0,rC(C6))};kn.unstable_pauseExecution=function(){};kn.unstable_getFirstCallbackNode=function(){return nc(ru)};kn.unstable_Profiling=null});var w6=_((wKt,xEe)=>{"use strict";xEe.exports=bEe()});var kEe=_((IKt,Y2)=>{Y2.exports=function t(e){"use strict";var r=VH(),o=an(),a=w6();function n(P){for(var D="https://reactjs.org/docs/error-decoder.html?invariant="+P,T=1;T<arguments.length;T++)D+="&args[]="+encodeURIComponent(arguments[T]);return"Minified React error #"+P+"; visit "+D+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var u=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;u.hasOwnProperty("ReactCurrentDispatcher")||(u.ReactCurrentDispatcher={current:null}),u.hasOwnProperty("ReactCurrentBatchConfig")||(u.ReactCurrentBatchConfig={suspense:null});var A=typeof Symbol=="function"&&Symbol.for,p=A?Symbol.for("react.element"):60103,h=A?Symbol.for("react.portal"):60106,E=A?Symbol.for("react.fragment"):60107,I=A?Symbol.for("react.strict_mode"):60108,v=A?Symbol.for("react.profiler"):60114,x=A?Symbol.for("react.provider"):60109,C=A?Symbol.for("react.context"):60110,R=A?Symbol.for("react.concurrent_mode"):60111,L=A?Symbol.for("react.forward_ref"):60112,U=A?Symbol.for("react.suspense"):60113,z=A?Symbol.for("react.suspense_list"):60120,te=A?Symbol.for("react.memo"):60115,ae=A?Symbol.for("react.lazy"):60116;A&&Symbol.for("react.fundamental"),A&&Symbol.for("react.responder"),A&&Symbol.for("react.scope");var le=typeof Symbol=="function"&&Symbol.iterator;function ce(P){return P===null||typeof P!="object"?null:(P=le&&P[le]||P["@@iterator"],typeof P=="function"?P:null)}function Ce(P){if(P._status===-1){P._status=0;var D=P._ctor;D=D(),P._result=D,D.then(function(T){P._status===0&&(T=T.default,P._status=1,P._result=T)},function(T){P._status===0&&(P._status=2,P._result=T)})}}function de(P){if(P==null)return null;if(typeof P=="function")return P.displayName||P.name||null;if(typeof P=="string")return P;switch(P){case E:return"Fragment";case h:return"Portal";case v:return"Profiler";case I:return"StrictMode";case U:return"Suspense";case z:return"SuspenseList"}if(typeof P=="object")switch(P.$$typeof){case C:return"Context.Consumer";case x:return"Context.Provider";case L:var D=P.render;return D=D.displayName||D.name||"",P.displayName||(D!==""?"ForwardRef("+D+")":"ForwardRef");case te:return de(P.type);case ae:if(P=P._status===1?P._result:null)return de(P)}return null}function Be(P){var D=P,T=P;if(P.alternate)for(;D.return;)D=D.return;else{P=D;do D=P,D.effectTag&1026&&(T=D.return),P=D.return;while(P)}return D.tag===3?T:null}function Ee(P){if(Be(P)!==P)throw Error(n(188))}function g(P){var D=P.alternate;if(!D){if(D=Be(P),D===null)throw Error(n(188));return D!==P?null:P}for(var T=P,q=D;;){var W=T.return;if(W===null)break;var fe=W.alternate;if(fe===null){if(q=W.return,q!==null){T=q;continue}break}if(W.child===fe.child){for(fe=W.child;fe;){if(fe===T)return Ee(W),P;if(fe===q)return Ee(W),D;fe=fe.sibling}throw Error(n(188))}if(T.return!==q.return)T=W,q=fe;else{for(var De=!1,vt=W.child;vt;){if(vt===T){De=!0,T=W,q=fe;break}if(vt===q){De=!0,q=W,T=fe;break}vt=vt.sibling}if(!De){for(vt=fe.child;vt;){if(vt===T){De=!0,T=fe,q=W;break}if(vt===q){De=!0,q=fe,T=W;break}vt=vt.sibling}if(!De)throw Error(n(189))}}if(T.alternate!==q)throw Error(n(190))}if(T.tag!==3)throw Error(n(188));return T.stateNode.current===T?P:D}function me(P){if(P=g(P),!P)return null;for(var D=P;;){if(D.tag===5||D.tag===6)return D;if(D.child)D.child.return=D,D=D.child;else{if(D===P)break;for(;!D.sibling;){if(!D.return||D.return===P)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}}return null}function we(P){if(P=g(P),!P)return null;for(var D=P;;){if(D.tag===5||D.tag===6)return D;if(D.child&&D.tag!==4)D.child.return=D,D=D.child;else{if(D===P)break;for(;!D.sibling;){if(!D.return||D.return===P)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}}return null}var Ae=e.getPublicInstance,ne=e.getRootHostContext,Z=e.getChildHostContext,xe=e.prepareForCommit,Ne=e.resetAfterCommit,ht=e.createInstance,H=e.appendInitialChild,rt=e.finalizeInitialChildren,Te=e.prepareUpdate,Fe=e.shouldSetTextContent,ke=e.shouldDeprioritizeSubtree,Ye=e.createTextInstance,Se=e.setTimeout,et=e.clearTimeout,Ue=e.noTimeout,b=e.isPrimaryRenderer,w=e.supportsMutation,S=e.supportsPersistence,y=e.supportsHydration,F=e.appendChild,J=e.appendChildToContainer,X=e.commitTextUpdate,$=e.commitMount,ie=e.commitUpdate,be=e.insertBefore,Re=e.insertInContainerBefore,at=e.removeChild,dt=e.removeChildFromContainer,jt=e.resetTextContent,tr=e.hideInstance,St=e.hideTextInstance,ln=e.unhideInstance,kr=e.unhideTextInstance,mr=e.cloneInstance,br=e.createContainerChildSet,Kr=e.appendChildToContainerChildSet,Kn=e.finalizeContainerChildren,Ms=e.replaceContainerChildren,Ri=e.cloneHiddenInstance,gs=e.cloneHiddenTextInstance,io=e.canHydrateInstance,Pi=e.canHydrateTextInstance,Os=e.isSuspenseInstancePending,so=e.isSuspenseInstanceFallback,uc=e.getNextHydratableSibling,Au=e.getFirstHydratableChild,sp=e.hydrateInstance,op=e.hydrateTextInstance,Us=e.getNextHydratableInstanceAfterSuspenseInstance,Dn=e.commitHydratedContainer,oo=e.commitHydratedSuspenseInstance,_s=/^(.*)[\\\/]/;function ml(P){var D="";do{e:switch(P.tag){case 3:case 4:case 6:case 7:case 10:case 9:var T="";break e;default:var q=P._debugOwner,W=P._debugSource,fe=de(P.type);T=null,q&&(T=de(q.type)),q=fe,fe="",W?fe=" (at "+W.fileName.replace(_s,"")+":"+W.lineNumber+")":T&&(fe=" (created by "+T+")"),T=` + in `+(q||"Unknown")+fe}D+=T,P=P.return}while(P);return D}var yl=[],ao=-1;function Vn(P){0>ao||(P.current=yl[ao],yl[ao]=null,ao--)}function Mn(P,D){ao++,yl[ao]=P.current,P.current=D}var Ti={},On={current:Ti},_i={current:!1},ir=Ti;function Me(P,D){var T=P.type.contextTypes;if(!T)return Ti;var q=P.stateNode;if(q&&q.__reactInternalMemoizedUnmaskedChildContext===D)return q.__reactInternalMemoizedMaskedChildContext;var W={},fe;for(fe in T)W[fe]=D[fe];return q&&(P=P.stateNode,P.__reactInternalMemoizedUnmaskedChildContext=D,P.__reactInternalMemoizedMaskedChildContext=W),W}function ii(P){return P=P.childContextTypes,P!=null}function Ha(P){Vn(_i,P),Vn(On,P)}function hr(P){Vn(_i,P),Vn(On,P)}function Ac(P,D,T){if(On.current!==Ti)throw Error(n(168));Mn(On,D,P),Mn(_i,T,P)}function fu(P,D,T){var q=P.stateNode;if(P=D.childContextTypes,typeof q.getChildContext!="function")return T;q=q.getChildContext();for(var W in q)if(!(W in P))throw Error(n(108,de(D)||"Unknown",W));return r({},T,{},q)}function fc(P){var D=P.stateNode;return D=D&&D.__reactInternalMemoizedMergedChildContext||Ti,ir=On.current,Mn(On,D,P),Mn(_i,_i.current,P),!0}function El(P,D,T){var q=P.stateNode;if(!q)throw Error(n(169));T?(D=fu(P,D,ir),q.__reactInternalMemoizedMergedChildContext=D,Vn(_i,P),Vn(On,P),Mn(On,D,P)):Vn(_i,P),Mn(_i,T,P)}var vA=a.unstable_runWithPriority,pu=a.unstable_scheduleCallback,Ie=a.unstable_cancelCallback,Tt=a.unstable_shouldYield,pc=a.unstable_requestPaint,Hi=a.unstable_now,hu=a.unstable_getCurrentPriorityLevel,Yt=a.unstable_ImmediatePriority,Cl=a.unstable_UserBlockingPriority,DA=a.unstable_NormalPriority,ap=a.unstable_LowPriority,hc=a.unstable_IdlePriority,PA={},Qn=pc!==void 0?pc:function(){},hi=null,gc=null,SA=!1,aa=Hi(),Ni=1e4>aa?Hi:function(){return Hi()-aa};function _o(){switch(hu()){case Yt:return 99;case Cl:return 98;case DA:return 97;case ap:return 96;case hc:return 95;default:throw Error(n(332))}}function Xe(P){switch(P){case 99:return Yt;case 98:return Cl;case 97:return DA;case 96:return ap;case 95:return hc;default:throw Error(n(332))}}function lo(P,D){return P=Xe(P),vA(P,D)}function dc(P,D,T){return P=Xe(P),pu(P,D,T)}function gu(P){return hi===null?(hi=[P],gc=pu(Yt,du)):hi.push(P),PA}function qi(){if(gc!==null){var P=gc;gc=null,Ie(P)}du()}function du(){if(!SA&&hi!==null){SA=!0;var P=0;try{var D=hi;lo(99,function(){for(;P<D.length;P++){var T=D[P];do T=T(!0);while(T!==null)}}),hi=null}catch(T){throw hi!==null&&(hi=hi.slice(P+1)),pu(Yt,qi),T}finally{SA=!1}}}var bA=3;function qa(P,D,T){return T/=10,1073741821-(((1073741821-P+D/10)/T|0)+1)*T}function mc(P,D){return P===D&&(P!==0||1/P===1/D)||P!==P&&D!==D}var ds=typeof Object.is=="function"?Object.is:mc,Ht=Object.prototype.hasOwnProperty;function Fn(P,D){if(ds(P,D))return!0;if(typeof P!="object"||P===null||typeof D!="object"||D===null)return!1;var T=Object.keys(P),q=Object.keys(D);if(T.length!==q.length)return!1;for(q=0;q<T.length;q++)if(!Ht.call(D,T[q])||!ds(P[T[q]],D[T[q]]))return!1;return!0}function Ei(P,D){if(P&&P.defaultProps){D=r({},D),P=P.defaultProps;for(var T in P)D[T]===void 0&&(D[T]=P[T])}return D}var la={current:null},co=null,Hs=null,ca=null;function ua(){ca=Hs=co=null}function Ho(P,D){var T=P.type._context;b?(Mn(la,T._currentValue,P),T._currentValue=D):(Mn(la,T._currentValue2,P),T._currentValue2=D)}function Ci(P){var D=la.current;Vn(la,P),P=P.type._context,b?P._currentValue=D:P._currentValue2=D}function ms(P,D){for(;P!==null;){var T=P.alternate;if(P.childExpirationTime<D)P.childExpirationTime=D,T!==null&&T.childExpirationTime<D&&(T.childExpirationTime=D);else if(T!==null&&T.childExpirationTime<D)T.childExpirationTime=D;else break;P=P.return}}function ys(P,D){co=P,ca=Hs=null,P=P.dependencies,P!==null&&P.firstContext!==null&&(P.expirationTime>=D&&(jo=!0),P.firstContext=null)}function Es(P,D){if(ca!==P&&D!==!1&&D!==0)if((typeof D!="number"||D===1073741823)&&(ca=P,D=1073741823),D={context:P,observedBits:D,next:null},Hs===null){if(co===null)throw Error(n(308));Hs=D,co.dependencies={expirationTime:0,firstContext:D,responders:null}}else Hs=Hs.next=D;return b?P._currentValue:P._currentValue2}var qs=!1;function Un(P){return{baseState:P,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Pn(P){return{baseState:P.baseState,firstUpdate:P.firstUpdate,lastUpdate:P.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Cs(P,D){return{expirationTime:P,suspenseConfig:D,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function We(P,D){P.lastUpdate===null?P.firstUpdate=P.lastUpdate=D:(P.lastUpdate.next=D,P.lastUpdate=D)}function tt(P,D){var T=P.alternate;if(T===null){var q=P.updateQueue,W=null;q===null&&(q=P.updateQueue=Un(P.memoizedState))}else q=P.updateQueue,W=T.updateQueue,q===null?W===null?(q=P.updateQueue=Un(P.memoizedState),W=T.updateQueue=Un(T.memoizedState)):q=P.updateQueue=Pn(W):W===null&&(W=T.updateQueue=Pn(q));W===null||q===W?We(q,D):q.lastUpdate===null||W.lastUpdate===null?(We(q,D),We(W,D)):(We(q,D),W.lastUpdate=D)}function Bt(P,D){var T=P.updateQueue;T=T===null?P.updateQueue=Un(P.memoizedState):or(P,T),T.lastCapturedUpdate===null?T.firstCapturedUpdate=T.lastCapturedUpdate=D:(T.lastCapturedUpdate.next=D,T.lastCapturedUpdate=D)}function or(P,D){var T=P.alternate;return T!==null&&D===T.updateQueue&&(D=P.updateQueue=Pn(D)),D}function ee(P,D,T,q,W,fe){switch(T.tag){case 1:return P=T.payload,typeof P=="function"?P.call(fe,q,W):P;case 3:P.effectTag=P.effectTag&-4097|64;case 0:if(P=T.payload,W=typeof P=="function"?P.call(fe,q,W):P,W==null)break;return r({},q,W);case 2:qs=!0}return q}function ye(P,D,T,q,W){qs=!1,D=or(P,D);for(var fe=D.baseState,De=null,vt=0,wt=D.firstUpdate,bt=fe;wt!==null;){var _r=wt.expirationTime;_r<W?(De===null&&(De=wt,fe=bt),vt<_r&&(vt=_r)):(uw(_r,wt.suspenseConfig),bt=ee(P,D,wt,bt,T,q),wt.callback!==null&&(P.effectTag|=32,wt.nextEffect=null,D.lastEffect===null?D.firstEffect=D.lastEffect=wt:(D.lastEffect.nextEffect=wt,D.lastEffect=wt))),wt=wt.next}for(_r=null,wt=D.firstCapturedUpdate;wt!==null;){var os=wt.expirationTime;os<W?(_r===null&&(_r=wt,De===null&&(fe=bt)),vt<os&&(vt=os)):(bt=ee(P,D,wt,bt,T,q),wt.callback!==null&&(P.effectTag|=32,wt.nextEffect=null,D.lastCapturedEffect===null?D.firstCapturedEffect=D.lastCapturedEffect=wt:(D.lastCapturedEffect.nextEffect=wt,D.lastCapturedEffect=wt))),wt=wt.next}De===null&&(D.lastUpdate=null),_r===null?D.lastCapturedUpdate=null:P.effectTag|=32,De===null&&_r===null&&(fe=bt),D.baseState=fe,D.firstUpdate=De,D.firstCapturedUpdate=_r,bd(vt),P.expirationTime=vt,P.memoizedState=bt}function Le(P,D,T){D.firstCapturedUpdate!==null&&(D.lastUpdate!==null&&(D.lastUpdate.next=D.firstCapturedUpdate,D.lastUpdate=D.lastCapturedUpdate),D.firstCapturedUpdate=D.lastCapturedUpdate=null),ft(D.firstEffect,T),D.firstEffect=D.lastEffect=null,ft(D.firstCapturedEffect,T),D.firstCapturedEffect=D.lastCapturedEffect=null}function ft(P,D){for(;P!==null;){var T=P.callback;if(T!==null){P.callback=null;var q=D;if(typeof T!="function")throw Error(n(191,T));T.call(q)}P=P.nextEffect}}var pt=u.ReactCurrentBatchConfig,Nt=new o.Component().refs;function rr(P,D,T,q){D=P.memoizedState,T=T(q,D),T=T==null?D:r({},D,T),P.memoizedState=T,q=P.updateQueue,q!==null&&P.expirationTime===0&&(q.baseState=T)}var $r={isMounted:function(P){return(P=P._reactInternalFiber)?Be(P)===P:!1},enqueueSetState:function(P,D,T){P=P._reactInternalFiber;var q=ma(),W=pt.suspense;q=HA(q,P,W),W=Cs(q,W),W.payload=D,T!=null&&(W.callback=T),tt(P,W),bc(P,q)},enqueueReplaceState:function(P,D,T){P=P._reactInternalFiber;var q=ma(),W=pt.suspense;q=HA(q,P,W),W=Cs(q,W),W.tag=1,W.payload=D,T!=null&&(W.callback=T),tt(P,W),bc(P,q)},enqueueForceUpdate:function(P,D){P=P._reactInternalFiber;var T=ma(),q=pt.suspense;T=HA(T,P,q),q=Cs(T,q),q.tag=2,D!=null&&(q.callback=D),tt(P,q),bc(P,T)}};function ji(P,D,T,q,W,fe,De){return P=P.stateNode,typeof P.shouldComponentUpdate=="function"?P.shouldComponentUpdate(q,fe,De):D.prototype&&D.prototype.isPureReactComponent?!Fn(T,q)||!Fn(W,fe):!0}function rs(P,D,T){var q=!1,W=Ti,fe=D.contextType;return typeof fe=="object"&&fe!==null?fe=Es(fe):(W=ii(D)?ir:On.current,q=D.contextTypes,fe=(q=q!=null)?Me(P,W):Ti),D=new D(T,fe),P.memoizedState=D.state!==null&&D.state!==void 0?D.state:null,D.updater=$r,P.stateNode=D,D._reactInternalFiber=P,q&&(P=P.stateNode,P.__reactInternalMemoizedUnmaskedChildContext=W,P.__reactInternalMemoizedMaskedChildContext=fe),D}function Si(P,D,T,q){P=D.state,typeof D.componentWillReceiveProps=="function"&&D.componentWillReceiveProps(T,q),typeof D.UNSAFE_componentWillReceiveProps=="function"&&D.UNSAFE_componentWillReceiveProps(T,q),D.state!==P&&$r.enqueueReplaceState(D,D.state,null)}function qo(P,D,T,q){var W=P.stateNode;W.props=T,W.state=P.memoizedState,W.refs=Nt;var fe=D.contextType;typeof fe=="object"&&fe!==null?W.context=Es(fe):(fe=ii(D)?ir:On.current,W.context=Me(P,fe)),fe=P.updateQueue,fe!==null&&(ye(P,fe,T,W,q),W.state=P.memoizedState),fe=D.getDerivedStateFromProps,typeof fe=="function"&&(rr(P,D,fe,T),W.state=P.memoizedState),typeof D.getDerivedStateFromProps=="function"||typeof W.getSnapshotBeforeUpdate=="function"||typeof W.UNSAFE_componentWillMount!="function"&&typeof W.componentWillMount!="function"||(D=W.state,typeof W.componentWillMount=="function"&&W.componentWillMount(),typeof W.UNSAFE_componentWillMount=="function"&&W.UNSAFE_componentWillMount(),D!==W.state&&$r.enqueueReplaceState(W,W.state,null),fe=P.updateQueue,fe!==null&&(ye(P,fe,T,W,q),W.state=P.memoizedState)),typeof W.componentDidMount=="function"&&(P.effectTag|=4)}var xA=Array.isArray;function kA(P,D,T){if(P=T.ref,P!==null&&typeof P!="function"&&typeof P!="object"){if(T._owner){if(T=T._owner,T){if(T.tag!==1)throw Error(n(309));var q=T.stateNode}if(!q)throw Error(n(147,P));var W=""+P;return D!==null&&D.ref!==null&&typeof D.ref=="function"&&D.ref._stringRef===W?D.ref:(D=function(fe){var De=q.refs;De===Nt&&(De=q.refs={}),fe===null?delete De[W]:De[W]=fe},D._stringRef=W,D)}if(typeof P!="string")throw Error(n(284));if(!T._owner)throw Error(n(290,P))}return P}function lp(P,D){if(P.type!=="textarea")throw Error(n(31,Object.prototype.toString.call(D)==="[object Object]"?"object with keys {"+Object.keys(D).join(", ")+"}":D,""))}function e0(P){function D(nt,Ve){if(P){var At=nt.lastEffect;At!==null?(At.nextEffect=Ve,nt.lastEffect=Ve):nt.firstEffect=nt.lastEffect=Ve,Ve.nextEffect=null,Ve.effectTag=8}}function T(nt,Ve){if(!P)return null;for(;Ve!==null;)D(nt,Ve),Ve=Ve.sibling;return null}function q(nt,Ve){for(nt=new Map;Ve!==null;)Ve.key!==null?nt.set(Ve.key,Ve):nt.set(Ve.index,Ve),Ve=Ve.sibling;return nt}function W(nt,Ve,At){return nt=YA(nt,Ve,At),nt.index=0,nt.sibling=null,nt}function fe(nt,Ve,At){return nt.index=At,P?(At=nt.alternate,At!==null?(At=At.index,At<Ve?(nt.effectTag=2,Ve):At):(nt.effectTag=2,Ve)):Ve}function De(nt){return P&&nt.alternate===null&&(nt.effectTag=2),nt}function vt(nt,Ve,At,Wt){return Ve===null||Ve.tag!==6?(Ve=gw(At,nt.mode,Wt),Ve.return=nt,Ve):(Ve=W(Ve,At,Wt),Ve.return=nt,Ve)}function wt(nt,Ve,At,Wt){return Ve!==null&&Ve.elementType===At.type?(Wt=W(Ve,At.props,Wt),Wt.ref=kA(nt,Ve,At),Wt.return=nt,Wt):(Wt=xd(At.type,At.key,At.props,null,nt.mode,Wt),Wt.ref=kA(nt,Ve,At),Wt.return=nt,Wt)}function bt(nt,Ve,At,Wt){return Ve===null||Ve.tag!==4||Ve.stateNode.containerInfo!==At.containerInfo||Ve.stateNode.implementation!==At.implementation?(Ve=dw(At,nt.mode,Wt),Ve.return=nt,Ve):(Ve=W(Ve,At.children||[],Wt),Ve.return=nt,Ve)}function _r(nt,Ve,At,Wt,vr){return Ve===null||Ve.tag!==7?(Ve=ku(At,nt.mode,Wt,vr),Ve.return=nt,Ve):(Ve=W(Ve,At,Wt),Ve.return=nt,Ve)}function os(nt,Ve,At){if(typeof Ve=="string"||typeof Ve=="number")return Ve=gw(""+Ve,nt.mode,At),Ve.return=nt,Ve;if(typeof Ve=="object"&&Ve!==null){switch(Ve.$$typeof){case p:return At=xd(Ve.type,Ve.key,Ve.props,null,nt.mode,At),At.ref=kA(nt,null,Ve),At.return=nt,At;case h:return Ve=dw(Ve,nt.mode,At),Ve.return=nt,Ve}if(xA(Ve)||ce(Ve))return Ve=ku(Ve,nt.mode,At,null),Ve.return=nt,Ve;lp(nt,Ve)}return null}function di(nt,Ve,At,Wt){var vr=Ve!==null?Ve.key:null;if(typeof At=="string"||typeof At=="number")return vr!==null?null:vt(nt,Ve,""+At,Wt);if(typeof At=="object"&&At!==null){switch(At.$$typeof){case p:return At.key===vr?At.type===E?_r(nt,Ve,At.props.children,Wt,vr):wt(nt,Ve,At,Wt):null;case h:return At.key===vr?bt(nt,Ve,At,Wt):null}if(xA(At)||ce(At))return vr!==null?null:_r(nt,Ve,At,Wt,null);lp(nt,At)}return null}function po(nt,Ve,At,Wt,vr){if(typeof Wt=="string"||typeof Wt=="number")return nt=nt.get(At)||null,vt(Ve,nt,""+Wt,vr);if(typeof Wt=="object"&&Wt!==null){switch(Wt.$$typeof){case p:return nt=nt.get(Wt.key===null?At:Wt.key)||null,Wt.type===E?_r(Ve,nt,Wt.props.children,vr,Wt.key):wt(Ve,nt,Wt,vr);case h:return nt=nt.get(Wt.key===null?At:Wt.key)||null,bt(Ve,nt,Wt,vr)}if(xA(Wt)||ce(Wt))return nt=nt.get(At)||null,_r(Ve,nt,Wt,vr,null);lp(Ve,Wt)}return null}function KA(nt,Ve,At,Wt){for(var vr=null,Sn=null,Qr=Ve,bn=Ve=0,ai=null;Qr!==null&&bn<At.length;bn++){Qr.index>bn?(ai=Qr,Qr=null):ai=Qr.sibling;var tn=di(nt,Qr,At[bn],Wt);if(tn===null){Qr===null&&(Qr=ai);break}P&&Qr&&tn.alternate===null&&D(nt,Qr),Ve=fe(tn,Ve,bn),Sn===null?vr=tn:Sn.sibling=tn,Sn=tn,Qr=ai}if(bn===At.length)return T(nt,Qr),vr;if(Qr===null){for(;bn<At.length;bn++)Qr=os(nt,At[bn],Wt),Qr!==null&&(Ve=fe(Qr,Ve,bn),Sn===null?vr=Qr:Sn.sibling=Qr,Sn=Qr);return vr}for(Qr=q(nt,Qr);bn<At.length;bn++)ai=po(Qr,nt,bn,At[bn],Wt),ai!==null&&(P&&ai.alternate!==null&&Qr.delete(ai.key===null?bn:ai.key),Ve=fe(ai,Ve,bn),Sn===null?vr=ai:Sn.sibling=ai,Sn=ai);return P&&Qr.forEach(function(ho){return D(nt,ho)}),vr}function Yo(nt,Ve,At,Wt){var vr=ce(At);if(typeof vr!="function")throw Error(n(150));if(At=vr.call(At),At==null)throw Error(n(151));for(var Sn=vr=null,Qr=Ve,bn=Ve=0,ai=null,tn=At.next();Qr!==null&&!tn.done;bn++,tn=At.next()){Qr.index>bn?(ai=Qr,Qr=null):ai=Qr.sibling;var ho=di(nt,Qr,tn.value,Wt);if(ho===null){Qr===null&&(Qr=ai);break}P&&Qr&&ho.alternate===null&&D(nt,Qr),Ve=fe(ho,Ve,bn),Sn===null?vr=ho:Sn.sibling=ho,Sn=ho,Qr=ai}if(tn.done)return T(nt,Qr),vr;if(Qr===null){for(;!tn.done;bn++,tn=At.next())tn=os(nt,tn.value,Wt),tn!==null&&(Ve=fe(tn,Ve,bn),Sn===null?vr=tn:Sn.sibling=tn,Sn=tn);return vr}for(Qr=q(nt,Qr);!tn.done;bn++,tn=At.next())tn=po(Qr,nt,bn,tn.value,Wt),tn!==null&&(P&&tn.alternate!==null&&Qr.delete(tn.key===null?bn:tn.key),Ve=fe(tn,Ve,bn),Sn===null?vr=tn:Sn.sibling=tn,Sn=tn);return P&&Qr.forEach(function(pF){return D(nt,pF)}),vr}return function(nt,Ve,At,Wt){var vr=typeof At=="object"&&At!==null&&At.type===E&&At.key===null;vr&&(At=At.props.children);var Sn=typeof At=="object"&&At!==null;if(Sn)switch(At.$$typeof){case p:e:{for(Sn=At.key,vr=Ve;vr!==null;){if(vr.key===Sn)if(vr.tag===7?At.type===E:vr.elementType===At.type){T(nt,vr.sibling),Ve=W(vr,At.type===E?At.props.children:At.props,Wt),Ve.ref=kA(nt,vr,At),Ve.return=nt,nt=Ve;break e}else{T(nt,vr);break}else D(nt,vr);vr=vr.sibling}At.type===E?(Ve=ku(At.props.children,nt.mode,Wt,At.key),Ve.return=nt,nt=Ve):(Wt=xd(At.type,At.key,At.props,null,nt.mode,Wt),Wt.ref=kA(nt,Ve,At),Wt.return=nt,nt=Wt)}return De(nt);case h:e:{for(vr=At.key;Ve!==null;){if(Ve.key===vr)if(Ve.tag===4&&Ve.stateNode.containerInfo===At.containerInfo&&Ve.stateNode.implementation===At.implementation){T(nt,Ve.sibling),Ve=W(Ve,At.children||[],Wt),Ve.return=nt,nt=Ve;break e}else{T(nt,Ve);break}else D(nt,Ve);Ve=Ve.sibling}Ve=dw(At,nt.mode,Wt),Ve.return=nt,nt=Ve}return De(nt)}if(typeof At=="string"||typeof At=="number")return At=""+At,Ve!==null&&Ve.tag===6?(T(nt,Ve.sibling),Ve=W(Ve,At,Wt),Ve.return=nt,nt=Ve):(T(nt,Ve),Ve=gw(At,nt.mode,Wt),Ve.return=nt,nt=Ve),De(nt);if(xA(At))return KA(nt,Ve,At,Wt);if(ce(At))return Yo(nt,Ve,At,Wt);if(Sn&&lp(nt,At),typeof At>"u"&&!vr)switch(nt.tag){case 1:case 0:throw nt=nt.type,Error(n(152,nt.displayName||nt.name||"Component"))}return T(nt,Ve)}}var mu=e0(!0),t0=e0(!1),yu={},uo={current:yu},QA={current:yu},yc={current:yu};function Aa(P){if(P===yu)throw Error(n(174));return P}function r0(P,D){Mn(yc,D,P),Mn(QA,P,P),Mn(uo,yu,P),D=ne(D),Vn(uo,P),Mn(uo,D,P)}function Ec(P){Vn(uo,P),Vn(QA,P),Vn(yc,P)}function hd(P){var D=Aa(yc.current),T=Aa(uo.current);D=Z(T,P.type,D),T!==D&&(Mn(QA,P,P),Mn(uo,D,P))}function n0(P){QA.current===P&&(Vn(uo,P),Vn(QA,P))}var $n={current:0};function cp(P){for(var D=P;D!==null;){if(D.tag===13){var T=D.memoizedState;if(T!==null&&(T=T.dehydrated,T===null||Os(T)||so(T)))return D}else if(D.tag===19&&D.memoizedProps.revealOrder!==void 0){if(D.effectTag&64)return D}else if(D.child!==null){D.child.return=D,D=D.child;continue}if(D===P)break;for(;D.sibling===null;){if(D.return===null||D.return===P)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}return null}function i0(P,D){return{responder:P,props:D}}var FA=u.ReactCurrentDispatcher,js=u.ReactCurrentBatchConfig,Eu=0,ja=null,Gi=null,fa=null,Cu=null,ws=null,Cc=null,wc=0,Y=null,Dt=0,wl=!1,bi=null,Ic=0;function ct(){throw Error(n(321))}function wu(P,D){if(D===null)return!1;for(var T=0;T<D.length&&T<P.length;T++)if(!ds(P[T],D[T]))return!1;return!0}function s0(P,D,T,q,W,fe){if(Eu=fe,ja=D,fa=P!==null?P.memoizedState:null,FA.current=fa===null?rw:md,D=T(q,W),wl){do wl=!1,Ic+=1,fa=P!==null?P.memoizedState:null,Cc=Cu,Y=ws=Gi=null,FA.current=md,D=T(q,W);while(wl);bi=null,Ic=0}if(FA.current=Bu,P=ja,P.memoizedState=Cu,P.expirationTime=wc,P.updateQueue=Y,P.effectTag|=Dt,P=Gi!==null&&Gi.next!==null,Eu=0,Cc=ws=Cu=fa=Gi=ja=null,wc=0,Y=null,Dt=0,P)throw Error(n(300));return D}function tw(){FA.current=Bu,Eu=0,Cc=ws=Cu=fa=Gi=ja=null,wc=0,Y=null,Dt=0,wl=!1,bi=null,Ic=0}function RA(){var P={memoizedState:null,baseState:null,queue:null,baseUpdate:null,next:null};return ws===null?Cu=ws=P:ws=ws.next=P,ws}function up(){if(Cc!==null)ws=Cc,Cc=ws.next,Gi=fa,fa=Gi!==null?Gi.next:null;else{if(fa===null)throw Error(n(310));Gi=fa;var P={memoizedState:Gi.memoizedState,baseState:Gi.baseState,queue:Gi.queue,baseUpdate:Gi.baseUpdate,next:null};ws=ws===null?Cu=P:ws.next=P,fa=Gi.next}return ws}function Br(P,D){return typeof D=="function"?D(P):D}function Is(P){var D=up(),T=D.queue;if(T===null)throw Error(n(311));if(T.lastRenderedReducer=P,0<Ic){var q=T.dispatch;if(bi!==null){var W=bi.get(T);if(W!==void 0){bi.delete(T);var fe=D.memoizedState;do fe=P(fe,W.action),W=W.next;while(W!==null);return ds(fe,D.memoizedState)||(jo=!0),D.memoizedState=fe,D.baseUpdate===T.last&&(D.baseState=fe),T.lastRenderedState=fe,[fe,q]}}return[D.memoizedState,q]}q=T.last;var De=D.baseUpdate;if(fe=D.baseState,De!==null?(q!==null&&(q.next=null),q=De.next):q=q!==null?q.next:null,q!==null){var vt=W=null,wt=q,bt=!1;do{var _r=wt.expirationTime;_r<Eu?(bt||(bt=!0,vt=De,W=fe),_r>wc&&(wc=_r,bd(wc))):(uw(_r,wt.suspenseConfig),fe=wt.eagerReducer===P?wt.eagerState:P(fe,wt.action)),De=wt,wt=wt.next}while(wt!==null&&wt!==q);bt||(vt=De,W=fe),ds(fe,D.memoizedState)||(jo=!0),D.memoizedState=fe,D.baseUpdate=vt,D.baseState=W,T.lastRenderedState=fe}return[D.memoizedState,T.dispatch]}function o0(P){var D=RA();return typeof P=="function"&&(P=P()),D.memoizedState=D.baseState=P,P=D.queue={last:null,dispatch:null,lastRenderedReducer:Br,lastRenderedState:P},P=P.dispatch=A0.bind(null,ja,P),[D.memoizedState,P]}function a0(P){return Is(Br,P)}function l0(P,D,T,q){return P={tag:P,create:D,destroy:T,deps:q,next:null},Y===null?(Y={lastEffect:null},Y.lastEffect=P.next=P):(D=Y.lastEffect,D===null?Y.lastEffect=P.next=P:(T=D.next,D.next=P,P.next=T,Y.lastEffect=P)),P}function Ap(P,D,T,q){var W=RA();Dt|=P,W.memoizedState=l0(D,T,void 0,q===void 0?null:q)}function Bc(P,D,T,q){var W=up();q=q===void 0?null:q;var fe=void 0;if(Gi!==null){var De=Gi.memoizedState;if(fe=De.destroy,q!==null&&wu(q,De.deps)){l0(0,T,fe,q);return}}Dt|=P,W.memoizedState=l0(D,T,fe,q)}function Ct(P,D){return Ap(516,192,P,D)}function gd(P,D){return Bc(516,192,P,D)}function c0(P,D){if(typeof D=="function")return P=P(),D(P),function(){D(null)};if(D!=null)return P=P(),D.current=P,function(){D.current=null}}function u0(){}function Iu(P,D){return RA().memoizedState=[P,D===void 0?null:D],P}function dd(P,D){var T=up();D=D===void 0?null:D;var q=T.memoizedState;return q!==null&&D!==null&&wu(D,q[1])?q[0]:(T.memoizedState=[P,D],P)}function A0(P,D,T){if(!(25>Ic))throw Error(n(301));var q=P.alternate;if(P===ja||q!==null&&q===ja)if(wl=!0,P={expirationTime:Eu,suspenseConfig:null,action:T,eagerReducer:null,eagerState:null,next:null},bi===null&&(bi=new Map),T=bi.get(D),T===void 0)bi.set(D,P);else{for(D=T;D.next!==null;)D=D.next;D.next=P}else{var W=ma(),fe=pt.suspense;W=HA(W,P,fe),fe={expirationTime:W,suspenseConfig:fe,action:T,eagerReducer:null,eagerState:null,next:null};var De=D.last;if(De===null)fe.next=fe;else{var vt=De.next;vt!==null&&(fe.next=vt),De.next=fe}if(D.last=fe,P.expirationTime===0&&(q===null||q.expirationTime===0)&&(q=D.lastRenderedReducer,q!==null))try{var wt=D.lastRenderedState,bt=q(wt,T);if(fe.eagerReducer=q,fe.eagerState=bt,ds(bt,wt))return}catch{}finally{}bc(P,W)}}var Bu={readContext:Es,useCallback:ct,useContext:ct,useEffect:ct,useImperativeHandle:ct,useLayoutEffect:ct,useMemo:ct,useReducer:ct,useRef:ct,useState:ct,useDebugValue:ct,useResponder:ct,useDeferredValue:ct,useTransition:ct},rw={readContext:Es,useCallback:Iu,useContext:Es,useEffect:Ct,useImperativeHandle:function(P,D,T){return T=T!=null?T.concat([P]):null,Ap(4,36,c0.bind(null,D,P),T)},useLayoutEffect:function(P,D){return Ap(4,36,P,D)},useMemo:function(P,D){var T=RA();return D=D===void 0?null:D,P=P(),T.memoizedState=[P,D],P},useReducer:function(P,D,T){var q=RA();return D=T!==void 0?T(D):D,q.memoizedState=q.baseState=D,P=q.queue={last:null,dispatch:null,lastRenderedReducer:P,lastRenderedState:D},P=P.dispatch=A0.bind(null,ja,P),[q.memoizedState,P]},useRef:function(P){var D=RA();return P={current:P},D.memoizedState=P},useState:o0,useDebugValue:u0,useResponder:i0,useDeferredValue:function(P,D){var T=o0(P),q=T[0],W=T[1];return Ct(function(){a.unstable_next(function(){var fe=js.suspense;js.suspense=D===void 0?null:D;try{W(P)}finally{js.suspense=fe}})},[P,D]),q},useTransition:function(P){var D=o0(!1),T=D[0],q=D[1];return[Iu(function(W){q(!0),a.unstable_next(function(){var fe=js.suspense;js.suspense=P===void 0?null:P;try{q(!1),W()}finally{js.suspense=fe}})},[P,T]),T]}},md={readContext:Es,useCallback:dd,useContext:Es,useEffect:gd,useImperativeHandle:function(P,D,T){return T=T!=null?T.concat([P]):null,Bc(4,36,c0.bind(null,D,P),T)},useLayoutEffect:function(P,D){return Bc(4,36,P,D)},useMemo:function(P,D){var T=up();D=D===void 0?null:D;var q=T.memoizedState;return q!==null&&D!==null&&wu(D,q[1])?q[0]:(P=P(),T.memoizedState=[P,D],P)},useReducer:Is,useRef:function(){return up().memoizedState},useState:a0,useDebugValue:u0,useResponder:i0,useDeferredValue:function(P,D){var T=a0(P),q=T[0],W=T[1];return gd(function(){a.unstable_next(function(){var fe=js.suspense;js.suspense=D===void 0?null:D;try{W(P)}finally{js.suspense=fe}})},[P,D]),q},useTransition:function(P){var D=a0(!1),T=D[0],q=D[1];return[dd(function(W){q(!0),a.unstable_next(function(){var fe=js.suspense;js.suspense=P===void 0?null:P;try{q(!1),W()}finally{js.suspense=fe}})},[P,T]),T]}},pa=null,vc=null,Il=!1;function vu(P,D){var T=Dl(5,null,null,0);T.elementType="DELETED",T.type="DELETED",T.stateNode=D,T.return=P,T.effectTag=8,P.lastEffect!==null?(P.lastEffect.nextEffect=T,P.lastEffect=T):P.firstEffect=P.lastEffect=T}function f0(P,D){switch(P.tag){case 5:return D=io(D,P.type,P.pendingProps),D!==null?(P.stateNode=D,!0):!1;case 6:return D=Pi(D,P.pendingProps),D!==null?(P.stateNode=D,!0):!1;case 13:return!1;default:return!1}}function TA(P){if(Il){var D=vc;if(D){var T=D;if(!f0(P,D)){if(D=uc(T),!D||!f0(P,D)){P.effectTag=P.effectTag&-1025|2,Il=!1,pa=P;return}vu(pa,T)}pa=P,vc=Au(D)}else P.effectTag=P.effectTag&-1025|2,Il=!1,pa=P}}function fp(P){for(P=P.return;P!==null&&P.tag!==5&&P.tag!==3&&P.tag!==13;)P=P.return;pa=P}function Ga(P){if(!y||P!==pa)return!1;if(!Il)return fp(P),Il=!0,!1;var D=P.type;if(P.tag!==5||D!=="head"&&D!=="body"&&!Fe(D,P.memoizedProps))for(D=vc;D;)vu(P,D),D=uc(D);if(fp(P),P.tag===13){if(!y)throw Error(n(316));if(P=P.memoizedState,P=P!==null?P.dehydrated:null,!P)throw Error(n(317));vc=Us(P)}else vc=pa?uc(P.stateNode):null;return!0}function p0(){y&&(vc=pa=null,Il=!1)}var pp=u.ReactCurrentOwner,jo=!1;function Bs(P,D,T,q){D.child=P===null?t0(D,null,T,q):mu(D,P.child,T,q)}function wi(P,D,T,q,W){T=T.render;var fe=D.ref;return ys(D,W),q=s0(P,D,T,q,fe,W),P!==null&&!jo?(D.updateQueue=P.updateQueue,D.effectTag&=-517,P.expirationTime<=W&&(P.expirationTime=0),si(P,D,W)):(D.effectTag|=1,Bs(P,D,q,W),D.child)}function yd(P,D,T,q,W,fe){if(P===null){var De=T.type;return typeof De=="function"&&!hw(De)&&De.defaultProps===void 0&&T.compare===null&&T.defaultProps===void 0?(D.tag=15,D.type=De,Ed(P,D,De,q,W,fe)):(P=xd(T.type,null,q,null,D.mode,fe),P.ref=D.ref,P.return=D,D.child=P)}return De=P.child,W<fe&&(W=De.memoizedProps,T=T.compare,T=T!==null?T:Fn,T(W,q)&&P.ref===D.ref)?si(P,D,fe):(D.effectTag|=1,P=YA(De,q,fe),P.ref=D.ref,P.return=D,D.child=P)}function Ed(P,D,T,q,W,fe){return P!==null&&Fn(P.memoizedProps,q)&&P.ref===D.ref&&(jo=!1,W<fe)?si(P,D,fe):NA(P,D,T,q,fe)}function Go(P,D){var T=D.ref;(P===null&&T!==null||P!==null&&P.ref!==T)&&(D.effectTag|=128)}function NA(P,D,T,q,W){var fe=ii(T)?ir:On.current;return fe=Me(D,fe),ys(D,W),T=s0(P,D,T,q,fe,W),P!==null&&!jo?(D.updateQueue=P.updateQueue,D.effectTag&=-517,P.expirationTime<=W&&(P.expirationTime=0),si(P,D,W)):(D.effectTag|=1,Bs(P,D,T,W),D.child)}function hp(P,D,T,q,W){if(ii(T)){var fe=!0;fc(D)}else fe=!1;if(ys(D,W),D.stateNode===null)P!==null&&(P.alternate=null,D.alternate=null,D.effectTag|=2),rs(D,T,q,W),qo(D,T,q,W),q=!0;else if(P===null){var De=D.stateNode,vt=D.memoizedProps;De.props=vt;var wt=De.context,bt=T.contextType;typeof bt=="object"&&bt!==null?bt=Es(bt):(bt=ii(T)?ir:On.current,bt=Me(D,bt));var _r=T.getDerivedStateFromProps,os=typeof _r=="function"||typeof De.getSnapshotBeforeUpdate=="function";os||typeof De.UNSAFE_componentWillReceiveProps!="function"&&typeof De.componentWillReceiveProps!="function"||(vt!==q||wt!==bt)&&Si(D,De,q,bt),qs=!1;var di=D.memoizedState;wt=De.state=di;var po=D.updateQueue;po!==null&&(ye(D,po,q,De,W),wt=D.memoizedState),vt!==q||di!==wt||_i.current||qs?(typeof _r=="function"&&(rr(D,T,_r,q),wt=D.memoizedState),(vt=qs||ji(D,T,vt,q,di,wt,bt))?(os||typeof De.UNSAFE_componentWillMount!="function"&&typeof De.componentWillMount!="function"||(typeof De.componentWillMount=="function"&&De.componentWillMount(),typeof De.UNSAFE_componentWillMount=="function"&&De.UNSAFE_componentWillMount()),typeof De.componentDidMount=="function"&&(D.effectTag|=4)):(typeof De.componentDidMount=="function"&&(D.effectTag|=4),D.memoizedProps=q,D.memoizedState=wt),De.props=q,De.state=wt,De.context=bt,q=vt):(typeof De.componentDidMount=="function"&&(D.effectTag|=4),q=!1)}else De=D.stateNode,vt=D.memoizedProps,De.props=D.type===D.elementType?vt:Ei(D.type,vt),wt=De.context,bt=T.contextType,typeof bt=="object"&&bt!==null?bt=Es(bt):(bt=ii(T)?ir:On.current,bt=Me(D,bt)),_r=T.getDerivedStateFromProps,(os=typeof _r=="function"||typeof De.getSnapshotBeforeUpdate=="function")||typeof De.UNSAFE_componentWillReceiveProps!="function"&&typeof De.componentWillReceiveProps!="function"||(vt!==q||wt!==bt)&&Si(D,De,q,bt),qs=!1,wt=D.memoizedState,di=De.state=wt,po=D.updateQueue,po!==null&&(ye(D,po,q,De,W),di=D.memoizedState),vt!==q||wt!==di||_i.current||qs?(typeof _r=="function"&&(rr(D,T,_r,q),di=D.memoizedState),(_r=qs||ji(D,T,vt,q,wt,di,bt))?(os||typeof De.UNSAFE_componentWillUpdate!="function"&&typeof De.componentWillUpdate!="function"||(typeof De.componentWillUpdate=="function"&&De.componentWillUpdate(q,di,bt),typeof De.UNSAFE_componentWillUpdate=="function"&&De.UNSAFE_componentWillUpdate(q,di,bt)),typeof De.componentDidUpdate=="function"&&(D.effectTag|=4),typeof De.getSnapshotBeforeUpdate=="function"&&(D.effectTag|=256)):(typeof De.componentDidUpdate!="function"||vt===P.memoizedProps&&wt===P.memoizedState||(D.effectTag|=4),typeof De.getSnapshotBeforeUpdate!="function"||vt===P.memoizedProps&&wt===P.memoizedState||(D.effectTag|=256),D.memoizedProps=q,D.memoizedState=di),De.props=q,De.state=di,De.context=bt,q=_r):(typeof De.componentDidUpdate!="function"||vt===P.memoizedProps&&wt===P.memoizedState||(D.effectTag|=4),typeof De.getSnapshotBeforeUpdate!="function"||vt===P.memoizedProps&&wt===P.memoizedState||(D.effectTag|=256),q=!1);return gp(P,D,T,q,fe,W)}function gp(P,D,T,q,W,fe){Go(P,D);var De=(D.effectTag&64)!==0;if(!q&&!De)return W&&El(D,T,!1),si(P,D,fe);q=D.stateNode,pp.current=D;var vt=De&&typeof T.getDerivedStateFromError!="function"?null:q.render();return D.effectTag|=1,P!==null&&De?(D.child=mu(D,P.child,null,fe),D.child=mu(D,null,vt,fe)):Bs(P,D,vt,fe),D.memoizedState=q.state,W&&El(D,T,!0),D.child}function h0(P){var D=P.stateNode;D.pendingContext?Ac(P,D.pendingContext,D.pendingContext!==D.context):D.context&&Ac(P,D.context,!1),r0(P,D.containerInfo)}var ha={dehydrated:null,retryTime:0};function cn(P,D,T){var q=D.mode,W=D.pendingProps,fe=$n.current,De=!1,vt;if((vt=(D.effectTag&64)!==0)||(vt=(fe&2)!==0&&(P===null||P.memoizedState!==null)),vt?(De=!0,D.effectTag&=-65):P!==null&&P.memoizedState===null||W.fallback===void 0||W.unstable_avoidThisFallback===!0||(fe|=1),Mn($n,fe&1,D),P===null){if(W.fallback!==void 0&&TA(D),De){if(De=W.fallback,W=ku(null,q,0,null),W.return=D,!(D.mode&2))for(P=D.memoizedState!==null?D.child.child:D.child,W.child=P;P!==null;)P.return=W,P=P.sibling;return T=ku(De,q,T,null),T.return=D,W.sibling=T,D.memoizedState=ha,D.child=W,T}return q=W.children,D.memoizedState=null,D.child=t0(D,null,q,T)}if(P.memoizedState!==null){if(P=P.child,q=P.sibling,De){if(W=W.fallback,T=YA(P,P.pendingProps,0),T.return=D,!(D.mode&2)&&(De=D.memoizedState!==null?D.child.child:D.child,De!==P.child))for(T.child=De;De!==null;)De.return=T,De=De.sibling;return q=YA(q,W,q.expirationTime),q.return=D,T.sibling=q,T.childExpirationTime=0,D.memoizedState=ha,D.child=T,q}return T=mu(D,P.child,W.children,T),D.memoizedState=null,D.child=T}if(P=P.child,De){if(De=W.fallback,W=ku(null,q,0,null),W.return=D,W.child=P,P!==null&&(P.return=W),!(D.mode&2))for(P=D.memoizedState!==null?D.child.child:D.child,W.child=P;P!==null;)P.return=W,P=P.sibling;return T=ku(De,q,T,null),T.return=D,W.sibling=T,T.effectTag|=2,W.childExpirationTime=0,D.memoizedState=ha,D.child=W,T}return D.memoizedState=null,D.child=mu(D,P,W.children,T)}function Ao(P,D){P.expirationTime<D&&(P.expirationTime=D);var T=P.alternate;T!==null&&T.expirationTime<D&&(T.expirationTime=D),ms(P.return,D)}function LA(P,D,T,q,W,fe){var De=P.memoizedState;De===null?P.memoizedState={isBackwards:D,rendering:null,last:q,tail:T,tailExpiration:0,tailMode:W,lastEffect:fe}:(De.isBackwards=D,De.rendering=null,De.last=q,De.tail=T,De.tailExpiration=0,De.tailMode=W,De.lastEffect=fe)}function Ya(P,D,T){var q=D.pendingProps,W=q.revealOrder,fe=q.tail;if(Bs(P,D,q.children,T),q=$n.current,q&2)q=q&1|2,D.effectTag|=64;else{if(P!==null&&P.effectTag&64)e:for(P=D.child;P!==null;){if(P.tag===13)P.memoizedState!==null&&Ao(P,T);else if(P.tag===19)Ao(P,T);else if(P.child!==null){P.child.return=P,P=P.child;continue}if(P===D)break e;for(;P.sibling===null;){if(P.return===null||P.return===D)break e;P=P.return}P.sibling.return=P.return,P=P.sibling}q&=1}if(Mn($n,q,D),!(D.mode&2))D.memoizedState=null;else switch(W){case"forwards":for(T=D.child,W=null;T!==null;)P=T.alternate,P!==null&&cp(P)===null&&(W=T),T=T.sibling;T=W,T===null?(W=D.child,D.child=null):(W=T.sibling,T.sibling=null),LA(D,!1,W,T,fe,D.lastEffect);break;case"backwards":for(T=null,W=D.child,D.child=null;W!==null;){if(P=W.alternate,P!==null&&cp(P)===null){D.child=W;break}P=W.sibling,W.sibling=T,T=W,W=P}LA(D,!0,T,null,fe,D.lastEffect);break;case"together":LA(D,!1,null,null,void 0,D.lastEffect);break;default:D.memoizedState=null}return D.child}function si(P,D,T){P!==null&&(D.dependencies=P.dependencies);var q=D.expirationTime;if(q!==0&&bd(q),D.childExpirationTime<T)return null;if(P!==null&&D.child!==P.child)throw Error(n(153));if(D.child!==null){for(P=D.child,T=YA(P,P.pendingProps,P.expirationTime),D.child=T,T.return=D;P.sibling!==null;)P=P.sibling,T=T.sibling=YA(P,P.pendingProps,P.expirationTime),T.return=D;T.sibling=null}return D.child}function ga(P){P.effectTag|=4}var Dc,Bl,ns,Yr;if(w)Dc=function(P,D){for(var T=D.child;T!==null;){if(T.tag===5||T.tag===6)H(P,T.stateNode);else if(T.tag!==4&&T.child!==null){T.child.return=T,T=T.child;continue}if(T===D)break;for(;T.sibling===null;){if(T.return===null||T.return===D)return;T=T.return}T.sibling.return=T.return,T=T.sibling}},Bl=function(){},ns=function(P,D,T,q,W){if(P=P.memoizedProps,P!==q){var fe=D.stateNode,De=Aa(uo.current);T=Te(fe,T,P,q,W,De),(D.updateQueue=T)&&ga(D)}},Yr=function(P,D,T,q){T!==q&&ga(D)};else if(S){Dc=function(P,D,T,q){for(var W=D.child;W!==null;){if(W.tag===5){var fe=W.stateNode;T&&q&&(fe=Ri(fe,W.type,W.memoizedProps,W)),H(P,fe)}else if(W.tag===6)fe=W.stateNode,T&&q&&(fe=gs(fe,W.memoizedProps,W)),H(P,fe);else if(W.tag!==4){if(W.tag===13&&W.effectTag&4&&(fe=W.memoizedState!==null)){var De=W.child;if(De!==null&&(De.child!==null&&(De.child.return=De,Dc(P,De,!0,fe)),fe=De.sibling,fe!==null)){fe.return=W,W=fe;continue}}if(W.child!==null){W.child.return=W,W=W.child;continue}}if(W===D)break;for(;W.sibling===null;){if(W.return===null||W.return===D)return;W=W.return}W.sibling.return=W.return,W=W.sibling}};var dp=function(P,D,T,q){for(var W=D.child;W!==null;){if(W.tag===5){var fe=W.stateNode;T&&q&&(fe=Ri(fe,W.type,W.memoizedProps,W)),Kr(P,fe)}else if(W.tag===6)fe=W.stateNode,T&&q&&(fe=gs(fe,W.memoizedProps,W)),Kr(P,fe);else if(W.tag!==4){if(W.tag===13&&W.effectTag&4&&(fe=W.memoizedState!==null)){var De=W.child;if(De!==null&&(De.child!==null&&(De.child.return=De,dp(P,De,!0,fe)),fe=De.sibling,fe!==null)){fe.return=W,W=fe;continue}}if(W.child!==null){W.child.return=W,W=W.child;continue}}if(W===D)break;for(;W.sibling===null;){if(W.return===null||W.return===D)return;W=W.return}W.sibling.return=W.return,W=W.sibling}};Bl=function(P){var D=P.stateNode;if(P.firstEffect!==null){var T=D.containerInfo,q=br(T);dp(q,P,!1,!1),D.pendingChildren=q,ga(P),Kn(T,q)}},ns=function(P,D,T,q,W){var fe=P.stateNode,De=P.memoizedProps;if((P=D.firstEffect===null)&&De===q)D.stateNode=fe;else{var vt=D.stateNode,wt=Aa(uo.current),bt=null;De!==q&&(bt=Te(vt,T,De,q,W,wt)),P&&bt===null?D.stateNode=fe:(fe=mr(fe,bt,T,De,q,D,P,vt),rt(fe,T,q,W,wt)&&ga(D),D.stateNode=fe,P?ga(D):Dc(fe,D,!1,!1))}},Yr=function(P,D,T,q){T!==q&&(P=Aa(yc.current),T=Aa(uo.current),D.stateNode=Ye(q,P,T,D),ga(D))}}else Bl=function(){},ns=function(){},Yr=function(){};function Pc(P,D){switch(P.tailMode){case"hidden":D=P.tail;for(var T=null;D!==null;)D.alternate!==null&&(T=D),D=D.sibling;T===null?P.tail=null:T.sibling=null;break;case"collapsed":T=P.tail;for(var q=null;T!==null;)T.alternate!==null&&(q=T),T=T.sibling;q===null?D||P.tail===null?P.tail=null:P.tail.sibling=null:q.sibling=null}}function nw(P){switch(P.tag){case 1:ii(P.type)&&Ha(P);var D=P.effectTag;return D&4096?(P.effectTag=D&-4097|64,P):null;case 3:if(Ec(P),hr(P),D=P.effectTag,D&64)throw Error(n(285));return P.effectTag=D&-4097|64,P;case 5:return n0(P),null;case 13:return Vn($n,P),D=P.effectTag,D&4096?(P.effectTag=D&-4097|64,P):null;case 19:return Vn($n,P),null;case 4:return Ec(P),null;case 10:return Ci(P),null;default:return null}}function g0(P,D){return{value:P,source:D,stack:ml(D)}}var d0=typeof WeakSet=="function"?WeakSet:Set;function Wa(P,D){var T=D.source,q=D.stack;q===null&&T!==null&&(q=ml(T)),T!==null&&de(T.type),D=D.value,P!==null&&P.tag===1&&de(P.type);try{console.error(D)}catch(W){setTimeout(function(){throw W})}}function Cd(P,D){try{D.props=P.memoizedProps,D.state=P.memoizedState,D.componentWillUnmount()}catch(T){GA(P,T)}}function m0(P){var D=P.ref;if(D!==null)if(typeof D=="function")try{D(null)}catch(T){GA(P,T)}else D.current=null}function Qt(P,D){switch(D.tag){case 0:case 11:case 15:N(2,0,D);break;case 1:if(D.effectTag&256&&P!==null){var T=P.memoizedProps,q=P.memoizedState;P=D.stateNode,D=P.getSnapshotBeforeUpdate(D.elementType===D.type?T:Ei(D.type,T),q),P.__reactInternalSnapshotBeforeUpdate=D}break;case 3:case 5:case 6:case 4:case 17:break;default:throw Error(n(163))}}function N(P,D,T){if(T=T.updateQueue,T=T!==null?T.lastEffect:null,T!==null){var q=T=T.next;do{if(q.tag&P){var W=q.destroy;q.destroy=void 0,W!==void 0&&W()}q.tag&D&&(W=q.create,q.destroy=W()),q=q.next}while(q!==T)}}function V(P,D,T){switch(typeof pw=="function"&&pw(D),D.tag){case 0:case 11:case 14:case 15:if(P=D.updateQueue,P!==null&&(P=P.lastEffect,P!==null)){var q=P.next;lo(97<T?97:T,function(){var W=q;do{var fe=W.destroy;if(fe!==void 0){var De=D;try{fe()}catch(vt){GA(De,vt)}}W=W.next}while(W!==q)})}break;case 1:m0(D),T=D.stateNode,typeof T.componentWillUnmount=="function"&&Cd(D,T);break;case 5:m0(D);break;case 4:w?Cr(P,D,T):S&&ze(D)}}function re(P,D,T){for(var q=D;;)if(V(P,q,T),q.child===null||w&&q.tag===4){if(q===D)break;for(;q.sibling===null;){if(q.return===null||q.return===D)return;q=q.return}q.sibling.return=q.return,q=q.sibling}else q.child.return=q,q=q.child}function he(P){var D=P.alternate;P.return=null,P.child=null,P.memoizedState=null,P.updateQueue=null,P.dependencies=null,P.alternate=null,P.firstEffect=null,P.lastEffect=null,P.pendingProps=null,P.memoizedProps=null,D!==null&&he(D)}function ze(P){if(S){P=P.stateNode.containerInfo;var D=br(P);Ms(P,D)}}function mt(P){return P.tag===5||P.tag===3||P.tag===4}function fr(P){if(w){e:{for(var D=P.return;D!==null;){if(mt(D)){var T=D;break e}D=D.return}throw Error(n(160))}switch(D=T.stateNode,T.tag){case 5:var q=!1;break;case 3:D=D.containerInfo,q=!0;break;case 4:D=D.containerInfo,q=!0;break;default:throw Error(n(161))}T.effectTag&16&&(jt(D),T.effectTag&=-17);e:t:for(T=P;;){for(;T.sibling===null;){if(T.return===null||mt(T.return)){T=null;break e}T=T.return}for(T.sibling.return=T.return,T=T.sibling;T.tag!==5&&T.tag!==6&&T.tag!==18;){if(T.effectTag&2||T.child===null||T.tag===4)continue t;T.child.return=T,T=T.child}if(!(T.effectTag&2)){T=T.stateNode;break e}}for(var W=P;;){var fe=W.tag===5||W.tag===6;if(fe)fe=fe?W.stateNode:W.stateNode.instance,T?q?Re(D,fe,T):be(D,fe,T):q?J(D,fe):F(D,fe);else if(W.tag!==4&&W.child!==null){W.child.return=W,W=W.child;continue}if(W===P)break;for(;W.sibling===null;){if(W.return===null||W.return===P)return;W=W.return}W.sibling.return=W.return,W=W.sibling}}}function Cr(P,D,T){for(var q=D,W=!1,fe,De;;){if(!W){W=q.return;e:for(;;){if(W===null)throw Error(n(160));switch(fe=W.stateNode,W.tag){case 5:De=!1;break e;case 3:fe=fe.containerInfo,De=!0;break e;case 4:fe=fe.containerInfo,De=!0;break e}W=W.return}W=!0}if(q.tag===5||q.tag===6)re(P,q,T),De?dt(fe,q.stateNode):at(fe,q.stateNode);else if(q.tag===4){if(q.child!==null){fe=q.stateNode.containerInfo,De=!0,q.child.return=q,q=q.child;continue}}else if(V(P,q,T),q.child!==null){q.child.return=q,q=q.child;continue}if(q===D)break;for(;q.sibling===null;){if(q.return===null||q.return===D)return;q=q.return,q.tag===4&&(W=!1)}q.sibling.return=q.return,q=q.sibling}}function yn(P,D){if(w)switch(D.tag){case 0:case 11:case 14:case 15:N(4,8,D);break;case 1:break;case 5:var T=D.stateNode;if(T!=null){var q=D.memoizedProps;P=P!==null?P.memoizedProps:q;var W=D.type,fe=D.updateQueue;D.updateQueue=null,fe!==null&&ie(T,fe,W,P,q,D)}break;case 6:if(D.stateNode===null)throw Error(n(162));T=D.memoizedProps,X(D.stateNode,P!==null?P.memoizedProps:T,T);break;case 3:y&&(D=D.stateNode,D.hydrate&&(D.hydrate=!1,Dn(D.containerInfo)));break;case 12:break;case 13:oi(D),Li(D);break;case 19:Li(D);break;case 17:break;case 20:break;case 21:break;default:throw Error(n(163))}else{switch(D.tag){case 0:case 11:case 14:case 15:N(4,8,D);return;case 12:return;case 13:oi(D),Li(D);return;case 19:Li(D);return;case 3:y&&(T=D.stateNode,T.hydrate&&(T.hydrate=!1,Dn(T.containerInfo)))}e:if(S)switch(D.tag){case 1:case 5:case 6:case 20:break e;case 3:case 4:D=D.stateNode,Ms(D.containerInfo,D.pendingChildren);break e;default:throw Error(n(163))}}}function oi(P){var D=P;if(P.memoizedState===null)var T=!1;else T=!0,D=P.child,ow=Ni();if(w&&D!==null){e:if(P=D,w)for(D=P;;){if(D.tag===5){var q=D.stateNode;T?tr(q):ln(D.stateNode,D.memoizedProps)}else if(D.tag===6)q=D.stateNode,T?St(q):kr(q,D.memoizedProps);else if(D.tag===13&&D.memoizedState!==null&&D.memoizedState.dehydrated===null){q=D.child.sibling,q.return=D,D=q;continue}else if(D.child!==null){D.child.return=D,D=D.child;continue}if(D===P)break e;for(;D.sibling===null;){if(D.return===null||D.return===P)break e;D=D.return}D.sibling.return=D.return,D=D.sibling}}}function Li(P){var D=P.updateQueue;if(D!==null){P.updateQueue=null;var T=P.stateNode;T===null&&(T=P.stateNode=new d0),D.forEach(function(q){var W=aF.bind(null,P,q);T.has(q)||(T.add(q),q.then(W,W))})}}var y0=typeof WeakMap=="function"?WeakMap:Map;function Sv(P,D,T){T=Cs(T,null),T.tag=3,T.payload={element:null};var q=D.value;return T.callback=function(){Pu||(Pu=!0,Dd=q),Wa(P,D)},T}function bv(P,D,T){T=Cs(T,null),T.tag=3;var q=P.type.getDerivedStateFromError;if(typeof q=="function"){var W=D.value;T.payload=function(){return Wa(P,D),q(W)}}var fe=P.stateNode;return fe!==null&&typeof fe.componentDidCatch=="function"&&(T.callback=function(){typeof q!="function"&&(Su===null?Su=new Set([this]):Su.add(this),Wa(P,D));var De=D.stack;this.componentDidCatch(D.value,{componentStack:De!==null?De:""})}),T}var iw=Math.ceil,mp=u.ReactCurrentDispatcher,sw=u.ReactCurrentOwner,En=0,wd=8,is=16,Gs=32,Du=0,Id=1,Ii=2,da=3,vl=4,Sc=5,yr=En,gi=null,Mr=null,ss=0,Yi=Du,Bd=null,Ka=1073741823,MA=1073741823,vd=null,yp=0,OA=!1,ow=0,aw=500,lr=null,Pu=!1,Dd=null,Su=null,Ep=!1,E0=null,UA=90,_A=null,C0=0,lw=null,Pd=0;function ma(){return(yr&(is|Gs))!==En?1073741821-(Ni()/10|0):Pd!==0?Pd:Pd=1073741821-(Ni()/10|0)}function HA(P,D,T){if(D=D.mode,!(D&2))return 1073741823;var q=_o();if(!(D&4))return q===99?1073741823:1073741822;if((yr&is)!==En)return ss;if(T!==null)P=qa(P,T.timeoutMs|0||5e3,250);else switch(q){case 99:P=1073741823;break;case 98:P=qa(P,150,100);break;case 97:case 96:P=qa(P,5e3,250);break;case 95:P=2;break;default:throw Error(n(326))}return gi!==null&&P===ss&&--P,P}function bc(P,D){if(50<C0)throw C0=0,lw=null,Error(n(185));if(P=w0(P,D),P!==null){var T=_o();D===1073741823?(yr&wd)!==En&&(yr&(is|Gs))===En?cw(P):(fo(P),yr===En&&qi()):fo(P),(yr&4)===En||T!==98&&T!==99||(_A===null?_A=new Map([[P,D]]):(T=_A.get(P),(T===void 0||T>D)&&_A.set(P,D)))}}function w0(P,D){P.expirationTime<D&&(P.expirationTime=D);var T=P.alternate;T!==null&&T.expirationTime<D&&(T.expirationTime=D);var q=P.return,W=null;if(q===null&&P.tag===3)W=P.stateNode;else for(;q!==null;){if(T=q.alternate,q.childExpirationTime<D&&(q.childExpirationTime=D),T!==null&&T.childExpirationTime<D&&(T.childExpirationTime=D),q.return===null&&q.tag===3){W=q.stateNode;break}q=q.return}return W!==null&&(gi===W&&(bd(D),Yi===vl&&WA(W,ss)),Mv(W,D)),W}function Sd(P){var D=P.lastExpiredTime;return D!==0||(D=P.firstPendingTime,!Lv(P,D))?D:(D=P.lastPingedTime,P=P.nextKnownPendingLevel,D>P?D:P)}function fo(P){if(P.lastExpiredTime!==0)P.callbackExpirationTime=1073741823,P.callbackPriority=99,P.callbackNode=gu(cw.bind(null,P));else{var D=Sd(P),T=P.callbackNode;if(D===0)T!==null&&(P.callbackNode=null,P.callbackExpirationTime=0,P.callbackPriority=90);else{var q=ma();if(D===1073741823?q=99:D===1||D===2?q=95:(q=10*(1073741821-D)-10*(1073741821-q),q=0>=q?99:250>=q?98:5250>=q?97:95),T!==null){var W=P.callbackPriority;if(P.callbackExpirationTime===D&&W>=q)return;T!==PA&&Ie(T)}P.callbackExpirationTime=D,P.callbackPriority=q,D=D===1073741823?gu(cw.bind(null,P)):dc(q,xv.bind(null,P),{timeout:10*(1073741821-D)-Ni()}),P.callbackNode=D}}}function xv(P,D){if(Pd=0,D)return D=ma(),kd(P,D),fo(P),null;var T=Sd(P);if(T!==0){if(D=P.callbackNode,(yr&(is|Gs))!==En)throw Error(n(327));if(Cp(),P===gi&&T===ss||bu(P,T),Mr!==null){var q=yr;yr|=is;var W=jA(P);do try{rF();break}catch(vt){qA(P,vt)}while(!0);if(ua(),yr=q,mp.current=W,Yi===Id)throw D=Bd,bu(P,T),WA(P,T),fo(P),D;if(Mr===null)switch(W=P.finishedWork=P.current.alternate,P.finishedExpirationTime=T,q=Yi,gi=null,q){case Du:case Id:throw Error(n(345));case Ii:kd(P,2<T?2:T);break;case da:if(WA(P,T),q=P.lastSuspendedTime,T===q&&(P.nextKnownPendingLevel=Aw(W)),Ka===1073741823&&(W=ow+aw-Ni(),10<W)){if(OA){var fe=P.lastPingedTime;if(fe===0||fe>=T){P.lastPingedTime=T,bu(P,T);break}}if(fe=Sd(P),fe!==0&&fe!==T)break;if(q!==0&&q!==T){P.lastPingedTime=q;break}P.timeoutHandle=Se(xu.bind(null,P),W);break}xu(P);break;case vl:if(WA(P,T),q=P.lastSuspendedTime,T===q&&(P.nextKnownPendingLevel=Aw(W)),OA&&(W=P.lastPingedTime,W===0||W>=T)){P.lastPingedTime=T,bu(P,T);break}if(W=Sd(P),W!==0&&W!==T)break;if(q!==0&&q!==T){P.lastPingedTime=q;break}if(MA!==1073741823?q=10*(1073741821-MA)-Ni():Ka===1073741823?q=0:(q=10*(1073741821-Ka)-5e3,W=Ni(),T=10*(1073741821-T)-W,q=W-q,0>q&&(q=0),q=(120>q?120:480>q?480:1080>q?1080:1920>q?1920:3e3>q?3e3:4320>q?4320:1960*iw(q/1960))-q,T<q&&(q=T)),10<q){P.timeoutHandle=Se(xu.bind(null,P),q);break}xu(P);break;case Sc:if(Ka!==1073741823&&vd!==null){fe=Ka;var De=vd;if(q=De.busyMinDurationMs|0,0>=q?q=0:(W=De.busyDelayMs|0,fe=Ni()-(10*(1073741821-fe)-(De.timeoutMs|0||5e3)),q=fe<=W?0:W+q-fe),10<q){WA(P,T),P.timeoutHandle=Se(xu.bind(null,P),q);break}}xu(P);break;default:throw Error(n(329))}if(fo(P),P.callbackNode===D)return xv.bind(null,P)}}return null}function cw(P){var D=P.lastExpiredTime;if(D=D!==0?D:1073741823,P.finishedExpirationTime===D)xu(P);else{if((yr&(is|Gs))!==En)throw Error(n(327));if(Cp(),P===gi&&D===ss||bu(P,D),Mr!==null){var T=yr;yr|=is;var q=jA(P);do try{tF();break}catch(W){qA(P,W)}while(!0);if(ua(),yr=T,mp.current=q,Yi===Id)throw T=Bd,bu(P,D),WA(P,D),fo(P),T;if(Mr!==null)throw Error(n(261));P.finishedWork=P.current.alternate,P.finishedExpirationTime=D,gi=null,xu(P),fo(P)}}return null}function kv(P,D){kd(P,D),fo(P),(yr&(is|Gs))===En&&qi()}function eF(){if(_A!==null){var P=_A;_A=null,P.forEach(function(D,T){kd(T,D),fo(T)}),qi()}}function Qv(P,D){if((yr&(is|Gs))!==En)throw Error(n(187));var T=yr;yr|=1;try{return lo(99,P.bind(null,D))}finally{yr=T,qi()}}function bu(P,D){P.finishedWork=null,P.finishedExpirationTime=0;var T=P.timeoutHandle;if(T!==Ue&&(P.timeoutHandle=Ue,et(T)),Mr!==null)for(T=Mr.return;T!==null;){var q=T;switch(q.tag){case 1:var W=q.type.childContextTypes;W!=null&&Ha(q);break;case 3:Ec(q),hr(q);break;case 5:n0(q);break;case 4:Ec(q);break;case 13:Vn($n,q);break;case 19:Vn($n,q);break;case 10:Ci(q)}T=T.return}gi=P,Mr=YA(P.current,null,D),ss=D,Yi=Du,Bd=null,MA=Ka=1073741823,vd=null,yp=0,OA=!1}function qA(P,D){do{try{if(ua(),tw(),Mr===null||Mr.return===null)return Yi=Id,Bd=D,null;e:{var T=P,q=Mr.return,W=Mr,fe=D;if(D=ss,W.effectTag|=2048,W.firstEffect=W.lastEffect=null,fe!==null&&typeof fe=="object"&&typeof fe.then=="function"){var De=fe,vt=($n.current&1)!==0,wt=q;do{var bt;if(bt=wt.tag===13){var _r=wt.memoizedState;if(_r!==null)bt=_r.dehydrated!==null;else{var os=wt.memoizedProps;bt=os.fallback===void 0?!1:os.unstable_avoidThisFallback!==!0?!0:!vt}}if(bt){var di=wt.updateQueue;if(di===null){var po=new Set;po.add(De),wt.updateQueue=po}else di.add(De);if(!(wt.mode&2)){if(wt.effectTag|=64,W.effectTag&=-2981,W.tag===1)if(W.alternate===null)W.tag=17;else{var KA=Cs(1073741823,null);KA.tag=2,tt(W,KA)}W.expirationTime=1073741823;break e}fe=void 0,W=D;var Yo=T.pingCache;if(Yo===null?(Yo=T.pingCache=new y0,fe=new Set,Yo.set(De,fe)):(fe=Yo.get(De),fe===void 0&&(fe=new Set,Yo.set(De,fe))),!fe.has(W)){fe.add(W);var nt=oF.bind(null,T,De,W);De.then(nt,nt)}wt.effectTag|=4096,wt.expirationTime=D;break e}wt=wt.return}while(wt!==null);fe=Error((de(W.type)||"A React component")+` suspended while rendering, but no fallback UI was specified. + +Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.`+ml(W))}Yi!==Sc&&(Yi=Ii),fe=g0(fe,W),wt=q;do{switch(wt.tag){case 3:De=fe,wt.effectTag|=4096,wt.expirationTime=D;var Ve=Sv(wt,De,D);Bt(wt,Ve);break e;case 1:De=fe;var At=wt.type,Wt=wt.stateNode;if(!(wt.effectTag&64)&&(typeof At.getDerivedStateFromError=="function"||Wt!==null&&typeof Wt.componentDidCatch=="function"&&(Su===null||!Su.has(Wt)))){wt.effectTag|=4096,wt.expirationTime=D;var vr=bv(wt,De,D);Bt(wt,vr);break e}}wt=wt.return}while(wt!==null)}Mr=Rv(Mr)}catch(Sn){D=Sn;continue}break}while(!0)}function jA(){var P=mp.current;return mp.current=Bu,P===null?Bu:P}function uw(P,D){P<Ka&&2<P&&(Ka=P),D!==null&&P<MA&&2<P&&(MA=P,vd=D)}function bd(P){P>yp&&(yp=P)}function tF(){for(;Mr!==null;)Mr=Fv(Mr)}function rF(){for(;Mr!==null&&!Tt();)Mr=Fv(Mr)}function Fv(P){var D=Nv(P.alternate,P,ss);return P.memoizedProps=P.pendingProps,D===null&&(D=Rv(P)),sw.current=null,D}function Rv(P){Mr=P;do{var D=Mr.alternate;if(P=Mr.return,Mr.effectTag&2048){if(D=nw(Mr,ss),D!==null)return D.effectTag&=2047,D;P!==null&&(P.firstEffect=P.lastEffect=null,P.effectTag|=2048)}else{e:{var T=D;D=Mr;var q=ss,W=D.pendingProps;switch(D.tag){case 2:break;case 16:break;case 15:case 0:break;case 1:ii(D.type)&&Ha(D);break;case 3:Ec(D),hr(D),W=D.stateNode,W.pendingContext&&(W.context=W.pendingContext,W.pendingContext=null),(T===null||T.child===null)&&Ga(D)&&ga(D),Bl(D);break;case 5:n0(D);var fe=Aa(yc.current);if(q=D.type,T!==null&&D.stateNode!=null)ns(T,D,q,W,fe),T.ref!==D.ref&&(D.effectTag|=128);else if(W){if(T=Aa(uo.current),Ga(D)){if(W=D,!y)throw Error(n(175));T=sp(W.stateNode,W.type,W.memoizedProps,fe,T,W),W.updateQueue=T,T=T!==null,T&&ga(D)}else{var De=ht(q,W,fe,T,D);Dc(De,D,!1,!1),D.stateNode=De,rt(De,q,W,fe,T)&&ga(D)}D.ref!==null&&(D.effectTag|=128)}else if(D.stateNode===null)throw Error(n(166));break;case 6:if(T&&D.stateNode!=null)Yr(T,D,T.memoizedProps,W);else{if(typeof W!="string"&&D.stateNode===null)throw Error(n(166));if(T=Aa(yc.current),fe=Aa(uo.current),Ga(D)){if(T=D,!y)throw Error(n(176));(T=op(T.stateNode,T.memoizedProps,T))&&ga(D)}else D.stateNode=Ye(W,T,fe,D)}break;case 11:break;case 13:if(Vn($n,D),W=D.memoizedState,D.effectTag&64){D.expirationTime=q;break e}W=W!==null,fe=!1,T===null?D.memoizedProps.fallback!==void 0&&Ga(D):(q=T.memoizedState,fe=q!==null,W||q===null||(q=T.child.sibling,q!==null&&(De=D.firstEffect,De!==null?(D.firstEffect=q,q.nextEffect=De):(D.firstEffect=D.lastEffect=q,q.nextEffect=null),q.effectTag=8))),W&&!fe&&D.mode&2&&(T===null&&D.memoizedProps.unstable_avoidThisFallback!==!0||$n.current&1?Yi===Du&&(Yi=da):((Yi===Du||Yi===da)&&(Yi=vl),yp!==0&&gi!==null&&(WA(gi,ss),Mv(gi,yp)))),S&&W&&(D.effectTag|=4),w&&(W||fe)&&(D.effectTag|=4);break;case 7:break;case 8:break;case 12:break;case 4:Ec(D),Bl(D);break;case 10:Ci(D);break;case 9:break;case 14:break;case 17:ii(D.type)&&Ha(D);break;case 19:if(Vn($n,D),W=D.memoizedState,W===null)break;if(fe=(D.effectTag&64)!==0,De=W.rendering,De===null){if(fe)Pc(W,!1);else if(Yi!==Du||T!==null&&T.effectTag&64)for(T=D.child;T!==null;){if(De=cp(T),De!==null){for(D.effectTag|=64,Pc(W,!1),T=De.updateQueue,T!==null&&(D.updateQueue=T,D.effectTag|=4),W.lastEffect===null&&(D.firstEffect=null),D.lastEffect=W.lastEffect,T=q,W=D.child;W!==null;)fe=W,q=T,fe.effectTag&=2,fe.nextEffect=null,fe.firstEffect=null,fe.lastEffect=null,De=fe.alternate,De===null?(fe.childExpirationTime=0,fe.expirationTime=q,fe.child=null,fe.memoizedProps=null,fe.memoizedState=null,fe.updateQueue=null,fe.dependencies=null):(fe.childExpirationTime=De.childExpirationTime,fe.expirationTime=De.expirationTime,fe.child=De.child,fe.memoizedProps=De.memoizedProps,fe.memoizedState=De.memoizedState,fe.updateQueue=De.updateQueue,q=De.dependencies,fe.dependencies=q===null?null:{expirationTime:q.expirationTime,firstContext:q.firstContext,responders:q.responders}),W=W.sibling;Mn($n,$n.current&1|2,D),D=D.child;break e}T=T.sibling}}else{if(!fe)if(T=cp(De),T!==null){if(D.effectTag|=64,fe=!0,T=T.updateQueue,T!==null&&(D.updateQueue=T,D.effectTag|=4),Pc(W,!0),W.tail===null&&W.tailMode==="hidden"&&!De.alternate){D=D.lastEffect=W.lastEffect,D!==null&&(D.nextEffect=null);break}}else Ni()>W.tailExpiration&&1<q&&(D.effectTag|=64,fe=!0,Pc(W,!1),D.expirationTime=D.childExpirationTime=q-1);W.isBackwards?(De.sibling=D.child,D.child=De):(T=W.last,T!==null?T.sibling=De:D.child=De,W.last=De)}if(W.tail!==null){W.tailExpiration===0&&(W.tailExpiration=Ni()+500),T=W.tail,W.rendering=T,W.tail=T.sibling,W.lastEffect=D.lastEffect,T.sibling=null,W=$n.current,W=fe?W&1|2:W&1,Mn($n,W,D),D=T;break e}break;case 20:break;case 21:break;default:throw Error(n(156,D.tag))}D=null}if(T=Mr,ss===1||T.childExpirationTime!==1){for(W=0,fe=T.child;fe!==null;)q=fe.expirationTime,De=fe.childExpirationTime,q>W&&(W=q),De>W&&(W=De),fe=fe.sibling;T.childExpirationTime=W}if(D!==null)return D;P!==null&&!(P.effectTag&2048)&&(P.firstEffect===null&&(P.firstEffect=Mr.firstEffect),Mr.lastEffect!==null&&(P.lastEffect!==null&&(P.lastEffect.nextEffect=Mr.firstEffect),P.lastEffect=Mr.lastEffect),1<Mr.effectTag&&(P.lastEffect!==null?P.lastEffect.nextEffect=Mr:P.firstEffect=Mr,P.lastEffect=Mr))}if(D=Mr.sibling,D!==null)return D;Mr=P}while(Mr!==null);return Yi===Du&&(Yi=Sc),null}function Aw(P){var D=P.expirationTime;return P=P.childExpirationTime,D>P?D:P}function xu(P){var D=_o();return lo(99,nF.bind(null,P,D)),null}function nF(P,D){do Cp();while(E0!==null);if((yr&(is|Gs))!==En)throw Error(n(327));var T=P.finishedWork,q=P.finishedExpirationTime;if(T===null)return null;if(P.finishedWork=null,P.finishedExpirationTime=0,T===P.current)throw Error(n(177));P.callbackNode=null,P.callbackExpirationTime=0,P.callbackPriority=90,P.nextKnownPendingLevel=0;var W=Aw(T);if(P.firstPendingTime=W,q<=P.lastSuspendedTime?P.firstSuspendedTime=P.lastSuspendedTime=P.nextKnownPendingLevel=0:q<=P.firstSuspendedTime&&(P.firstSuspendedTime=q-1),q<=P.lastPingedTime&&(P.lastPingedTime=0),q<=P.lastExpiredTime&&(P.lastExpiredTime=0),P===gi&&(Mr=gi=null,ss=0),1<T.effectTag?T.lastEffect!==null?(T.lastEffect.nextEffect=T,W=T.firstEffect):W=T:W=T.firstEffect,W!==null){var fe=yr;yr|=Gs,sw.current=null,xe(P.containerInfo),lr=W;do try{iF()}catch(ho){if(lr===null)throw Error(n(330));GA(lr,ho),lr=lr.nextEffect}while(lr!==null);lr=W;do try{for(var De=P,vt=D;lr!==null;){var wt=lr.effectTag;if(wt&16&&w&&jt(lr.stateNode),wt&128){var bt=lr.alternate;if(bt!==null){var _r=bt.ref;_r!==null&&(typeof _r=="function"?_r(null):_r.current=null)}}switch(wt&1038){case 2:fr(lr),lr.effectTag&=-3;break;case 6:fr(lr),lr.effectTag&=-3,yn(lr.alternate,lr);break;case 1024:lr.effectTag&=-1025;break;case 1028:lr.effectTag&=-1025,yn(lr.alternate,lr);break;case 4:yn(lr.alternate,lr);break;case 8:var os=De,di=lr,po=vt;w?Cr(os,di,po):re(os,di,po),he(di)}lr=lr.nextEffect}}catch(ho){if(lr===null)throw Error(n(330));GA(lr,ho),lr=lr.nextEffect}while(lr!==null);Ne(P.containerInfo),P.current=T,lr=W;do try{for(wt=q;lr!==null;){var KA=lr.effectTag;if(KA&36){var Yo=lr.alternate;switch(bt=lr,_r=wt,bt.tag){case 0:case 11:case 15:N(16,32,bt);break;case 1:var nt=bt.stateNode;if(bt.effectTag&4)if(Yo===null)nt.componentDidMount();else{var Ve=bt.elementType===bt.type?Yo.memoizedProps:Ei(bt.type,Yo.memoizedProps);nt.componentDidUpdate(Ve,Yo.memoizedState,nt.__reactInternalSnapshotBeforeUpdate)}var At=bt.updateQueue;At!==null&&Le(bt,At,nt,_r);break;case 3:var Wt=bt.updateQueue;if(Wt!==null){if(De=null,bt.child!==null)switch(bt.child.tag){case 5:De=Ae(bt.child.stateNode);break;case 1:De=bt.child.stateNode}Le(bt,Wt,De,_r)}break;case 5:var vr=bt.stateNode;Yo===null&&bt.effectTag&4&&$(vr,bt.type,bt.memoizedProps,bt);break;case 6:break;case 4:break;case 12:break;case 13:if(y&&bt.memoizedState===null){var Sn=bt.alternate;if(Sn!==null){var Qr=Sn.memoizedState;if(Qr!==null){var bn=Qr.dehydrated;bn!==null&&oo(bn)}}}break;case 19:case 17:case 20:case 21:break;default:throw Error(n(163))}}if(KA&128){bt=void 0;var ai=lr.ref;if(ai!==null){var tn=lr.stateNode;switch(lr.tag){case 5:bt=Ae(tn);break;default:bt=tn}typeof ai=="function"?ai(bt):ai.current=bt}}lr=lr.nextEffect}}catch(ho){if(lr===null)throw Error(n(330));GA(lr,ho),lr=lr.nextEffect}while(lr!==null);lr=null,Qn(),yr=fe}else P.current=T;if(Ep)Ep=!1,E0=P,UA=D;else for(lr=W;lr!==null;)D=lr.nextEffect,lr.nextEffect=null,lr=D;if(D=P.firstPendingTime,D===0&&(Su=null),D===1073741823?P===lw?C0++:(C0=0,lw=P):C0=0,typeof fw=="function"&&fw(T.stateNode,q),fo(P),Pu)throw Pu=!1,P=Dd,Dd=null,P;return(yr&wd)!==En||qi(),null}function iF(){for(;lr!==null;){var P=lr.effectTag;P&256&&Qt(lr.alternate,lr),!(P&512)||Ep||(Ep=!0,dc(97,function(){return Cp(),null})),lr=lr.nextEffect}}function Cp(){if(UA!==90){var P=97<UA?97:UA;return UA=90,lo(P,sF)}}function sF(){if(E0===null)return!1;var P=E0;if(E0=null,(yr&(is|Gs))!==En)throw Error(n(331));var D=yr;for(yr|=Gs,P=P.current.firstEffect;P!==null;){try{var T=P;if(T.effectTag&512)switch(T.tag){case 0:case 11:case 15:N(128,0,T),N(0,64,T)}}catch(q){if(P===null)throw Error(n(330));GA(P,q)}T=P.nextEffect,P.nextEffect=null,P=T}return yr=D,qi(),!0}function Tv(P,D,T){D=g0(T,D),D=Sv(P,D,1073741823),tt(P,D),P=w0(P,1073741823),P!==null&&fo(P)}function GA(P,D){if(P.tag===3)Tv(P,P,D);else for(var T=P.return;T!==null;){if(T.tag===3){Tv(T,P,D);break}else if(T.tag===1){var q=T.stateNode;if(typeof T.type.getDerivedStateFromError=="function"||typeof q.componentDidCatch=="function"&&(Su===null||!Su.has(q))){P=g0(D,P),P=bv(T,P,1073741823),tt(T,P),T=w0(T,1073741823),T!==null&&fo(T);break}}T=T.return}}function oF(P,D,T){var q=P.pingCache;q!==null&&q.delete(D),gi===P&&ss===T?Yi===vl||Yi===da&&Ka===1073741823&&Ni()-ow<aw?bu(P,ss):OA=!0:Lv(P,T)&&(D=P.lastPingedTime,D!==0&&D<T||(P.lastPingedTime=T,P.finishedExpirationTime===T&&(P.finishedExpirationTime=0,P.finishedWork=null),fo(P)))}function aF(P,D){var T=P.stateNode;T!==null&&T.delete(D),D=0,D===0&&(D=ma(),D=HA(D,P,null)),P=w0(P,D),P!==null&&fo(P)}var Nv;Nv=function(P,D,T){var q=D.expirationTime;if(P!==null){var W=D.pendingProps;if(P.memoizedProps!==W||_i.current)jo=!0;else{if(q<T){switch(jo=!1,D.tag){case 3:h0(D),p0();break;case 5:if(hd(D),D.mode&4&&T!==1&&ke(D.type,W))return D.expirationTime=D.childExpirationTime=1,null;break;case 1:ii(D.type)&&fc(D);break;case 4:r0(D,D.stateNode.containerInfo);break;case 10:Ho(D,D.memoizedProps.value);break;case 13:if(D.memoizedState!==null)return q=D.child.childExpirationTime,q!==0&&q>=T?cn(P,D,T):(Mn($n,$n.current&1,D),D=si(P,D,T),D!==null?D.sibling:null);Mn($n,$n.current&1,D);break;case 19:if(q=D.childExpirationTime>=T,P.effectTag&64){if(q)return Ya(P,D,T);D.effectTag|=64}if(W=D.memoizedState,W!==null&&(W.rendering=null,W.tail=null),Mn($n,$n.current,D),!q)return null}return si(P,D,T)}jo=!1}}else jo=!1;switch(D.expirationTime=0,D.tag){case 2:if(q=D.type,P!==null&&(P.alternate=null,D.alternate=null,D.effectTag|=2),P=D.pendingProps,W=Me(D,On.current),ys(D,T),W=s0(null,D,q,P,W,T),D.effectTag|=1,typeof W=="object"&&W!==null&&typeof W.render=="function"&&W.$$typeof===void 0){if(D.tag=1,tw(),ii(q)){var fe=!0;fc(D)}else fe=!1;D.memoizedState=W.state!==null&&W.state!==void 0?W.state:null;var De=q.getDerivedStateFromProps;typeof De=="function"&&rr(D,q,De,P),W.updater=$r,D.stateNode=W,W._reactInternalFiber=D,qo(D,q,P,T),D=gp(null,D,q,!0,fe,T)}else D.tag=0,Bs(null,D,W,T),D=D.child;return D;case 16:if(W=D.elementType,P!==null&&(P.alternate=null,D.alternate=null,D.effectTag|=2),P=D.pendingProps,Ce(W),W._status!==1)throw W._result;switch(W=W._result,D.type=W,fe=D.tag=uF(W),P=Ei(W,P),fe){case 0:D=NA(null,D,W,P,T);break;case 1:D=hp(null,D,W,P,T);break;case 11:D=wi(null,D,W,P,T);break;case 14:D=yd(null,D,W,Ei(W.type,P),q,T);break;default:throw Error(n(306,W,""))}return D;case 0:return q=D.type,W=D.pendingProps,W=D.elementType===q?W:Ei(q,W),NA(P,D,q,W,T);case 1:return q=D.type,W=D.pendingProps,W=D.elementType===q?W:Ei(q,W),hp(P,D,q,W,T);case 3:if(h0(D),q=D.updateQueue,q===null)throw Error(n(282));if(W=D.memoizedState,W=W!==null?W.element:null,ye(D,q,D.pendingProps,null,T),q=D.memoizedState.element,q===W)p0(),D=si(P,D,T);else{if((W=D.stateNode.hydrate)&&(y?(vc=Au(D.stateNode.containerInfo),pa=D,W=Il=!0):W=!1),W)for(T=t0(D,null,q,T),D.child=T;T;)T.effectTag=T.effectTag&-3|1024,T=T.sibling;else Bs(P,D,q,T),p0();D=D.child}return D;case 5:return hd(D),P===null&&TA(D),q=D.type,W=D.pendingProps,fe=P!==null?P.memoizedProps:null,De=W.children,Fe(q,W)?De=null:fe!==null&&Fe(q,fe)&&(D.effectTag|=16),Go(P,D),D.mode&4&&T!==1&&ke(q,W)?(D.expirationTime=D.childExpirationTime=1,D=null):(Bs(P,D,De,T),D=D.child),D;case 6:return P===null&&TA(D),null;case 13:return cn(P,D,T);case 4:return r0(D,D.stateNode.containerInfo),q=D.pendingProps,P===null?D.child=mu(D,null,q,T):Bs(P,D,q,T),D.child;case 11:return q=D.type,W=D.pendingProps,W=D.elementType===q?W:Ei(q,W),wi(P,D,q,W,T);case 7:return Bs(P,D,D.pendingProps,T),D.child;case 8:return Bs(P,D,D.pendingProps.children,T),D.child;case 12:return Bs(P,D,D.pendingProps.children,T),D.child;case 10:e:{if(q=D.type._context,W=D.pendingProps,De=D.memoizedProps,fe=W.value,Ho(D,fe),De!==null){var vt=De.value;if(fe=ds(vt,fe)?0:(typeof q._calculateChangedBits=="function"?q._calculateChangedBits(vt,fe):1073741823)|0,fe===0){if(De.children===W.children&&!_i.current){D=si(P,D,T);break e}}else for(vt=D.child,vt!==null&&(vt.return=D);vt!==null;){var wt=vt.dependencies;if(wt!==null){De=vt.child;for(var bt=wt.firstContext;bt!==null;){if(bt.context===q&&bt.observedBits&fe){vt.tag===1&&(bt=Cs(T,null),bt.tag=2,tt(vt,bt)),vt.expirationTime<T&&(vt.expirationTime=T),bt=vt.alternate,bt!==null&&bt.expirationTime<T&&(bt.expirationTime=T),ms(vt.return,T),wt.expirationTime<T&&(wt.expirationTime=T);break}bt=bt.next}}else De=vt.tag===10&&vt.type===D.type?null:vt.child;if(De!==null)De.return=vt;else for(De=vt;De!==null;){if(De===D){De=null;break}if(vt=De.sibling,vt!==null){vt.return=De.return,De=vt;break}De=De.return}vt=De}}Bs(P,D,W.children,T),D=D.child}return D;case 9:return W=D.type,fe=D.pendingProps,q=fe.children,ys(D,T),W=Es(W,fe.unstable_observedBits),q=q(W),D.effectTag|=1,Bs(P,D,q,T),D.child;case 14:return W=D.type,fe=Ei(W,D.pendingProps),fe=Ei(W.type,fe),yd(P,D,W,fe,q,T);case 15:return Ed(P,D,D.type,D.pendingProps,q,T);case 17:return q=D.type,W=D.pendingProps,W=D.elementType===q?W:Ei(q,W),P!==null&&(P.alternate=null,D.alternate=null,D.effectTag|=2),D.tag=1,ii(q)?(P=!0,fc(D)):P=!1,ys(D,T),rs(D,q,W,T),qo(D,q,W,T),gp(null,D,q,!0,P,T);case 19:return Ya(P,D,T)}throw Error(n(156,D.tag))};var fw=null,pw=null;function lF(P){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")return!1;var D=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(D.isDisabled||!D.supportsFiber)return!0;try{var T=D.inject(P);fw=function(q){try{D.onCommitFiberRoot(T,q,void 0,(q.current.effectTag&64)===64)}catch{}},pw=function(q){try{D.onCommitFiberUnmount(T,q)}catch{}}}catch{}return!0}function cF(P,D,T,q){this.tag=P,this.key=T,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=D,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=q,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childExpirationTime=this.expirationTime=0,this.alternate=null}function Dl(P,D,T,q){return new cF(P,D,T,q)}function hw(P){return P=P.prototype,!(!P||!P.isReactComponent)}function uF(P){if(typeof P=="function")return hw(P)?1:0;if(P!=null){if(P=P.$$typeof,P===L)return 11;if(P===te)return 14}return 2}function YA(P,D){var T=P.alternate;return T===null?(T=Dl(P.tag,D,P.key,P.mode),T.elementType=P.elementType,T.type=P.type,T.stateNode=P.stateNode,T.alternate=P,P.alternate=T):(T.pendingProps=D,T.effectTag=0,T.nextEffect=null,T.firstEffect=null,T.lastEffect=null),T.childExpirationTime=P.childExpirationTime,T.expirationTime=P.expirationTime,T.child=P.child,T.memoizedProps=P.memoizedProps,T.memoizedState=P.memoizedState,T.updateQueue=P.updateQueue,D=P.dependencies,T.dependencies=D===null?null:{expirationTime:D.expirationTime,firstContext:D.firstContext,responders:D.responders},T.sibling=P.sibling,T.index=P.index,T.ref=P.ref,T}function xd(P,D,T,q,W,fe){var De=2;if(q=P,typeof P=="function")hw(P)&&(De=1);else if(typeof P=="string")De=5;else e:switch(P){case E:return ku(T.children,W,fe,D);case R:De=8,W|=7;break;case I:De=8,W|=1;break;case v:return P=Dl(12,T,D,W|8),P.elementType=v,P.type=v,P.expirationTime=fe,P;case U:return P=Dl(13,T,D,W),P.type=U,P.elementType=U,P.expirationTime=fe,P;case z:return P=Dl(19,T,D,W),P.elementType=z,P.expirationTime=fe,P;default:if(typeof P=="object"&&P!==null)switch(P.$$typeof){case x:De=10;break e;case C:De=9;break e;case L:De=11;break e;case te:De=14;break e;case ae:De=16,q=null;break e}throw Error(n(130,P==null?P:typeof P,""))}return D=Dl(De,T,D,W),D.elementType=P,D.type=q,D.expirationTime=fe,D}function ku(P,D,T,q){return P=Dl(7,P,q,D),P.expirationTime=T,P}function gw(P,D,T){return P=Dl(6,P,null,D),P.expirationTime=T,P}function dw(P,D,T){return D=Dl(4,P.children!==null?P.children:[],P.key,D),D.expirationTime=T,D.stateNode={containerInfo:P.containerInfo,pendingChildren:null,implementation:P.implementation},D}function AF(P,D,T){this.tag=D,this.current=null,this.containerInfo=P,this.pingCache=this.pendingChildren=null,this.finishedExpirationTime=0,this.finishedWork=null,this.timeoutHandle=Ue,this.pendingContext=this.context=null,this.hydrate=T,this.callbackNode=null,this.callbackPriority=90,this.lastExpiredTime=this.lastPingedTime=this.nextKnownPendingLevel=this.lastSuspendedTime=this.firstSuspendedTime=this.firstPendingTime=0}function Lv(P,D){var T=P.firstSuspendedTime;return P=P.lastSuspendedTime,T!==0&&T>=D&&P<=D}function WA(P,D){var T=P.firstSuspendedTime,q=P.lastSuspendedTime;T<D&&(P.firstSuspendedTime=D),(q>D||T===0)&&(P.lastSuspendedTime=D),D<=P.lastPingedTime&&(P.lastPingedTime=0),D<=P.lastExpiredTime&&(P.lastExpiredTime=0)}function Mv(P,D){D>P.firstPendingTime&&(P.firstPendingTime=D);var T=P.firstSuspendedTime;T!==0&&(D>=T?P.firstSuspendedTime=P.lastSuspendedTime=P.nextKnownPendingLevel=0:D>=P.lastSuspendedTime&&(P.lastSuspendedTime=D+1),D>P.nextKnownPendingLevel&&(P.nextKnownPendingLevel=D))}function kd(P,D){var T=P.lastExpiredTime;(T===0||T>D)&&(P.lastExpiredTime=D)}function Ov(P){var D=P._reactInternalFiber;if(D===void 0)throw typeof P.render=="function"?Error(n(188)):Error(n(268,Object.keys(P)));return P=me(D),P===null?null:P.stateNode}function Uv(P,D){P=P.memoizedState,P!==null&&P.dehydrated!==null&&P.retryTime<D&&(P.retryTime=D)}function Qd(P,D){Uv(P,D),(P=P.alternate)&&Uv(P,D)}var _v={createContainer:function(P,D,T){return P=new AF(P,D,T),D=Dl(3,null,null,D===2?7:D===1?3:0),P.current=D,D.stateNode=P},updateContainer:function(P,D,T,q){var W=D.current,fe=ma(),De=pt.suspense;fe=HA(fe,W,De);e:if(T){T=T._reactInternalFiber;t:{if(Be(T)!==T||T.tag!==1)throw Error(n(170));var vt=T;do{switch(vt.tag){case 3:vt=vt.stateNode.context;break t;case 1:if(ii(vt.type)){vt=vt.stateNode.__reactInternalMemoizedMergedChildContext;break t}}vt=vt.return}while(vt!==null);throw Error(n(171))}if(T.tag===1){var wt=T.type;if(ii(wt)){T=fu(T,wt,vt);break e}}T=vt}else T=Ti;return D.context===null?D.context=T:D.pendingContext=T,D=Cs(fe,De),D.payload={element:P},q=q===void 0?null:q,q!==null&&(D.callback=q),tt(W,D),bc(W,fe),fe},batchedEventUpdates:function(P,D){var T=yr;yr|=2;try{return P(D)}finally{yr=T,yr===En&&qi()}},batchedUpdates:function(P,D){var T=yr;yr|=1;try{return P(D)}finally{yr=T,yr===En&&qi()}},unbatchedUpdates:function(P,D){var T=yr;yr&=-2,yr|=wd;try{return P(D)}finally{yr=T,yr===En&&qi()}},deferredUpdates:function(P){return lo(97,P)},syncUpdates:function(P,D,T,q){return lo(99,P.bind(null,D,T,q))},discreteUpdates:function(P,D,T,q){var W=yr;yr|=4;try{return lo(98,P.bind(null,D,T,q))}finally{yr=W,yr===En&&qi()}},flushDiscreteUpdates:function(){(yr&(1|is|Gs))===En&&(eF(),Cp())},flushControlled:function(P){var D=yr;yr|=1;try{lo(99,P)}finally{yr=D,yr===En&&qi()}},flushSync:Qv,flushPassiveEffects:Cp,IsThisRendererActing:{current:!1},getPublicRootInstance:function(P){if(P=P.current,!P.child)return null;switch(P.child.tag){case 5:return Ae(P.child.stateNode);default:return P.child.stateNode}},attemptSynchronousHydration:function(P){switch(P.tag){case 3:var D=P.stateNode;D.hydrate&&kv(D,D.firstPendingTime);break;case 13:Qv(function(){return bc(P,1073741823)}),D=qa(ma(),150,100),Qd(P,D)}},attemptUserBlockingHydration:function(P){if(P.tag===13){var D=qa(ma(),150,100);bc(P,D),Qd(P,D)}},attemptContinuousHydration:function(P){if(P.tag===13){ma();var D=bA++;bc(P,D),Qd(P,D)}},attemptHydrationAtCurrentPriority:function(P){if(P.tag===13){var D=ma();D=HA(D,P,null),bc(P,D),Qd(P,D)}},findHostInstance:Ov,findHostInstanceWithWarning:function(P){return Ov(P)},findHostInstanceWithNoPortals:function(P){return P=we(P),P===null?null:P.tag===20?P.stateNode.instance:P.stateNode},shouldSuspend:function(){return!1},injectIntoDevTools:function(P){var D=P.findFiberByHostInstance;return lF(r({},P,{overrideHookState:null,overrideProps:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:u.ReactCurrentDispatcher,findHostInstanceByFiber:function(T){return T=me(T),T===null?null:T.stateNode},findFiberByHostInstance:function(T){return D?D(T):null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null}))}};Y2.exports=_v.default||_v;var fF=Y2.exports;return Y2.exports=t,fF}});var FEe=_((BKt,QEe)=>{"use strict";QEe.exports=kEe()});var TEe=_((vKt,REe)=>{"use strict";var Kyt={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};REe.exports=Kyt});var OEe=_((DKt,MEe)=>{"use strict";var Vyt=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(t[o]=r[o])}return t},Nk=function(){function t(e,r){for(var o=0;o<r.length;o++){var a=r[o];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}return function(e,r,o){return r&&t(e.prototype,r),o&&t(e,o),e}}();function I6(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function B6(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var nu=TEe(),zyt=function(){function t(e,r,o,a,n,u){B6(this,t),this.left=e,this.right=r,this.top=o,this.bottom=a,this.width=n,this.height=u}return Nk(t,[{key:"fromJS",value:function(r){r(this.left,this.right,this.top,this.bottom,this.width,this.height)}},{key:"toString",value:function(){return"<Layout#"+this.left+":"+this.right+";"+this.top+":"+this.bottom+";"+this.width+":"+this.height+">"}}]),t}(),NEe=function(){Nk(t,null,[{key:"fromJS",value:function(r){var o=r.width,a=r.height;return new t(o,a)}}]);function t(e,r){B6(this,t),this.width=e,this.height=r}return Nk(t,[{key:"fromJS",value:function(r){r(this.width,this.height)}},{key:"toString",value:function(){return"<Size#"+this.width+"x"+this.height+">"}}]),t}(),LEe=function(){function t(e,r){B6(this,t),this.unit=e,this.value=r}return Nk(t,[{key:"fromJS",value:function(r){r(this.unit,this.value)}},{key:"toString",value:function(){switch(this.unit){case nu.UNIT_POINT:return String(this.value);case nu.UNIT_PERCENT:return this.value+"%";case nu.UNIT_AUTO:return"auto";default:return this.value+"?"}}},{key:"valueOf",value:function(){return this.value}}]),t}();MEe.exports=function(t,e){function r(u,A,p){var h=u[A];u[A]=function(){for(var E=arguments.length,I=Array(E),v=0;v<E;v++)I[v]=arguments[v];return p.call.apply(p,[this,h].concat(I))}}for(var o=["setPosition","setMargin","setFlexBasis","setWidth","setHeight","setMinWidth","setMinHeight","setMaxWidth","setMaxHeight","setPadding"],a=function(){var A,p=o[n],h=(A={},I6(A,nu.UNIT_POINT,e.Node.prototype[p]),I6(A,nu.UNIT_PERCENT,e.Node.prototype[p+"Percent"]),I6(A,nu.UNIT_AUTO,e.Node.prototype[p+"Auto"]),A);r(e.Node.prototype,p,function(E){for(var I=arguments.length,v=Array(I>1?I-1:0),x=1;x<I;x++)v[x-1]=arguments[x];var C=v.pop(),R=void 0,L=void 0;if(C==="auto")R=nu.UNIT_AUTO,L=void 0;else if(C instanceof LEe)R=C.unit,L=C.valueOf();else if(R=typeof C=="string"&&C.endsWith("%")?nu.UNIT_PERCENT:nu.UNIT_POINT,L=parseFloat(C),!Number.isNaN(C)&&Number.isNaN(L))throw new Error("Invalid value "+C+" for "+p);if(!h[R])throw new Error('Failed to execute "'+p+`": Unsupported unit '`+C+"'");if(L!==void 0){var U;return(U=h[R]).call.apply(U,[this].concat(v,[L]))}else{var z;return(z=h[R]).call.apply(z,[this].concat(v))}})},n=0;n<o.length;n++)a();return r(e.Config.prototype,"free",function(){e.Config.destroy(this)}),r(e.Node,"create",function(u,A){return A?e.Node.createWithConfig(A):e.Node.createDefault()}),r(e.Node.prototype,"free",function(){e.Node.destroy(this)}),r(e.Node.prototype,"freeRecursive",function(){for(var u=0,A=this.getChildCount();u<A;++u)this.getChild(0).freeRecursive();this.free()}),r(e.Node.prototype,"setMeasureFunc",function(u,A){return A?u.call(this,function(){return NEe.fromJS(A.apply(void 0,arguments))}):this.unsetMeasureFunc()}),r(e.Node.prototype,"calculateLayout",function(u){var A=arguments.length>1&&arguments[1]!==void 0?arguments[1]:NaN,p=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,h=arguments.length>3&&arguments[3]!==void 0?arguments[3]:nu.DIRECTION_LTR;return u.call(this,A,p,h)}),Vyt({Config:e.Config,Node:e.Node,Layout:t("Layout",zyt),Size:t("Size",NEe),Value:t("Value",LEe),getInstanceCount:function(){return e.getInstanceCount.apply(e,arguments)}},nu)}});var UEe=_((exports,module)=>{(function(t,e){typeof define=="function"&&define.amd?define([],function(){return e}):typeof module=="object"&&module.exports?module.exports=e:(t.nbind=t.nbind||{}).init=e})(exports,function(Module,cb){typeof Module=="function"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(t,e){return function(){t&&t.apply(this,arguments);try{Module.ccall("nbind_init")}catch(r){e(r);return}e(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module<"u"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT==="WEB")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT==="WORKER")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT==="NODE")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT==="SHELL")ENVIRONMENT_IS_SHELL=!0;else throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ENVIRONMENT_IS_WEB=typeof window=="object",ENVIRONMENT_IS_WORKER=typeof importScripts=="function",ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof ve=="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(e,r){nodeFS||(nodeFS={}("")),nodePath||(nodePath={}("")),e=nodePath.normalize(e);var o=nodeFS.readFileSync(e);return r?o:o.toString()},Module.readBinary=function(e){var r=Module.read(e,!0);return r.buffer||(r=new Uint8Array(r)),assert(r.buffer),r},Module.load=function(e){globalEval(read(e))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\/g,"/"):Module.thisProgram="unknown-program"),Module.arguments=process.argv.slice(2),typeof module<"u"&&(module.exports=Module),Module.inspect=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr<"u"&&(Module.printErr=printErr),typeof read<"u"?Module.read=read:Module.read=function(){throw"no read() available"},Module.readBinary=function(e){if(typeof readbuffer=="function")return new Uint8Array(readbuffer(e));var r=read(e,"binary");return assert(typeof r=="object"),r},typeof scriptArgs<"u"?Module.arguments=scriptArgs:typeof arguments<"u"&&(Module.arguments=arguments),typeof quit=="function"&&(Module.quit=function(t,e){quit(t)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(e){var r=new XMLHttpRequest;return r.open("GET",e,!1),r.send(null),r.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(e){var r=new XMLHttpRequest;return r.open("GET",e,!1),r.responseType="arraybuffer",r.send(null),new Uint8Array(r.response)}),Module.readAsync=function(e,r,o){var a=new XMLHttpRequest;a.open("GET",e,!0),a.responseType="arraybuffer",a.onload=function(){a.status==200||a.status==0&&a.response?r(a.response):o()},a.onerror=o,a.send(null)},typeof arguments<"u"&&(Module.arguments=arguments),typeof console<"u")Module.print||(Module.print=function(e){console.log(e)}),Module.printErr||(Module.printErr=function(e){console.warn(e)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump<"u"?function(t){dump(t)}:function(t){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle>"u"&&(Module.setWindowTitle=function(t){document.title=t})}else throw"Unknown runtime environment. Where are we?";function globalEval(t){eval.call(null,t)}!Module.load&&Module.read&&(Module.load=function(e){globalEval(Module.read(e))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram="./this.program"),Module.quit||(Module.quit=function(t,e){throw e}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(t){return tempRet0=t,t},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(t){STACKTOP=t},getNativeTypeSize:function(t){switch(t){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(t[t.length-1]==="*")return Runtime.QUANTUM_SIZE;if(t[0]==="i"){var e=parseInt(t.substr(1));return assert(e%8===0),e/8}else return 0}}},getNativeFieldSize:function(t){return Math.max(Runtime.getNativeTypeSize(t),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(t,e){return e==="double"||e==="i64"?t&7&&(assert((t&7)===4),t+=4):assert((t&3)===0),t},getAlignSize:function(t,e,r){return!r&&(t=="i64"||t=="double")?8:t?Math.min(e||(t?Runtime.getNativeFieldSize(t):0),Runtime.QUANTUM_SIZE):Math.min(e,8)},dynCall:function(t,e,r){return r&&r.length?Module["dynCall_"+t].apply(null,[e].concat(r)):Module["dynCall_"+t].call(null,e)},functionPointers:[],addFunction:function(t){for(var e=0;e<Runtime.functionPointers.length;e++)if(!Runtime.functionPointers[e])return Runtime.functionPointers[e]=t,2*(1+e);throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."},removeFunction:function(t){Runtime.functionPointers[(t-2)/2]=null},warnOnce:function(t){Runtime.warnOnce.shown||(Runtime.warnOnce.shown={}),Runtime.warnOnce.shown[t]||(Runtime.warnOnce.shown[t]=1,Module.printErr(t))},funcWrappers:{},getFuncWrapper:function(t,e){if(t){assert(e),Runtime.funcWrappers[e]||(Runtime.funcWrappers[e]={});var r=Runtime.funcWrappers[e];return r[t]||(e.length===1?r[t]=function(){return Runtime.dynCall(e,t)}:e.length===2?r[t]=function(a){return Runtime.dynCall(e,t,[a])}:r[t]=function(){return Runtime.dynCall(e,t,Array.prototype.slice.call(arguments))}),r[t]}},getCompilerSetting:function(t){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"},stackAlloc:function(t){var e=STACKTOP;return STACKTOP=STACKTOP+t|0,STACKTOP=STACKTOP+15&-16,e},staticAlloc:function(t){var e=STATICTOP;return STATICTOP=STATICTOP+t|0,STATICTOP=STATICTOP+15&-16,e},dynamicAlloc:function(t){var e=HEAP32[DYNAMICTOP_PTR>>2],r=(e+t+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=r,r>=TOTAL_MEMORY){var o=enlargeMemory();if(!o)return HEAP32[DYNAMICTOP_PTR>>2]=e,0}return e},alignMemory:function(t,e){var r=t=Math.ceil(t/(e||16))*(e||16);return r},makeBigInt:function(t,e,r){var o=r?+(t>>>0)+ +(e>>>0)*4294967296:+(t>>>0)+ +(e|0)*4294967296;return o},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(t,e){t||abort("Assertion failed: "+e)}function getCFunc(ident){var func=Module["_"+ident];if(!func)try{func=eval("_"+ident)}catch(t){}return assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(t){var e=Runtime.stackAlloc(t.length);return writeArrayToMemory(t,e),e},stringToC:function(t){var e=0;if(t!=null&&t!==0){var r=(t.length<<2)+1;e=Runtime.stackAlloc(r),stringToUTF8(t,e,r)}return e}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(e,r,o,a,n){var u=getCFunc(e),A=[],p=0;if(a)for(var h=0;h<a.length;h++){var E=toC[o[h]];E?(p===0&&(p=Runtime.stackSave()),A[h]=E(a[h])):A[h]=a[h]}var I=u.apply(null,A);if(r==="string"&&(I=Pointer_stringify(I)),p!==0){if(n&&n.async){EmterpreterAsync.asyncFinalizers.push(function(){Runtime.stackRestore(p)});return}Runtime.stackRestore(p)}return I};var sourceRegex=/^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(t){var e=t.toString().match(sourceRegex).slice(1);return{arguments:e[0],body:e[1],returnValue:e[2]}}var JSsource=null;function ensureJSsource(){if(!JSsource){JSsource={};for(var t in JSfuncs)JSfuncs.hasOwnProperty(t)&&(JSsource[t]=parseJSFunc(JSfuncs[t]))}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident),numericArgs=argTypes.every(function(t){return t==="number"}),numericRet=returnType!=="string";if(numericRet&&numericArgs)return cfunc;var argNames=argTypes.map(function(t,e){return"$"+e}),funcstr="(function("+argNames.join(",")+") {",nargs=argTypes.length;if(!numericArgs){ensureJSsource(),funcstr+="var stack = "+JSsource.stackSave.body+";";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type!=="number"){var convertCode=JSsource[type+"ToC"];funcstr+="var "+convertCode.arguments+" = "+arg+";",funcstr+=convertCode.body+";",funcstr+=arg+"=("+convertCode.returnValue+");"}}}var cfuncname=parseJSFunc(function(){return cfunc}).returnValue;if(funcstr+="var ret = "+cfuncname+"("+argNames.join(",")+");",!numericRet){var strgfy=parseJSFunc(function(){return Pointer_stringify}).returnValue;funcstr+="ret = "+strgfy+"(ret);"}return numericArgs||(ensureJSsource(),funcstr+=JSsource.stackRestore.body.replace("()","(stack)")+";"),funcstr+="return ret})",eval(funcstr)}})(),Module.ccall=ccall,Module.cwrap=cwrap;function setValue(t,e,r,o){switch(r=r||"i8",r.charAt(r.length-1)==="*"&&(r="i32"),r){case"i1":HEAP8[t>>0]=e;break;case"i8":HEAP8[t>>0]=e;break;case"i16":HEAP16[t>>1]=e;break;case"i32":HEAP32[t>>2]=e;break;case"i64":tempI64=[e>>>0,(tempDouble=e,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t>>2]=tempI64[0],HEAP32[t+4>>2]=tempI64[1];break;case"float":HEAPF32[t>>2]=e;break;case"double":HEAPF64[t>>3]=e;break;default:abort("invalid type for setValue: "+r)}}Module.setValue=setValue;function getValue(t,e,r){switch(e=e||"i8",e.charAt(e.length-1)==="*"&&(e="i32"),e){case"i1":return HEAP8[t>>0];case"i8":return HEAP8[t>>0];case"i16":return HEAP16[t>>1];case"i32":return HEAP32[t>>2];case"i64":return HEAP32[t>>2];case"float":return HEAPF32[t>>2];case"double":return HEAPF64[t>>3];default:abort("invalid type for setValue: "+e)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(t,e,r,o){var a,n;typeof t=="number"?(a=!0,n=t):(a=!1,n=t.length);var u=typeof e=="string"?e:null,A;if(r==ALLOC_NONE?A=o:A=[typeof _malloc=="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][r===void 0?ALLOC_STATIC:r](Math.max(n,u?1:e.length)),a){var o=A,p;for(assert((A&3)==0),p=A+(n&-4);o<p;o+=4)HEAP32[o>>2]=0;for(p=A+n;o<p;)HEAP8[o++>>0]=0;return A}if(u==="i8")return t.subarray||t.slice?HEAPU8.set(t,A):HEAPU8.set(new Uint8Array(t),A),A;for(var h=0,E,I,v;h<n;){var x=t[h];if(typeof x=="function"&&(x=Runtime.getFunctionIndex(x)),E=u||e[h],E===0){h++;continue}E=="i64"&&(E="i32"),setValue(A+h,x,E),v!==E&&(I=Runtime.getNativeTypeSize(E),v=E),h+=I}return A}Module.allocate=allocate;function getMemory(t){return staticSealed?runtimeInitialized?_malloc(t):Runtime.dynamicAlloc(t):Runtime.staticAlloc(t)}Module.getMemory=getMemory;function Pointer_stringify(t,e){if(e===0||!t)return"";for(var r=0,o,a=0;o=HEAPU8[t+a>>0],r|=o,!(o==0&&!e||(a++,e&&a==e)););e||(e=a);var n="";if(r<128){for(var u=1024,A;e>0;)A=String.fromCharCode.apply(String,HEAPU8.subarray(t,t+Math.min(e,u))),n=n?n+A:A,t+=u,e-=u;return n}return Module.UTF8ToString(t)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(t){for(var e="";;){var r=HEAP8[t++>>0];if(!r)return e;e+=String.fromCharCode(r)}}Module.AsciiToString=AsciiToString;function stringToAscii(t,e){return writeAsciiToMemory(t,e,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder<"u"?new TextDecoder("utf8"):void 0;function UTF8ArrayToString(t,e){for(var r=e;t[r];)++r;if(r-e>16&&t.subarray&&UTF8Decoder)return UTF8Decoder.decode(t.subarray(e,r));for(var o,a,n,u,A,p,h="";;){if(o=t[e++],!o)return h;if(!(o&128)){h+=String.fromCharCode(o);continue}if(a=t[e++]&63,(o&224)==192){h+=String.fromCharCode((o&31)<<6|a);continue}if(n=t[e++]&63,(o&240)==224?o=(o&15)<<12|a<<6|n:(u=t[e++]&63,(o&248)==240?o=(o&7)<<18|a<<12|n<<6|u:(A=t[e++]&63,(o&252)==248?o=(o&3)<<24|a<<18|n<<12|u<<6|A:(p=t[e++]&63,o=(o&1)<<30|a<<24|n<<18|u<<12|A<<6|p))),o<65536)h+=String.fromCharCode(o);else{var E=o-65536;h+=String.fromCharCode(55296|E>>10,56320|E&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(t){return UTF8ArrayToString(HEAPU8,t)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(t,e,r,o){if(!(o>0))return 0;for(var a=r,n=r+o-1,u=0;u<t.length;++u){var A=t.charCodeAt(u);if(A>=55296&&A<=57343&&(A=65536+((A&1023)<<10)|t.charCodeAt(++u)&1023),A<=127){if(r>=n)break;e[r++]=A}else if(A<=2047){if(r+1>=n)break;e[r++]=192|A>>6,e[r++]=128|A&63}else if(A<=65535){if(r+2>=n)break;e[r++]=224|A>>12,e[r++]=128|A>>6&63,e[r++]=128|A&63}else if(A<=2097151){if(r+3>=n)break;e[r++]=240|A>>18,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}else if(A<=67108863){if(r+4>=n)break;e[r++]=248|A>>24,e[r++]=128|A>>18&63,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}else{if(r+5>=n)break;e[r++]=252|A>>30,e[r++]=128|A>>24&63,e[r++]=128|A>>18&63,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}}return e[r]=0,r-a}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(t,e,r){return stringToUTF8Array(t,HEAPU8,e,r)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(t){for(var e=0,r=0;r<t.length;++r){var o=t.charCodeAt(r);o>=55296&&o<=57343&&(o=65536+((o&1023)<<10)|t.charCodeAt(++r)&1023),o<=127?++e:o<=2047?e+=2:o<=65535?e+=3:o<=2097151?e+=4:o<=67108863?e+=5:e+=6}return e}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder<"u"?new TextDecoder("utf-16le"):void 0;function demangle(t){var e=Module.___cxa_demangle||Module.__cxa_demangle;if(e){try{var r=t.substr(1),o=lengthBytesUTF8(r)+1,a=_malloc(o);stringToUTF8(r,a,o);var n=_malloc(4),u=e(a,0,0,n);if(getValue(n,"i32")===0&&u)return Pointer_stringify(u)}catch{}finally{a&&_free(a),n&&_free(n),u&&_free(u)}return t}return Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling"),t}function demangleAll(t){var e=/__Z[\w\d_]+/g;return t.replace(e,function(r){var o=demangle(r);return r===o?r:r+" ["+o+"]"})}function jsStackTrace(){var t=new Error;if(!t.stack){try{throw new Error(0)}catch(e){t=e}if(!t.stack)return"(no stack trace available)"}return t.stack.toString()}function stackTrace(){var t=jsStackTrace();return Module.extraStackTrace&&(t+=` +`+Module.extraStackTrace()),demangleAll(t)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY<TOTAL_STACK&&Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+TOTAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")"),Module.buffer?buffer=Module.buffer:buffer=new ArrayBuffer(TOTAL_MEMORY),updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}if(HEAP32[0]=1668509029,HEAP16[1]=25459,HEAPU8[2]!==115||HEAPU8[3]!==99)throw"Runtime error: expected the system to be little-endian!";Module.HEAP=HEAP,Module.buffer=buffer,Module.HEAP8=HEAP8,Module.HEAP16=HEAP16,Module.HEAP32=HEAP32,Module.HEAPU8=HEAPU8,Module.HEAPU16=HEAPU16,Module.HEAPU32=HEAPU32,Module.HEAPF32=HEAPF32,Module.HEAPF64=HEAPF64;function callRuntimeCallbacks(t){for(;t.length>0;){var e=t.shift();if(typeof e=="function"){e();continue}var r=e.func;typeof r=="number"?e.arg===void 0?Module.dynCall_v(r):Module.dynCall_vi(r,e.arg):r(e.arg===void 0?null:e.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun=="function"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun=="function"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(t){__ATPRERUN__.unshift(t)}Module.addOnPreRun=addOnPreRun;function addOnInit(t){__ATINIT__.unshift(t)}Module.addOnInit=addOnInit;function addOnPreMain(t){__ATMAIN__.unshift(t)}Module.addOnPreMain=addOnPreMain;function addOnExit(t){__ATEXIT__.unshift(t)}Module.addOnExit=addOnExit;function addOnPostRun(t){__ATPOSTRUN__.unshift(t)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(t,e,r){var o=r>0?r:lengthBytesUTF8(t)+1,a=new Array(o),n=stringToUTF8Array(t,a,0,a.length);return e&&(a.length=n),a}Module.intArrayFromString=intArrayFromString;function intArrayToString(t){for(var e=[],r=0;r<t.length;r++){var o=t[r];o>255&&(o&=255),e.push(String.fromCharCode(o))}return e.join("")}Module.intArrayToString=intArrayToString;function writeStringToMemory(t,e,r){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var o,a;r&&(a=e+lengthBytesUTF8(t),o=HEAP8[a]),stringToUTF8(t,e,1/0),r&&(HEAP8[a]=o)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(t,e){HEAP8.set(t,e)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(t,e,r){for(var o=0;o<t.length;++o)HEAP8[e++>>0]=t.charCodeAt(o);r||(HEAP8[e>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function t(e,r){var o=e>>>16,a=e&65535,n=r>>>16,u=r&65535;return a*u+(o*u+a*n<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(t){return froundBuffer[0]=t,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(t){t=t>>>0;for(var e=0;e<32;e++)if(t&1<<31-e)return e;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(t){return t<0?Math.ceil(t):Math.floor(t)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(t){return t}function addRunDependency(t){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(t){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var e=dependenciesFulfilled;dependenciesFulfilled=null,e()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(t,e,r,o,a,n,u,A){return _nbind.callbackSignatureList[t].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(t,e,r,o,a,n,u,A){return ASM_CONSTS[t](e,r,o,a,n,u,A)}function _emscripten_asm_const_iiiii(t,e,r,o,a){return ASM_CONSTS[t](e,r,o,a)}function _emscripten_asm_const_iiidddddd(t,e,r,o,a,n,u,A,p){return ASM_CONSTS[t](e,r,o,a,n,u,A,p)}function _emscripten_asm_const_iiididi(t,e,r,o,a,n,u){return ASM_CONSTS[t](e,r,o,a,n,u)}function _emscripten_asm_const_iiii(t,e,r,o){return ASM_CONSTS[t](e,r,o)}function _emscripten_asm_const_iiiid(t,e,r,o,a){return ASM_CONSTS[t](e,r,o,a)}function _emscripten_asm_const_iiiiii(t,e,r,o,a,n){return ASM_CONSTS[t](e,r,o,a,n)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(t,e){__ATEXIT__.unshift({func:t,arg:e})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr("missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj"),abort(-1)}function __decorate(t,e,r,o){var a=arguments.length,n=a<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,r):o,u;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")n=Reflect.decorate(t,e,r,o);else for(var A=t.length-1;A>=0;A--)(u=t[A])&&(n=(a<3?u(n):a>3?u(e,r,n):u(e,r))||n);return a>3&&n&&Object.defineProperty(e,r,n),n}function _defineHidden(t){return function(e,r){Object.defineProperty(e,r,{configurable:!1,enumerable:!1,value:t,writable:!0})}}var _nbind={};function __nbind_free_external(t){_nbind.externalList[t].dereference(t)}function __nbind_reference_external(t){_nbind.externalList[t].reference()}function _llvm_stackrestore(t){var e=_llvm_stacksave,r=e.LLVM_SAVEDSTACKS[t];e.LLVM_SAVEDSTACKS.splice(t,1),Runtime.stackRestore(r)}function __nbind_register_pool(t,e,r,o){_nbind.Pool.pageSize=t,_nbind.Pool.usedPtr=e/4,_nbind.Pool.rootPtr=r,_nbind.Pool.pagePtr=o/4,HEAP32[e/4]=16909060,HEAP8[e]==1&&(_nbind.bigEndian=!0),HEAP32[e/4]=0,_nbind.makeTypeKindTbl=(n={},n[1024]=_nbind.PrimitiveType,n[64]=_nbind.Int64Type,n[2048]=_nbind.BindClass,n[3072]=_nbind.BindClassPtr,n[4096]=_nbind.SharedClassPtr,n[5120]=_nbind.ArrayType,n[6144]=_nbind.ArrayType,n[7168]=_nbind.CStringType,n[9216]=_nbind.CallbackType,n[10240]=_nbind.BindType,n),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,"cbFunction &":_nbind.CallbackType,"const cbFunction &":_nbind.CallbackType,"const std::string &":_nbind.StringType,"std::string":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var a=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:""});a.proto=Module,_nbind.BindClass.list.push(a);var n}function _emscripten_set_main_loop_timing(t,e){if(Browser.mainLoop.timingMode=t,Browser.mainLoop.timingValue=e,!Browser.mainLoop.func)return 1;if(t==0)Browser.mainLoop.scheduler=function(){var u=Math.max(0,Browser.mainLoop.tickStartTime+e-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,u)},Browser.mainLoop.method="timeout";else if(t==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method="rAF";else if(t==2){if(!window.setImmediate){let n=function(u){u.source===window&&u.data===o&&(u.stopPropagation(),r.shift()())};var a=n,r=[],o="setimmediate";window.addEventListener("message",n,!0),window.setImmediate=function(A){r.push(A),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(A),window.postMessage({target:o})):window.postMessage(o,"*")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(t,e,r,o,a){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters."),Browser.mainLoop.func=t,Browser.mainLoop.arg=o;var n;typeof o<"u"?n=function(){Module.dynCall_vi(t,o)}:n=function(){Module.dynCall_v(t)};var u=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var p=Date.now(),h=Browser.mainLoop.queue.shift();if(h.func(h.arg),Browser.mainLoop.remainingBlockers){var E=Browser.mainLoop.remainingBlockers,I=E%1==0?E-1:Math.floor(E);h.counted?Browser.mainLoop.remainingBlockers=I:(I=I+.5,Browser.mainLoop.remainingBlockers=(8*E+I)/9)}if(console.log('main loop blocker "'+h.name+'" took '+(Date.now()-p)+" ms"),Browser.mainLoop.updateStatus(),u<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(!(u<Browser.mainLoop.currentlyRunningMainloop)){if(Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0,Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method==="timeout"&&Module.ctx&&(Module.printErr("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),Browser.mainLoop.method=""),Browser.mainLoop.runIter(n),!(u<Browser.mainLoop.currentlyRunningMainloop)&&(typeof SDL=="object"&&SDL.audio&&SDL.audio.queueNewAudioData&&SDL.audio.queueNewAudioData(),Browser.mainLoop.scheduler())}}},a||(e&&e>0?_emscripten_set_main_loop_timing(0,1e3/e):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),r)throw"SimulateInfiniteLoop"}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var t=Browser.mainLoop.timingMode,e=Browser.mainLoop.timingValue,r=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(r,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(t,e),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var t=Module.statusMessage||"Please wait...",e=Browser.mainLoop.remainingBlockers,r=Browser.mainLoop.expectedBlockers;e?e<r?Module.setStatus(t+" ("+(r-e)+"/"+r+")"):Module.setStatus(t):Module.setStatus("")}},runIter:function(t){if(!ABORT){if(Module.preMainLoop){var e=Module.preMainLoop();if(e===!1)return}try{t()}catch(r){if(r instanceof ExitStatus)return;throw r&&typeof r=="object"&&r.stack&&Module.printErr("exception thrown: "+[r,r.stack]),r}Module.postMainLoop&&Module.postMainLoop()}}},isFullscreen:!1,pointerLock:!1,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(Module.preloadPlugins||(Module.preloadPlugins=[]),Browser.initted)return;Browser.initted=!0;try{new Blob,Browser.hasBlobConstructor=!0}catch{Browser.hasBlobConstructor=!1,console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Browser.BlobBuilder=typeof MozBlobBuilder<"u"?MozBlobBuilder:typeof WebKitBlobBuilder<"u"?WebKitBlobBuilder:Browser.hasBlobConstructor?null:console.log("warning: no BlobBuilder"),Browser.URLObject=typeof window<"u"?window.URL?window.URL:window.webkitURL:void 0,!Module.noImageDecoding&&typeof Browser.URLObject>"u"&&(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."),Module.noImageDecoding=!0);var t={};t.canHandle=function(n){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(n)},t.handle=function(n,u,A,p){var h=null;if(Browser.hasBlobConstructor)try{h=new Blob([n],{type:Browser.getMimetype(u)}),h.size!==n.length&&(h=new Blob([new Uint8Array(n).buffer],{type:Browser.getMimetype(u)}))}catch(x){Runtime.warnOnce("Blob constructor present but fails: "+x+"; falling back to blob builder")}if(!h){var E=new Browser.BlobBuilder;E.append(new Uint8Array(n).buffer),h=E.getBlob()}var I=Browser.URLObject.createObjectURL(h),v=new Image;v.onload=function(){assert(v.complete,"Image "+u+" could not be decoded");var C=document.createElement("canvas");C.width=v.width,C.height=v.height;var R=C.getContext("2d");R.drawImage(v,0,0),Module.preloadedImages[u]=C,Browser.URLObject.revokeObjectURL(I),A&&A(n)},v.onerror=function(C){console.log("Image "+I+" could not be decoded"),p&&p()},v.src=I},Module.preloadPlugins.push(t);var e={};e.canHandle=function(n){return!Module.noAudioDecoding&&n.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},e.handle=function(n,u,A,p){var h=!1;function E(R){h||(h=!0,Module.preloadedAudios[u]=R,A&&A(n))}function I(){h||(h=!0,Module.preloadedAudios[u]=new Audio,p&&p())}if(Browser.hasBlobConstructor){try{var v=new Blob([n],{type:Browser.getMimetype(u)})}catch{return I()}var x=Browser.URLObject.createObjectURL(v),C=new Audio;C.addEventListener("canplaythrough",function(){E(C)},!1),C.onerror=function(L){if(h)return;console.log("warning: browser could not fully decode audio "+u+", trying slower base64 approach");function U(z){for(var te="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ae="=",le="",ce=0,Ce=0,de=0;de<z.length;de++)for(ce=ce<<8|z[de],Ce+=8;Ce>=6;){var Be=ce>>Ce-6&63;Ce-=6,le+=te[Be]}return Ce==2?(le+=te[(ce&3)<<4],le+=ae+ae):Ce==4&&(le+=te[(ce&15)<<2],le+=ae),le}C.src="data:audio/x-"+u.substr(-3)+";base64,"+U(n),E(C)},C.src=x,Browser.safeSetTimeout(function(){E(C)},1e4)}else return I()},Module.preloadPlugins.push(e);function r(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var o=Module.canvas;o&&(o.requestPointerLock=o.requestPointerLock||o.mozRequestPointerLock||o.webkitRequestPointerLock||o.msRequestPointerLock||function(){},o.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},o.exitPointerLock=o.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",r,!1),document.addEventListener("mozpointerlockchange",r,!1),document.addEventListener("webkitpointerlockchange",r,!1),document.addEventListener("mspointerlockchange",r,!1),Module.elementPointerLock&&o.addEventListener("click",function(a){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),a.preventDefault())},!1))},createContext:function(t,e,r,o){if(e&&Module.ctx&&t==Module.canvas)return Module.ctx;var a,n;if(e){var u={antialias:!1,alpha:!1};if(o)for(var A in o)u[A]=o[A];n=GL.createContext(t,u),n&&(a=GL.getContext(n).GLctx)}else a=t.getContext("2d");return a?(r&&(e||assert(typeof GLctx>"u","cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),Module.ctx=a,e&&GL.makeContextCurrent(n),Module.useWebGL=e,Browser.moduleContextCreatedCallbacks.forEach(function(p){p()}),Browser.init()),a):null},destroyContext:function(t,e,r){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(t,e,r){Browser.lockPointer=t,Browser.resizeCanvas=e,Browser.vrDevice=r,typeof Browser.lockPointer>"u"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas>"u"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice>"u"&&(Browser.vrDevice=null);var o=Module.canvas;function a(){Browser.isFullscreen=!1;var u=o.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===u?(o.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},o.exitFullscreen=o.exitFullscreen.bind(document),Browser.lockPointer&&o.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(u.parentNode.insertBefore(o,u),u.parentNode.removeChild(u),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(o)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",a,!1),document.addEventListener("mozfullscreenchange",a,!1),document.addEventListener("webkitfullscreenchange",a,!1),document.addEventListener("MSFullscreenChange",a,!1));var n=document.createElement("div");o.parentNode.insertBefore(n,o),n.appendChild(o),n.requestFullscreen=n.requestFullscreen||n.mozRequestFullScreen||n.msRequestFullscreen||(n.webkitRequestFullscreen?function(){n.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(n.webkitRequestFullScreen?function(){n.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),r?n.requestFullscreen({vrDisplay:r}):n.requestFullscreen()},requestFullScreen:function(t,e,r){return Module.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead."),Browser.requestFullScreen=function(o,a,n){return Browser.requestFullscreen(o,a,n)},Browser.requestFullscreen(t,e,r)},nextRAF:0,fakeRequestAnimationFrame:function(t){var e=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=e+1e3/60;else for(;e+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var r=Math.max(Browser.nextRAF-e,0);setTimeout(t,r)},requestAnimationFrame:function t(e){typeof window>"u"?Browser.fakeRequestAnimationFrame(e):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(e))},safeCallback:function(t){return function(){if(!ABORT)return t.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var t=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],t.forEach(function(e){e()})}},safeRequestAnimationFrame:function(t){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?t():Browser.queuedAsyncCallbacks.push(t))})},safeSetTimeout:function(t,e){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?t():Browser.queuedAsyncCallbacks.push(t))},e)},safeSetInterval:function(t,e){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&t()},e)},getMimetype:function(t){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[t.substr(t.lastIndexOf(".")+1)]},getUserMedia:function(t){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(t)},getMovementX:function(t){return t.movementX||t.mozMovementX||t.webkitMovementX||0},getMovementY:function(t){return t.movementY||t.mozMovementY||t.webkitMovementY||0},getMouseWheelDelta:function(t){var e=0;switch(t.type){case"DOMMouseScroll":e=t.detail;break;case"mousewheel":e=t.wheelDelta;break;case"wheel":e=t.deltaY;break;default:throw"unrecognized mouse wheel event: "+t.type}return e},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(t){if(Browser.pointerLock)t.type!="mousemove"&&"mozMovementX"in t?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(t),Browser.mouseMovementY=Browser.getMovementY(t)),typeof SDL<"u"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var e=Module.canvas.getBoundingClientRect(),r=Module.canvas.width,o=Module.canvas.height,a=typeof window.scrollX<"u"?window.scrollX:window.pageXOffset,n=typeof window.scrollY<"u"?window.scrollY:window.pageYOffset;if(t.type==="touchstart"||t.type==="touchend"||t.type==="touchmove"){var u=t.touch;if(u===void 0)return;var A=u.pageX-(a+e.left),p=u.pageY-(n+e.top);A=A*(r/e.width),p=p*(o/e.height);var h={x:A,y:p};if(t.type==="touchstart")Browser.lastTouches[u.identifier]=h,Browser.touches[u.identifier]=h;else if(t.type==="touchend"||t.type==="touchmove"){var E=Browser.touches[u.identifier];E||(E=h),Browser.lastTouches[u.identifier]=E,Browser.touches[u.identifier]=h}return}var I=t.pageX-(a+e.left),v=t.pageY-(n+e.top);I=I*(r/e.width),v=v*(o/e.height),Browser.mouseMovementX=I-Browser.mouseX,Browser.mouseMovementY=v-Browser.mouseY,Browser.mouseX=I,Browser.mouseY=v}},asyncLoad:function(t,e,r,o){var a=o?"":"al "+t;Module.readAsync(t,function(n){assert(n,'Loading data file "'+t+'" failed (no arrayBuffer).'),e(new Uint8Array(n)),a&&removeRunDependency(a)},function(n){if(r)r();else throw'Loading data file "'+t+'" failed.'}),a&&addRunDependency(a)},resizeListeners:[],updateResizeListeners:function(){var t=Module.canvas;Browser.resizeListeners.forEach(function(e){e(t.width,t.height)})},setCanvasSize:function(t,e,r){var o=Module.canvas;Browser.updateCanvasDimensions(o,t,e),r||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL<"u"){var t=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];t=t|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=t}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL<"u"){var t=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];t=t&-8388609,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=t}Browser.updateResizeListeners()},updateCanvasDimensions:function(t,e,r){e&&r?(t.widthNative=e,t.heightNative=r):(e=t.widthNative,r=t.heightNative);var o=e,a=r;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(o/a<Module.forcedAspectRatio?o=Math.round(a*Module.forcedAspectRatio):a=Math.round(o/Module.forcedAspectRatio)),(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===t.parentNode&&typeof screen<"u"){var n=Math.min(screen.width/o,screen.height/a);o=Math.round(o*n),a=Math.round(a*n)}Browser.resizeCanvas?(t.width!=o&&(t.width=o),t.height!=a&&(t.height=a),typeof t.style<"u"&&(t.style.removeProperty("width"),t.style.removeProperty("height"))):(t.width!=e&&(t.width=e),t.height!=r&&(t.height=r),typeof t.style<"u"&&(o!=e||a!=r?(t.style.setProperty("width",o+"px","important"),t.style.setProperty("height",a+"px","important")):(t.style.removeProperty("width"),t.style.removeProperty("height"))))},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function(){var t=Browser.nextWgetRequestHandle;return Browser.nextWgetRequestHandle++,t}},SYSCALLS={varargs:0,get:function(t){SYSCALLS.varargs+=4;var e=HEAP32[SYSCALLS.varargs-4>>2];return e},getStr:function(){var t=Pointer_stringify(SYSCALLS.get());return t},get64:function(){var t=SYSCALLS.get(),e=SYSCALLS.get();return t>=0?assert(e===0):assert(e===-1),t},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.getStreamFromFD();return FS.close(r),0}catch(o){return(typeof FS>"u"||!(o instanceof FS.ErrnoError))&&abort(o),-o.errno}}function ___syscall54(t,e){SYSCALLS.varargs=e;try{return 0}catch(r){return(typeof FS>"u"||!(r instanceof FS.ErrnoError))&&abort(r),-r.errno}}function _typeModule(t){var e=[[0,1,"X"],[1,1,"const X"],[128,1,"X *"],[256,1,"X &"],[384,1,"X &&"],[512,1,"std::shared_ptr<X>"],[640,1,"std::unique_ptr<X>"],[5120,1,"std::vector<X>"],[6144,2,"std::array<X, Y>"],[9216,-1,"std::function<X (Y)>"]];function r(p,h,E,I,v,x){if(h==1){var C=I&896;(C==128||C==256||C==384)&&(p="X const")}var R;return x?R=E.replace("X",p).replace("Y",v):R=p.replace("X",E).replace("Y",v),R.replace(/([*&]) (?=[*&])/g,"$1")}function o(p,h,E,I,v){throw new Error(p+" type "+E.replace("X",h+"?")+(I?" with flag "+I:"")+" in "+v)}function a(p,h,E,I,v,x,C,R){x===void 0&&(x="X"),R===void 0&&(R=1);var L=E(p);if(L)return L;var U=I(p),z=U.placeholderFlag,te=e[z];C&&te&&(x=r(C[2],C[0],x,te[0],"?",!0));var ae;z==0&&(ae="Unbound"),z>=10&&(ae="Corrupt"),R>20&&(ae="Deeply nested"),ae&&o(ae,p,x,z,v||"?");var le=U.paramList[0],ce=a(le,h,E,I,v,x,te,R+1),Ce,de={flags:te[0],id:p,name:"",paramList:[ce]},Be=[],Ee="?";switch(U.placeholderFlag){case 1:Ce=ce.spec;break;case 2:if((ce.flags&15360)==1024&&ce.spec.ptrSize==1){de.flags=7168;break}case 3:case 6:case 5:Ce=ce.spec,ce.flags&15360;break;case 8:Ee=""+U.paramList[1],de.paramList.push(U.paramList[1]);break;case 9:for(var g=0,me=U.paramList[1];g<me.length;g++){var we=me[g],Ae=a(we,h,E,I,v,x,te,R+1);Be.push(Ae.name),de.paramList.push(Ae)}Ee=Be.join(", ");break;default:break}if(de.name=r(te[2],te[0],ce.name,ce.flags,Ee),Ce){for(var ne=0,Z=Object.keys(Ce);ne<Z.length;ne++){var xe=Z[ne];de[xe]=de[xe]||Ce[xe]}de.flags|=Ce.flags}return n(h,de)}function n(p,h){var E=h.flags,I=E&896,v=E&15360;return!h.name&&v==1024&&(h.ptrSize==1?h.name=(E&16?"":(E&8?"un":"")+"signed ")+"char":h.name=(E&8?"u":"")+(E&32?"float":"int")+(h.ptrSize*8+"_t")),h.ptrSize==8&&!(E&32)&&(v=64),v==2048&&(I==512||I==640?v=4096:I&&(v=3072)),p(v,h)}var u=function(){function p(h){this.id=h.id,this.name=h.name,this.flags=h.flags,this.spec=h}return p.prototype.toString=function(){return this.name},p}(),A={Type:u,getComplexType:a,makeType:n,structureList:e};return t.output=A,t.output||A}function __nbind_register_type(t,e){var r=_nbind.readAsciiString(e),o={flags:10240,id:t,name:r};_nbind.makeType(_nbind.constructType,o)}function __nbind_register_callback_signature(t,e){var r=_nbind.readTypeIdList(t,e),o=_nbind.callbackSignatureList.length;return _nbind.callbackSignatureList[o]=_nbind.makeJSCaller(r),o}function __extends(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);function o(){this.constructor=t}o.prototype=e.prototype,t.prototype=new o}function __nbind_register_class(t,e,r,o,a,n,u){var A=_nbind.readAsciiString(u),p=_nbind.readPolicyList(e),h=HEAPU32.subarray(t/4,t/4+2),E={flags:2048|(p.Value?2:0),id:h[0],name:A},I=_nbind.makeType(_nbind.constructType,E);I.ptrType=_nbind.getComplexType(h[1],_nbind.constructType,_nbind.getType,_nbind.queryType),I.destroy=_nbind.makeMethodCaller(I.ptrType,{boundID:E.id,flags:0,name:"destroy",num:0,ptr:n,title:I.name+".free",typeList:["void","uint32_t","uint32_t"]}),a&&(I.superIdList=Array.prototype.slice.call(HEAPU32.subarray(r/4,r/4+a)),I.upcastList=Array.prototype.slice.call(HEAPU32.subarray(o/4,o/4+a))),Module[I.name]=I.makeBound(p),_nbind.BindClass.list.push(I)}function _removeAccessorPrefix(t){var e=/^[Gg]et_?([A-Z]?([A-Z]?))/;return t.replace(e,function(r,o,a){return a?o:o.toLowerCase()})}function __nbind_register_function(t,e,r,o,a,n,u,A,p,h){var E=_nbind.getType(t),I=_nbind.readPolicyList(e),v=_nbind.readTypeIdList(r,o),x;if(u==5)x=[{direct:a,name:"__nbindConstructor",ptr:0,title:E.name+" constructor",typeList:["uint32_t"].concat(v.slice(1))},{direct:n,name:"__nbindValueConstructor",ptr:0,title:E.name+" value constructor",typeList:["void","uint32_t"].concat(v.slice(1))}];else{var C=_nbind.readAsciiString(A),R=(E.name&&E.name+".")+C;(u==3||u==4)&&(C=_removeAccessorPrefix(C)),x=[{boundID:t,direct:n,name:C,ptr:a,title:R,typeList:v}]}for(var L=0,U=x;L<U.length;L++){var z=U[L];z.signatureType=u,z.policyTbl=I,z.num=p,z.flags=h,E.addMethod(z)}}function _nbind_value(t,e){_nbind.typeNameTbl[t]||_nbind.throwError("Unknown value type "+t),Module.NBind.bind_value(t,e),_defineHidden(_nbind.typeNameTbl[t].proto.prototype.__nbindValueConstructor)(e.prototype,"__nbindValueConstructor")}Module._nbind_value=_nbind_value;function __nbind_get_value_object(t,e){var r=_nbind.popValue(t);if(!r.fromJS)throw new Error("Object "+r+" has no fromJS function");r.fromJS(function(){r.__nbindValueConstructor.apply(this,Array.prototype.concat.apply([e],arguments))})}function _emscripten_memcpy_big(t,e,r){return HEAPU8.set(HEAPU8.subarray(e,e+r),t),t}function __nbind_register_primitive(t,e,r){var o={flags:1024|r,id:t,ptrSize:e};_nbind.makeType(_nbind.constructType,o)}var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_STATIC);function ___setErrNo(t){return Module.___errno_location&&(HEAP32[Module.___errno_location()>>2]=t),t}function _llvm_stacksave(){var t=_llvm_stacksave;return t.LLVM_SAVEDSTACKS||(t.LLVM_SAVEDSTACKS=[]),t.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),t.LLVM_SAVEDSTACKS.length-1}function ___syscall140(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.getStreamFromFD(),o=SYSCALLS.get(),a=SYSCALLS.get(),n=SYSCALLS.get(),u=SYSCALLS.get(),A=a;return FS.llseek(r,A,u),HEAP32[n>>2]=r.position,r.getdents&&A===0&&u===0&&(r.getdents=null),0}catch(p){return(typeof FS>"u"||!(p instanceof FS.ErrnoError))&&abort(p),-p.errno}}function ___syscall146(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.get(),o=SYSCALLS.get(),a=SYSCALLS.get(),n=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(E,I){var v=___syscall146.buffers[E];assert(v),I===0||I===10?((E===1?Module.print:Module.printErr)(UTF8ArrayToString(v,0)),v.length=0):v.push(I)});for(var u=0;u<a;u++){for(var A=HEAP32[o+u*8>>2],p=HEAP32[o+(u*8+4)>>2],h=0;h<p;h++)___syscall146.printChar(r,HEAPU8[A+h]);n+=p}return n}catch(E){return(typeof FS>"u"||!(E instanceof FS.ErrnoError))&&abort(E),-E.errno}}function __nbind_finish(){for(var t=0,e=_nbind.BindClass.list;t<e.length;t++){var r=e[t];r.finish()}}var ___dso_handle=STATICTOP;STATICTOP+=16,function(_nbind){var typeIdTbl={};_nbind.typeNameTbl={};var Pool=function(){function t(){}return t.lalloc=function(e){e=e+7&-8;var r=HEAPU32[t.usedPtr];if(e>t.pageSize/2||e>t.pageSize-r){var o=_nbind.typeNameTbl.NBind.proto;return o.lalloc(e)}else return HEAPU32[t.usedPtr]=r+e,t.rootPtr+r},t.lreset=function(e,r){var o=HEAPU32[t.pagePtr];if(o){var a=_nbind.typeNameTbl.NBind.proto;a.lreset(e,r)}else HEAPU32[t.usedPtr]=e},t}();_nbind.Pool=Pool;function constructType(t,e){var r=t==10240?_nbind.makeTypeNameTbl[e.name]||_nbind.BindType:_nbind.makeTypeKindTbl[t],o=new r(e);return typeIdTbl[e.id]=o,_nbind.typeNameTbl[e.name]=o,o}_nbind.constructType=constructType;function getType(t){return typeIdTbl[t]}_nbind.getType=getType;function queryType(t){var e=HEAPU8[t],r=_nbind.structureList[e][1];t/=4,r<0&&(++t,r=HEAPU32[t]+1);var o=Array.prototype.slice.call(HEAPU32.subarray(t+1,t+1+r));return e==9&&(o=[o[0],o.slice(1)]),{paramList:o,placeholderFlag:e}}_nbind.queryType=queryType;function getTypes(t,e){return t.map(function(r){return typeof r=="number"?_nbind.getComplexType(r,constructType,getType,queryType,e):_nbind.typeNameTbl[r]})}_nbind.getTypes=getTypes;function readTypeIdList(t,e){return Array.prototype.slice.call(HEAPU32,t/4,t/4+e)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(t){for(var e=t;HEAPU8[e++];);return String.fromCharCode.apply("",HEAPU8.subarray(t,e-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(t){var e={};if(t)for(;;){var r=HEAPU32[t/4];if(!r)break;e[readAsciiString(r)]=!0,t+=4}return e}_nbind.readPolicyList=readPolicyList;function getDynCall(t,e){var r={float32_t:"d",float64_t:"d",int64_t:"d",uint64_t:"d",void:"v"},o=t.map(function(n){return r[n.name]||"i"}).join(""),a=Module["dynCall_"+o];if(!a)throw new Error("dynCall_"+o+" not found for "+e+"("+t.map(function(n){return n.name}).join(", ")+")");return a}_nbind.getDynCall=getDynCall;function addMethod(t,e,r,o){var a=t[e];t.hasOwnProperty(e)&&a?((a.arity||a.arity===0)&&(a=_nbind.makeOverloader(a,a.arity),t[e]=a),a.addMethod(r,o)):(r.arity=o,t[e]=r)}_nbind.addMethod=addMethod;function throwError(t){throw new Error(t)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.heap=HEAPU32,r.ptrSize=4,r}return e.prototype.needsWireRead=function(r){return!!this.wireRead||!!this.makeWireRead},e.prototype.needsWireWrite=function(r){return!!this.wireWrite||!!this.makeWireWrite},e}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this,a=r.flags&32?{32:HEAPF32,64:HEAPF64}:r.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return o.heap=a[r.ptrSize*8],o.ptrSize=r.ptrSize,o}return e.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},e.prototype.makeWireWrite=function(r,o){return o&&o.Strict&&function(a){if(typeof a=="number")return a;throw new Error("Type mismatch")}},e}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(t,e){if(t==null){if(e&&e.Nullable)return 0;throw new Error("Type mismatch")}if(e&&e.Strict){if(typeof t!="string")throw new Error("Type mismatch")}else t=t.toString();var r=Module.lengthBytesUTF8(t)+1,o=_nbind.Pool.lalloc(r);return Module.stringToUTF8Array(t,HEAPU8,o,r),o}_nbind.pushCString=pushCString;function popCString(t){return t===0?null:Module.Pointer_stringify(t)}_nbind.popCString=popCString;var CStringType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popCString,r.wireWrite=pushCString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushCString(a,o)}},e}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=function(o){return!!o},r}return e.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},e.prototype.makeWireRead=function(r){return"!!("+r+")"},e.prototype.makeWireWrite=function(r,o){return o&&o.Strict&&function(a){if(typeof a=="boolean")return a;throw new Error("Type mismatch")}||r},e}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function t(){}return t.prototype.persist=function(){this.__nbindState|=1},t}();_nbind.Wrapper=Wrapper;function makeBound(t,e){var r=function(o){__extends(a,o);function a(n,u,A,p){var h=o.call(this)||this;if(!(h instanceof a))return new(Function.prototype.bind.apply(a,Array.prototype.concat.apply([null],arguments)));var E=u,I=A,v=p;if(n!==_nbind.ptrMarker){var x=h.__nbindConstructor.apply(h,arguments);E=4608,v=HEAPU32[x/4],I=HEAPU32[x/4+1]}var C={configurable:!0,enumerable:!1,value:null,writable:!1},R={__nbindFlags:E,__nbindPtr:I};v&&(R.__nbindShared=v,_nbind.mark(h));for(var L=0,U=Object.keys(R);L<U.length;L++){var z=U[L];C.value=R[z],Object.defineProperty(h,z,C)}return _defineHidden(0)(h,"__nbindState"),h}return a.prototype.free=function(){e.destroy.call(this,this.__nbindShared,this.__nbindFlags),this.__nbindState|=2,disableMember(this,"__nbindShared"),disableMember(this,"__nbindPtr")},a}(Wrapper);return __decorate([_defineHidden()],r.prototype,"__nbindConstructor",void 0),__decorate([_defineHidden()],r.prototype,"__nbindValueConstructor",void 0),__decorate([_defineHidden(t)],r.prototype,"__nbindPolicies",void 0),r}_nbind.makeBound=makeBound;function disableMember(t,e){function r(){throw new Error("Accessing deleted object")}Object.defineProperty(t,e,{configurable:!1,enumerable:!1,get:r,set:r})}_nbind.ptrMarker={};var BindClass=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;return o.wireRead=function(a){return _nbind.popValue(a,o.ptrType)},o.wireWrite=function(a){return pushPointer(a,o.ptrType,!0)},o.pendingSuperCount=0,o.ready=!1,o.methodTbl={},r.paramList?(o.classType=r.paramList[0].classType,o.proto=o.classType.proto):o.classType=o,o}return e.prototype.makeBound=function(r){var o=_nbind.makeBound(r,this);return this.proto=o,this.ptrType.proto=o,o},e.prototype.addMethod=function(r){var o=this.methodTbl[r.name]||[];o.push(r),this.methodTbl[r.name]=o},e.prototype.registerMethods=function(r,o){for(var a,n=0,u=Object.keys(r.methodTbl);n<u.length;n++)for(var A=u[n],p=r.methodTbl[A],h=0,E=p;h<E.length;h++){var I=E[h],v=void 0,x=void 0;if(v=this.proto.prototype,!(o&&I.signatureType!=1))switch(I.signatureType){case 1:v=this.proto;case 5:x=_nbind.makeCaller(I),_nbind.addMethod(v,I.name,x,I.typeList.length-1);break;case 4:a=_nbind.makeMethodCaller(r.ptrType,I);break;case 3:Object.defineProperty(v,I.name,{configurable:!0,enumerable:!1,get:_nbind.makeMethodCaller(r.ptrType,I),set:a});break;case 2:x=_nbind.makeMethodCaller(r.ptrType,I),_nbind.addMethod(v,I.name,x,I.typeList.length-1);break;default:break}}},e.prototype.registerSuperMethods=function(r,o,a){if(!a[r.name]){a[r.name]=!0;for(var n=0,u,A=0,p=r.superIdList||[];A<p.length;A++){var h=p[A],E=_nbind.getType(h);n++<o||o<0?u=-1:u=0,this.registerSuperMethods(E,u,a)}this.registerMethods(r,o<0)}},e.prototype.finish=function(){if(this.ready)return this;this.ready=!0,this.superList=(this.superIdList||[]).map(function(a){return _nbind.getType(a).finish()});var r=this.proto;if(this.superList.length){var o=function(){this.constructor=r};o.prototype=this.superList[0].proto.prototype,r.prototype=new o}return r!=Module&&(r.prototype.__nbindType=this),this.registerSuperMethods(this,1,{}),this},e.prototype.upcastStep=function(r,o){if(r==this)return o;for(var a=0;a<this.superList.length;++a){var n=this.superList[a].upcastStep(r,_nbind.callUpcast(this.upcastList[a],o));if(n)return n}return 0},e}(_nbind.BindType);BindClass.list=[],_nbind.BindClass=BindClass;function popPointer(t,e){return t?new e.proto(_nbind.ptrMarker,e.flags,t):null}_nbind.popPointer=popPointer;function pushPointer(t,e,r){if(!(t instanceof _nbind.Wrapper)){if(r)return _nbind.pushValue(t);throw new Error("Type mismatch")}var o=t.__nbindPtr,a=t.__nbindType.classType,n=e.classType;if(t instanceof e.proto)for(;a!=n;)o=_nbind.callUpcast(a.upcastList[0],o),a=a.superList[0];else if(o=a.upcastStep(n,o),!o)throw new Error("Type mismatch");return o}_nbind.pushPointer=pushPointer;function pushMutablePointer(t,e){var r=pushPointer(t,e);if(t.__nbindFlags&1)throw new Error("Passing a const value as a non-const argument");return r}var BindClassPtr=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;o.classType=r.paramList[0].classType,o.proto=o.classType.proto;var a=r.flags&1,n=(o.flags&896)==256&&r.flags&2,u=a?pushPointer:pushMutablePointer,A=n?_nbind.popValue:popPointer;return o.makeWireWrite=function(p,h){return h.Nullable?function(E){return E?u(E,o):0}:function(E){return u(E,o)}},o.wireRead=function(p){return A(p,o)},o.wireWrite=function(p){return u(p,o)},o}return e}(_nbind.BindType);_nbind.BindClassPtr=BindClassPtr;function popShared(t,e){var r=HEAPU32[t/4],o=HEAPU32[t/4+1];return o?new e.proto(_nbind.ptrMarker,e.flags,o,r):null}_nbind.popShared=popShared;function pushShared(t,e){if(!(t instanceof e.proto))throw new Error("Type mismatch");return t.__nbindShared}function pushMutableShared(t,e){if(!(t instanceof e.proto))throw new Error("Type mismatch");if(t.__nbindFlags&1)throw new Error("Passing a const value as a non-const argument");return t.__nbindShared}var SharedClassPtr=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;o.readResources=[_nbind.resources.pool],o.classType=r.paramList[0].classType,o.proto=o.classType.proto;var a=r.flags&1,n=a?pushShared:pushMutableShared;return o.wireRead=function(u){return popShared(u,o)},o.wireWrite=function(u){return n(u,o)},o}return e}(_nbind.BindType);_nbind.SharedClassPtr=SharedClassPtr,_nbind.externalList=[0];var firstFreeExternal=0,External=function(){function t(e){this.refCount=1,this.data=e}return t.prototype.register=function(){var e=firstFreeExternal;return e?firstFreeExternal=_nbind.externalList[e]:e=_nbind.externalList.length,_nbind.externalList[e]=this,e},t.prototype.reference=function(){++this.refCount},t.prototype.dereference=function(e){--this.refCount==0&&(this.free&&this.free(),_nbind.externalList[e]=firstFreeExternal,firstFreeExternal=e)},t}();_nbind.External=External;function popExternal(t){var e=_nbind.externalList[t];return e.dereference(t),e.data}function pushExternal(t){var e=new External(t);return e.reference(),e.register()}var ExternalType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popExternal,r.wireWrite=pushExternal,r}return e}(_nbind.BindType);_nbind.ExternalType=ExternalType,_nbind.callbackSignatureList=[];var CallbackType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireWrite=function(o){return typeof o!="function"&&_nbind.throwError("Type mismatch"),new _nbind.External(o).register()},r}return e}(_nbind.BindType);_nbind.CallbackType=CallbackType,_nbind.valueList=[0];var firstFreeValue=0;function pushValue(t){var e=firstFreeValue;return e?firstFreeValue=_nbind.valueList[e]:e=_nbind.valueList.length,_nbind.valueList[e]=t,e*2+1}_nbind.pushValue=pushValue;function popValue(t,e){if(t||_nbind.throwError("Value type JavaScript class is missing or not registered"),t&1){t>>=1;var r=_nbind.valueList[t];return _nbind.valueList[t]=firstFreeValue,firstFreeValue=t,r}else{if(e)return _nbind.popShared(t,e);throw new Error("Invalid value slot "+t)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(t){return typeof t=="number"?t:pushValue(t)*4096+valueBase}function pop64(t){return t<valueBase?t:popValue((t-valueBase)/4096)}var CreateValueType=function(t){__extends(e,t);function e(){return t!==null&&t.apply(this,arguments)||this}return e.prototype.makeWireWrite=function(r){return"(_nbind.pushValue(new "+r+"))"},e}(_nbind.BindType);_nbind.CreateValueType=CreateValueType;var Int64Type=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireWrite=push64,r.wireRead=pop64,r}return e}(_nbind.BindType);_nbind.Int64Type=Int64Type;function pushArray(t,e){if(!t)return 0;var r=t.length;if((e.size||e.size===0)&&r<e.size)throw new Error("Type mismatch");var o=e.memberType.ptrSize,a=_nbind.Pool.lalloc(4+r*o);HEAPU32[a/4]=r;var n=e.memberType.heap,u=(a+4)/o,A=e.memberType.wireWrite,p=0;if(A)for(;p<r;)n[u++]=A(t[p++]);else for(;p<r;)n[u++]=t[p++];return a}_nbind.pushArray=pushArray;function popArray(t,e){if(t===0)return null;var r=HEAPU32[t/4],o=new Array(r),a=e.memberType.heap;t=(t+4)/e.memberType.ptrSize;var n=e.memberType.wireRead,u=0;if(n)for(;u<r;)o[u++]=n(a[t++]);else for(;u<r;)o[u++]=a[t++];return o}_nbind.popArray=popArray;var ArrayType=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;return o.wireRead=function(a){return popArray(a,o)},o.wireWrite=function(a){return pushArray(a,o)},o.readResources=[_nbind.resources.pool],o.writeResources=[_nbind.resources.pool],o.memberType=r.paramList[0],r.paramList[1]&&(o.size=r.paramList[1]),o}return e}(_nbind.BindType);_nbind.ArrayType=ArrayType;function pushString(t,e){if(t==null)if(e&&e.Nullable)t="";else throw new Error("Type mismatch");if(e&&e.Strict){if(typeof t!="string")throw new Error("Type mismatch")}else t=t.toString();var r=Module.lengthBytesUTF8(t),o=_nbind.Pool.lalloc(4+r+1);return HEAPU32[o/4]=r,Module.stringToUTF8Array(t,HEAPU8,o+4,r+1),o}_nbind.pushString=pushString;function popString(t){if(t===0)return null;var e=HEAPU32[t/4];return Module.Pointer_stringify(t+4,e)}_nbind.popString=popString;var StringType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popString,r.wireWrite=pushString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushString(a,o)}},e}(_nbind.BindType);_nbind.StringType=StringType;function makeArgList(t){return Array.apply(null,Array(t)).map(function(e,r){return"a"+(r+1)})}function anyNeedsWireWrite(t,e){return t.reduce(function(r,o){return r||o.needsWireWrite(e)},!1)}function anyNeedsWireRead(t,e){return t.reduce(function(r,o){return r||!!o.needsWireRead(e)},!1)}function makeWireRead(t,e,r,o){var a=t.length;return r.makeWireRead?r.makeWireRead(o,t,a):r.wireRead?(t[a]=r.wireRead,"(convertParamList["+a+"]("+o+"))"):o}function makeWireWrite(t,e,r,o){var a,n=t.length;return r.makeWireWrite?a=r.makeWireWrite(o,e,t,n):a=r.wireWrite,a?typeof a=="string"?a:(t[n]=a,"(convertParamList["+n+"]("+o+"))"):o}function buildCallerFunction(dynCall,ptrType,ptr,num,policyTbl,needsWireWrite,prefix,returnType,argTypeList,mask,err){var argList=makeArgList(argTypeList.length),convertParamList=[],callExpression=makeWireRead(convertParamList,policyTbl,returnType,"dynCall("+[prefix].concat(argList.map(function(t,e){return makeWireWrite(convertParamList,policyTbl,argTypeList[e],t)})).join(",")+")"),resourceSet=_nbind.listResources([returnType],argTypeList),sourceCode="function("+argList.join(",")+"){"+(mask?"this.__nbindFlags&mask&&err();":"")+resourceSet.makeOpen()+"var r="+callExpression+";"+resourceSet.makeClose()+"return r;}";return eval("("+sourceCode+")")}function buildJSCallerFunction(returnType,argTypeList){var argList=makeArgList(argTypeList.length),convertParamList=[],callExpression=makeWireWrite(convertParamList,null,returnType,"_nbind.externalList[num].data("+argList.map(function(t,e){return makeWireRead(convertParamList,null,argTypeList[e],t)}).join(",")+")"),resourceSet=_nbind.listResources(argTypeList,[returnType]);resourceSet.remove(_nbind.resources.pool);var sourceCode="function("+["dummy","num"].concat(argList).join(",")+"){"+resourceSet.makeOpen()+"var r="+callExpression+";"+resourceSet.makeClose()+"return r;}";return eval("("+sourceCode+")")}_nbind.buildJSCallerFunction=buildJSCallerFunction;function makeJSCaller(t){var e=t.length-1,r=_nbind.getTypes(t,"callback"),o=r[0],a=r.slice(1),n=anyNeedsWireRead(a,null),u=o.needsWireWrite(null);if(!u&&!n)switch(e){case 0:return function(A,p){return _nbind.externalList[p].data()};case 1:return function(A,p,h){return _nbind.externalList[p].data(h)};case 2:return function(A,p,h,E){return _nbind.externalList[p].data(h,E)};case 3:return function(A,p,h,E,I){return _nbind.externalList[p].data(h,E,I)};default:break}return buildJSCallerFunction(o,a)}_nbind.makeJSCaller=makeJSCaller;function makeMethodCaller(t,e){var r=e.typeList.length-1,o=e.typeList.slice(0);o.splice(1,0,"uint32_t",e.boundID);var a=_nbind.getTypes(o,e.title),n=a[0],u=a.slice(3),A=n.needsWireRead(e.policyTbl),p=anyNeedsWireWrite(u,e.policyTbl),h=e.ptr,E=e.num,I=_nbind.getDynCall(a,e.title),v=~e.flags&1;function x(){throw new Error("Calling a non-const method on a const object")}if(!A&&!p)switch(r){case 0:return function(){return this.__nbindFlags&v?x():I(h,E,_nbind.pushPointer(this,t))};case 1:return function(C){return this.__nbindFlags&v?x():I(h,E,_nbind.pushPointer(this,t),C)};case 2:return function(C,R){return this.__nbindFlags&v?x():I(h,E,_nbind.pushPointer(this,t),C,R)};case 3:return function(C,R,L){return this.__nbindFlags&v?x():I(h,E,_nbind.pushPointer(this,t),C,R,L)};default:break}return buildCallerFunction(I,t,h,E,e.policyTbl,p,"ptr,num,pushPointer(this,ptrType)",n,u,v,x)}_nbind.makeMethodCaller=makeMethodCaller;function makeCaller(t){var e=t.typeList.length-1,r=_nbind.getTypes(t.typeList,t.title),o=r[0],a=r.slice(1),n=o.needsWireRead(t.policyTbl),u=anyNeedsWireWrite(a,t.policyTbl),A=t.direct,p=t.ptr;if(t.direct&&!n&&!u){var h=_nbind.getDynCall(r,t.title);switch(e){case 0:return function(){return h(A)};case 1:return function(x){return h(A,x)};case 2:return function(x,C){return h(A,x,C)};case 3:return function(x,C,R){return h(A,x,C,R)};default:break}p=0}var E;if(p){var I=t.typeList.slice(0);I.splice(1,0,"uint32_t"),r=_nbind.getTypes(I,t.title),E="ptr,num"}else p=A,E="ptr";var v=_nbind.getDynCall(r,t.title);return buildCallerFunction(v,null,p,t.num,t.policyTbl,u,E,o,a)}_nbind.makeCaller=makeCaller;function makeOverloader(t,e){var r=[];function o(){return r[arguments.length].apply(this,arguments)}return o.addMethod=function(a,n){r[n]=a},o.addMethod(t,e),o}_nbind.makeOverloader=makeOverloader;var Resource=function(){function t(e,r){var o=this;this.makeOpen=function(){return Object.keys(o.openTbl).join("")},this.makeClose=function(){return Object.keys(o.closeTbl).join("")},this.openTbl={},this.closeTbl={},e&&(this.openTbl[e]=!0),r&&(this.closeTbl[r]=!0)}return t.prototype.add=function(e){for(var r=0,o=Object.keys(e.openTbl);r<o.length;r++){var a=o[r];this.openTbl[a]=!0}for(var n=0,u=Object.keys(e.closeTbl);n<u.length;n++){var a=u[n];this.closeTbl[a]=!0}},t.prototype.remove=function(e){for(var r=0,o=Object.keys(e.openTbl);r<o.length;r++){var a=o[r];delete this.openTbl[a]}for(var n=0,u=Object.keys(e.closeTbl);n<u.length;n++){var a=u[n];delete this.closeTbl[a]}},t}();_nbind.Resource=Resource;function listResources(t,e){for(var r=new Resource,o=0,a=t;o<a.length;o++)for(var n=a[o],u=0,A=n.readResources||[];u<A.length;u++){var p=A[u];r.add(p)}for(var h=0,E=e;h<E.length;h++)for(var n=E[h],I=0,v=n.writeResources||[];I<v.length;I++){var p=v[I];r.add(p)}return r}_nbind.listResources=listResources,_nbind.resources={pool:new Resource("var used=HEAPU32[_nbind.Pool.usedPtr],page=HEAPU32[_nbind.Pool.pagePtr];","_nbind.Pool.lreset(used,page);")};var ExternalBuffer=function(t){__extends(e,t);function e(r,o){var a=t.call(this,r)||this;return a.ptr=o,a}return e.prototype.free=function(){_free(this.ptr)},e}(_nbind.External);function getBuffer(t){return t instanceof ArrayBuffer?new Uint8Array(t):t instanceof DataView?new Uint8Array(t.buffer,t.byteOffset,t.byteLength):t}function pushBuffer(t,e){if(t==null&&e&&e.Nullable&&(t=[]),typeof t!="object")throw new Error("Type mismatch");var r=t,o=r.byteLength||r.length;if(!o&&o!==0&&r.byteLength!==0)throw new Error("Type mismatch");var a=_nbind.Pool.lalloc(8),n=_malloc(o),u=a/4;return HEAPU32[u++]=o,HEAPU32[u++]=n,HEAPU32[u++]=new ExternalBuffer(t,n).register(),HEAPU8.set(getBuffer(t),n),a}var BufferType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireWrite=pushBuffer,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushBuffer(a,o)}},e}(_nbind.BindType);_nbind.BufferType=BufferType;function commitBuffer(t,e,r){var o=_nbind.externalList[t].data,a=Buffer;if(typeof Buffer!="function"&&(a=function(){}),!(o instanceof Array)){var n=HEAPU8.subarray(e,e+r);if(o instanceof a){var u=void 0;typeof Buffer.from=="function"&&Buffer.from.length>=3?u=Buffer.from(n):u=new Buffer(n),u.copy(o)}else getBuffer(o).set(n)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var t=0,e=dirtyList;t<e.length;t++){var r=e[t];r.__nbindState&3||r.free()}dirtyList=[],gcTimer=0}_nbind.mark=function(t){};function toggleLightGC(t){t?_nbind.mark=function(e){dirtyList.push(e),gcTimer||(gcTimer=setTimeout(sweep,0))}:_nbind.mark=function(e){}}_nbind.toggleLightGC=toggleLightGC}(_nbind),Module.requestFullScreen=function t(e,r,o){Module.printErr("Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead."),Module.requestFullScreen=Module.requestFullscreen,Browser.requestFullScreen(e,r,o)},Module.requestFullscreen=function t(e,r,o){Browser.requestFullscreen(e,r,o)},Module.requestAnimationFrame=function t(e){Browser.requestAnimationFrame(e)},Module.setCanvasSize=function t(e,r,o){Browser.setCanvasSize(e,r,o)},Module.pauseMainLoop=function t(){Browser.mainLoop.pause()},Module.resumeMainLoop=function t(){Browser.mainLoop.resume()},Module.getUserMedia=function t(){Browser.getUserMedia()},Module.createContext=function t(e,r,o,a){return Browser.createContext(e,r,o,a)},ENVIRONMENT_IS_NODE?_emscripten_get_now=function(){var e=process.hrtime();return e[0]*1e3+e[1]/1e6}:typeof dateNow<"u"?_emscripten_get_now=dateNow:typeof self=="object"&&self.performance&&typeof self.performance.now=="function"?_emscripten_get_now=function(){return self.performance.now()}:typeof performance=="object"&&typeof performance.now=="function"?_emscripten_get_now=function(){return performance.now()}:_emscripten_get_now=Date.now,__ATEXIT__.push(function(){var t=Module._fflush;t&&t(0);var e=___syscall146.printChar;if(e){var r=___syscall146.buffers;r[1].length&&e(1,10),r[2].length&&e(2,10)}}),DYNAMICTOP_PTR=allocate(1,"i32",ALLOC_STATIC),STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP),STACK_MAX=STACK_BASE+TOTAL_STACK,DYNAMIC_BASE=Runtime.alignMemory(STACK_MAX),HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(t,e,r,o,a,n){try{Module.dynCall_viiiii(t,e,r,o,a,n)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_vif(t,e,r){try{Module.dynCall_vif(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_vid(t,e,r){try{Module.dynCall_vid(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_fiff(t,e,r,o){try{return Module.dynCall_fiff(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_vi(t,e){try{Module.dynCall_vi(t,e)}catch(r){if(typeof r!="number"&&r!=="longjmp")throw r;Module.setThrew(1,0)}}function invoke_vii(t,e,r){try{Module.dynCall_vii(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_ii(t,e){try{return Module.dynCall_ii(t,e)}catch(r){if(typeof r!="number"&&r!=="longjmp")throw r;Module.setThrew(1,0)}}function invoke_viddi(t,e,r,o,a){try{Module.dynCall_viddi(t,e,r,o,a)}catch(n){if(typeof n!="number"&&n!=="longjmp")throw n;Module.setThrew(1,0)}}function invoke_vidd(t,e,r,o){try{Module.dynCall_vidd(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_iiii(t,e,r,o){try{return Module.dynCall_iiii(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_diii(t,e,r,o){try{return Module.dynCall_diii(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_di(t,e){try{return Module.dynCall_di(t,e)}catch(r){if(typeof r!="number"&&r!=="longjmp")throw r;Module.setThrew(1,0)}}function invoke_iid(t,e,r){try{return Module.dynCall_iid(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_iii(t,e,r){try{return Module.dynCall_iii(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_viiddi(t,e,r,o,a,n){try{Module.dynCall_viiddi(t,e,r,o,a,n)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_viiiiii(t,e,r,o,a,n,u){try{Module.dynCall_viiiiii(t,e,r,o,a,n,u)}catch(A){if(typeof A!="number"&&A!=="longjmp")throw A;Module.setThrew(1,0)}}function invoke_dii(t,e,r){try{return Module.dynCall_dii(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_i(t){try{return Module.dynCall_i(t)}catch(e){if(typeof e!="number"&&e!=="longjmp")throw e;Module.setThrew(1,0)}}function invoke_iiiiii(t,e,r,o,a,n){try{return Module.dynCall_iiiiii(t,e,r,o,a,n)}catch(u){if(typeof u!="number"&&u!=="longjmp")throw u;Module.setThrew(1,0)}}function invoke_viiid(t,e,r,o,a){try{Module.dynCall_viiid(t,e,r,o,a)}catch(n){if(typeof n!="number"&&n!=="longjmp")throw n;Module.setThrew(1,0)}}function invoke_viififi(t,e,r,o,a,n,u){try{Module.dynCall_viififi(t,e,r,o,a,n,u)}catch(A){if(typeof A!="number"&&A!=="longjmp")throw A;Module.setThrew(1,0)}}function invoke_viii(t,e,r,o){try{Module.dynCall_viii(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_v(t){try{Module.dynCall_v(t)}catch(e){if(typeof e!="number"&&e!=="longjmp")throw e;Module.setThrew(1,0)}}function invoke_viid(t,e,r,o){try{Module.dynCall_viid(t,e,r,o)}catch(a){if(typeof a!="number"&&a!=="longjmp")throw a;Module.setThrew(1,0)}}function invoke_idd(t,e,r){try{return Module.dynCall_idd(t,e,r)}catch(o){if(typeof o!="number"&&o!=="longjmp")throw o;Module.setThrew(1,0)}}function invoke_viiii(t,e,r,o,a){try{Module.dynCall_viiii(t,e,r,o,a)}catch(n){if(typeof n!="number"&&n!=="longjmp")throw n;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:1/0},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(t,e,r){var o=new t.Int8Array(r),a=new t.Int16Array(r),n=new t.Int32Array(r),u=new t.Uint8Array(r),A=new t.Uint16Array(r),p=new t.Uint32Array(r),h=new t.Float32Array(r),E=new t.Float64Array(r),I=e.DYNAMICTOP_PTR|0,v=e.tempDoublePtr|0,x=e.ABORT|0,C=e.STACKTOP|0,R=e.STACK_MAX|0,L=e.cttz_i8|0,U=e.___dso_handle|0,z=0,te=0,ae=0,le=0,ce=t.NaN,Ce=t.Infinity,de=0,Be=0,Ee=0,g=0,me=0,we=0,Ae=t.Math.floor,ne=t.Math.abs,Z=t.Math.sqrt,xe=t.Math.pow,Ne=t.Math.cos,ht=t.Math.sin,H=t.Math.tan,rt=t.Math.acos,Te=t.Math.asin,Fe=t.Math.atan,ke=t.Math.atan2,Ye=t.Math.exp,Se=t.Math.log,et=t.Math.ceil,Ue=t.Math.imul,b=t.Math.min,w=t.Math.max,S=t.Math.clz32,y=t.Math.fround,F=e.abort,J=e.assert,X=e.enlargeMemory,$=e.getTotalMemory,ie=e.abortOnCannotGrowMemory,be=e.invoke_viiiii,Re=e.invoke_vif,at=e.invoke_vid,dt=e.invoke_fiff,jt=e.invoke_vi,tr=e.invoke_vii,St=e.invoke_ii,ln=e.invoke_viddi,kr=e.invoke_vidd,mr=e.invoke_iiii,br=e.invoke_diii,Kr=e.invoke_di,Kn=e.invoke_iid,Ms=e.invoke_iii,Ri=e.invoke_viiddi,gs=e.invoke_viiiiii,io=e.invoke_dii,Pi=e.invoke_i,Os=e.invoke_iiiiii,so=e.invoke_viiid,uc=e.invoke_viififi,Au=e.invoke_viii,sp=e.invoke_v,op=e.invoke_viid,Us=e.invoke_idd,Dn=e.invoke_viiii,oo=e._emscripten_asm_const_iiiii,_s=e._emscripten_asm_const_iiidddddd,ml=e._emscripten_asm_const_iiiid,yl=e.__nbind_reference_external,ao=e._emscripten_asm_const_iiiiiiii,Vn=e._removeAccessorPrefix,Mn=e._typeModule,Ti=e.__nbind_register_pool,On=e.__decorate,_i=e._llvm_stackrestore,ir=e.___cxa_atexit,Me=e.__extends,ii=e.__nbind_get_value_object,Ha=e.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,hr=e._emscripten_set_main_loop_timing,Ac=e.__nbind_register_primitive,fu=e.__nbind_register_type,fc=e._emscripten_memcpy_big,El=e.__nbind_register_function,vA=e.___setErrNo,pu=e.__nbind_register_class,Ie=e.__nbind_finish,Tt=e._abort,pc=e._nbind_value,Hi=e._llvm_stacksave,hu=e.___syscall54,Yt=e._defineHidden,Cl=e._emscripten_set_main_loop,DA=e._emscripten_get_now,ap=e.__nbind_register_callback_signature,hc=e._emscripten_asm_const_iiiiii,PA=e.__nbind_free_external,Qn=e._emscripten_asm_const_iiii,hi=e._emscripten_asm_const_iiididi,gc=e.___syscall6,SA=e._atexit,aa=e.___syscall140,Ni=e.___syscall146,_o=y(0);let Xe=y(0);function lo(s){s=s|0;var l=0;return l=C,C=C+s|0,C=C+15&-16,l|0}function dc(){return C|0}function gu(s){s=s|0,C=s}function qi(s,l){s=s|0,l=l|0,C=s,R=l}function du(s,l){s=s|0,l=l|0,z||(z=s,te=l)}function bA(s){s=s|0,we=s}function qa(){return we|0}function mc(){var s=0,l=0;Dr(8104,8,400)|0,Dr(8504,408,540)|0,s=9044,l=s+44|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));o[9088]=0,o[9089]=1,n[2273]=0,n[2274]=948,n[2275]=948,ir(17,8104,U|0)|0}function ds(s){s=s|0,ft(s+948|0)}function Ht(s){return s=y(s),((Su(s)|0)&2147483647)>>>0>2139095040|0}function Fn(s,l,c){s=s|0,l=l|0,c=c|0;e:do if(n[s+(l<<3)+4>>2]|0)s=s+(l<<3)|0;else{if((l|2|0)==3&&n[s+60>>2]|0){s=s+56|0;break}switch(l|0){case 0:case 2:case 4:case 5:{if(n[s+52>>2]|0){s=s+48|0;break e}break}default:}if(n[s+68>>2]|0){s=s+64|0;break}else{s=(l|1|0)==5?948:c;break}}while(!1);return s|0}function Ei(s){s=s|0;var l=0;return l=Jv(1e3)|0,la(s,(l|0)!=0,2456),n[2276]=(n[2276]|0)+1,Dr(l|0,8104,1e3)|0,o[s+2>>0]|0&&(n[l+4>>2]=2,n[l+12>>2]=4),n[l+976>>2]=s,l|0}function la(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;d=C,C=C+16|0,f=d,l||(n[f>>2]=c,g0(s,5,3197,f)),C=d}function co(){return Ei(956)|0}function Hs(s){s=s|0;var l=0;return l=Kt(1e3)|0,ca(l,s),la(n[s+976>>2]|0,1,2456),n[2276]=(n[2276]|0)+1,n[l+944>>2]=0,l|0}function ca(s,l){s=s|0,l=l|0;var c=0;Dr(s|0,l|0,948)|0,Cd(s+948|0,l+948|0),c=s+960|0,s=l+960|0,l=c+40|0;do n[c>>2]=n[s>>2],c=c+4|0,s=s+4|0;while((c|0)<(l|0))}function ua(s){s=s|0;var l=0,c=0,f=0,d=0;if(l=s+944|0,c=n[l>>2]|0,c|0&&(Ho(c+948|0,s)|0,n[l>>2]=0),c=Ci(s)|0,c|0){l=0;do n[(ms(s,l)|0)+944>>2]=0,l=l+1|0;while((l|0)!=(c|0))}c=s+948|0,f=n[c>>2]|0,d=s+952|0,l=n[d>>2]|0,(l|0)!=(f|0)&&(n[d>>2]=l+(~((l+-4-f|0)>>>2)<<2)),ys(c),Xv(s),n[2276]=(n[2276]|0)+-1}function Ho(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0;f=n[s>>2]|0,k=s+4|0,c=n[k>>2]|0,m=c;e:do if((f|0)==(c|0))d=f,B=4;else for(s=f;;){if((n[s>>2]|0)==(l|0)){d=s,B=4;break e}if(s=s+4|0,(s|0)==(c|0)){s=0;break}}while(!1);return(B|0)==4&&((d|0)!=(c|0)?(f=d+4|0,s=m-f|0,l=s>>2,l&&(ww(d|0,f|0,s|0)|0,c=n[k>>2]|0),s=d+(l<<2)|0,(c|0)==(s|0)||(n[k>>2]=c+(~((c+-4-s|0)>>>2)<<2)),s=1):s=0),s|0}function Ci(s){return s=s|0,(n[s+952>>2]|0)-(n[s+948>>2]|0)>>2|0}function ms(s,l){s=s|0,l=l|0;var c=0;return c=n[s+948>>2]|0,(n[s+952>>2]|0)-c>>2>>>0>l>>>0?s=n[c+(l<<2)>>2]|0:s=0,s|0}function ys(s){s=s|0;var l=0,c=0,f=0,d=0;f=C,C=C+32|0,l=f,d=n[s>>2]|0,c=(n[s+4>>2]|0)-d|0,((n[s+8>>2]|0)-d|0)>>>0>c>>>0&&(d=c>>2,Ep(l,d,d,s+8|0),E0(s,l),UA(l)),C=f}function Es(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0;O=Ci(s)|0;do if(O|0){if((n[(ms(s,0)|0)+944>>2]|0)==(s|0)){if(!(Ho(s+948|0,l)|0))break;Dr(l+400|0,8504,540)|0,n[l+944>>2]=0,Le(s);break}B=n[(n[s+976>>2]|0)+12>>2]|0,k=s+948|0,Q=(B|0)==0,c=0,m=0;do f=n[(n[k>>2]|0)+(m<<2)>>2]|0,(f|0)==(l|0)?Le(s):(d=Hs(f)|0,n[(n[k>>2]|0)+(c<<2)>>2]=d,n[d+944>>2]=s,Q||BR[B&15](f,d,s,c),c=c+1|0),m=m+1|0;while((m|0)!=(O|0));if(c>>>0<O>>>0){Q=s+948|0,k=s+952|0,B=c,c=n[k>>2]|0;do m=(n[Q>>2]|0)+(B<<2)|0,f=m+4|0,d=c-f|0,l=d>>2,l&&(ww(m|0,f|0,d|0)|0,c=n[k>>2]|0),d=c,f=m+(l<<2)|0,(d|0)!=(f|0)&&(c=d+(~((d+-4-f|0)>>>2)<<2)|0,n[k>>2]=c),B=B+1|0;while((B|0)!=(O|0))}}while(!1)}function qs(s){s=s|0;var l=0,c=0,f=0,d=0;Un(s,(Ci(s)|0)==0,2491),Un(s,(n[s+944>>2]|0)==0,2545),l=s+948|0,c=n[l>>2]|0,f=s+952|0,d=n[f>>2]|0,(d|0)!=(c|0)&&(n[f>>2]=d+(~((d+-4-c|0)>>>2)<<2)),ys(l),l=s+976|0,c=n[l>>2]|0,Dr(s|0,8104,1e3)|0,o[c+2>>0]|0&&(n[s+4>>2]=2,n[s+12>>2]=4),n[l>>2]=c}function Un(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;d=C,C=C+16|0,f=d,l||(n[f>>2]=c,Ao(s,5,3197,f)),C=d}function Pn(){return n[2276]|0}function Cs(){var s=0;return s=Jv(20)|0,We((s|0)!=0,2592),n[2277]=(n[2277]|0)+1,n[s>>2]=n[239],n[s+4>>2]=n[240],n[s+8>>2]=n[241],n[s+12>>2]=n[242],n[s+16>>2]=n[243],s|0}function We(s,l){s=s|0,l=l|0;var c=0,f=0;f=C,C=C+16|0,c=f,s||(n[c>>2]=l,Ao(0,5,3197,c)),C=f}function tt(s){s=s|0,Xv(s),n[2277]=(n[2277]|0)+-1}function Bt(s,l){s=s|0,l=l|0;var c=0;l?(Un(s,(Ci(s)|0)==0,2629),c=1):(c=0,l=0),n[s+964>>2]=l,n[s+988>>2]=c}function or(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,m=f+8|0,d=f+4|0,B=f,n[d>>2]=l,Un(s,(n[l+944>>2]|0)==0,2709),Un(s,(n[s+964>>2]|0)==0,2763),ee(s),l=s+948|0,n[B>>2]=(n[l>>2]|0)+(c<<2),n[m>>2]=n[B>>2],ye(l,m,d)|0,n[(n[d>>2]|0)+944>>2]=s,Le(s),C=f}function ee(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;if(c=Ci(s)|0,c|0&&(n[(ms(s,0)|0)+944>>2]|0)!=(s|0)){f=n[(n[s+976>>2]|0)+12>>2]|0,d=s+948|0,m=(f|0)==0,l=0;do B=n[(n[d>>2]|0)+(l<<2)>>2]|0,k=Hs(B)|0,n[(n[d>>2]|0)+(l<<2)>>2]=k,n[k+944>>2]=s,m||BR[f&15](B,k,s,l),l=l+1|0;while((l|0)!=(c|0))}}function ye(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0,$e=0,Je=0;$e=C,C=C+64|0,j=$e+52|0,k=$e+48|0,se=$e+28|0,je=$e+24|0,Oe=$e+20|0,Qe=$e,f=n[s>>2]|0,m=f,l=f+((n[l>>2]|0)-m>>2<<2)|0,f=s+4|0,d=n[f>>2]|0,B=s+8|0;do if(d>>>0<(n[B>>2]|0)>>>0){if((l|0)==(d|0)){n[l>>2]=n[c>>2],n[f>>2]=(n[f>>2]|0)+4;break}_A(s,l,d,l+4|0),l>>>0<=c>>>0&&(c=(n[f>>2]|0)>>>0>c>>>0?c+4|0:c),n[l>>2]=n[c>>2]}else{f=(d-m>>2)+1|0,d=N(s)|0,d>>>0<f>>>0&&Jr(s),M=n[s>>2]|0,O=(n[B>>2]|0)-M|0,m=O>>1,Ep(Qe,O>>2>>>0<d>>>1>>>0?m>>>0<f>>>0?f:m:d,l-M>>2,s+8|0),M=Qe+8|0,f=n[M>>2]|0,m=Qe+12|0,O=n[m>>2]|0,B=O,Q=f;do if((f|0)==(O|0)){if(O=Qe+4|0,f=n[O>>2]|0,Je=n[Qe>>2]|0,d=Je,f>>>0<=Je>>>0){f=B-d>>1,f=f|0?f:1,Ep(se,f,f>>>2,n[Qe+16>>2]|0),n[je>>2]=n[O>>2],n[Oe>>2]=n[M>>2],n[k>>2]=n[je>>2],n[j>>2]=n[Oe>>2],lw(se,k,j),f=n[Qe>>2]|0,n[Qe>>2]=n[se>>2],n[se>>2]=f,f=se+4|0,Je=n[O>>2]|0,n[O>>2]=n[f>>2],n[f>>2]=Je,f=se+8|0,Je=n[M>>2]|0,n[M>>2]=n[f>>2],n[f>>2]=Je,f=se+12|0,Je=n[m>>2]|0,n[m>>2]=n[f>>2],n[f>>2]=Je,UA(se),f=n[M>>2]|0;break}m=f,B=((m-d>>2)+1|0)/-2|0,k=f+(B<<2)|0,d=Q-m|0,m=d>>2,m&&(ww(k|0,f|0,d|0)|0,f=n[O>>2]|0),Je=k+(m<<2)|0,n[M>>2]=Je,n[O>>2]=f+(B<<2),f=Je}while(!1);n[f>>2]=n[c>>2],n[M>>2]=(n[M>>2]|0)+4,l=C0(s,Qe,l)|0,UA(Qe)}while(!1);return C=$e,l|0}function Le(s){s=s|0;var l=0;do{if(l=s+984|0,o[l>>0]|0)break;o[l>>0]=1,h[s+504>>2]=y(ce),s=n[s+944>>2]|0}while(s|0)}function ft(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),gt(c))}function pt(s){return s=s|0,n[s+944>>2]|0}function Nt(s){s=s|0,Un(s,(n[s+964>>2]|0)!=0,2832),Le(s)}function rr(s){return s=s|0,(o[s+984>>0]|0)!=0|0}function $r(s,l){s=s|0,l=l|0,TUe(s,l,400)|0&&(Dr(s|0,l|0,400)|0,Le(s))}function ji(s){s=s|0;var l=Xe;return l=y(h[s+44>>2]),s=Ht(l)|0,y(s?y(0):l)}function rs(s){s=s|0;var l=Xe;return l=y(h[s+48>>2]),Ht(l)|0&&(l=o[(n[s+976>>2]|0)+2>>0]|0?y(1):y(0)),y(l)}function Si(s,l){s=s|0,l=l|0,n[s+980>>2]=l}function qo(s){return s=s|0,n[s+980>>2]|0}function xA(s,l){s=s|0,l=l|0;var c=0;c=s+4|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function kA(s){return s=s|0,n[s+4>>2]|0}function lp(s,l){s=s|0,l=l|0;var c=0;c=s+8|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function e0(s){return s=s|0,n[s+8>>2]|0}function mu(s,l){s=s|0,l=l|0;var c=0;c=s+12|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function t0(s){return s=s|0,n[s+12>>2]|0}function yu(s,l){s=s|0,l=l|0;var c=0;c=s+16|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function uo(s){return s=s|0,n[s+16>>2]|0}function QA(s,l){s=s|0,l=l|0;var c=0;c=s+20|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function yc(s){return s=s|0,n[s+20>>2]|0}function Aa(s,l){s=s|0,l=l|0;var c=0;c=s+24|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function r0(s){return s=s|0,n[s+24>>2]|0}function Ec(s,l){s=s|0,l=l|0;var c=0;c=s+28|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function hd(s){return s=s|0,n[s+28>>2]|0}function n0(s,l){s=s|0,l=l|0;var c=0;c=s+32|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function $n(s){return s=s|0,n[s+32>>2]|0}function cp(s,l){s=s|0,l=l|0;var c=0;c=s+36|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Le(s))}function i0(s){return s=s|0,n[s+36>>2]|0}function FA(s,l){s=s|0,l=y(l);var c=0;c=s+40|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function js(s,l){s=s|0,l=y(l);var c=0;c=s+44|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function Eu(s,l){s=s|0,l=y(l);var c=0;c=s+48|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function ja(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+52|0,d=s+56|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function Gi(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+52|0,c=s+56|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Ht(l)|0,n[c>>2]=f?3:2,Le(s))}function fa(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+52|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Cu(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=(m^1)&1,d=s+132+(l<<3)|0,l=s+132+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function ws(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=m?0:2,d=s+132+(l<<3)|0,l=s+132+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Cc(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+132+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function wc(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=(m^1)&1,d=s+60+(l<<3)|0,l=s+60+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Y(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=m?0:2,d=s+60+(l<<3)|0,l=s+60+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Dt(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+60+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function wl(s,l){s=s|0,l=l|0;var c=0;c=s+60+(l<<3)+4|0,(n[c>>2]|0)!=3&&(h[s+60+(l<<3)>>2]=y(ce),n[c>>2]=3,Le(s))}function bi(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=(m^1)&1,d=s+204+(l<<3)|0,l=s+204+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function Ic(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=m?0:2,d=s+204+(l<<3)|0,l=s+204+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function ct(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+204+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function wu(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ht(c)|0,f=(m^1)&1,d=s+276+(l<<3)|0,l=s+276+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Le(s))}function s0(s,l){return s=s|0,l=l|0,y(h[s+276+(l<<3)>>2])}function tw(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+348|0,d=s+352|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function RA(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+348|0,c=s+352|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Ht(l)|0,n[c>>2]=f?3:2,Le(s))}function up(s){s=s|0;var l=0;l=s+352|0,(n[l>>2]|0)!=3&&(h[s+348>>2]=y(ce),n[l>>2]=3,Le(s))}function Br(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+348|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Is(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+356|0,d=s+360|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function o0(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+356|0,c=s+360|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Ht(l)|0,n[c>>2]=f?3:2,Le(s))}function a0(s){s=s|0;var l=0;l=s+360|0,(n[l>>2]|0)!=3&&(h[s+356>>2]=y(ce),n[l>>2]=3,Le(s))}function l0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+356|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Ap(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+364|0,d=s+368|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function Bc(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=m?0:2,f=s+364|0,d=s+368|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function Ct(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+364|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function gd(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+372|0,d=s+376|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function c0(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=m?0:2,f=s+372|0,d=s+376|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function u0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+372|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Iu(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+380|0,d=s+384|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function dd(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=m?0:2,f=s+380|0,d=s+384|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function A0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+380|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Bu(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=(m^1)&1,f=s+388|0,d=s+392|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function rw(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ht(l)|0,c=m?0:2,f=s+388|0,d=s+392|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Le(s))}function md(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+388|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function pa(s,l){s=s|0,l=y(l);var c=0;c=s+396|0,y(h[c>>2])!=l&&(h[c>>2]=l,Le(s))}function vc(s){return s=s|0,y(h[s+396>>2])}function Il(s){return s=s|0,y(h[s+400>>2])}function vu(s){return s=s|0,y(h[s+404>>2])}function f0(s){return s=s|0,y(h[s+408>>2])}function TA(s){return s=s|0,y(h[s+412>>2])}function fp(s){return s=s|0,y(h[s+416>>2])}function Ga(s){return s=s|0,y(h[s+420>>2])}function p0(s,l){switch(s=s|0,l=l|0,Un(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+424+(l<<2)>>2])}function pp(s,l){switch(s=s|0,l=l|0,Un(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+448+(l<<2)>>2])}function jo(s,l){switch(s=s|0,l=l|0,Un(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+472+(l<<2)>>2])}function Bs(s,l){s=s|0,l=l|0;var c=0,f=Xe;return c=n[s+4>>2]|0,(c|0)==(n[l+4>>2]|0)?c?(f=y(h[s>>2]),s=y(ne(y(f-y(h[l>>2]))))<y(999999974e-13)):s=1:s=0,s|0}function wi(s,l){s=y(s),l=y(l);var c=0;return Ht(s)|0?c=Ht(l)|0:c=y(ne(y(s-l)))<y(999999974e-13),c|0}function yd(s,l){s=s|0,l=l|0,Ed(s,l)}function Ed(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c+4|0,n[f>>2]=0,n[f+4>>2]=0,n[f+8>>2]=0,Ha(f|0,s|0,l|0,0),Ao(s,3,(o[f+11>>0]|0)<0?n[f>>2]|0:f,c),n3e(f),C=c}function Go(s,l,c,f){s=y(s),l=y(l),c=c|0,f=f|0;var d=Xe;s=y(s*l),d=y(mR(s,y(1)));do if(wi(d,y(0))|0)s=y(s-d);else{if(s=y(s-d),wi(d,y(1))|0){s=y(s+y(1));break}if(c){s=y(s+y(1));break}f||(d>y(.5)?d=y(1):(f=wi(d,y(.5))|0,d=y(f?1:0)),s=y(s+d))}while(!1);return y(s/l)}function NA(s,l,c,f,d,m,B,k,Q,O,M,j,se){s=s|0,l=y(l),c=c|0,f=y(f),d=d|0,m=y(m),B=B|0,k=y(k),Q=y(Q),O=y(O),M=y(M),j=y(j),se=se|0;var je=0,Oe=Xe,Qe=Xe,$e=Xe,Je=Xe,lt=Xe,_e=Xe;return Q<y(0)|O<y(0)?se=0:(se|0&&(Oe=y(h[se+4>>2]),Oe!=y(0))?($e=y(Go(l,Oe,0,0)),Je=y(Go(f,Oe,0,0)),Qe=y(Go(m,Oe,0,0)),Oe=y(Go(k,Oe,0,0))):(Qe=m,$e=l,Oe=k,Je=f),(d|0)==(s|0)?je=wi(Qe,$e)|0:je=0,(B|0)==(c|0)?se=wi(Oe,Je)|0:se=0,!je&&(lt=y(l-M),!(hp(s,lt,Q)|0))&&!(gp(s,lt,d,Q)|0)?je=h0(s,lt,d,m,Q)|0:je=1,!se&&(_e=y(f-j),!(hp(c,_e,O)|0))&&!(gp(c,_e,B,O)|0)?se=h0(c,_e,B,k,O)|0:se=1,se=je&se),se|0}function hp(s,l,c){return s=s|0,l=y(l),c=y(c),(s|0)==1?s=wi(l,c)|0:s=0,s|0}function gp(s,l,c,f){return s=s|0,l=y(l),c=c|0,f=y(f),(s|0)==2&(c|0)==0?l>=f?s=1:s=wi(l,f)|0:s=0,s|0}function h0(s,l,c,f,d){return s=s|0,l=y(l),c=c|0,f=y(f),d=y(d),(s|0)==2&(c|0)==2&f>l?d<=l?s=1:s=wi(l,d)|0:s=0,s|0}function ha(s,l,c,f,d,m,B,k,Q,O,M){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=m|0,B=y(B),k=y(k),Q=Q|0,O=O|0,M=M|0;var j=0,se=0,je=0,Oe=0,Qe=Xe,$e=Xe,Je=0,lt=0,_e=0,qe=0,Lt=0,Or=0,cr=0,Xt=0,Pr=0,Tr=0,ar=0,xn=Xe,go=Xe,mo=Xe,yo=0,Ca=0;ar=C,C=C+160|0,Xt=ar+152|0,cr=ar+120|0,Or=ar+104|0,_e=ar+72|0,Oe=ar+56|0,Lt=ar+8|0,lt=ar,qe=(n[2279]|0)+1|0,n[2279]=qe,Pr=s+984|0,o[Pr>>0]|0&&(n[s+512>>2]|0)!=(n[2278]|0)?Je=4:(n[s+516>>2]|0)==(f|0)?Tr=0:Je=4,(Je|0)==4&&(n[s+520>>2]=0,n[s+924>>2]=-1,n[s+928>>2]=-1,h[s+932>>2]=y(-1),h[s+936>>2]=y(-1),Tr=1);e:do if(n[s+964>>2]|0)if(Qe=y(cn(s,2,B)),$e=y(cn(s,0,B)),j=s+916|0,mo=y(h[j>>2]),go=y(h[s+920>>2]),xn=y(h[s+932>>2]),NA(d,l,m,c,n[s+924>>2]|0,mo,n[s+928>>2]|0,go,xn,y(h[s+936>>2]),Qe,$e,M)|0)Je=22;else if(je=n[s+520>>2]|0,!je)Je=21;else for(se=0;;){if(j=s+524+(se*24|0)|0,xn=y(h[j>>2]),go=y(h[s+524+(se*24|0)+4>>2]),mo=y(h[s+524+(se*24|0)+16>>2]),NA(d,l,m,c,n[s+524+(se*24|0)+8>>2]|0,xn,n[s+524+(se*24|0)+12>>2]|0,go,mo,y(h[s+524+(se*24|0)+20>>2]),Qe,$e,M)|0){Je=22;break e}if(se=se+1|0,se>>>0>=je>>>0){Je=21;break}}else{if(Q){if(j=s+916|0,!(wi(y(h[j>>2]),l)|0)){Je=21;break}if(!(wi(y(h[s+920>>2]),c)|0)){Je=21;break}if((n[s+924>>2]|0)!=(d|0)){Je=21;break}j=(n[s+928>>2]|0)==(m|0)?j:0,Je=22;break}if(je=n[s+520>>2]|0,!je)Je=21;else for(se=0;;){if(j=s+524+(se*24|0)|0,wi(y(h[j>>2]),l)|0&&wi(y(h[s+524+(se*24|0)+4>>2]),c)|0&&(n[s+524+(se*24|0)+8>>2]|0)==(d|0)&&(n[s+524+(se*24|0)+12>>2]|0)==(m|0)){Je=22;break e}if(se=se+1|0,se>>>0>=je>>>0){Je=21;break}}}while(!1);do if((Je|0)==21)o[11697]|0?(j=0,Je=28):(j=0,Je=31);else if((Je|0)==22){if(se=(o[11697]|0)!=0,!((j|0)!=0&(Tr^1)))if(se){Je=28;break}else{Je=31;break}Oe=j+16|0,n[s+908>>2]=n[Oe>>2],je=j+20|0,n[s+912>>2]=n[je>>2],(o[11698]|0)==0|se^1||(n[lt>>2]=LA(qe)|0,n[lt+4>>2]=qe,Ao(s,4,2972,lt),se=n[s+972>>2]|0,se|0&&ef[se&127](s),d=Ya(d,Q)|0,m=Ya(m,Q)|0,Ca=+y(h[Oe>>2]),yo=+y(h[je>>2]),n[Lt>>2]=d,n[Lt+4>>2]=m,E[Lt+8>>3]=+l,E[Lt+16>>3]=+c,E[Lt+24>>3]=Ca,E[Lt+32>>3]=yo,n[Lt+40>>2]=O,Ao(s,4,2989,Lt))}while(!1);return(Je|0)==28&&(se=LA(qe)|0,n[Oe>>2]=se,n[Oe+4>>2]=qe,n[Oe+8>>2]=Tr?3047:11699,Ao(s,4,3038,Oe),se=n[s+972>>2]|0,se|0&&ef[se&127](s),Lt=Ya(d,Q)|0,Je=Ya(m,Q)|0,n[_e>>2]=Lt,n[_e+4>>2]=Je,E[_e+8>>3]=+l,E[_e+16>>3]=+c,n[_e+24>>2]=O,Ao(s,4,3049,_e),Je=31),(Je|0)==31&&(si(s,l,c,f,d,m,B,k,Q,M),o[11697]|0&&(se=n[2279]|0,Lt=LA(se)|0,n[Or>>2]=Lt,n[Or+4>>2]=se,n[Or+8>>2]=Tr?3047:11699,Ao(s,4,3083,Or),se=n[s+972>>2]|0,se|0&&ef[se&127](s),Lt=Ya(d,Q)|0,Or=Ya(m,Q)|0,yo=+y(h[s+908>>2]),Ca=+y(h[s+912>>2]),n[cr>>2]=Lt,n[cr+4>>2]=Or,E[cr+8>>3]=yo,E[cr+16>>3]=Ca,n[cr+24>>2]=O,Ao(s,4,3092,cr)),n[s+516>>2]=f,j||(se=s+520|0,j=n[se>>2]|0,(j|0)==16&&(o[11697]|0&&Ao(s,4,3124,Xt),n[se>>2]=0,j=0),Q?j=s+916|0:(n[se>>2]=j+1,j=s+524+(j*24|0)|0),h[j>>2]=l,h[j+4>>2]=c,n[j+8>>2]=d,n[j+12>>2]=m,n[j+16>>2]=n[s+908>>2],n[j+20>>2]=n[s+912>>2],j=0)),Q&&(n[s+416>>2]=n[s+908>>2],n[s+420>>2]=n[s+912>>2],o[s+985>>0]=1,o[Pr>>0]=0),n[2279]=(n[2279]|0)+-1,n[s+512>>2]=n[2278],C=ar,Tr|(j|0)==0|0}function cn(s,l,c){s=s|0,l=l|0,c=y(c);var f=Xe;return f=y(V(s,l,c)),y(f+y(re(s,l,c)))}function Ao(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=C,C=C+16|0,d=m,n[d>>2]=f,s?f=n[s+976>>2]|0:f=0,d0(f,s,l,c,d),C=m}function LA(s){return s=s|0,(s>>>0>60?3201:3201+(60-s)|0)|0}function Ya(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+32|0,c=d+12|0,f=d,n[c>>2]=n[254],n[c+4>>2]=n[255],n[c+8>>2]=n[256],n[f>>2]=n[257],n[f+4>>2]=n[258],n[f+8>>2]=n[259],(s|0)>2?s=11699:s=n[(l?f:c)+(s<<2)>>2]|0,C=d,s|0}function si(s,l,c,f,d,m,B,k,Q,O){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=m|0,B=y(B),k=y(k),Q=Q|0,O=O|0;var M=0,j=0,se=0,je=0,Oe=Xe,Qe=Xe,$e=Xe,Je=Xe,lt=Xe,_e=Xe,qe=Xe,Lt=0,Or=0,cr=0,Xt=Xe,Pr=Xe,Tr=0,ar=Xe,xn=0,go=0,mo=0,yo=0,Ca=0,xp=0,kp=0,bl=0,Qp=0,Tu=0,Nu=0,Fp=0,Rp=0,Tp=0,Xr=0,xl=0,Np=0,kc=0,Lp=Xe,Mp=Xe,Lu=Xe,Mu=Xe,Qc=Xe,Ys=0,Za=0,Wo=0,kl=0,rf=0,nf=Xe,Ou=Xe,sf=Xe,of=Xe,Ws=Xe,Ps=Xe,Ql=0,Rn=Xe,af=Xe,Eo=Xe,Fc=Xe,Co=Xe,Rc=Xe,lf=0,cf=0,Tc=Xe,Ks=Xe,Fl=0,uf=0,Af=0,ff=0,xr=Xe,zn=0,Ss=0,wo=0,Vs=0,Fr=0,ur=0,Rl=0,zt=Xe,pf=0,li=0;Rl=C,C=C+16|0,Ys=Rl+12|0,Za=Rl+8|0,Wo=Rl+4|0,kl=Rl,Un(s,(d|0)==0|(Ht(l)|0)^1,3326),Un(s,(m|0)==0|(Ht(c)|0)^1,3406),Ss=mt(s,f)|0,n[s+496>>2]=Ss,Fr=fr(2,Ss)|0,ur=fr(0,Ss)|0,h[s+440>>2]=y(V(s,Fr,B)),h[s+444>>2]=y(re(s,Fr,B)),h[s+428>>2]=y(V(s,ur,B)),h[s+436>>2]=y(re(s,ur,B)),h[s+464>>2]=y(Cr(s,Fr)),h[s+468>>2]=y(yn(s,Fr)),h[s+452>>2]=y(Cr(s,ur)),h[s+460>>2]=y(yn(s,ur)),h[s+488>>2]=y(oi(s,Fr,B)),h[s+492>>2]=y(Li(s,Fr,B)),h[s+476>>2]=y(oi(s,ur,B)),h[s+484>>2]=y(Li(s,ur,B));do if(n[s+964>>2]|0)y0(s,l,c,d,m,B,k);else{if(wo=s+948|0,Vs=(n[s+952>>2]|0)-(n[wo>>2]|0)>>2,!Vs){Sv(s,l,c,d,m,B,k);break}if(!Q&&bv(s,l,c,d,m,B,k)|0)break;ee(s),xl=s+508|0,o[xl>>0]=0,Fr=fr(n[s+4>>2]|0,Ss)|0,ur=iw(Fr,Ss)|0,zn=he(Fr)|0,Np=n[s+8>>2]|0,uf=s+28|0,kc=(n[uf>>2]|0)!=0,Co=zn?B:k,Tc=zn?k:B,Lp=y(mp(s,Fr,B)),Mp=y(sw(s,Fr,B)),Oe=y(mp(s,ur,B)),Rc=y(En(s,Fr,B)),Ks=y(En(s,ur,B)),cr=zn?d:m,Fl=zn?m:d,xr=zn?Rc:Ks,lt=zn?Ks:Rc,Fc=y(cn(s,2,B)),Je=y(cn(s,0,B)),Qe=y(y(Yr(s+364|0,B))-xr),$e=y(y(Yr(s+380|0,B))-xr),_e=y(y(Yr(s+372|0,k))-lt),qe=y(y(Yr(s+388|0,k))-lt),Lu=zn?Qe:_e,Mu=zn?$e:qe,Fc=y(l-Fc),l=y(Fc-xr),Ht(l)|0?xr=l:xr=y(_n(y(k0(l,$e)),Qe)),af=y(c-Je),l=y(af-lt),Ht(l)|0?Eo=l:Eo=y(_n(y(k0(l,qe)),_e)),Qe=zn?xr:Eo,Rn=zn?Eo:xr;e:do if((cr|0)==1)for(f=0,j=0;;){if(M=ms(s,j)|0,!f)y(is(M))>y(0)&&y(Gs(M))>y(0)?f=M:f=0;else if(wd(M)|0){je=0;break e}if(j=j+1|0,j>>>0>=Vs>>>0){je=f;break}}else je=0;while(!1);Lt=je+500|0,Or=je+504|0,f=0,M=0,l=y(0),se=0;do{if(j=n[(n[wo>>2]|0)+(se<<2)>>2]|0,(n[j+36>>2]|0)==1)Du(j),o[j+985>>0]=1,o[j+984>>0]=0;else{Bl(j),Q&&dp(j,mt(j,Ss)|0,Qe,Rn,xr);do if((n[j+24>>2]|0)!=1)if((j|0)==(je|0)){n[Lt>>2]=n[2278],h[Or>>2]=y(0);break}else{Id(s,j,xr,d,Eo,xr,Eo,m,Ss,O);break}else M|0&&(n[M+960>>2]=j),n[j+960>>2]=0,M=j,f=f|0?f:j;while(!1);Ps=y(h[j+504>>2]),l=y(l+y(Ps+y(cn(j,Fr,xr))))}se=se+1|0}while((se|0)!=(Vs|0));for(mo=l>Qe,Ql=kc&((cr|0)==2&mo)?1:cr,xn=(Fl|0)==1,Ca=xn&(Q^1),xp=(Ql|0)==1,kp=(Ql|0)==2,bl=976+(Fr<<2)|0,Qp=(Fl|2|0)==2,Tp=xn&(kc^1),Tu=1040+(ur<<2)|0,Nu=1040+(Fr<<2)|0,Fp=976+(ur<<2)|0,Rp=(Fl|0)!=1,mo=kc&((cr|0)!=0&mo),go=s+976|0,xn=xn^1,l=Qe,Tr=0,yo=0,Ps=y(0),Qc=y(0);;){e:do if(Tr>>>0<Vs>>>0)for(Or=n[wo>>2]|0,se=0,qe=y(0),_e=y(0),$e=y(0),Qe=y(0),j=0,M=0,je=Tr;;){if(Lt=n[Or+(je<<2)>>2]|0,(n[Lt+36>>2]|0)!=1&&(n[Lt+940>>2]=yo,(n[Lt+24>>2]|0)!=1)){if(Je=y(cn(Lt,Fr,xr)),Xr=n[bl>>2]|0,c=y(Yr(Lt+380+(Xr<<3)|0,Co)),lt=y(h[Lt+504>>2]),c=y(k0(c,lt)),c=y(_n(y(Yr(Lt+364+(Xr<<3)|0,Co)),c)),kc&(se|0)!=0&y(Je+y(_e+c))>l){m=se,Je=qe,cr=je;break e}Je=y(Je+c),c=y(_e+Je),Je=y(qe+Je),wd(Lt)|0&&($e=y($e+y(is(Lt))),Qe=y(Qe-y(lt*y(Gs(Lt))))),M|0&&(n[M+960>>2]=Lt),n[Lt+960>>2]=0,se=se+1|0,M=Lt,j=j|0?j:Lt}else Je=qe,c=_e;if(je=je+1|0,je>>>0<Vs>>>0)qe=Je,_e=c;else{m=se,cr=je;break}}else m=0,Je=y(0),$e=y(0),Qe=y(0),j=0,cr=Tr;while(!1);Xr=$e>y(0)&$e<y(1),Xt=Xr?y(1):$e,Xr=Qe>y(0)&Qe<y(1),qe=Xr?y(1):Qe;do if(xp)Xr=51;else if(Je<Lu&((Ht(Lu)|0)^1))l=Lu,Xr=51;else if(Je>Mu&((Ht(Mu)|0)^1))l=Mu,Xr=51;else if(o[(n[go>>2]|0)+3>>0]|0)Xr=51;else{if(Xt!=y(0)&&y(is(s))!=y(0)){Xr=53;break}l=Je,Xr=53}while(!1);if((Xr|0)==51&&(Xr=0,Ht(l)|0?Xr=53:(Pr=y(l-Je),ar=l)),(Xr|0)==53&&(Xr=0,Je<y(0)?(Pr=y(-Je),ar=l):(Pr=y(0),ar=l)),!Ca&&(rf=(j|0)==0,!rf)){se=n[bl>>2]|0,je=Pr<y(0),lt=y(Pr/qe),Lt=Pr>y(0),_e=y(Pr/Xt),$e=y(0),Je=y(0),l=y(0),M=j;do c=y(Yr(M+380+(se<<3)|0,Co)),Qe=y(Yr(M+364+(se<<3)|0,Co)),Qe=y(k0(c,y(_n(Qe,y(h[M+504>>2]))))),je?(c=y(Qe*y(Gs(M))),c!=y(-0)&&(zt=y(Qe-y(lt*c)),nf=y(Ii(M,Fr,zt,ar,xr)),zt!=nf)&&($e=y($e-y(nf-Qe)),l=y(l+c))):Lt&&(Ou=y(is(M)),Ou!=y(0))&&(zt=y(Qe+y(_e*Ou)),sf=y(Ii(M,Fr,zt,ar,xr)),zt!=sf)&&($e=y($e-y(sf-Qe)),Je=y(Je-Ou)),M=n[M+960>>2]|0;while(M|0);if(l=y(qe+l),Qe=y(Pr+$e),rf)l=y(0);else{lt=y(Xt+Je),je=n[bl>>2]|0,Lt=Qe<y(0),Or=l==y(0),_e=y(Qe/l),se=Qe>y(0),lt=y(Qe/lt),l=y(0);do{zt=y(Yr(j+380+(je<<3)|0,Co)),$e=y(Yr(j+364+(je<<3)|0,Co)),$e=y(k0(zt,y(_n($e,y(h[j+504>>2]))))),Lt?(zt=y($e*y(Gs(j))),Qe=y(-zt),zt!=y(-0)?(zt=y(_e*Qe),Qe=y(Ii(j,Fr,y($e+(Or?Qe:zt)),ar,xr))):Qe=$e):se&&(of=y(is(j)),of!=y(0))?Qe=y(Ii(j,Fr,y($e+y(lt*of)),ar,xr)):Qe=$e,l=y(l-y(Qe-$e)),Je=y(cn(j,Fr,xr)),c=y(cn(j,ur,xr)),Qe=y(Qe+Je),h[Za>>2]=Qe,n[kl>>2]=1,$e=y(h[j+396>>2]);e:do if(Ht($e)|0){M=Ht(Rn)|0;do if(!M){if(mo|(ns(j,ur,Rn)|0|xn)||(da(s,j)|0)!=4||(n[(vl(j,ur)|0)+4>>2]|0)==3||(n[(Sc(j,ur)|0)+4>>2]|0)==3)break;h[Ys>>2]=Rn,n[Wo>>2]=1;break e}while(!1);if(ns(j,ur,Rn)|0){M=n[j+992+(n[Fp>>2]<<2)>>2]|0,zt=y(c+y(Yr(M,Rn))),h[Ys>>2]=zt,M=Rp&(n[M+4>>2]|0)==2,n[Wo>>2]=((Ht(zt)|0|M)^1)&1;break}else{h[Ys>>2]=Rn,n[Wo>>2]=M?0:2;break}}else zt=y(Qe-Je),Xt=y(zt/$e),zt=y($e*zt),n[Wo>>2]=1,h[Ys>>2]=y(c+(zn?Xt:zt));while(!1);yr(j,Fr,ar,xr,kl,Za),yr(j,ur,Rn,xr,Wo,Ys);do if(!(ns(j,ur,Rn)|0)&&(da(s,j)|0)==4){if((n[(vl(j,ur)|0)+4>>2]|0)==3){M=0;break}M=(n[(Sc(j,ur)|0)+4>>2]|0)!=3}else M=0;while(!1);zt=y(h[Za>>2]),Xt=y(h[Ys>>2]),pf=n[kl>>2]|0,li=n[Wo>>2]|0,ha(j,zn?zt:Xt,zn?Xt:zt,Ss,zn?pf:li,zn?li:pf,xr,Eo,Q&(M^1),3488,O)|0,o[xl>>0]=o[xl>>0]|o[j+508>>0],j=n[j+960>>2]|0}while(j|0)}}else l=y(0);if(l=y(Pr+l),li=l<y(0)&1,o[xl>>0]=li|u[xl>>0],kp&l>y(0)?(M=n[bl>>2]|0,n[s+364+(M<<3)+4>>2]|0&&(Ws=y(Yr(s+364+(M<<3)|0,Co)),Ws>=y(0))?Qe=y(_n(y(0),y(Ws-y(ar-l)))):Qe=y(0)):Qe=l,Lt=Tr>>>0<cr>>>0,Lt){je=n[wo>>2]|0,se=Tr,M=0;do j=n[je+(se<<2)>>2]|0,n[j+24>>2]|0||(M=((n[(vl(j,Fr)|0)+4>>2]|0)==3&1)+M|0,M=M+((n[(Sc(j,Fr)|0)+4>>2]|0)==3&1)|0),se=se+1|0;while((se|0)!=(cr|0));M?(Je=y(0),c=y(0)):Xr=101}else Xr=101;e:do if((Xr|0)==101)switch(Xr=0,Np|0){case 1:{M=0,Je=y(Qe*y(.5)),c=y(0);break e}case 2:{M=0,Je=Qe,c=y(0);break e}case 3:{if(m>>>0<=1){M=0,Je=y(0),c=y(0);break e}c=y((m+-1|0)>>>0),M=0,Je=y(0),c=y(y(_n(Qe,y(0)))/c);break e}case 5:{c=y(Qe/y((m+1|0)>>>0)),M=0,Je=c;break e}case 4:{c=y(Qe/y(m>>>0)),M=0,Je=y(c*y(.5));break e}default:{M=0,Je=y(0),c=y(0);break e}}while(!1);if(l=y(Lp+Je),Lt){$e=y(Qe/y(M|0)),se=n[wo>>2]|0,j=Tr,Qe=y(0);do{M=n[se+(j<<2)>>2]|0;e:do if((n[M+36>>2]|0)!=1){switch(n[M+24>>2]|0){case 1:{if(gi(M,Fr)|0){if(!Q)break e;zt=y(Mr(M,Fr,ar)),zt=y(zt+y(Cr(s,Fr))),zt=y(zt+y(V(M,Fr,xr))),h[M+400+(n[Nu>>2]<<2)>>2]=zt;break e}break}case 0:if(li=(n[(vl(M,Fr)|0)+4>>2]|0)==3,zt=y($e+l),l=li?zt:l,Q&&(li=M+400+(n[Nu>>2]<<2)|0,h[li>>2]=y(l+y(h[li>>2]))),li=(n[(Sc(M,Fr)|0)+4>>2]|0)==3,zt=y($e+l),l=li?zt:l,Ca){zt=y(c+y(cn(M,Fr,xr))),Qe=Rn,l=y(l+y(zt+y(h[M+504>>2])));break e}else{l=y(l+y(c+y(ss(M,Fr,xr)))),Qe=y(_n(Qe,y(ss(M,ur,xr))));break e}default:}Q&&(zt=y(Je+y(Cr(s,Fr))),li=M+400+(n[Nu>>2]<<2)|0,h[li>>2]=y(zt+y(h[li>>2])))}while(!1);j=j+1|0}while((j|0)!=(cr|0))}else Qe=y(0);if(c=y(Mp+l),Qp?Je=y(y(Ii(s,ur,y(Ks+Qe),Tc,B))-Ks):Je=Rn,$e=y(y(Ii(s,ur,y(Ks+(Tp?Rn:Qe)),Tc,B))-Ks),Lt&Q){j=Tr;do{se=n[(n[wo>>2]|0)+(j<<2)>>2]|0;do if((n[se+36>>2]|0)!=1){if((n[se+24>>2]|0)==1){if(gi(se,ur)|0){if(zt=y(Mr(se,ur,Rn)),zt=y(zt+y(Cr(s,ur))),zt=y(zt+y(V(se,ur,xr))),M=n[Tu>>2]|0,h[se+400+(M<<2)>>2]=zt,!(Ht(zt)|0))break}else M=n[Tu>>2]|0;zt=y(Cr(s,ur)),h[se+400+(M<<2)>>2]=y(zt+y(V(se,ur,xr)));break}M=da(s,se)|0;do if((M|0)==4){if((n[(vl(se,ur)|0)+4>>2]|0)==3){Xr=139;break}if((n[(Sc(se,ur)|0)+4>>2]|0)==3){Xr=139;break}if(ns(se,ur,Rn)|0){l=Oe;break}pf=n[se+908+(n[bl>>2]<<2)>>2]|0,n[Ys>>2]=pf,l=y(h[se+396>>2]),li=Ht(l)|0,Qe=(n[v>>2]=pf,y(h[v>>2])),li?l=$e:(Pr=y(cn(se,ur,xr)),zt=y(Qe/l),l=y(l*Qe),l=y(Pr+(zn?zt:l))),h[Za>>2]=l,h[Ys>>2]=y(y(cn(se,Fr,xr))+Qe),n[Wo>>2]=1,n[kl>>2]=1,yr(se,Fr,ar,xr,Wo,Ys),yr(se,ur,Rn,xr,kl,Za),l=y(h[Ys>>2]),Pr=y(h[Za>>2]),zt=zn?l:Pr,l=zn?Pr:l,li=((Ht(zt)|0)^1)&1,ha(se,zt,l,Ss,li,((Ht(l)|0)^1)&1,xr,Eo,1,3493,O)|0,l=Oe}else Xr=139;while(!1);e:do if((Xr|0)==139){Xr=0,l=y(Je-y(ss(se,ur,xr)));do if((n[(vl(se,ur)|0)+4>>2]|0)==3){if((n[(Sc(se,ur)|0)+4>>2]|0)!=3)break;l=y(Oe+y(_n(y(0),y(l*y(.5)))));break e}while(!1);if((n[(Sc(se,ur)|0)+4>>2]|0)==3){l=Oe;break}if((n[(vl(se,ur)|0)+4>>2]|0)==3){l=y(Oe+y(_n(y(0),l)));break}switch(M|0){case 1:{l=Oe;break e}case 2:{l=y(Oe+y(l*y(.5)));break e}default:{l=y(Oe+l);break e}}}while(!1);zt=y(Ps+l),li=se+400+(n[Tu>>2]<<2)|0,h[li>>2]=y(zt+y(h[li>>2]))}while(!1);j=j+1|0}while((j|0)!=(cr|0))}if(Ps=y(Ps+$e),Qc=y(_n(Qc,c)),m=yo+1|0,cr>>>0>=Vs>>>0)break;l=ar,Tr=cr,yo=m}do if(Q){if(M=m>>>0>1,!M&&!(Yi(s)|0))break;if(!(Ht(Rn)|0)){l=y(Rn-Ps);e:do switch(n[s+12>>2]|0){case 3:{Oe=y(Oe+l),_e=y(0);break}case 2:{Oe=y(Oe+y(l*y(.5))),_e=y(0);break}case 4:{Rn>Ps?_e=y(l/y(m>>>0)):_e=y(0);break}case 7:if(Rn>Ps){Oe=y(Oe+y(l/y(m<<1>>>0))),_e=y(l/y(m>>>0)),_e=M?_e:y(0);break e}else{Oe=y(Oe+y(l*y(.5))),_e=y(0);break e}case 6:{_e=y(l/y(yo>>>0)),_e=Rn>Ps&M?_e:y(0);break}default:_e=y(0)}while(!1);if(m|0)for(Lt=1040+(ur<<2)|0,Or=976+(ur<<2)|0,je=0,j=0;;){e:do if(j>>>0<Vs>>>0)for(Qe=y(0),$e=y(0),l=y(0),se=j;;){M=n[(n[wo>>2]|0)+(se<<2)>>2]|0;do if((n[M+36>>2]|0)!=1&&!(n[M+24>>2]|0)){if((n[M+940>>2]|0)!=(je|0))break e;if(Bd(M,ur)|0&&(zt=y(h[M+908+(n[Or>>2]<<2)>>2]),l=y(_n(l,y(zt+y(cn(M,ur,xr)))))),(da(s,M)|0)!=5)break;Ws=y(Ka(M)),Ws=y(Ws+y(V(M,0,xr))),zt=y(h[M+912>>2]),zt=y(y(zt+y(cn(M,0,xr)))-Ws),Ws=y(_n($e,Ws)),zt=y(_n(Qe,zt)),Qe=zt,$e=Ws,l=y(_n(l,y(Ws+zt)))}while(!1);if(M=se+1|0,M>>>0<Vs>>>0)se=M;else{se=M;break}}else $e=y(0),l=y(0),se=j;while(!1);if(lt=y(_e+l),c=Oe,Oe=y(Oe+lt),j>>>0<se>>>0){Je=y(c+$e),M=j;do{j=n[(n[wo>>2]|0)+(M<<2)>>2]|0;e:do if((n[j+36>>2]|0)!=1&&!(n[j+24>>2]|0))switch(da(s,j)|0){case 1:{zt=y(c+y(V(j,ur,xr))),h[j+400+(n[Lt>>2]<<2)>>2]=zt;break e}case 3:{zt=y(y(Oe-y(re(j,ur,xr)))-y(h[j+908+(n[Or>>2]<<2)>>2])),h[j+400+(n[Lt>>2]<<2)>>2]=zt;break e}case 2:{zt=y(c+y(y(lt-y(h[j+908+(n[Or>>2]<<2)>>2]))*y(.5))),h[j+400+(n[Lt>>2]<<2)>>2]=zt;break e}case 4:{if(zt=y(c+y(V(j,ur,xr))),h[j+400+(n[Lt>>2]<<2)>>2]=zt,ns(j,ur,Rn)|0||(zn?(Qe=y(h[j+908>>2]),l=y(Qe+y(cn(j,Fr,xr))),$e=lt):($e=y(h[j+912>>2]),$e=y($e+y(cn(j,ur,xr))),l=lt,Qe=y(h[j+908>>2])),wi(l,Qe)|0&&wi($e,y(h[j+912>>2]))|0))break e;ha(j,l,$e,Ss,1,1,xr,Eo,1,3501,O)|0;break e}case 5:{h[j+404>>2]=y(y(Je-y(Ka(j)))+y(Mr(j,0,Rn)));break e}default:break e}while(!1);M=M+1|0}while((M|0)!=(se|0))}if(je=je+1|0,(je|0)==(m|0))break;j=se}}}while(!1);if(h[s+908>>2]=y(Ii(s,2,Fc,B,B)),h[s+912>>2]=y(Ii(s,0,af,k,B)),Ql|0&&(lf=n[s+32>>2]|0,cf=(Ql|0)==2,!(cf&(lf|0)!=2))?cf&(lf|0)==2&&(l=y(Rc+ar),l=y(_n(y(k0(l,y(MA(s,Fr,Qc,Co)))),Rc)),Xr=198):(l=y(Ii(s,Fr,Qc,Co,B)),Xr=198),(Xr|0)==198&&(h[s+908+(n[976+(Fr<<2)>>2]<<2)>>2]=l),Fl|0&&(Af=n[s+32>>2]|0,ff=(Fl|0)==2,!(ff&(Af|0)!=2))?ff&(Af|0)==2&&(l=y(Ks+Rn),l=y(_n(y(k0(l,y(MA(s,ur,y(Ks+Ps),Tc)))),Ks)),Xr=204):(l=y(Ii(s,ur,y(Ks+Ps),Tc,B)),Xr=204),(Xr|0)==204&&(h[s+908+(n[976+(ur<<2)>>2]<<2)>>2]=l),Q){if((n[uf>>2]|0)==2){j=976+(ur<<2)|0,se=1040+(ur<<2)|0,M=0;do je=ms(s,M)|0,n[je+24>>2]|0||(pf=n[j>>2]|0,zt=y(h[s+908+(pf<<2)>>2]),li=je+400+(n[se>>2]<<2)|0,zt=y(zt-y(h[li>>2])),h[li>>2]=y(zt-y(h[je+908+(pf<<2)>>2]))),M=M+1|0;while((M|0)!=(Vs|0))}if(f|0){M=zn?Ql:d;do vd(s,f,xr,M,Eo,Ss,O),f=n[f+960>>2]|0;while(f|0)}if(M=(Fr|2|0)==3,j=(ur|2|0)==3,M|j){f=0;do se=n[(n[wo>>2]|0)+(f<<2)>>2]|0,(n[se+36>>2]|0)!=1&&(M&&yp(s,se,Fr),j&&yp(s,se,ur)),f=f+1|0;while((f|0)!=(Vs|0))}}}while(!1);C=Rl}function ga(s,l){s=s|0,l=y(l);var c=0;la(s,l>=y(0),3147),c=l==y(0),h[s+4>>2]=c?y(0):l}function Dc(s,l,c,f){s=s|0,l=y(l),c=y(c),f=f|0;var d=Xe,m=Xe,B=0,k=0,Q=0;n[2278]=(n[2278]|0)+1,Bl(s),ns(s,2,l)|0?(d=y(Yr(n[s+992>>2]|0,l)),Q=1,d=y(d+y(cn(s,2,l)))):(d=y(Yr(s+380|0,l)),d>=y(0)?Q=2:(Q=((Ht(l)|0)^1)&1,d=l)),ns(s,0,c)|0?(m=y(Yr(n[s+996>>2]|0,c)),k=1,m=y(m+y(cn(s,0,l)))):(m=y(Yr(s+388|0,c)),m>=y(0)?k=2:(k=((Ht(c)|0)^1)&1,m=c)),B=s+976|0,ha(s,d,m,f,Q,k,l,c,1,3189,n[B>>2]|0)|0&&(dp(s,n[s+496>>2]|0,l,c,l),Pc(s,y(h[(n[B>>2]|0)+4>>2]),y(0),y(0)),o[11696]|0)&&yd(s,7)}function Bl(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;k=C,C=C+32|0,B=k+24|0,m=k+16|0,f=k+8|0,d=k,c=0;do l=s+380+(c<<3)|0,n[s+380+(c<<3)+4>>2]|0&&(Q=l,O=n[Q+4>>2]|0,M=f,n[M>>2]=n[Q>>2],n[M+4>>2]=O,M=s+364+(c<<3)|0,O=n[M+4>>2]|0,Q=d,n[Q>>2]=n[M>>2],n[Q+4>>2]=O,n[m>>2]=n[f>>2],n[m+4>>2]=n[f+4>>2],n[B>>2]=n[d>>2],n[B+4>>2]=n[d+4>>2],Bs(m,B)|0)||(l=s+348+(c<<3)|0),n[s+992+(c<<2)>>2]=l,c=c+1|0;while((c|0)!=2);C=k}function ns(s,l,c){s=s|0,l=l|0,c=y(c);var f=0;switch(s=n[s+992+(n[976+(l<<2)>>2]<<2)>>2]|0,n[s+4>>2]|0){case 0:case 3:{s=0;break}case 1:{y(h[s>>2])<y(0)?s=0:f=5;break}case 2:{y(h[s>>2])<y(0)?s=0:s=(Ht(c)|0)^1;break}default:f=5}return(f|0)==5&&(s=1),s|0}function Yr(s,l){switch(s=s|0,l=y(l),n[s+4>>2]|0){case 2:{l=y(y(y(h[s>>2])*l)/y(100));break}case 1:{l=y(h[s>>2]);break}default:l=y(ce)}return y(l)}function dp(s,l,c,f,d){s=s|0,l=l|0,c=y(c),f=y(f),d=y(d);var m=0,B=Xe;l=n[s+944>>2]|0?l:1,m=fr(n[s+4>>2]|0,l)|0,l=iw(m,l)|0,c=y(Dd(s,m,c)),f=y(Dd(s,l,f)),B=y(c+y(V(s,m,d))),h[s+400+(n[1040+(m<<2)>>2]<<2)>>2]=B,c=y(c+y(re(s,m,d))),h[s+400+(n[1e3+(m<<2)>>2]<<2)>>2]=c,c=y(f+y(V(s,l,d))),h[s+400+(n[1040+(l<<2)>>2]<<2)>>2]=c,d=y(f+y(re(s,l,d))),h[s+400+(n[1e3+(l<<2)>>2]<<2)>>2]=d}function Pc(s,l,c,f){s=s|0,l=y(l),c=y(c),f=y(f);var d=0,m=0,B=Xe,k=Xe,Q=0,O=0,M=Xe,j=0,se=Xe,je=Xe,Oe=Xe,Qe=Xe;if(l!=y(0)&&(d=s+400|0,Qe=y(h[d>>2]),m=s+404|0,Oe=y(h[m>>2]),j=s+416|0,je=y(h[j>>2]),O=s+420|0,B=y(h[O>>2]),se=y(Qe+c),M=y(Oe+f),f=y(se+je),k=y(M+B),Q=(n[s+988>>2]|0)==1,h[d>>2]=y(Go(Qe,l,0,Q)),h[m>>2]=y(Go(Oe,l,0,Q)),c=y(mR(y(je*l),y(1))),wi(c,y(0))|0?m=0:m=(wi(c,y(1))|0)^1,c=y(mR(y(B*l),y(1))),wi(c,y(0))|0?d=0:d=(wi(c,y(1))|0)^1,Qe=y(Go(f,l,Q&m,Q&(m^1))),h[j>>2]=y(Qe-y(Go(se,l,0,Q))),Qe=y(Go(k,l,Q&d,Q&(d^1))),h[O>>2]=y(Qe-y(Go(M,l,0,Q))),m=(n[s+952>>2]|0)-(n[s+948>>2]|0)>>2,m|0)){d=0;do Pc(ms(s,d)|0,l,se,M),d=d+1|0;while((d|0)!=(m|0))}}function nw(s,l,c,f,d){switch(s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,c|0){case 5:case 0:{s=e7(n[489]|0,f,d)|0;break}default:s=$Ue(f,d)|0}return s|0}function g0(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;d=C,C=C+16|0,m=d,n[m>>2]=f,d0(s,0,l,c,m),C=d}function d0(s,l,c,f,d){if(s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,s=s|0?s:956,w7[n[s+8>>2]&1](s,l,c,f,d)|0,(c|0)==5)Tt();else return}function Wa(s,l,c){s=s|0,l=l|0,c=c|0,o[s+l>>0]=c&1}function Cd(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(m0(s,f),Qt(s,n[l>>2]|0,n[c>>2]|0,f))}function m0(s,l){s=s|0,l=l|0;var c=0;if((N(s)|0)>>>0<l>>>0&&Jr(s),l>>>0>1073741823)Tt();else{c=Kt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function Qt(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(Dr(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function N(s){return s=s|0,1073741823}function V(s,l,c){return s=s|0,l=l|0,c=y(c),he(l)|0&&n[s+96>>2]|0?s=s+92|0:s=Fn(s+60|0,n[1040+(l<<2)>>2]|0,992)|0,y(ze(s,c))}function re(s,l,c){return s=s|0,l=l|0,c=y(c),he(l)|0&&n[s+104>>2]|0?s=s+100|0:s=Fn(s+60|0,n[1e3+(l<<2)>>2]|0,992)|0,y(ze(s,c))}function he(s){return s=s|0,(s|1|0)==3|0}function ze(s,l){return s=s|0,l=y(l),(n[s+4>>2]|0)==3?l=y(0):l=y(Yr(s,l)),y(l)}function mt(s,l){return s=s|0,l=l|0,s=n[s>>2]|0,(s|0?s:(l|0)>1?l:1)|0}function fr(s,l){s=s|0,l=l|0;var c=0;e:do if((l|0)==2){switch(s|0){case 2:{s=3;break e}case 3:break;default:{c=4;break e}}s=2}else c=4;while(!1);return s|0}function Cr(s,l){s=s|0,l=l|0;var c=Xe;return he(l)|0&&n[s+312>>2]|0&&(c=y(h[s+308>>2]),c>=y(0))||(c=y(_n(y(h[(Fn(s+276|0,n[1040+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(c)}function yn(s,l){s=s|0,l=l|0;var c=Xe;return he(l)|0&&n[s+320>>2]|0&&(c=y(h[s+316>>2]),c>=y(0))||(c=y(_n(y(h[(Fn(s+276|0,n[1e3+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(c)}function oi(s,l,c){s=s|0,l=l|0,c=y(c);var f=Xe;return he(l)|0&&n[s+240>>2]|0&&(f=y(Yr(s+236|0,c)),f>=y(0))||(f=y(_n(y(Yr(Fn(s+204|0,n[1040+(l<<2)>>2]|0,992)|0,c)),y(0)))),y(f)}function Li(s,l,c){s=s|0,l=l|0,c=y(c);var f=Xe;return he(l)|0&&n[s+248>>2]|0&&(f=y(Yr(s+244|0,c)),f>=y(0))||(f=y(_n(y(Yr(Fn(s+204|0,n[1e3+(l<<2)>>2]|0,992)|0,c)),y(0)))),y(f)}function y0(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=Xe,Q=Xe,O=Xe,M=Xe,j=Xe,se=Xe,je=0,Oe=0,Qe=0;Qe=C,C=C+16|0,je=Qe,Oe=s+964|0,Un(s,(n[Oe>>2]|0)!=0,3519),k=y(En(s,2,l)),Q=y(En(s,0,l)),O=y(cn(s,2,l)),M=y(cn(s,0,l)),Ht(l)|0?j=l:j=y(_n(y(0),y(y(l-O)-k))),Ht(c)|0?se=c:se=y(_n(y(0),y(y(c-M)-Q))),(f|0)==1&(d|0)==1?(h[s+908>>2]=y(Ii(s,2,y(l-O),m,m)),l=y(Ii(s,0,y(c-M),B,m))):(I7[n[Oe>>2]&1](je,s,j,f,se,d),j=y(k+y(h[je>>2])),se=y(l-O),h[s+908>>2]=y(Ii(s,2,(f|2|0)==2?j:se,m,m)),se=y(Q+y(h[je+4>>2])),l=y(c-M),l=y(Ii(s,0,(d|2|0)==2?se:l,B,m))),h[s+912>>2]=l,C=Qe}function Sv(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=Xe,Q=Xe,O=Xe,M=Xe;O=y(En(s,2,m)),k=y(En(s,0,m)),M=y(cn(s,2,m)),Q=y(cn(s,0,m)),l=y(l-M),h[s+908>>2]=y(Ii(s,2,(f|2|0)==2?O:l,m,m)),c=y(c-Q),h[s+912>>2]=y(Ii(s,0,(d|2|0)==2?k:c,B,m))}function bv(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=0,Q=Xe,O=Xe;return k=(f|0)==2,!(l<=y(0)&k)&&!(c<=y(0)&(d|0)==2)&&!((f|0)==1&(d|0)==1)?s=0:(Q=y(cn(s,0,m)),O=y(cn(s,2,m)),k=l<y(0)&k|(Ht(l)|0),l=y(l-O),h[s+908>>2]=y(Ii(s,2,k?y(0):l,m,m)),l=y(c-Q),k=c<y(0)&(d|0)==2|(Ht(c)|0),h[s+912>>2]=y(Ii(s,0,k?y(0):l,B,m)),s=1),s|0}function iw(s,l){return s=s|0,l=l|0,OA(s)|0?s=fr(2,l)|0:s=0,s|0}function mp(s,l,c){return s=s|0,l=l|0,c=y(c),c=y(oi(s,l,c)),y(c+y(Cr(s,l)))}function sw(s,l,c){return s=s|0,l=l|0,c=y(c),c=y(Li(s,l,c)),y(c+y(yn(s,l)))}function En(s,l,c){s=s|0,l=l|0,c=y(c);var f=Xe;return f=y(mp(s,l,c)),y(f+y(sw(s,l,c)))}function wd(s){return s=s|0,n[s+24>>2]|0?s=0:y(is(s))!=y(0)?s=1:s=y(Gs(s))!=y(0),s|0}function is(s){s=s|0;var l=Xe;if(n[s+944>>2]|0){if(l=y(h[s+44>>2]),Ht(l)|0)return l=y(h[s+40>>2]),s=l>y(0)&((Ht(l)|0)^1),y(s?l:y(0))}else l=y(0);return y(l)}function Gs(s){s=s|0;var l=Xe,c=0,f=Xe;do if(n[s+944>>2]|0){if(l=y(h[s+48>>2]),Ht(l)|0){if(c=o[(n[s+976>>2]|0)+2>>0]|0,!(c<<24>>24)&&(f=y(h[s+40>>2]),f<y(0)&((Ht(f)|0)^1))){l=y(-f);break}l=c<<24>>24?y(1):y(0)}}else l=y(0);while(!1);return y(l)}function Du(s){s=s|0;var l=0,c=0;if(Od(s+400|0,0,540)|0,o[s+985>>0]=1,ee(s),c=Ci(s)|0,c|0){l=s+948|0,s=0;do Du(n[(n[l>>2]|0)+(s<<2)>>2]|0),s=s+1|0;while((s|0)!=(c|0))}}function Id(s,l,c,f,d,m,B,k,Q,O){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=y(m),B=y(B),k=k|0,Q=Q|0,O=O|0;var M=0,j=Xe,se=0,je=0,Oe=Xe,Qe=Xe,$e=0,Je=Xe,lt=0,_e=Xe,qe=0,Lt=0,Or=0,cr=0,Xt=0,Pr=0,Tr=0,ar=0,xn=0,go=0;xn=C,C=C+16|0,Or=xn+12|0,cr=xn+8|0,Xt=xn+4|0,Pr=xn,ar=fr(n[s+4>>2]|0,Q)|0,qe=he(ar)|0,j=y(Yr(ow(l)|0,qe?m:B)),Lt=ns(l,2,m)|0,Tr=ns(l,0,B)|0;do if(!(Ht(j)|0)&&!(Ht(qe?c:d)|0)){if(M=l+504|0,!(Ht(y(h[M>>2]))|0)&&(!(aw(n[l+976>>2]|0,0)|0)||(n[l+500>>2]|0)==(n[2278]|0)))break;h[M>>2]=y(_n(j,y(En(l,ar,m))))}else se=7;while(!1);do if((se|0)==7){if(lt=qe^1,!(lt|Lt^1)){B=y(Yr(n[l+992>>2]|0,m)),h[l+504>>2]=y(_n(B,y(En(l,2,m))));break}if(!(qe|Tr^1)){B=y(Yr(n[l+996>>2]|0,B)),h[l+504>>2]=y(_n(B,y(En(l,0,m))));break}h[Or>>2]=y(ce),h[cr>>2]=y(ce),n[Xt>>2]=0,n[Pr>>2]=0,Je=y(cn(l,2,m)),_e=y(cn(l,0,m)),Lt?(Oe=y(Je+y(Yr(n[l+992>>2]|0,m))),h[Or>>2]=Oe,n[Xt>>2]=1,je=1):(je=0,Oe=y(ce)),Tr?(j=y(_e+y(Yr(n[l+996>>2]|0,B))),h[cr>>2]=j,n[Pr>>2]=1,M=1):(M=0,j=y(ce)),se=n[s+32>>2]|0,qe&(se|0)==2?se=2:Ht(Oe)|0&&!(Ht(c)|0)&&(h[Or>>2]=c,n[Xt>>2]=2,je=2,Oe=c),!((se|0)==2<)&&Ht(j)|0&&!(Ht(d)|0)&&(h[cr>>2]=d,n[Pr>>2]=2,M=2,j=d),Qe=y(h[l+396>>2]),$e=Ht(Qe)|0;do if($e)se=je;else{if((je|0)==1<){h[cr>>2]=y(y(Oe-Je)/Qe),n[Pr>>2]=1,M=1,se=1;break}qe&(M|0)==1?(h[Or>>2]=y(Qe*y(j-_e)),n[Xt>>2]=1,M=1,se=1):se=je}while(!1);go=Ht(c)|0,je=(da(s,l)|0)!=4,!(qe|Lt|((f|0)!=1|go)|(je|(se|0)==1))&&(h[Or>>2]=c,n[Xt>>2]=1,!$e)&&(h[cr>>2]=y(y(c-Je)/Qe),n[Pr>>2]=1,M=1),!(Tr|lt|((k|0)!=1|(Ht(d)|0))|(je|(M|0)==1))&&(h[cr>>2]=d,n[Pr>>2]=1,!$e)&&(h[Or>>2]=y(Qe*y(d-_e)),n[Xt>>2]=1),yr(l,2,m,m,Xt,Or),yr(l,0,B,m,Pr,cr),c=y(h[Or>>2]),d=y(h[cr>>2]),ha(l,c,d,Q,n[Xt>>2]|0,n[Pr>>2]|0,m,B,0,3565,O)|0,B=y(h[l+908+(n[976+(ar<<2)>>2]<<2)>>2]),h[l+504>>2]=y(_n(B,y(En(l,ar,m))))}while(!1);n[l+500>>2]=n[2278],C=xn}function Ii(s,l,c,f,d){return s=s|0,l=l|0,c=y(c),f=y(f),d=y(d),f=y(MA(s,l,c,f)),y(_n(f,y(En(s,l,d))))}function da(s,l){return s=s|0,l=l|0,l=l+20|0,l=n[(n[l>>2]|0?l:s+16|0)>>2]|0,(l|0)==5&&OA(n[s+4>>2]|0)|0&&(l=1),l|0}function vl(s,l){return s=s|0,l=l|0,he(l)|0&&n[s+96>>2]|0?l=4:l=n[1040+(l<<2)>>2]|0,s+60+(l<<3)|0}function Sc(s,l){return s=s|0,l=l|0,he(l)|0&&n[s+104>>2]|0?l=5:l=n[1e3+(l<<2)>>2]|0,s+60+(l<<3)|0}function yr(s,l,c,f,d,m){switch(s=s|0,l=l|0,c=y(c),f=y(f),d=d|0,m=m|0,c=y(Yr(s+380+(n[976+(l<<2)>>2]<<3)|0,c)),c=y(c+y(cn(s,l,f))),n[d>>2]|0){case 2:case 1:{d=Ht(c)|0,f=y(h[m>>2]),h[m>>2]=d|f<c?f:c;break}case 0:{Ht(c)|0||(n[d>>2]=2,h[m>>2]=c);break}default:}}function gi(s,l){return s=s|0,l=l|0,s=s+132|0,he(l)|0&&n[(Fn(s,4,948)|0)+4>>2]|0?s=1:s=(n[(Fn(s,n[1040+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,s|0}function Mr(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0;return s=s+132|0,he(l)|0&&(f=Fn(s,4,948)|0,(n[f+4>>2]|0)!=0)?d=4:(f=Fn(s,n[1040+(l<<2)>>2]|0,948)|0,n[f+4>>2]|0?d=4:c=y(0)),(d|0)==4&&(c=y(Yr(f,c))),y(c)}function ss(s,l,c){s=s|0,l=l|0,c=y(c);var f=Xe;return f=y(h[s+908+(n[976+(l<<2)>>2]<<2)>>2]),f=y(f+y(V(s,l,c))),y(f+y(re(s,l,c)))}function Yi(s){s=s|0;var l=0,c=0,f=0;e:do if(OA(n[s+4>>2]|0)|0)l=0;else if((n[s+16>>2]|0)!=5)if(c=Ci(s)|0,!c)l=0;else for(l=0;;){if(f=ms(s,l)|0,!(n[f+24>>2]|0)&&(n[f+20>>2]|0)==5){l=1;break e}if(l=l+1|0,l>>>0>=c>>>0){l=0;break}}else l=1;while(!1);return l|0}function Bd(s,l){s=s|0,l=l|0;var c=Xe;return c=y(h[s+908+(n[976+(l<<2)>>2]<<2)>>2]),c>=y(0)&((Ht(c)|0)^1)|0}function Ka(s){s=s|0;var l=Xe,c=0,f=0,d=0,m=0,B=0,k=0,Q=Xe;if(c=n[s+968>>2]|0,c)Q=y(h[s+908>>2]),l=y(h[s+912>>2]),l=y(m7[c&0](s,Q,l)),Un(s,(Ht(l)|0)^1,3573);else{m=Ci(s)|0;do if(m|0){for(c=0,d=0;;){if(f=ms(s,d)|0,n[f+940>>2]|0){B=8;break}if((n[f+24>>2]|0)!=1)if(k=(da(s,f)|0)==5,k){c=f;break}else c=c|0?c:f;if(d=d+1|0,d>>>0>=m>>>0){B=8;break}}if((B|0)==8&&!c)break;return l=y(Ka(c)),y(l+y(h[c+404>>2]))}while(!1);l=y(h[s+912>>2])}return y(l)}function MA(s,l,c,f){s=s|0,l=l|0,c=y(c),f=y(f);var d=Xe,m=0;return OA(l)|0?(l=1,m=3):he(l)|0?(l=0,m=3):(f=y(ce),d=y(ce)),(m|0)==3&&(d=y(Yr(s+364+(l<<3)|0,f)),f=y(Yr(s+380+(l<<3)|0,f))),m=f<c&(f>=y(0)&((Ht(f)|0)^1)),c=m?f:c,m=d>=y(0)&((Ht(d)|0)^1)&c<d,y(m?d:c)}function vd(s,l,c,f,d,m,B){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0,B=B|0;var k=Xe,Q=Xe,O=0,M=0,j=Xe,se=Xe,je=Xe,Oe=0,Qe=0,$e=0,Je=0,lt=Xe,_e=0;$e=fr(n[s+4>>2]|0,m)|0,Oe=iw($e,m)|0,Qe=he($e)|0,j=y(cn(l,2,c)),se=y(cn(l,0,c)),ns(l,2,c)|0?k=y(j+y(Yr(n[l+992>>2]|0,c))):gi(l,2)|0&&lr(l,2)|0?(k=y(h[s+908>>2]),Q=y(Cr(s,2)),Q=y(k-y(Q+y(yn(s,2)))),k=y(Mr(l,2,c)),k=y(Ii(l,2,y(Q-y(k+y(Pu(l,2,c)))),c,c))):k=y(ce),ns(l,0,d)|0?Q=y(se+y(Yr(n[l+996>>2]|0,d))):gi(l,0)|0&&lr(l,0)|0?(Q=y(h[s+912>>2]),lt=y(Cr(s,0)),lt=y(Q-y(lt+y(yn(s,0)))),Q=y(Mr(l,0,d)),Q=y(Ii(l,0,y(lt-y(Q+y(Pu(l,0,d)))),d,c))):Q=y(ce),O=Ht(k)|0,M=Ht(Q)|0;do if(O^M&&(je=y(h[l+396>>2]),!(Ht(je)|0)))if(O){k=y(j+y(y(Q-se)*je));break}else{lt=y(se+y(y(k-j)/je)),Q=M?lt:Q;break}while(!1);M=Ht(k)|0,O=Ht(Q)|0,M|O&&(_e=(M^1)&1,f=c>y(0)&((f|0)!=0&M),k=Qe?k:f?c:k,ha(l,k,Q,m,Qe?_e:f?2:_e,M&(O^1)&1,k,Q,0,3623,B)|0,k=y(h[l+908>>2]),k=y(k+y(cn(l,2,c))),Q=y(h[l+912>>2]),Q=y(Q+y(cn(l,0,c)))),ha(l,k,Q,m,1,1,k,Q,1,3635,B)|0,lr(l,$e)|0&&!(gi(l,$e)|0)?(_e=n[976+($e<<2)>>2]|0,lt=y(h[s+908+(_e<<2)>>2]),lt=y(lt-y(h[l+908+(_e<<2)>>2])),lt=y(lt-y(yn(s,$e))),lt=y(lt-y(re(l,$e,c))),lt=y(lt-y(Pu(l,$e,Qe?c:d))),h[l+400+(n[1040+($e<<2)>>2]<<2)>>2]=lt):Je=21;do if((Je|0)==21){if(!(gi(l,$e)|0)&&(n[s+8>>2]|0)==1){_e=n[976+($e<<2)>>2]|0,lt=y(h[s+908+(_e<<2)>>2]),lt=y(y(lt-y(h[l+908+(_e<<2)>>2]))*y(.5)),h[l+400+(n[1040+($e<<2)>>2]<<2)>>2]=lt;break}!(gi(l,$e)|0)&&(n[s+8>>2]|0)==2&&(_e=n[976+($e<<2)>>2]|0,lt=y(h[s+908+(_e<<2)>>2]),lt=y(lt-y(h[l+908+(_e<<2)>>2])),h[l+400+(n[1040+($e<<2)>>2]<<2)>>2]=lt)}while(!1);lr(l,Oe)|0&&!(gi(l,Oe)|0)?(_e=n[976+(Oe<<2)>>2]|0,lt=y(h[s+908+(_e<<2)>>2]),lt=y(lt-y(h[l+908+(_e<<2)>>2])),lt=y(lt-y(yn(s,Oe))),lt=y(lt-y(re(l,Oe,c))),lt=y(lt-y(Pu(l,Oe,Qe?d:c))),h[l+400+(n[1040+(Oe<<2)>>2]<<2)>>2]=lt):Je=30;do if((Je|0)==30&&!(gi(l,Oe)|0)){if((da(s,l)|0)==2){_e=n[976+(Oe<<2)>>2]|0,lt=y(h[s+908+(_e<<2)>>2]),lt=y(y(lt-y(h[l+908+(_e<<2)>>2]))*y(.5)),h[l+400+(n[1040+(Oe<<2)>>2]<<2)>>2]=lt;break}_e=(da(s,l)|0)==3,_e^(n[s+28>>2]|0)==2&&(_e=n[976+(Oe<<2)>>2]|0,lt=y(h[s+908+(_e<<2)>>2]),lt=y(lt-y(h[l+908+(_e<<2)>>2])),h[l+400+(n[1040+(Oe<<2)>>2]<<2)>>2]=lt)}while(!1)}function yp(s,l,c){s=s|0,l=l|0,c=c|0;var f=Xe,d=0;d=n[976+(c<<2)>>2]|0,f=y(h[l+908+(d<<2)>>2]),f=y(y(h[s+908+(d<<2)>>2])-f),f=y(f-y(h[l+400+(n[1040+(c<<2)>>2]<<2)>>2])),h[l+400+(n[1e3+(c<<2)>>2]<<2)>>2]=f}function OA(s){return s=s|0,(s|1|0)==1|0}function ow(s){s=s|0;var l=Xe;switch(n[s+56>>2]|0){case 0:case 3:{l=y(h[s+40>>2]),l>y(0)&((Ht(l)|0)^1)?s=o[(n[s+976>>2]|0)+2>>0]|0?1056:992:s=1056;break}default:s=s+52|0}return s|0}function aw(s,l){return s=s|0,l=l|0,(o[s+l>>0]|0)!=0|0}function lr(s,l){return s=s|0,l=l|0,s=s+132|0,he(l)|0&&n[(Fn(s,5,948)|0)+4>>2]|0?s=1:s=(n[(Fn(s,n[1e3+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,s|0}function Pu(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0;return s=s+132|0,he(l)|0&&(f=Fn(s,5,948)|0,(n[f+4>>2]|0)!=0)?d=4:(f=Fn(s,n[1e3+(l<<2)>>2]|0,948)|0,n[f+4>>2]|0?d=4:c=y(0)),(d|0)==4&&(c=y(Yr(f,c))),y(c)}function Dd(s,l,c){return s=s|0,l=l|0,c=y(c),gi(s,l)|0?c=y(Mr(s,l,c)):c=y(-y(Pu(s,l,c))),y(c)}function Su(s){return s=y(s),h[v>>2]=s,n[v>>2]|0|0}function Ep(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Kt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function E0(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function UA(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&>(s)}function _A(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;if(B=s+4|0,k=n[B>>2]|0,d=k-f|0,m=d>>2,s=l+(m<<2)|0,s>>>0<c>>>0){f=k;do n[f>>2]=n[s>>2],s=s+4|0,f=(n[B>>2]|0)+4|0,n[B>>2]=f;while(s>>>0<c>>>0)}m|0&&ww(k+(0-m<<2)|0,l|0,d|0)|0}function C0(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0;return k=l+4|0,Q=n[k>>2]|0,d=n[s>>2]|0,B=c,m=B-d|0,f=Q+(0-(m>>2)<<2)|0,n[k>>2]=f,(m|0)>0&&Dr(f|0,d|0,m|0)|0,d=s+4|0,m=l+8|0,f=(n[d>>2]|0)-B|0,(f|0)>0&&(Dr(n[m>>2]|0,c|0,f|0)|0,n[m>>2]=(n[m>>2]|0)+(f>>>2<<2)),B=n[s>>2]|0,n[s>>2]=n[k>>2],n[k>>2]=B,B=n[d>>2]|0,n[d>>2]=n[m>>2],n[m>>2]=B,B=s+8|0,c=l+12|0,s=n[B>>2]|0,n[B>>2]=n[c>>2],n[c>>2]=s,n[l>>2]=n[k>>2],Q|0}function lw(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;if(B=n[l>>2]|0,m=n[c>>2]|0,(B|0)!=(m|0)){d=s+8|0,c=((m+-4-B|0)>>>2)+1|0,s=B,f=n[d>>2]|0;do n[f>>2]=n[s>>2],f=(n[d>>2]|0)+4|0,n[d>>2]=f,s=s+4|0;while((s|0)!=(m|0));n[l>>2]=B+(c<<2)}}function Pd(){mc()}function ma(){var s=0;return s=Kt(4)|0,HA(s),s|0}function HA(s){s=s|0,n[s>>2]=Cs()|0}function bc(s){s=s|0,s|0&&(w0(s),gt(s))}function w0(s){s=s|0,tt(n[s>>2]|0)}function Sd(s,l,c){s=s|0,l=l|0,c=c|0,Wa(n[s>>2]|0,l,c)}function fo(s,l){s=s|0,l=y(l),ga(n[s>>2]|0,l)}function xv(s,l){return s=s|0,l=l|0,aw(n[s>>2]|0,l)|0}function cw(){var s=0;return s=Kt(8)|0,kv(s,0),s|0}function kv(s,l){s=s|0,l=l|0,l?l=Ei(n[l>>2]|0)|0:l=co()|0,n[s>>2]=l,n[s+4>>2]=0,Si(l,s)}function eF(s){s=s|0;var l=0;return l=Kt(8)|0,kv(l,s),l|0}function Qv(s){s=s|0,s|0&&(bu(s),gt(s))}function bu(s){s=s|0;var l=0;ua(n[s>>2]|0),l=s+4|0,s=n[l>>2]|0,n[l>>2]=0,s|0&&(qA(s),gt(s))}function qA(s){s=s|0,jA(s)}function jA(s){s=s|0,s=n[s>>2]|0,s|0&&PA(s|0)}function uw(s){return s=s|0,qo(s)|0}function bd(s){s=s|0;var l=0,c=0;c=s+4|0,l=n[c>>2]|0,n[c>>2]=0,l|0&&(qA(l),gt(l)),qs(n[s>>2]|0)}function tF(s,l){s=s|0,l=l|0,$r(n[s>>2]|0,n[l>>2]|0)}function rF(s,l){s=s|0,l=l|0,Aa(n[s>>2]|0,l)}function Fv(s,l,c){s=s|0,l=l|0,c=+c,Cu(n[s>>2]|0,l,y(c))}function Rv(s,l,c){s=s|0,l=l|0,c=+c,ws(n[s>>2]|0,l,y(c))}function Aw(s,l){s=s|0,l=l|0,mu(n[s>>2]|0,l)}function xu(s,l){s=s|0,l=l|0,yu(n[s>>2]|0,l)}function nF(s,l){s=s|0,l=l|0,QA(n[s>>2]|0,l)}function iF(s,l){s=s|0,l=l|0,xA(n[s>>2]|0,l)}function Cp(s,l){s=s|0,l=l|0,Ec(n[s>>2]|0,l)}function sF(s,l){s=s|0,l=l|0,lp(n[s>>2]|0,l)}function Tv(s,l,c){s=s|0,l=l|0,c=+c,wc(n[s>>2]|0,l,y(c))}function GA(s,l,c){s=s|0,l=l|0,c=+c,Y(n[s>>2]|0,l,y(c))}function oF(s,l){s=s|0,l=l|0,wl(n[s>>2]|0,l)}function aF(s,l){s=s|0,l=l|0,n0(n[s>>2]|0,l)}function Nv(s,l){s=s|0,l=l|0,cp(n[s>>2]|0,l)}function fw(s,l){s=s|0,l=+l,FA(n[s>>2]|0,y(l))}function pw(s,l){s=s|0,l=+l,ja(n[s>>2]|0,y(l))}function lF(s,l){s=s|0,l=+l,Gi(n[s>>2]|0,y(l))}function cF(s,l){s=s|0,l=+l,js(n[s>>2]|0,y(l))}function Dl(s,l){s=s|0,l=+l,Eu(n[s>>2]|0,y(l))}function hw(s,l){s=s|0,l=+l,tw(n[s>>2]|0,y(l))}function uF(s,l){s=s|0,l=+l,RA(n[s>>2]|0,y(l))}function YA(s){s=s|0,up(n[s>>2]|0)}function xd(s,l){s=s|0,l=+l,Is(n[s>>2]|0,y(l))}function ku(s,l){s=s|0,l=+l,o0(n[s>>2]|0,y(l))}function gw(s){s=s|0,a0(n[s>>2]|0)}function dw(s,l){s=s|0,l=+l,Ap(n[s>>2]|0,y(l))}function AF(s,l){s=s|0,l=+l,Bc(n[s>>2]|0,y(l))}function Lv(s,l){s=s|0,l=+l,gd(n[s>>2]|0,y(l))}function WA(s,l){s=s|0,l=+l,c0(n[s>>2]|0,y(l))}function Mv(s,l){s=s|0,l=+l,Iu(n[s>>2]|0,y(l))}function kd(s,l){s=s|0,l=+l,dd(n[s>>2]|0,y(l))}function Ov(s,l){s=s|0,l=+l,Bu(n[s>>2]|0,y(l))}function Uv(s,l){s=s|0,l=+l,rw(n[s>>2]|0,y(l))}function Qd(s,l){s=s|0,l=+l,pa(n[s>>2]|0,y(l))}function _v(s,l,c){s=s|0,l=l|0,c=+c,wu(n[s>>2]|0,l,y(c))}function fF(s,l,c){s=s|0,l=l|0,c=+c,bi(n[s>>2]|0,l,y(c))}function P(s,l,c){s=s|0,l=l|0,c=+c,Ic(n[s>>2]|0,l,y(c))}function D(s){return s=s|0,r0(n[s>>2]|0)|0}function T(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,Cc(d,n[l>>2]|0,c),q(s,d),C=f}function q(s,l){s=s|0,l=l|0,W(s,n[l+4>>2]|0,+y(h[l>>2]))}function W(s,l,c){s=s|0,l=l|0,c=+c,n[s>>2]=l,E[s+8>>3]=c}function fe(s){return s=s|0,t0(n[s>>2]|0)|0}function De(s){return s=s|0,uo(n[s>>2]|0)|0}function vt(s){return s=s|0,yc(n[s>>2]|0)|0}function wt(s){return s=s|0,kA(n[s>>2]|0)|0}function bt(s){return s=s|0,hd(n[s>>2]|0)|0}function _r(s){return s=s|0,e0(n[s>>2]|0)|0}function os(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,Dt(d,n[l>>2]|0,c),q(s,d),C=f}function di(s){return s=s|0,$n(n[s>>2]|0)|0}function po(s){return s=s|0,i0(n[s>>2]|0)|0}function KA(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,fa(f,n[l>>2]|0),q(s,f),C=c}function Yo(s){return s=s|0,+ +y(ji(n[s>>2]|0))}function nt(s){return s=s|0,+ +y(rs(n[s>>2]|0))}function Ve(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,Br(f,n[l>>2]|0),q(s,f),C=c}function At(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,l0(f,n[l>>2]|0),q(s,f),C=c}function Wt(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,Ct(f,n[l>>2]|0),q(s,f),C=c}function vr(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,u0(f,n[l>>2]|0),q(s,f),C=c}function Sn(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,A0(f,n[l>>2]|0),q(s,f),C=c}function Qr(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,md(f,n[l>>2]|0),q(s,f),C=c}function bn(s){return s=s|0,+ +y(vc(n[s>>2]|0))}function ai(s,l){return s=s|0,l=l|0,+ +y(s0(n[s>>2]|0,l))}function tn(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,ct(d,n[l>>2]|0,c),q(s,d),C=f}function ho(s,l,c){s=s|0,l=l|0,c=c|0,or(n[s>>2]|0,n[l>>2]|0,c)}function pF(s,l){s=s|0,l=l|0,Es(n[s>>2]|0,n[l>>2]|0)}function nve(s){return s=s|0,Ci(n[s>>2]|0)|0}function ive(s){return s=s|0,s=pt(n[s>>2]|0)|0,s?s=uw(s)|0:s=0,s|0}function sve(s,l){return s=s|0,l=l|0,s=ms(n[s>>2]|0,l)|0,s?s=uw(s)|0:s=0,s|0}function ove(s,l){s=s|0,l=l|0;var c=0,f=0;f=Kt(4)|0,W5(f,l),c=s+4|0,l=n[c>>2]|0,n[c>>2]=f,l|0&&(qA(l),gt(l)),Bt(n[s>>2]|0,1)}function W5(s,l){s=s|0,l=l|0,yve(s,l)}function ave(s,l,c,f,d,m){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0;var B=0,k=0;B=C,C=C+16|0,k=B,lve(k,qo(l)|0,+c,f,+d,m),h[s>>2]=y(+E[k>>3]),h[s+4>>2]=y(+E[k+8>>3]),C=B}function lve(s,l,c,f,d,m){s=s|0,l=l|0,c=+c,f=f|0,d=+d,m=m|0;var B=0,k=0,Q=0,O=0,M=0;B=C,C=C+32|0,M=B+8|0,O=B+20|0,Q=B,k=B+16|0,E[M>>3]=c,n[O>>2]=f,E[Q>>3]=d,n[k>>2]=m,cve(s,n[l+4>>2]|0,M,O,Q,k),C=B}function cve(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0;B=C,C=C+16|0,k=B,za(k),l=ya(l)|0,uve(s,l,+E[c>>3],n[f>>2]|0,+E[d>>3],n[m>>2]|0),Ja(k),C=B}function ya(s){return s=s|0,n[s>>2]|0}function uve(s,l,c,f,d,m){s=s|0,l=l|0,c=+c,f=f|0,d=+d,m=m|0;var B=0;B=Pl(Ave()|0)|0,c=+VA(c),f=hF(f)|0,d=+VA(d),fve(s,hi(0,B|0,l|0,+c,f|0,+d,hF(m)|0)|0)}function Ave(){var s=0;return o[7608]|0||(dve(9120),s=7608,n[s>>2]=1,n[s+4>>2]=0),9120}function Pl(s){return s=s|0,n[s+8>>2]|0}function VA(s){return s=+s,+ +gF(s)}function hF(s){return s=s|0,V5(s)|0}function fve(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+32|0,c=d,f=l,f&1?(pve(c,0),ii(f|0,c|0)|0,hve(s,c),gve(c)):(n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2]),C=d}function pve(s,l){s=s|0,l=l|0,K5(s,l),n[s+8>>2]=0,o[s+24>>0]=0}function hve(s,l){s=s|0,l=l|0,l=l+8|0,n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2]}function gve(s){s=s|0,o[s+24>>0]=0}function K5(s,l){s=s|0,l=l|0,n[s>>2]=l}function V5(s){return s=s|0,s|0}function gF(s){return s=+s,+s}function dve(s){s=s|0,Sl(s,mve()|0,4)}function mve(){return 1064}function Sl(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=ap(l|0,c+1|0)|0}function yve(s,l){s=s|0,l=l|0,l=n[l>>2]|0,n[s>>2]=l,yl(l|0)}function Eve(s){s=s|0;var l=0,c=0;c=s+4|0,l=n[c>>2]|0,n[c>>2]=0,l|0&&(qA(l),gt(l)),Bt(n[s>>2]|0,0)}function Cve(s){s=s|0,Nt(n[s>>2]|0)}function wve(s){return s=s|0,rr(n[s>>2]|0)|0}function Ive(s,l,c,f){s=s|0,l=+l,c=+c,f=f|0,Dc(n[s>>2]|0,y(l),y(c),f)}function Bve(s){return s=s|0,+ +y(Il(n[s>>2]|0))}function vve(s){return s=s|0,+ +y(f0(n[s>>2]|0))}function Dve(s){return s=s|0,+ +y(vu(n[s>>2]|0))}function Pve(s){return s=s|0,+ +y(TA(n[s>>2]|0))}function Sve(s){return s=s|0,+ +y(fp(n[s>>2]|0))}function bve(s){return s=s|0,+ +y(Ga(n[s>>2]|0))}function xve(s,l){s=s|0,l=l|0,E[s>>3]=+y(Il(n[l>>2]|0)),E[s+8>>3]=+y(f0(n[l>>2]|0)),E[s+16>>3]=+y(vu(n[l>>2]|0)),E[s+24>>3]=+y(TA(n[l>>2]|0)),E[s+32>>3]=+y(fp(n[l>>2]|0)),E[s+40>>3]=+y(Ga(n[l>>2]|0))}function kve(s,l){return s=s|0,l=l|0,+ +y(p0(n[s>>2]|0,l))}function Qve(s,l){return s=s|0,l=l|0,+ +y(pp(n[s>>2]|0,l))}function Fve(s,l){return s=s|0,l=l|0,+ +y(jo(n[s>>2]|0,l))}function Rve(){return Pn()|0}function Tve(){Nve(),Lve(),Mve(),Ove(),Uve(),_ve()}function Nve(){UNe(11713,4938,1)}function Lve(){iNe(10448)}function Mve(){UTe(10408)}function Ove(){lTe(10324)}function Uve(){dFe(10096)}function _ve(){Hve(9132)}function Hve(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0,$e=0,Je=0,lt=0,_e=0,qe=0,Lt=0,Or=0,cr=0,Xt=0,Pr=0,Tr=0,ar=0,xn=0,go=0,mo=0,yo=0,Ca=0,xp=0,kp=0,bl=0,Qp=0,Tu=0,Nu=0,Fp=0,Rp=0,Tp=0,Xr=0,xl=0,Np=0,kc=0,Lp=0,Mp=0,Lu=0,Mu=0,Qc=0,Ys=0,Za=0,Wo=0,kl=0,rf=0,nf=0,Ou=0,sf=0,of=0,Ws=0,Ps=0,Ql=0,Rn=0,af=0,Eo=0,Fc=0,Co=0,Rc=0,lf=0,cf=0,Tc=0,Ks=0,Fl=0,uf=0,Af=0,ff=0,xr=0,zn=0,Ss=0,wo=0,Vs=0,Fr=0,ur=0,Rl=0;l=C,C=C+672|0,c=l+656|0,Rl=l+648|0,ur=l+640|0,Fr=l+632|0,Vs=l+624|0,wo=l+616|0,Ss=l+608|0,zn=l+600|0,xr=l+592|0,ff=l+584|0,Af=l+576|0,uf=l+568|0,Fl=l+560|0,Ks=l+552|0,Tc=l+544|0,cf=l+536|0,lf=l+528|0,Rc=l+520|0,Co=l+512|0,Fc=l+504|0,Eo=l+496|0,af=l+488|0,Rn=l+480|0,Ql=l+472|0,Ps=l+464|0,Ws=l+456|0,of=l+448|0,sf=l+440|0,Ou=l+432|0,nf=l+424|0,rf=l+416|0,kl=l+408|0,Wo=l+400|0,Za=l+392|0,Ys=l+384|0,Qc=l+376|0,Mu=l+368|0,Lu=l+360|0,Mp=l+352|0,Lp=l+344|0,kc=l+336|0,Np=l+328|0,xl=l+320|0,Xr=l+312|0,Tp=l+304|0,Rp=l+296|0,Fp=l+288|0,Nu=l+280|0,Tu=l+272|0,Qp=l+264|0,bl=l+256|0,kp=l+248|0,xp=l+240|0,Ca=l+232|0,yo=l+224|0,mo=l+216|0,go=l+208|0,xn=l+200|0,ar=l+192|0,Tr=l+184|0,Pr=l+176|0,Xt=l+168|0,cr=l+160|0,Or=l+152|0,Lt=l+144|0,qe=l+136|0,_e=l+128|0,lt=l+120|0,Je=l+112|0,$e=l+104|0,Qe=l+96|0,Oe=l+88|0,je=l+80|0,se=l+72|0,j=l+64|0,M=l+56|0,O=l+48|0,Q=l+40|0,k=l+32|0,B=l+24|0,m=l+16|0,d=l+8|0,f=l,qve(s,3646),jve(s,3651,2)|0,Gve(s,3665,2)|0,Yve(s,3682,18)|0,n[Rl>>2]=19,n[Rl+4>>2]=0,n[c>>2]=n[Rl>>2],n[c+4>>2]=n[Rl+4>>2],mw(s,3690,c)|0,n[ur>>2]=1,n[ur+4>>2]=0,n[c>>2]=n[ur>>2],n[c+4>>2]=n[ur+4>>2],Wve(s,3696,c)|0,n[Fr>>2]=2,n[Fr+4>>2]=0,n[c>>2]=n[Fr>>2],n[c+4>>2]=n[Fr+4>>2],Qu(s,3706,c)|0,n[Vs>>2]=1,n[Vs+4>>2]=0,n[c>>2]=n[Vs>>2],n[c+4>>2]=n[Vs+4>>2],I0(s,3722,c)|0,n[wo>>2]=2,n[wo+4>>2]=0,n[c>>2]=n[wo>>2],n[c+4>>2]=n[wo+4>>2],I0(s,3734,c)|0,n[Ss>>2]=3,n[Ss+4>>2]=0,n[c>>2]=n[Ss>>2],n[c+4>>2]=n[Ss+4>>2],Qu(s,3753,c)|0,n[zn>>2]=4,n[zn+4>>2]=0,n[c>>2]=n[zn>>2],n[c+4>>2]=n[zn+4>>2],Qu(s,3769,c)|0,n[xr>>2]=5,n[xr+4>>2]=0,n[c>>2]=n[xr>>2],n[c+4>>2]=n[xr+4>>2],Qu(s,3783,c)|0,n[ff>>2]=6,n[ff+4>>2]=0,n[c>>2]=n[ff>>2],n[c+4>>2]=n[ff+4>>2],Qu(s,3796,c)|0,n[Af>>2]=7,n[Af+4>>2]=0,n[c>>2]=n[Af>>2],n[c+4>>2]=n[Af+4>>2],Qu(s,3813,c)|0,n[uf>>2]=8,n[uf+4>>2]=0,n[c>>2]=n[uf>>2],n[c+4>>2]=n[uf+4>>2],Qu(s,3825,c)|0,n[Fl>>2]=3,n[Fl+4>>2]=0,n[c>>2]=n[Fl>>2],n[c+4>>2]=n[Fl+4>>2],I0(s,3843,c)|0,n[Ks>>2]=4,n[Ks+4>>2]=0,n[c>>2]=n[Ks>>2],n[c+4>>2]=n[Ks+4>>2],I0(s,3853,c)|0,n[Tc>>2]=9,n[Tc+4>>2]=0,n[c>>2]=n[Tc>>2],n[c+4>>2]=n[Tc+4>>2],Qu(s,3870,c)|0,n[cf>>2]=10,n[cf+4>>2]=0,n[c>>2]=n[cf>>2],n[c+4>>2]=n[cf+4>>2],Qu(s,3884,c)|0,n[lf>>2]=11,n[lf+4>>2]=0,n[c>>2]=n[lf>>2],n[c+4>>2]=n[lf+4>>2],Qu(s,3896,c)|0,n[Rc>>2]=1,n[Rc+4>>2]=0,n[c>>2]=n[Rc>>2],n[c+4>>2]=n[Rc+4>>2],vs(s,3907,c)|0,n[Co>>2]=2,n[Co+4>>2]=0,n[c>>2]=n[Co>>2],n[c+4>>2]=n[Co+4>>2],vs(s,3915,c)|0,n[Fc>>2]=3,n[Fc+4>>2]=0,n[c>>2]=n[Fc>>2],n[c+4>>2]=n[Fc+4>>2],vs(s,3928,c)|0,n[Eo>>2]=4,n[Eo+4>>2]=0,n[c>>2]=n[Eo>>2],n[c+4>>2]=n[Eo+4>>2],vs(s,3948,c)|0,n[af>>2]=5,n[af+4>>2]=0,n[c>>2]=n[af>>2],n[c+4>>2]=n[af+4>>2],vs(s,3960,c)|0,n[Rn>>2]=6,n[Rn+4>>2]=0,n[c>>2]=n[Rn>>2],n[c+4>>2]=n[Rn+4>>2],vs(s,3974,c)|0,n[Ql>>2]=7,n[Ql+4>>2]=0,n[c>>2]=n[Ql>>2],n[c+4>>2]=n[Ql+4>>2],vs(s,3983,c)|0,n[Ps>>2]=20,n[Ps+4>>2]=0,n[c>>2]=n[Ps>>2],n[c+4>>2]=n[Ps+4>>2],mw(s,3999,c)|0,n[Ws>>2]=8,n[Ws+4>>2]=0,n[c>>2]=n[Ws>>2],n[c+4>>2]=n[Ws+4>>2],vs(s,4012,c)|0,n[of>>2]=9,n[of+4>>2]=0,n[c>>2]=n[of>>2],n[c+4>>2]=n[of+4>>2],vs(s,4022,c)|0,n[sf>>2]=21,n[sf+4>>2]=0,n[c>>2]=n[sf>>2],n[c+4>>2]=n[sf+4>>2],mw(s,4039,c)|0,n[Ou>>2]=10,n[Ou+4>>2]=0,n[c>>2]=n[Ou>>2],n[c+4>>2]=n[Ou+4>>2],vs(s,4053,c)|0,n[nf>>2]=11,n[nf+4>>2]=0,n[c>>2]=n[nf>>2],n[c+4>>2]=n[nf+4>>2],vs(s,4065,c)|0,n[rf>>2]=12,n[rf+4>>2]=0,n[c>>2]=n[rf>>2],n[c+4>>2]=n[rf+4>>2],vs(s,4084,c)|0,n[kl>>2]=13,n[kl+4>>2]=0,n[c>>2]=n[kl>>2],n[c+4>>2]=n[kl+4>>2],vs(s,4097,c)|0,n[Wo>>2]=14,n[Wo+4>>2]=0,n[c>>2]=n[Wo>>2],n[c+4>>2]=n[Wo+4>>2],vs(s,4117,c)|0,n[Za>>2]=15,n[Za+4>>2]=0,n[c>>2]=n[Za>>2],n[c+4>>2]=n[Za+4>>2],vs(s,4129,c)|0,n[Ys>>2]=16,n[Ys+4>>2]=0,n[c>>2]=n[Ys>>2],n[c+4>>2]=n[Ys+4>>2],vs(s,4148,c)|0,n[Qc>>2]=17,n[Qc+4>>2]=0,n[c>>2]=n[Qc>>2],n[c+4>>2]=n[Qc+4>>2],vs(s,4161,c)|0,n[Mu>>2]=18,n[Mu+4>>2]=0,n[c>>2]=n[Mu>>2],n[c+4>>2]=n[Mu+4>>2],vs(s,4181,c)|0,n[Lu>>2]=5,n[Lu+4>>2]=0,n[c>>2]=n[Lu>>2],n[c+4>>2]=n[Lu+4>>2],I0(s,4196,c)|0,n[Mp>>2]=6,n[Mp+4>>2]=0,n[c>>2]=n[Mp>>2],n[c+4>>2]=n[Mp+4>>2],I0(s,4206,c)|0,n[Lp>>2]=7,n[Lp+4>>2]=0,n[c>>2]=n[Lp>>2],n[c+4>>2]=n[Lp+4>>2],I0(s,4217,c)|0,n[kc>>2]=3,n[kc+4>>2]=0,n[c>>2]=n[kc>>2],n[c+4>>2]=n[kc+4>>2],zA(s,4235,c)|0,n[Np>>2]=1,n[Np+4>>2]=0,n[c>>2]=n[Np>>2],n[c+4>>2]=n[Np+4>>2],dF(s,4251,c)|0,n[xl>>2]=4,n[xl+4>>2]=0,n[c>>2]=n[xl>>2],n[c+4>>2]=n[xl+4>>2],zA(s,4263,c)|0,n[Xr>>2]=5,n[Xr+4>>2]=0,n[c>>2]=n[Xr>>2],n[c+4>>2]=n[Xr+4>>2],zA(s,4279,c)|0,n[Tp>>2]=6,n[Tp+4>>2]=0,n[c>>2]=n[Tp>>2],n[c+4>>2]=n[Tp+4>>2],zA(s,4293,c)|0,n[Rp>>2]=7,n[Rp+4>>2]=0,n[c>>2]=n[Rp>>2],n[c+4>>2]=n[Rp+4>>2],zA(s,4306,c)|0,n[Fp>>2]=8,n[Fp+4>>2]=0,n[c>>2]=n[Fp>>2],n[c+4>>2]=n[Fp+4>>2],zA(s,4323,c)|0,n[Nu>>2]=9,n[Nu+4>>2]=0,n[c>>2]=n[Nu>>2],n[c+4>>2]=n[Nu+4>>2],zA(s,4335,c)|0,n[Tu>>2]=2,n[Tu+4>>2]=0,n[c>>2]=n[Tu>>2],n[c+4>>2]=n[Tu+4>>2],dF(s,4353,c)|0,n[Qp>>2]=12,n[Qp+4>>2]=0,n[c>>2]=n[Qp>>2],n[c+4>>2]=n[Qp+4>>2],B0(s,4363,c)|0,n[bl>>2]=1,n[bl+4>>2]=0,n[c>>2]=n[bl>>2],n[c+4>>2]=n[bl+4>>2],JA(s,4376,c)|0,n[kp>>2]=2,n[kp+4>>2]=0,n[c>>2]=n[kp>>2],n[c+4>>2]=n[kp+4>>2],JA(s,4388,c)|0,n[xp>>2]=13,n[xp+4>>2]=0,n[c>>2]=n[xp>>2],n[c+4>>2]=n[xp+4>>2],B0(s,4402,c)|0,n[Ca>>2]=14,n[Ca+4>>2]=0,n[c>>2]=n[Ca>>2],n[c+4>>2]=n[Ca+4>>2],B0(s,4411,c)|0,n[yo>>2]=15,n[yo+4>>2]=0,n[c>>2]=n[yo>>2],n[c+4>>2]=n[yo+4>>2],B0(s,4421,c)|0,n[mo>>2]=16,n[mo+4>>2]=0,n[c>>2]=n[mo>>2],n[c+4>>2]=n[mo+4>>2],B0(s,4433,c)|0,n[go>>2]=17,n[go+4>>2]=0,n[c>>2]=n[go>>2],n[c+4>>2]=n[go+4>>2],B0(s,4446,c)|0,n[xn>>2]=18,n[xn+4>>2]=0,n[c>>2]=n[xn>>2],n[c+4>>2]=n[xn+4>>2],B0(s,4458,c)|0,n[ar>>2]=3,n[ar+4>>2]=0,n[c>>2]=n[ar>>2],n[c+4>>2]=n[ar+4>>2],JA(s,4471,c)|0,n[Tr>>2]=1,n[Tr+4>>2]=0,n[c>>2]=n[Tr>>2],n[c+4>>2]=n[Tr+4>>2],Hv(s,4486,c)|0,n[Pr>>2]=10,n[Pr+4>>2]=0,n[c>>2]=n[Pr>>2],n[c+4>>2]=n[Pr+4>>2],zA(s,4496,c)|0,n[Xt>>2]=11,n[Xt+4>>2]=0,n[c>>2]=n[Xt>>2],n[c+4>>2]=n[Xt+4>>2],zA(s,4508,c)|0,n[cr>>2]=3,n[cr+4>>2]=0,n[c>>2]=n[cr>>2],n[c+4>>2]=n[cr+4>>2],dF(s,4519,c)|0,n[Or>>2]=4,n[Or+4>>2]=0,n[c>>2]=n[Or>>2],n[c+4>>2]=n[Or+4>>2],Kve(s,4530,c)|0,n[Lt>>2]=19,n[Lt+4>>2]=0,n[c>>2]=n[Lt>>2],n[c+4>>2]=n[Lt+4>>2],Vve(s,4542,c)|0,n[qe>>2]=12,n[qe+4>>2]=0,n[c>>2]=n[qe>>2],n[c+4>>2]=n[qe+4>>2],zve(s,4554,c)|0,n[_e>>2]=13,n[_e+4>>2]=0,n[c>>2]=n[_e>>2],n[c+4>>2]=n[_e+4>>2],Jve(s,4568,c)|0,n[lt>>2]=2,n[lt+4>>2]=0,n[c>>2]=n[lt>>2],n[c+4>>2]=n[lt+4>>2],Xve(s,4578,c)|0,n[Je>>2]=20,n[Je+4>>2]=0,n[c>>2]=n[Je>>2],n[c+4>>2]=n[Je+4>>2],Zve(s,4587,c)|0,n[$e>>2]=22,n[$e+4>>2]=0,n[c>>2]=n[$e>>2],n[c+4>>2]=n[$e+4>>2],mw(s,4602,c)|0,n[Qe>>2]=23,n[Qe+4>>2]=0,n[c>>2]=n[Qe>>2],n[c+4>>2]=n[Qe+4>>2],mw(s,4619,c)|0,n[Oe>>2]=14,n[Oe+4>>2]=0,n[c>>2]=n[Oe>>2],n[c+4>>2]=n[Oe+4>>2],$ve(s,4629,c)|0,n[je>>2]=1,n[je+4>>2]=0,n[c>>2]=n[je>>2],n[c+4>>2]=n[je+4>>2],eDe(s,4637,c)|0,n[se>>2]=4,n[se+4>>2]=0,n[c>>2]=n[se>>2],n[c+4>>2]=n[se+4>>2],JA(s,4653,c)|0,n[j>>2]=5,n[j+4>>2]=0,n[c>>2]=n[j>>2],n[c+4>>2]=n[j+4>>2],JA(s,4669,c)|0,n[M>>2]=6,n[M+4>>2]=0,n[c>>2]=n[M>>2],n[c+4>>2]=n[M+4>>2],JA(s,4686,c)|0,n[O>>2]=7,n[O+4>>2]=0,n[c>>2]=n[O>>2],n[c+4>>2]=n[O+4>>2],JA(s,4701,c)|0,n[Q>>2]=8,n[Q+4>>2]=0,n[c>>2]=n[Q>>2],n[c+4>>2]=n[Q+4>>2],JA(s,4719,c)|0,n[k>>2]=9,n[k+4>>2]=0,n[c>>2]=n[k>>2],n[c+4>>2]=n[k+4>>2],JA(s,4736,c)|0,n[B>>2]=21,n[B+4>>2]=0,n[c>>2]=n[B>>2],n[c+4>>2]=n[B+4>>2],tDe(s,4754,c)|0,n[m>>2]=2,n[m+4>>2]=0,n[c>>2]=n[m>>2],n[c+4>>2]=n[m+4>>2],Hv(s,4772,c)|0,n[d>>2]=3,n[d+4>>2]=0,n[c>>2]=n[d>>2],n[c+4>>2]=n[d+4>>2],Hv(s,4790,c)|0,n[f>>2]=4,n[f+4>>2]=0,n[c>>2]=n[f>>2],n[c+4>>2]=n[f+4>>2],Hv(s,4808,c)|0,C=l}function qve(s,l){s=s|0,l=l|0;var c=0;c=aFe()|0,n[s>>2]=c,lFe(c,l),Pp(n[s>>2]|0)}function jve(s,l,c){return s=s|0,l=l|0,c=c|0,KQe(s,pn(l)|0,c,0),s|0}function Gve(s,l,c){return s=s|0,l=l|0,c=c|0,QQe(s,pn(l)|0,c,0),s|0}function Yve(s,l,c){return s=s|0,l=l|0,c=c|0,mQe(s,pn(l)|0,c,0),s|0}function mw(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],tQe(s,l,d),C=f,s|0}function Wve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Lke(s,l,d),C=f,s|0}function Qu(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Cke(s,l,d),C=f,s|0}function I0(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ike(s,l,d),C=f,s|0}function vs(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],qxe(s,l,d),C=f,s|0}function zA(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Pxe(s,l,d),C=f,s|0}function dF(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],uxe(s,l,d),C=f,s|0}function B0(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Lbe(s,l,d),C=f,s|0}function JA(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Cbe(s,l,d),C=f,s|0}function Hv(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ibe(s,l,d),C=f,s|0}function Kve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],qSe(s,l,d),C=f,s|0}function Vve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],PSe(s,l,d),C=f,s|0}function zve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ASe(s,l,d),C=f,s|0}function Jve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],JPe(s,l,d),C=f,s|0}function Xve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],RPe(s,l,d),C=f,s|0}function Zve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],dPe(s,l,d),C=f,s|0}function $ve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ePe(s,l,d),C=f,s|0}function eDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],LDe(s,l,d),C=f,s|0}function tDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],rDe(s,l,d),C=f,s|0}function rDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],nDe(s,c,d,1),C=f}function pn(s){return s=s|0,s|0}function nDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=mF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=iDe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,sDe(m,f)|0,f),C=d}function mF(){var s=0,l=0;if(o[7616]|0||(X5(9136),ir(24,9136,U|0)|0,l=7616,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9136)|0)){s=9136,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));X5(9136)}return 9136}function iDe(s){return s=s|0,0}function sDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=mF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],J5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(lDe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function hn(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0;B=C,C=C+32|0,se=B+24|0,j=B+20|0,Q=B+16|0,M=B+12|0,O=B+8|0,k=B+4|0,je=B,n[j>>2]=l,n[Q>>2]=c,n[M>>2]=f,n[O>>2]=d,n[k>>2]=m,m=s+28|0,n[je>>2]=n[m>>2],n[se>>2]=n[je>>2],oDe(s+24|0,se,j,M,O,Q,k)|0,n[m>>2]=n[n[m>>2]>>2],C=B}function oDe(s,l,c,f,d,m,B){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,s=aDe(l)|0,l=Kt(24)|0,z5(l+4|0,n[c>>2]|0,n[f>>2]|0,n[d>>2]|0,n[m>>2]|0,n[B>>2]|0),n[l>>2]=n[s>>2],n[s>>2]=l,l|0}function aDe(s){return s=s|0,n[s>>2]|0}function z5(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=f,n[s+12>>2]=d,n[s+16>>2]=m}function gr(s,l){return s=s|0,l=l|0,l|s|0}function J5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function lDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=cDe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,uDe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],J5(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,ADe(s,k),fDe(k),C=O;return}}function cDe(s){return s=s|0,357913941}function uDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function ADe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function X5(s){s=s|0,gDe(s)}function pDe(s){s=s|0,hDe(s+24|0)}function Rr(s){return s=s|0,n[s>>2]|0}function hDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function gDe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,3,l,dDe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Vr(){return 9228}function dDe(){return 1140}function mDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=yDe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=EDe(l,f)|0,C=c,l|0}function zr(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=f,n[s+12>>2]=d,n[s+16>>2]=m}function yDe(s){return s=s|0,(n[(mF()|0)+24>>2]|0)+(s*12|0)|0}function EDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+48|0,f=d,c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),tf[c&31](f,s),f=CDe(f)|0,C=d,f|0}function CDe(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=yF(Z5()|0)|0,f?(EF(l,f),CF(c,l),wDe(s,c),s=wF(l)|0):s=IDe(s)|0,C=d,s|0}function Z5(){var s=0;return o[7632]|0||(FDe(9184),ir(25,9184,U|0)|0,s=7632,n[s>>2]=1,n[s+4>>2]=0),9184}function yF(s){return s=s|0,n[s+36>>2]|0}function EF(s,l){s=s|0,l=l|0,n[s>>2]=l,n[s+4>>2]=s,n[s+8>>2]=0}function CF(s,l){s=s|0,l=l|0,n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=0}function wDe(s,l){s=s|0,l=l|0,PDe(l,s,s+8|0,s+16|0,s+24|0,s+32|0,s+40|0)|0}function wF(s){return s=s|0,n[(n[s+4>>2]|0)+8>>2]|0}function IDe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,Q=0;Q=C,C=C+16|0,c=Q+4|0,f=Q,d=Va(8)|0,m=d,B=Kt(48)|0,k=B,l=k+48|0;do n[k>>2]=n[s>>2],k=k+4|0,s=s+4|0;while((k|0)<(l|0));return l=m+4|0,n[l>>2]=B,k=Kt(8)|0,B=n[l>>2]|0,n[f>>2]=0,n[c>>2]=n[f>>2],$5(k,B,c),n[d>>2]=k,C=Q,m|0}function $5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Kt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1092,n[c+12>>2]=l,n[s+4>>2]=c}function BDe(s){s=s|0,Md(s),gt(s)}function vDe(s){s=s|0,s=n[s+12>>2]|0,s|0&>(s)}function DDe(s){s=s|0,gt(s)}function PDe(s,l,c,f,d,m,B){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,m=SDe(n[s>>2]|0,l,c,f,d,m,B)|0,B=s+4|0,n[(n[B>>2]|0)+8>>2]=m,n[(n[B>>2]|0)+8>>2]|0}function SDe(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0;var k=0,Q=0;return k=C,C=C+16|0,Q=k,za(Q),s=ya(s)|0,B=bDe(s,+E[l>>3],+E[c>>3],+E[f>>3],+E[d>>3],+E[m>>3],+E[B>>3])|0,Ja(Q),C=k,B|0}function bDe(s,l,c,f,d,m,B){s=s|0,l=+l,c=+c,f=+f,d=+d,m=+m,B=+B;var k=0;return k=Pl(xDe()|0)|0,l=+VA(l),c=+VA(c),f=+VA(f),d=+VA(d),m=+VA(m),_s(0,k|0,s|0,+l,+c,+f,+d,+m,+ +VA(B))|0}function xDe(){var s=0;return o[7624]|0||(kDe(9172),s=7624,n[s>>2]=1,n[s+4>>2]=0),9172}function kDe(s){s=s|0,Sl(s,QDe()|0,6)}function QDe(){return 1112}function FDe(s){s=s|0,wp(s)}function RDe(s){s=s|0,eG(s+24|0),tG(s+16|0)}function eG(s){s=s|0,NDe(s)}function tG(s){s=s|0,TDe(s)}function TDe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,gt(c);while(l|0);n[s>>2]=0}function NDe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,gt(c);while(l|0);n[s>>2]=0}function wp(s){s=s|0;var l=0;n[s+16>>2]=0,n[s+20>>2]=0,l=s+24|0,n[l>>2]=0,n[s+28>>2]=l,n[s+36>>2]=0,o[s+40>>0]=0,o[s+41>>0]=0}function LDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],MDe(s,c,d,0),C=f}function MDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=IF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=ODe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,UDe(m,f)|0,f),C=d}function IF(){var s=0,l=0;if(o[7640]|0||(nG(9232),ir(26,9232,U|0)|0,l=7640,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9232)|0)){s=9232,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));nG(9232)}return 9232}function ODe(s){return s=s|0,0}function UDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=IF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],rG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(_De(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function rG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function _De(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=HDe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,qDe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],rG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,jDe(s,k),GDe(k),C=O;return}}function HDe(s){return s=s|0,357913941}function qDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function jDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function GDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function nG(s){s=s|0,KDe(s)}function YDe(s){s=s|0,WDe(s+24|0)}function WDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function KDe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,1,l,VDe()|0,3),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function VDe(){return 1144}function zDe(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0;var m=0,B=0,k=0,Q=0;m=C,C=C+16|0,B=m+8|0,k=m,Q=JDe(s)|0,s=n[Q+4>>2]|0,n[k>>2]=n[Q>>2],n[k+4>>2]=s,n[B>>2]=n[k>>2],n[B+4>>2]=n[k+4>>2],XDe(l,B,c,f,d),C=m}function JDe(s){return s=s|0,(n[(IF()|0)+24>>2]|0)+(s*12|0)|0}function XDe(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0;var m=0,B=0,k=0,Q=0,O=0;O=C,C=C+16|0,B=O+2|0,k=O+1|0,Q=O,m=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(m=n[(n[s>>2]|0)+m>>2]|0),Fu(B,c),c=+Ru(B,c),Fu(k,f),f=+Ru(k,f),XA(Q,d),Q=ZA(Q,d)|0,y7[m&1](s,c,f,Q),C=O}function Fu(s,l){s=s|0,l=+l}function Ru(s,l){return s=s|0,l=+l,+ +$De(l)}function XA(s,l){s=s|0,l=l|0}function ZA(s,l){return s=s|0,l=l|0,ZDe(l)|0}function ZDe(s){return s=s|0,s|0}function $De(s){return s=+s,+s}function ePe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],tPe(s,c,d,1),C=f}function tPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=BF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=rPe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,nPe(m,f)|0,f),C=d}function BF(){var s=0,l=0;if(o[7648]|0||(sG(9268),ir(27,9268,U|0)|0,l=7648,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9268)|0)){s=9268,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));sG(9268)}return 9268}function rPe(s){return s=s|0,0}function nPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=BF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],iG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(iPe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function iG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function iPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=sPe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,oPe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],iG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,aPe(s,k),lPe(k),C=O;return}}function sPe(s){return s=s|0,357913941}function oPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function aPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function lPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function sG(s){s=s|0,APe(s)}function cPe(s){s=s|0,uPe(s+24|0)}function uPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function APe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,4,l,fPe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function fPe(){return 1160}function pPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=hPe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=gPe(l,f)|0,C=c,l|0}function hPe(s){return s=s|0,(n[(BF()|0)+24>>2]|0)+(s*12|0)|0}function gPe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),oG(F0[c&31](s)|0)|0}function oG(s){return s=s|0,s&1|0}function dPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],mPe(s,c,d,0),C=f}function mPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=vF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=yPe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,EPe(m,f)|0,f),C=d}function vF(){var s=0,l=0;if(o[7656]|0||(lG(9304),ir(28,9304,U|0)|0,l=7656,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9304)|0)){s=9304,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));lG(9304)}return 9304}function yPe(s){return s=s|0,0}function EPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=vF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],aG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(CPe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function aG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function CPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=wPe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,IPe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],aG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,BPe(s,k),vPe(k),C=O;return}}function wPe(s){return s=s|0,357913941}function IPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function BPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function vPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function lG(s){s=s|0,SPe(s)}function DPe(s){s=s|0,PPe(s+24|0)}function PPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function SPe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,5,l,bPe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function bPe(){return 1164}function xPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=kPe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],QPe(l,d,c),C=f}function kPe(s){return s=s|0,(n[(vF()|0)+24>>2]|0)+(s*12|0)|0}function QPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),Ip(d,c),c=Bp(d,c)|0,tf[f&31](s,c),vp(d),C=m}function Ip(s,l){s=s|0,l=l|0,FPe(s,l)}function Bp(s,l){return s=s|0,l=l|0,s|0}function vp(s){s=s|0,qA(s)}function FPe(s,l){s=s|0,l=l|0,DF(s,l)}function DF(s,l){s=s|0,l=l|0,n[s>>2]=l}function RPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],TPe(s,c,d,0),C=f}function TPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=PF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=NPe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,LPe(m,f)|0,f),C=d}function PF(){var s=0,l=0;if(o[7664]|0||(uG(9340),ir(29,9340,U|0)|0,l=7664,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9340)|0)){s=9340,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));uG(9340)}return 9340}function NPe(s){return s=s|0,0}function LPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=PF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],cG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(MPe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function cG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function MPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=OPe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,UPe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],cG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,_Pe(s,k),HPe(k),C=O;return}}function OPe(s){return s=s|0,357913941}function UPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function _Pe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function HPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function uG(s){s=s|0,GPe(s)}function qPe(s){s=s|0,jPe(s+24|0)}function jPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function GPe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,4,l,YPe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function YPe(){return 1180}function WPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=KPe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=VPe(l,d,c)|0,C=f,c|0}function KPe(s){return s=s|0,(n[(PF()|0)+24>>2]|0)+(s*12|0)|0}function VPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),v0(d,c),d=D0(d,c)|0,d=qv(IR[f&15](s,d)|0)|0,C=m,d|0}function v0(s,l){s=s|0,l=l|0}function D0(s,l){return s=s|0,l=l|0,zPe(l)|0}function qv(s){return s=s|0,s|0}function zPe(s){return s=s|0,s|0}function JPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],XPe(s,c,d,0),C=f}function XPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=SF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=ZPe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,$Pe(m,f)|0,f),C=d}function SF(){var s=0,l=0;if(o[7672]|0||(fG(9376),ir(30,9376,U|0)|0,l=7672,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9376)|0)){s=9376,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));fG(9376)}return 9376}function ZPe(s){return s=s|0,0}function $Pe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=SF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],AG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(eSe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function AG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function eSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=tSe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,rSe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],AG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,nSe(s,k),iSe(k),C=O;return}}function tSe(s){return s=s|0,357913941}function rSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function nSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function iSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function fG(s){s=s|0,aSe(s)}function sSe(s){s=s|0,oSe(s+24|0)}function oSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function aSe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,5,l,pG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function pG(){return 1196}function lSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=cSe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=uSe(l,f)|0,C=c,l|0}function cSe(s){return s=s|0,(n[(SF()|0)+24>>2]|0)+(s*12|0)|0}function uSe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),qv(F0[c&31](s)|0)|0}function ASe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],fSe(s,c,d,1),C=f}function fSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=bF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=pSe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,hSe(m,f)|0,f),C=d}function bF(){var s=0,l=0;if(o[7680]|0||(gG(9412),ir(31,9412,U|0)|0,l=7680,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9412)|0)){s=9412,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));gG(9412)}return 9412}function pSe(s){return s=s|0,0}function hSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=bF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],hG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(gSe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function hG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function gSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=dSe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,mSe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],hG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,ySe(s,k),ESe(k),C=O;return}}function dSe(s){return s=s|0,357913941}function mSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function ySe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function ESe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function gG(s){s=s|0,ISe(s)}function CSe(s){s=s|0,wSe(s+24|0)}function wSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function ISe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,6,l,dG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dG(){return 1200}function BSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=vSe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=DSe(l,f)|0,C=c,l|0}function vSe(s){return s=s|0,(n[(bF()|0)+24>>2]|0)+(s*12|0)|0}function DSe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),jv(F0[c&31](s)|0)|0}function jv(s){return s=s|0,s|0}function PSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],SSe(s,c,d,0),C=f}function SSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=xF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=bSe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,xSe(m,f)|0,f),C=d}function xF(){var s=0,l=0;if(o[7688]|0||(yG(9448),ir(32,9448,U|0)|0,l=7688,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9448)|0)){s=9448,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));yG(9448)}return 9448}function bSe(s){return s=s|0,0}function xSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=xF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],mG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(kSe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function mG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function kSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=QSe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,FSe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],mG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,RSe(s,k),TSe(k),C=O;return}}function QSe(s){return s=s|0,357913941}function FSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function RSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function TSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function yG(s){s=s|0,MSe(s)}function NSe(s){s=s|0,LSe(s+24|0)}function LSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function MSe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,6,l,EG()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function EG(){return 1204}function OSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=USe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],_Se(l,d,c),C=f}function USe(s){return s=s|0,(n[(xF()|0)+24>>2]|0)+(s*12|0)|0}function _Se(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),kF(d,c),d=QF(d,c)|0,tf[f&31](s,d),C=m}function kF(s,l){s=s|0,l=l|0}function QF(s,l){return s=s|0,l=l|0,HSe(l)|0}function HSe(s){return s=s|0,s|0}function qSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],jSe(s,c,d,0),C=f}function jSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=FF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=GSe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,YSe(m,f)|0,f),C=d}function FF(){var s=0,l=0;if(o[7696]|0||(wG(9484),ir(33,9484,U|0)|0,l=7696,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9484)|0)){s=9484,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));wG(9484)}return 9484}function GSe(s){return s=s|0,0}function YSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=FF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],CG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(WSe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function CG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function WSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=KSe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,VSe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],CG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,zSe(s,k),JSe(k),C=O;return}}function KSe(s){return s=s|0,357913941}function VSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function zSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function JSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function wG(s){s=s|0,$Se(s)}function XSe(s){s=s|0,ZSe(s+24|0)}function ZSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function $Se(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,1,l,ebe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ebe(){return 1212}function tbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=rbe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],nbe(l,m,c,f),C=d}function rbe(s){return s=s|0,(n[(FF()|0)+24>>2]|0)+(s*12|0)|0}function nbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),kF(m,c),m=QF(m,c)|0,v0(B,f),B=D0(B,f)|0,vw[d&15](s,m,B),C=k}function ibe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],sbe(s,c,d,1),C=f}function sbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=RF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=obe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,abe(m,f)|0,f),C=d}function RF(){var s=0,l=0;if(o[7704]|0||(BG(9520),ir(34,9520,U|0)|0,l=7704,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9520)|0)){s=9520,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));BG(9520)}return 9520}function obe(s){return s=s|0,0}function abe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=RF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],IG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(lbe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function IG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function lbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=cbe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,ube(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],IG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,Abe(s,k),fbe(k),C=O;return}}function cbe(s){return s=s|0,357913941}function ube(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Abe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function BG(s){s=s|0,gbe(s)}function pbe(s){s=s|0,hbe(s+24|0)}function hbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function gbe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,1,l,dbe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dbe(){return 1224}function mbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;return d=C,C=C+16|0,m=d+8|0,B=d,k=ybe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],f=+Ebe(l,m,c),C=d,+f}function ybe(s){return s=s|0,(n[(RF()|0)+24>>2]|0)+(s*12|0)|0}function Ebe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,B=+gF(+C7[f&7](s,d)),C=m,+B}function Cbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],wbe(s,c,d,1),C=f}function wbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=TF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Ibe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,Bbe(m,f)|0,f),C=d}function TF(){var s=0,l=0;if(o[7712]|0||(DG(9556),ir(35,9556,U|0)|0,l=7712,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9556)|0)){s=9556,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));DG(9556)}return 9556}function Ibe(s){return s=s|0,0}function Bbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=TF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],vG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(vbe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function vG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function vbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Dbe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,Pbe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],vG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,Sbe(s,k),bbe(k),C=O;return}}function Dbe(s){return s=s|0,357913941}function Pbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Sbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function bbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function DG(s){s=s|0,Qbe(s)}function xbe(s){s=s|0,kbe(s+24|0)}function kbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function Qbe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,5,l,Fbe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Fbe(){return 1232}function Rbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=Tbe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=+Nbe(l,d),C=f,+c}function Tbe(s){return s=s|0,(n[(TF()|0)+24>>2]|0)+(s*12|0)|0}function Nbe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),+ +gF(+E7[c&15](s))}function Lbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Mbe(s,c,d,1),C=f}function Mbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=NF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Obe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,Ube(m,f)|0,f),C=d}function NF(){var s=0,l=0;if(o[7720]|0||(SG(9592),ir(36,9592,U|0)|0,l=7720,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9592)|0)){s=9592,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));SG(9592)}return 9592}function Obe(s){return s=s|0,0}function Ube(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=NF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],PG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(_be(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function PG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function _be(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Hbe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,qbe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],PG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,jbe(s,k),Gbe(k),C=O;return}}function Hbe(s){return s=s|0,357913941}function qbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function jbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Gbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function SG(s){s=s|0,Kbe(s)}function Ybe(s){s=s|0,Wbe(s+24|0)}function Wbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function Kbe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,7,l,Vbe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Vbe(){return 1276}function zbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=Jbe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=Xbe(l,f)|0,C=c,l|0}function Jbe(s){return s=s|0,(n[(NF()|0)+24>>2]|0)+(s*12|0)|0}function Xbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+16|0,f=d,c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),tf[c&31](f,s),f=bG(f)|0,C=d,f|0}function bG(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=yF(xG()|0)|0,f?(EF(l,f),CF(c,l),Zbe(s,c),s=wF(l)|0):s=$be(s)|0,C=d,s|0}function xG(){var s=0;return o[7736]|0||(cxe(9640),ir(25,9640,U|0)|0,s=7736,n[s>>2]=1,n[s+4>>2]=0),9640}function Zbe(s,l){s=s|0,l=l|0,nxe(l,s,s+8|0)|0}function $be(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Va(8)|0,l=f,k=Kt(16)|0,n[k>>2]=n[s>>2],n[k+4>>2]=n[s+4>>2],n[k+8>>2]=n[s+8>>2],n[k+12>>2]=n[s+12>>2],m=l+4|0,n[m>>2]=k,s=Kt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],LF(s,m,d),n[f>>2]=s,C=c,l|0}function LF(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Kt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1244,n[c+12>>2]=l,n[s+4>>2]=c}function exe(s){s=s|0,Md(s),gt(s)}function txe(s){s=s|0,s=n[s+12>>2]|0,s|0&>(s)}function rxe(s){s=s|0,gt(s)}function nxe(s,l,c){return s=s|0,l=l|0,c=c|0,l=ixe(n[s>>2]|0,l,c)|0,c=s+4|0,n[(n[c>>2]|0)+8>>2]=l,n[(n[c>>2]|0)+8>>2]|0}function ixe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;return f=C,C=C+16|0,d=f,za(d),s=ya(s)|0,c=sxe(s,n[l>>2]|0,+E[c>>3])|0,Ja(d),C=f,c|0}function sxe(s,l,c){s=s|0,l=l|0,c=+c;var f=0;return f=Pl(oxe()|0)|0,l=hF(l)|0,ml(0,f|0,s|0,l|0,+ +VA(c))|0}function oxe(){var s=0;return o[7728]|0||(axe(9628),s=7728,n[s>>2]=1,n[s+4>>2]=0),9628}function axe(s){s=s|0,Sl(s,lxe()|0,2)}function lxe(){return 1264}function cxe(s){s=s|0,wp(s)}function uxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Axe(s,c,d,1),C=f}function Axe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=MF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=fxe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,pxe(m,f)|0,f),C=d}function MF(){var s=0,l=0;if(o[7744]|0||(QG(9684),ir(37,9684,U|0)|0,l=7744,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9684)|0)){s=9684,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));QG(9684)}return 9684}function fxe(s){return s=s|0,0}function pxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=MF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],kG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(hxe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function kG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function hxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=gxe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,dxe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],kG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,mxe(s,k),yxe(k),C=O;return}}function gxe(s){return s=s|0,357913941}function dxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function mxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function yxe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function QG(s){s=s|0,wxe(s)}function Exe(s){s=s|0,Cxe(s+24|0)}function Cxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function wxe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,5,l,Ixe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Ixe(){return 1280}function Bxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=vxe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=Dxe(l,d,c)|0,C=f,c|0}function vxe(s){return s=s|0,(n[(MF()|0)+24>>2]|0)+(s*12|0)|0}function Dxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return B=C,C=C+32|0,d=B,m=B+16|0,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(m,c),m=ZA(m,c)|0,vw[f&15](d,s,m),m=bG(d)|0,C=B,m|0}function Pxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Sxe(s,c,d,1),C=f}function Sxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=OF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=bxe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,xxe(m,f)|0,f),C=d}function OF(){var s=0,l=0;if(o[7752]|0||(RG(9720),ir(38,9720,U|0)|0,l=7752,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9720)|0)){s=9720,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));RG(9720)}return 9720}function bxe(s){return s=s|0,0}function xxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=OF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],FG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(kxe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function FG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function kxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Qxe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,Fxe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],FG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,Rxe(s,k),Txe(k),C=O;return}}function Qxe(s){return s=s|0,357913941}function Fxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Rxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Txe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function RG(s){s=s|0,Mxe(s)}function Nxe(s){s=s|0,Lxe(s+24|0)}function Lxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function Mxe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,8,l,Oxe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Oxe(){return 1288}function Uxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=_xe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=Hxe(l,f)|0,C=c,l|0}function _xe(s){return s=s|0,(n[(OF()|0)+24>>2]|0)+(s*12|0)|0}function Hxe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),V5(F0[c&31](s)|0)|0}function qxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],jxe(s,c,d,0),C=f}function jxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=UF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Gxe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,Yxe(m,f)|0,f),C=d}function UF(){var s=0,l=0;if(o[7760]|0||(NG(9756),ir(39,9756,U|0)|0,l=7760,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9756)|0)){s=9756,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));NG(9756)}return 9756}function Gxe(s){return s=s|0,0}function Yxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=UF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],TG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Wxe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function TG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Wxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Kxe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,Vxe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],TG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,zxe(s,k),Jxe(k),C=O;return}}function Kxe(s){return s=s|0,357913941}function Vxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function zxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Jxe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function NG(s){s=s|0,$xe(s)}function Xxe(s){s=s|0,Zxe(s+24|0)}function Zxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function $xe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,8,l,eke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function eke(){return 1292}function tke(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=rke(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],nke(l,d,c),C=f}function rke(s){return s=s|0,(n[(UF()|0)+24>>2]|0)+(s*12|0)|0}function nke(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),Fu(d,c),c=+Ru(d,c),d7[f&31](s,c),C=m}function ike(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],ske(s,c,d,0),C=f}function ske(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=_F()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=oke(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,ake(m,f)|0,f),C=d}function _F(){var s=0,l=0;if(o[7768]|0||(MG(9792),ir(40,9792,U|0)|0,l=7768,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9792)|0)){s=9792,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));MG(9792)}return 9792}function oke(s){return s=s|0,0}function ake(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=_F()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],LG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(lke(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function LG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function lke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=cke(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,uke(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],LG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,Ake(s,k),fke(k),C=O;return}}function cke(s){return s=s|0,357913941}function uke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Ake(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function MG(s){s=s|0,gke(s)}function pke(s){s=s|0,hke(s+24|0)}function hke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function gke(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,1,l,dke()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dke(){return 1300}function mke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=yke(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],Eke(l,m,c,f),C=d}function yke(s){return s=s|0,(n[(_F()|0)+24>>2]|0)+(s*12|0)|0}function Eke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),XA(m,c),m=ZA(m,c)|0,Fu(B,f),f=+Ru(B,f),v7[d&15](s,m,f),C=k}function Cke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],wke(s,c,d,0),C=f}function wke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=HF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Ike(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,Bke(m,f)|0,f),C=d}function HF(){var s=0,l=0;if(o[7776]|0||(UG(9828),ir(41,9828,U|0)|0,l=7776,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9828)|0)){s=9828,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));UG(9828)}return 9828}function Ike(s){return s=s|0,0}function Bke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=HF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],OG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(vke(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function OG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function vke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Dke(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,Pke(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],OG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,Ske(s,k),bke(k),C=O;return}}function Dke(s){return s=s|0,357913941}function Pke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Ske(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function bke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function UG(s){s=s|0,Qke(s)}function xke(s){s=s|0,kke(s+24|0)}function kke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function Qke(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,7,l,Fke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Fke(){return 1312}function Rke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Tke(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Nke(l,d,c),C=f}function Tke(s){return s=s|0,(n[(HF()|0)+24>>2]|0)+(s*12|0)|0}function Nke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,tf[f&31](s,d),C=m}function Lke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Mke(s,c,d,0),C=f}function Mke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=qF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=Oke(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,Uke(m,f)|0,f),C=d}function qF(){var s=0,l=0;if(o[7784]|0||(HG(9864),ir(42,9864,U|0)|0,l=7784,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9864)|0)){s=9864,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));HG(9864)}return 9864}function Oke(s){return s=s|0,0}function Uke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=qF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],_G(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(_ke(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function _G(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function _ke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Hke(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,qke(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],_G(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,jke(s,k),Gke(k),C=O;return}}function Hke(s){return s=s|0,357913941}function qke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function jke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Gke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function HG(s){s=s|0,Kke(s)}function Yke(s){s=s|0,Wke(s+24|0)}function Wke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function Kke(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,8,l,Vke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Vke(){return 1320}function zke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Jke(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Xke(l,d,c),C=f}function Jke(s){return s=s|0,(n[(qF()|0)+24>>2]|0)+(s*12|0)|0}function Xke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),Zke(d,c),d=$ke(d,c)|0,tf[f&31](s,d),C=m}function Zke(s,l){s=s|0,l=l|0}function $ke(s,l){return s=s|0,l=l|0,eQe(l)|0}function eQe(s){return s=s|0,s|0}function tQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],rQe(s,c,d,0),C=f}function rQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=jF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=nQe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,iQe(m,f)|0,f),C=d}function jF(){var s=0,l=0;if(o[7792]|0||(jG(9900),ir(43,9900,U|0)|0,l=7792,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9900)|0)){s=9900,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));jG(9900)}return 9900}function nQe(s){return s=s|0,0}function iQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=jF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],qG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(sQe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function qG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function sQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=oQe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,aQe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],qG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,lQe(s,k),cQe(k),C=O;return}}function oQe(s){return s=s|0,357913941}function aQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function lQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function cQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function jG(s){s=s|0,fQe(s)}function uQe(s){s=s|0,AQe(s+24|0)}function AQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function fQe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,22,l,pQe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function pQe(){return 1344}function hQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;c=C,C=C+16|0,f=c+8|0,d=c,m=gQe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],dQe(l,f),C=c}function gQe(s){return s=s|0,(n[(jF()|0)+24>>2]|0)+(s*12|0)|0}function dQe(s,l){s=s|0,l=l|0;var c=0;c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),ef[c&127](s)}function mQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=GF()|0,s=yQe(c)|0,hn(m,l,d,s,EQe(c,f)|0,f)}function GF(){var s=0,l=0;if(o[7800]|0||(YG(9936),ir(44,9936,U|0)|0,l=7800,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9936)|0)){s=9936,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));YG(9936)}return 9936}function yQe(s){return s=s|0,s|0}function EQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=GF()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(GG(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(CQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function GG(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function CQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=wQe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,IQe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,GG(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,BQe(s,d),vQe(d),C=k;return}}function wQe(s){return s=s|0,536870911}function IQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function BQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function vQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function YG(s){s=s|0,SQe(s)}function DQe(s){s=s|0,PQe(s+24|0)}function PQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function SQe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,23,l,EG()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function bQe(s,l){s=s|0,l=l|0,kQe(n[(xQe(s)|0)>>2]|0,l)}function xQe(s){return s=s|0,(n[(GF()|0)+24>>2]|0)+(s<<3)|0}function kQe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,kF(f,l),l=QF(f,l)|0,ef[s&127](l),C=c}function QQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=YF()|0,s=FQe(c)|0,hn(m,l,d,s,RQe(c,f)|0,f)}function YF(){var s=0,l=0;if(o[7808]|0||(KG(9972),ir(45,9972,U|0)|0,l=7808,n[l>>2]=1,n[l+4>>2]=0),!(Rr(9972)|0)){s=9972,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));KG(9972)}return 9972}function FQe(s){return s=s|0,s|0}function RQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=YF()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(WG(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(TQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function WG(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function TQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=NQe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,LQe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,WG(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,MQe(s,d),OQe(d),C=k;return}}function NQe(s){return s=s|0,536870911}function LQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function MQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function OQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function KG(s){s=s|0,HQe(s)}function UQe(s){s=s|0,_Qe(s+24|0)}function _Qe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function HQe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,9,l,qQe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function qQe(){return 1348}function jQe(s,l){return s=s|0,l=l|0,YQe(n[(GQe(s)|0)>>2]|0,l)|0}function GQe(s){return s=s|0,(n[(YF()|0)+24>>2]|0)+(s<<3)|0}function YQe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,VG(f,l),l=zG(f,l)|0,l=qv(F0[s&31](l)|0)|0,C=c,l|0}function VG(s,l){s=s|0,l=l|0}function zG(s,l){return s=s|0,l=l|0,WQe(l)|0}function WQe(s){return s=s|0,s|0}function KQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=WF()|0,s=VQe(c)|0,hn(m,l,d,s,zQe(c,f)|0,f)}function WF(){var s=0,l=0;if(o[7816]|0||(XG(10008),ir(46,10008,U|0)|0,l=7816,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10008)|0)){s=10008,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));XG(10008)}return 10008}function VQe(s){return s=s|0,s|0}function zQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=WF()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(JG(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(JQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function JG(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function JQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=XQe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,ZQe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,JG(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,$Qe(s,d),eFe(d),C=k;return}}function XQe(s){return s=s|0,536870911}function ZQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function $Qe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function XG(s){s=s|0,nFe(s)}function tFe(s){s=s|0,rFe(s+24|0)}function rFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function nFe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,15,l,pG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function iFe(s){return s=s|0,oFe(n[(sFe(s)|0)>>2]|0)|0}function sFe(s){return s=s|0,(n[(WF()|0)+24>>2]|0)+(s<<3)|0}function oFe(s){return s=s|0,qv(nD[s&7]()|0)|0}function aFe(){var s=0;return o[7832]|0||(gFe(10052),ir(25,10052,U|0)|0,s=7832,n[s>>2]=1,n[s+4>>2]=0),10052}function lFe(s,l){s=s|0,l=l|0,n[s>>2]=cFe()|0,n[s+4>>2]=uFe()|0,n[s+12>>2]=l,n[s+8>>2]=AFe()|0,n[s+32>>2]=2}function cFe(){return 11709}function uFe(){return 1188}function AFe(){return Gv()|0}function fFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(pFe(c),gt(c)):l|0&&(bu(l),gt(l))}function Dp(s,l){return s=s|0,l=l|0,l&s|0}function pFe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function Gv(){var s=0;return o[7824]|0||(n[2511]=hFe()|0,n[2512]=0,s=7824,n[s>>2]=1,n[s+4>>2]=0),10044}function hFe(){return 0}function gFe(s){s=s|0,wp(s)}function dFe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0;l=C,C=C+32|0,c=l+24|0,m=l+16|0,d=l+8|0,f=l,mFe(s,4827),yFe(s,4834,3)|0,EFe(s,3682,47)|0,n[m>>2]=9,n[m+4>>2]=0,n[c>>2]=n[m>>2],n[c+4>>2]=n[m+4>>2],CFe(s,4841,c)|0,n[d>>2]=1,n[d+4>>2]=0,n[c>>2]=n[d>>2],n[c+4>>2]=n[d+4>>2],wFe(s,4871,c)|0,n[f>>2]=10,n[f+4>>2]=0,n[c>>2]=n[f>>2],n[c+4>>2]=n[f+4>>2],IFe(s,4891,c)|0,C=l}function mFe(s,l){s=s|0,l=l|0;var c=0;c=eTe()|0,n[s>>2]=c,tTe(c,l),Pp(n[s>>2]|0)}function yFe(s,l,c){return s=s|0,l=l|0,c=c|0,ORe(s,pn(l)|0,c,0),s|0}function EFe(s,l,c){return s=s|0,l=l|0,c=c|0,BRe(s,pn(l)|0,c,0),s|0}function CFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],iRe(s,l,d),C=f,s|0}function wFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],UFe(s,l,d),C=f,s|0}function IFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],BFe(s,l,d),C=f,s|0}function BFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vFe(s,c,d,1),C=f}function vFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=KF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=DFe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,PFe(m,f)|0,f),C=d}function KF(){var s=0,l=0;if(o[7840]|0||($G(10100),ir(48,10100,U|0)|0,l=7840,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10100)|0)){s=10100,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));$G(10100)}return 10100}function DFe(s){return s=s|0,0}function PFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=KF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],ZG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(SFe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function ZG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function SFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=bFe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,xFe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],ZG(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,kFe(s,k),QFe(k),C=O;return}}function bFe(s){return s=s|0,357913941}function xFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function kFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function QFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function $G(s){s=s|0,TFe(s)}function FFe(s){s=s|0,RFe(s+24|0)}function RFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function TFe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,6,l,NFe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function NFe(){return 1364}function LFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=MFe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=OFe(l,d,c)|0,C=f,c|0}function MFe(s){return s=s|0,(n[(KF()|0)+24>>2]|0)+(s*12|0)|0}function OFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,d=oG(IR[f&15](s,d)|0)|0,C=m,d|0}function UFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],_Fe(s,c,d,0),C=f}function _Fe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=VF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=HFe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,qFe(m,f)|0,f),C=d}function VF(){var s=0,l=0;if(o[7848]|0||(t9(10136),ir(49,10136,U|0)|0,l=7848,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10136)|0)){s=10136,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));t9(10136)}return 10136}function HFe(s){return s=s|0,0}function qFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=VF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],e9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(jFe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function e9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function jFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=GFe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,YFe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],e9(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,WFe(s,k),KFe(k),C=O;return}}function GFe(s){return s=s|0,357913941}function YFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function WFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function KFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function t9(s){s=s|0,JFe(s)}function VFe(s){s=s|0,zFe(s+24|0)}function zFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function JFe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,9,l,XFe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function XFe(){return 1372}function ZFe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=$Fe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],eRe(l,d,c),C=f}function $Fe(s){return s=s|0,(n[(VF()|0)+24>>2]|0)+(s*12|0)|0}function eRe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=Xe;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),tRe(d,c),B=y(rRe(d,c)),g7[f&1](s,B),C=m}function tRe(s,l){s=s|0,l=+l}function rRe(s,l){return s=s|0,l=+l,y(nRe(l))}function nRe(s){return s=+s,y(s)}function iRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=pn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],sRe(s,c,d,0),C=f}function sRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,Q=0,O=0,M=0;d=C,C=C+32|0,m=d+16|0,M=d+8|0,k=d,O=n[c>>2]|0,Q=n[c+4>>2]|0,B=n[s>>2]|0,s=zF()|0,n[M>>2]=O,n[M+4>>2]=Q,n[m>>2]=n[M>>2],n[m+4>>2]=n[M+4>>2],c=oRe(m)|0,n[k>>2]=O,n[k+4>>2]=Q,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],hn(B,l,s,c,aRe(m,f)|0,f),C=d}function zF(){var s=0,l=0;if(o[7856]|0||(n9(10172),ir(50,10172,U|0)|0,l=7856,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10172)|0)){s=10172,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));n9(10172)}return 10172}function oRe(s){return s=s|0,0}function aRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0;return M=C,C=C+32|0,d=M+24|0,B=M+16|0,k=M,Q=M+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=zF()|0,O=j+24|0,s=gr(l,4)|0,n[Q>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],r9(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(lRe(O,k,Q),s=n[l>>2]|0),C=M,((s-(n[O>>2]|0)|0)/12|0)+-1|0}function r9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function lRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;if(O=C,C=C+48|0,f=O+32|0,B=O+24|0,k=O,Q=s+4|0,d=(((n[Q>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=cRe(s)|0,m>>>0<d>>>0)Jr(s);else{M=n[s>>2]|0,se=((n[s+8>>2]|0)-M|0)/12|0,j=se<<1,uRe(k,se>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[Q>>2]|0)-M|0)/12|0,s+8|0),Q=k+8|0,m=n[Q>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],r9(m,f,c),n[Q>>2]=(n[Q>>2]|0)+12,ARe(s,k),fRe(k),C=O;return}}function cRe(s){return s=s|0,357913941}function uRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Kt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function ARe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&>(s)}function n9(s){s=s|0,gRe(s)}function pRe(s){s=s|0,hRe(s+24|0)}function hRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),gt(c))}function gRe(s){s=s|0;var l=0;l=Vr()|0,zr(s,2,3,l,dRe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dRe(){return 1380}function mRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=yRe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],ERe(l,m,c,f),C=d}function yRe(s){return s=s|0,(n[(zF()|0)+24>>2]|0)+(s*12|0)|0}function ERe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),XA(m,c),m=ZA(m,c)|0,CRe(B,f),B=wRe(B,f)|0,vw[d&15](s,m,B),C=k}function CRe(s,l){s=s|0,l=l|0}function wRe(s,l){return s=s|0,l=l|0,IRe(l)|0}function IRe(s){return s=s|0,(s|0)!=0|0}function BRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=JF()|0,s=vRe(c)|0,hn(m,l,d,s,DRe(c,f)|0,f)}function JF(){var s=0,l=0;if(o[7864]|0||(s9(10208),ir(51,10208,U|0)|0,l=7864,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10208)|0)){s=10208,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));s9(10208)}return 10208}function vRe(s){return s=s|0,s|0}function DRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=JF()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(i9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(PRe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function i9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function PRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=SRe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,bRe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,i9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,xRe(s,d),kRe(d),C=k;return}}function SRe(s){return s=s|0,536870911}function bRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function xRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function kRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function s9(s){s=s|0,RRe(s)}function QRe(s){s=s|0,FRe(s+24|0)}function FRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function RRe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,24,l,TRe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function TRe(){return 1392}function NRe(s,l){s=s|0,l=l|0,MRe(n[(LRe(s)|0)>>2]|0,l)}function LRe(s){return s=s|0,(n[(JF()|0)+24>>2]|0)+(s<<3)|0}function MRe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,VG(f,l),l=zG(f,l)|0,ef[s&127](l),C=c}function ORe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=XF()|0,s=URe(c)|0,hn(m,l,d,s,_Re(c,f)|0,f)}function XF(){var s=0,l=0;if(o[7872]|0||(a9(10244),ir(52,10244,U|0)|0,l=7872,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10244)|0)){s=10244,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));a9(10244)}return 10244}function URe(s){return s=s|0,s|0}function _Re(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=XF()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(o9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(HRe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function o9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function HRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=qRe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,jRe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,o9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,GRe(s,d),YRe(d),C=k;return}}function qRe(s){return s=s|0,536870911}function jRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function GRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function YRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function a9(s){s=s|0,VRe(s)}function WRe(s){s=s|0,KRe(s+24|0)}function KRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function VRe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,16,l,zRe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function zRe(){return 1400}function JRe(s){return s=s|0,ZRe(n[(XRe(s)|0)>>2]|0)|0}function XRe(s){return s=s|0,(n[(XF()|0)+24>>2]|0)+(s<<3)|0}function ZRe(s){return s=s|0,$Re(nD[s&7]()|0)|0}function $Re(s){return s=s|0,s|0}function eTe(){var s=0;return o[7880]|0||(aTe(10280),ir(25,10280,U|0)|0,s=7880,n[s>>2]=1,n[s+4>>2]=0),10280}function tTe(s,l){s=s|0,l=l|0,n[s>>2]=rTe()|0,n[s+4>>2]=nTe()|0,n[s+12>>2]=l,n[s+8>>2]=iTe()|0,n[s+32>>2]=4}function rTe(){return 11711}function nTe(){return 1356}function iTe(){return Gv()|0}function sTe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(oTe(c),gt(c)):l|0&&(w0(l),gt(l))}function oTe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function aTe(s){s=s|0,wp(s)}function lTe(s){s=s|0,cTe(s,4920),uTe(s)|0,ATe(s)|0}function cTe(s,l){s=s|0,l=l|0;var c=0;c=xG()|0,n[s>>2]=c,FTe(c,l),Pp(n[s>>2]|0)}function uTe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,ITe()|0),s|0}function ATe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,fTe()|0),s|0}function fTe(){var s=0;return o[7888]|0||(l9(10328),ir(53,10328,U|0)|0,s=7888,n[s>>2]=1,n[s+4>>2]=0),Rr(10328)|0||l9(10328),10328}function P0(s,l){s=s|0,l=l|0,hn(s,0,l,0,0,0)}function l9(s){s=s|0,gTe(s),S0(s,10)}function pTe(s){s=s|0,hTe(s+24|0)}function hTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function gTe(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,1,l,ETe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dTe(s,l,c){s=s|0,l=l|0,c=+c,mTe(s,l,c)}function S0(s,l){s=s|0,l=l|0,n[s+20>>2]=l}function mTe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,m=f+8|0,k=f+13|0,d=f,B=f+12|0,XA(k,l),n[m>>2]=ZA(k,l)|0,Fu(B,c),E[d>>3]=+Ru(B,c),yTe(s,m,d),C=f}function yTe(s,l,c){s=s|0,l=l|0,c=c|0,W(s+8|0,n[l>>2]|0,+E[c>>3]),o[s+24>>0]=1}function ETe(){return 1404}function CTe(s,l){return s=s|0,l=+l,wTe(s,l)|0}function wTe(s,l){s=s|0,l=+l;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return f=C,C=C+16|0,m=f+4|0,B=f+8|0,k=f,d=Va(8)|0,c=d,Q=Kt(16)|0,XA(m,s),s=ZA(m,s)|0,Fu(B,l),W(Q,s,+Ru(B,l)),B=c+4|0,n[B>>2]=Q,s=Kt(8)|0,B=n[B>>2]|0,n[k>>2]=0,n[m>>2]=n[k>>2],LF(s,B,m),n[d>>2]=s,C=f,c|0}function ITe(){var s=0;return o[7896]|0||(c9(10364),ir(54,10364,U|0)|0,s=7896,n[s>>2]=1,n[s+4>>2]=0),Rr(10364)|0||c9(10364),10364}function c9(s){s=s|0,DTe(s),S0(s,55)}function BTe(s){s=s|0,vTe(s+24|0)}function vTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function DTe(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,4,l,xTe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function PTe(s){s=s|0,STe(s)}function STe(s){s=s|0,bTe(s)}function bTe(s){s=s|0,u9(s+8|0),o[s+24>>0]=1}function u9(s){s=s|0,n[s>>2]=0,E[s+8>>3]=0}function xTe(){return 1424}function kTe(){return QTe()|0}function QTe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Va(8)|0,s=c,f=Kt(16)|0,u9(f),m=s+4|0,n[m>>2]=f,f=Kt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],LF(f,m,d),n[c>>2]=f,C=l,s|0}function FTe(s,l){s=s|0,l=l|0,n[s>>2]=RTe()|0,n[s+4>>2]=TTe()|0,n[s+12>>2]=l,n[s+8>>2]=NTe()|0,n[s+32>>2]=5}function RTe(){return 11710}function TTe(){return 1416}function NTe(){return Yv()|0}function LTe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(MTe(c),gt(c)):l|0&>(l)}function MTe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function Yv(){var s=0;return o[7904]|0||(n[2600]=OTe()|0,n[2601]=0,s=7904,n[s>>2]=1,n[s+4>>2]=0),10400}function OTe(){return n[357]|0}function UTe(s){s=s|0,_Te(s,4926),HTe(s)|0}function _Te(s,l){s=s|0,l=l|0;var c=0;c=Z5()|0,n[s>>2]=c,ZTe(c,l),Pp(n[s>>2]|0)}function HTe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,qTe()|0),s|0}function qTe(){var s=0;return o[7912]|0||(A9(10412),ir(56,10412,U|0)|0,s=7912,n[s>>2]=1,n[s+4>>2]=0),Rr(10412)|0||A9(10412),10412}function A9(s){s=s|0,YTe(s),S0(s,57)}function jTe(s){s=s|0,GTe(s+24|0)}function GTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function YTe(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,5,l,zTe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function WTe(s){s=s|0,KTe(s)}function KTe(s){s=s|0,VTe(s)}function VTe(s){s=s|0;var l=0,c=0;l=s+8|0,c=l+48|0;do n[l>>2]=0,l=l+4|0;while((l|0)<(c|0));o[s+56>>0]=1}function zTe(){return 1432}function JTe(){return XTe()|0}function XTe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0,k=0;B=C,C=C+16|0,s=B+4|0,l=B,c=Va(8)|0,f=c,d=Kt(48)|0,m=d,k=m+48|0;do n[m>>2]=0,m=m+4|0;while((m|0)<(k|0));return m=f+4|0,n[m>>2]=d,k=Kt(8)|0,m=n[m>>2]|0,n[l>>2]=0,n[s>>2]=n[l>>2],$5(k,m,s),n[c>>2]=k,C=B,f|0}function ZTe(s,l){s=s|0,l=l|0,n[s>>2]=$Te()|0,n[s+4>>2]=eNe()|0,n[s+12>>2]=l,n[s+8>>2]=tNe()|0,n[s+32>>2]=6}function $Te(){return 11704}function eNe(){return 1436}function tNe(){return Yv()|0}function rNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(nNe(c),gt(c)):l|0&>(l)}function nNe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function iNe(s){s=s|0,sNe(s,4933),oNe(s)|0,aNe(s)|0}function sNe(s,l){s=s|0,l=l|0;var c=0;c=QNe()|0,n[s>>2]=c,FNe(c,l),Pp(n[s>>2]|0)}function oNe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,wNe()|0),s|0}function aNe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,lNe()|0),s|0}function lNe(){var s=0;return o[7920]|0||(f9(10452),ir(58,10452,U|0)|0,s=7920,n[s>>2]=1,n[s+4>>2]=0),Rr(10452)|0||f9(10452),10452}function f9(s){s=s|0,ANe(s),S0(s,1)}function cNe(s){s=s|0,uNe(s+24|0)}function uNe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function ANe(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,1,l,gNe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function fNe(s,l,c){s=s|0,l=+l,c=+c,pNe(s,l,c)}function pNe(s,l,c){s=s|0,l=+l,c=+c;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,m=f+8|0,k=f+17|0,d=f,B=f+16|0,Fu(k,l),E[m>>3]=+Ru(k,l),Fu(B,c),E[d>>3]=+Ru(B,c),hNe(s,m,d),C=f}function hNe(s,l,c){s=s|0,l=l|0,c=c|0,p9(s+8|0,+E[l>>3],+E[c>>3]),o[s+24>>0]=1}function p9(s,l,c){s=s|0,l=+l,c=+c,E[s>>3]=l,E[s+8>>3]=c}function gNe(){return 1472}function dNe(s,l){return s=+s,l=+l,mNe(s,l)|0}function mNe(s,l){s=+s,l=+l;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return f=C,C=C+16|0,B=f+4|0,k=f+8|0,Q=f,d=Va(8)|0,c=d,m=Kt(16)|0,Fu(B,s),s=+Ru(B,s),Fu(k,l),p9(m,s,+Ru(k,l)),k=c+4|0,n[k>>2]=m,m=Kt(8)|0,k=n[k>>2]|0,n[Q>>2]=0,n[B>>2]=n[Q>>2],h9(m,k,B),n[d>>2]=m,C=f,c|0}function h9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Kt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1452,n[c+12>>2]=l,n[s+4>>2]=c}function yNe(s){s=s|0,Md(s),gt(s)}function ENe(s){s=s|0,s=n[s+12>>2]|0,s|0&>(s)}function CNe(s){s=s|0,gt(s)}function wNe(){var s=0;return o[7928]|0||(g9(10488),ir(59,10488,U|0)|0,s=7928,n[s>>2]=1,n[s+4>>2]=0),Rr(10488)|0||g9(10488),10488}function g9(s){s=s|0,vNe(s),S0(s,60)}function INe(s){s=s|0,BNe(s+24|0)}function BNe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function vNe(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,6,l,bNe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function DNe(s){s=s|0,PNe(s)}function PNe(s){s=s|0,SNe(s)}function SNe(s){s=s|0,d9(s+8|0),o[s+24>>0]=1}function d9(s){s=s|0,n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,n[s+12>>2]=0}function bNe(){return 1492}function xNe(){return kNe()|0}function kNe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Va(8)|0,s=c,f=Kt(16)|0,d9(f),m=s+4|0,n[m>>2]=f,f=Kt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],h9(f,m,d),n[c>>2]=f,C=l,s|0}function QNe(){var s=0;return o[7936]|0||(ONe(10524),ir(25,10524,U|0)|0,s=7936,n[s>>2]=1,n[s+4>>2]=0),10524}function FNe(s,l){s=s|0,l=l|0,n[s>>2]=RNe()|0,n[s+4>>2]=TNe()|0,n[s+12>>2]=l,n[s+8>>2]=NNe()|0,n[s+32>>2]=7}function RNe(){return 11700}function TNe(){return 1484}function NNe(){return Yv()|0}function LNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(MNe(c),gt(c)):l|0&>(l)}function MNe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function ONe(s){s=s|0,wp(s)}function UNe(s,l,c){s=s|0,l=l|0,c=c|0,s=pn(l)|0,l=_Ne(c)|0,c=HNe(c,0)|0,mLe(s,l,c,ZF()|0,0)}function _Ne(s){return s=s|0,s|0}function HNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=ZF()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(y9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(VNe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function ZF(){var s=0,l=0;if(o[7944]|0||(m9(10568),ir(61,10568,U|0)|0,l=7944,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10568)|0)){s=10568,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));m9(10568)}return 10568}function m9(s){s=s|0,GNe(s)}function qNe(s){s=s|0,jNe(s+24|0)}function jNe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function GNe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,17,l,dG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function YNe(s){return s=s|0,KNe(n[(WNe(s)|0)>>2]|0)|0}function WNe(s){return s=s|0,(n[(ZF()|0)+24>>2]|0)+(s<<3)|0}function KNe(s){return s=s|0,jv(nD[s&7]()|0)|0}function y9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function VNe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=zNe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,JNe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,y9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,XNe(s,d),ZNe(d),C=k;return}}function zNe(s){return s=s|0,536870911}function JNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function XNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function ZNe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function $Ne(){eLe()}function eLe(){tLe(10604)}function tLe(s){s=s|0,rLe(s,4955)}function rLe(s,l){s=s|0,l=l|0;var c=0;c=nLe()|0,n[s>>2]=c,iLe(c,l),Pp(n[s>>2]|0)}function nLe(){var s=0;return o[7952]|0||(pLe(10612),ir(25,10612,U|0)|0,s=7952,n[s>>2]=1,n[s+4>>2]=0),10612}function iLe(s,l){s=s|0,l=l|0,n[s>>2]=lLe()|0,n[s+4>>2]=cLe()|0,n[s+12>>2]=l,n[s+8>>2]=uLe()|0,n[s+32>>2]=8}function Pp(s){s=s|0;var l=0,c=0;l=C,C=C+16|0,c=l,Fd()|0,n[c>>2]=s,sLe(10608,c),C=l}function Fd(){return o[11714]|0||(n[2652]=0,ir(62,10608,U|0)|0,o[11714]=1),10608}function sLe(s,l){s=s|0,l=l|0;var c=0;c=Kt(8)|0,n[c+4>>2]=n[l>>2],n[c>>2]=n[s>>2],n[s>>2]=c}function oLe(s){s=s|0,aLe(s)}function aLe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,gt(c);while(l|0);n[s>>2]=0}function lLe(){return 11715}function cLe(){return 1496}function uLe(){return Gv()|0}function ALe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(fLe(c),gt(c)):l|0&>(l)}function fLe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function pLe(s){s=s|0,wp(s)}function hLe(s,l){s=s|0,l=l|0;var c=0,f=0;Fd()|0,c=n[2652]|0;e:do if(c|0){for(;f=n[c+4>>2]|0,!(f|0&&!($9($F(f)|0,s)|0));)if(c=n[c>>2]|0,!c)break e;gLe(f,l)}while(!1)}function $F(s){return s=s|0,n[s+12>>2]|0}function gLe(s,l){s=s|0,l=l|0;var c=0;s=s+36|0,c=n[s>>2]|0,c|0&&(qA(c),gt(c)),c=Kt(4)|0,W5(c,l),n[s>>2]=c}function eR(){return o[11716]|0||(n[2664]=0,ir(63,10656,U|0)|0,o[11716]=1),10656}function E9(){var s=0;return o[11717]|0?s=n[2665]|0:(dLe(),n[2665]=1504,o[11717]=1,s=1504),s|0}function dLe(){o[11740]|0||(o[11718]=gr(gr(8,0)|0,0)|0,o[11719]=gr(gr(0,0)|0,0)|0,o[11720]=gr(gr(0,16)|0,0)|0,o[11721]=gr(gr(8,0)|0,0)|0,o[11722]=gr(gr(0,0)|0,0)|0,o[11723]=gr(gr(8,0)|0,0)|0,o[11724]=gr(gr(0,0)|0,0)|0,o[11725]=gr(gr(8,0)|0,0)|0,o[11726]=gr(gr(0,0)|0,0)|0,o[11727]=gr(gr(8,0)|0,0)|0,o[11728]=gr(gr(0,0)|0,0)|0,o[11729]=gr(gr(0,0)|0,32)|0,o[11730]=gr(gr(0,0)|0,32)|0,o[11740]=1)}function C9(){return 1572}function mLe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0,O=0,M=0;m=C,C=C+32|0,M=m+16|0,O=m+12|0,Q=m+8|0,k=m+4|0,B=m,n[M>>2]=s,n[O>>2]=l,n[Q>>2]=c,n[k>>2]=f,n[B>>2]=d,eR()|0,yLe(10656,M,O,Q,k,B),C=m}function yLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0;B=Kt(24)|0,z5(B+4|0,n[l>>2]|0,n[c>>2]|0,n[f>>2]|0,n[d>>2]|0,n[m>>2]|0),n[B>>2]=n[s>>2],n[s>>2]=B}function w9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0,$e=0,Je=0,lt=0;if(lt=C,C=C+32|0,Oe=lt+20|0,Qe=lt+8|0,$e=lt+4|0,Je=lt,l=n[l>>2]|0,l|0){je=Oe+4|0,Q=Oe+8|0,O=Qe+4|0,M=Qe+8|0,j=Qe+8|0,se=Oe+8|0;do{if(B=l+4|0,k=tR(B)|0,k|0){if(d=yw(k)|0,n[Oe>>2]=0,n[je>>2]=0,n[Q>>2]=0,f=(Ew(k)|0)+1|0,ELe(Oe,f),f|0)for(;f=f+-1|0,xc(Qe,n[d>>2]|0),m=n[je>>2]|0,m>>>0<(n[se>>2]|0)>>>0?(n[m>>2]=n[Qe>>2],n[je>>2]=(n[je>>2]|0)+4):rR(Oe,Qe),f;)d=d+4|0;f=Cw(k)|0,n[Qe>>2]=0,n[O>>2]=0,n[M>>2]=0;e:do if(n[f>>2]|0)for(d=0,m=0;;){if((d|0)==(m|0)?CLe(Qe,f):(n[d>>2]=n[f>>2],n[O>>2]=(n[O>>2]|0)+4),f=f+4|0,!(n[f>>2]|0))break e;d=n[O>>2]|0,m=n[j>>2]|0}while(!1);n[$e>>2]=Wv(B)|0,n[Je>>2]=Rr(k)|0,wLe(c,s,$e,Je,Oe,Qe),nR(Qe),$A(Oe)}l=n[l>>2]|0}while(l|0)}C=lt}function tR(s){return s=s|0,n[s+12>>2]|0}function yw(s){return s=s|0,n[s+12>>2]|0}function Ew(s){return s=s|0,n[s+16>>2]|0}function ELe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+32|0,c=d,f=n[s>>2]|0,(n[s+8>>2]|0)-f>>2>>>0<l>>>0&&(x9(c,l,(n[s+4>>2]|0)-f>>2,s+8|0),k9(s,c),Q9(c)),C=d}function rR(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0;if(B=C,C=C+32|0,c=B,f=s+4|0,d=((n[f>>2]|0)-(n[s>>2]|0)>>2)+1|0,m=b9(s)|0,m>>>0<d>>>0)Jr(s);else{k=n[s>>2]|0,O=(n[s+8>>2]|0)-k|0,Q=O>>1,x9(c,O>>2>>>0<m>>>1>>>0?Q>>>0<d>>>0?d:Q:m,(n[f>>2]|0)-k>>2,s+8|0),m=c+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,k9(s,c),Q9(c),C=B;return}}function Cw(s){return s=s|0,n[s+8>>2]|0}function CLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0;if(B=C,C=C+32|0,c=B,f=s+4|0,d=((n[f>>2]|0)-(n[s>>2]|0)>>2)+1|0,m=S9(s)|0,m>>>0<d>>>0)Jr(s);else{k=n[s>>2]|0,O=(n[s+8>>2]|0)-k|0,Q=O>>1,_Le(c,O>>2>>>0<m>>>1>>>0?Q>>>0<d>>>0?d:Q:m,(n[f>>2]|0)-k>>2,s+8|0),m=c+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,HLe(s,c),qLe(c),C=B;return}}function Wv(s){return s=s|0,n[s>>2]|0}function wLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,ILe(s,l,c,f,d,m)}function nR(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),gt(c))}function $A(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),gt(c))}function ILe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,Q=0,O=0,M=0,j=0;B=C,C=C+48|0,M=B+40|0,k=B+32|0,j=B+24|0,Q=B+12|0,O=B,za(k),s=ya(s)|0,n[j>>2]=n[l>>2],c=n[c>>2]|0,f=n[f>>2]|0,iR(Q,d),BLe(O,m),n[M>>2]=n[j>>2],vLe(s,M,c,f,Q,O),nR(O),$A(Q),Ja(k),C=B}function iR(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(OLe(s,f),ULe(s,n[l>>2]|0,n[c>>2]|0,f))}function BLe(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(LLe(s,f),MLe(s,n[l>>2]|0,n[c>>2]|0,f))}function vLe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,Q=0,O=0,M=0,j=0;B=C,C=C+32|0,M=B+28|0,j=B+24|0,k=B+12|0,Q=B,O=Pl(DLe()|0)|0,n[j>>2]=n[l>>2],n[M>>2]=n[j>>2],l=b0(M)|0,c=I9(c)|0,f=sR(f)|0,n[k>>2]=n[d>>2],M=d+4|0,n[k+4>>2]=n[M>>2],j=d+8|0,n[k+8>>2]=n[j>>2],n[j>>2]=0,n[M>>2]=0,n[d>>2]=0,d=oR(k)|0,n[Q>>2]=n[m>>2],M=m+4|0,n[Q+4>>2]=n[M>>2],j=m+8|0,n[Q+8>>2]=n[j>>2],n[j>>2]=0,n[M>>2]=0,n[m>>2]=0,ao(0,O|0,s|0,l|0,c|0,f|0,d|0,PLe(Q)|0)|0,nR(Q),$A(k),C=B}function DLe(){var s=0;return o[7968]|0||(TLe(10708),s=7968,n[s>>2]=1,n[s+4>>2]=0),10708}function b0(s){return s=s|0,v9(s)|0}function I9(s){return s=s|0,B9(s)|0}function sR(s){return s=s|0,jv(s)|0}function oR(s){return s=s|0,bLe(s)|0}function PLe(s){return s=s|0,SLe(s)|0}function SLe(s){s=s|0;var l=0,c=0,f=0;if(f=(n[s+4>>2]|0)-(n[s>>2]|0)|0,c=f>>2,f=Va(f+4|0)|0,n[f>>2]=c,c|0){l=0;do n[f+4+(l<<2)>>2]=B9(n[(n[s>>2]|0)+(l<<2)>>2]|0)|0,l=l+1|0;while((l|0)!=(c|0))}return f|0}function B9(s){return s=s|0,s|0}function bLe(s){s=s|0;var l=0,c=0,f=0;if(f=(n[s+4>>2]|0)-(n[s>>2]|0)|0,c=f>>2,f=Va(f+4|0)|0,n[f>>2]=c,c|0){l=0;do n[f+4+(l<<2)>>2]=v9((n[s>>2]|0)+(l<<2)|0)|0,l=l+1|0;while((l|0)!=(c|0))}return f|0}function v9(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=yF(D9()|0)|0,f?(EF(l,f),CF(c,l),uUe(s,c),s=wF(l)|0):s=xLe(s)|0,C=d,s|0}function D9(){var s=0;return o[7960]|0||(RLe(10664),ir(25,10664,U|0)|0,s=7960,n[s>>2]=1,n[s+4>>2]=0),10664}function xLe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Va(8)|0,l=f,k=Kt(4)|0,n[k>>2]=n[s>>2],m=l+4|0,n[m>>2]=k,s=Kt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],P9(s,m,d),n[f>>2]=s,C=c,l|0}function P9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Kt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1656,n[c+12>>2]=l,n[s+4>>2]=c}function kLe(s){s=s|0,Md(s),gt(s)}function QLe(s){s=s|0,s=n[s+12>>2]|0,s|0&>(s)}function FLe(s){s=s|0,gt(s)}function RLe(s){s=s|0,wp(s)}function TLe(s){s=s|0,Sl(s,NLe()|0,5)}function NLe(){return 1676}function LLe(s,l){s=s|0,l=l|0;var c=0;if((S9(s)|0)>>>0<l>>>0&&Jr(s),l>>>0>1073741823)Tt();else{c=Kt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function MLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(Dr(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function S9(s){return s=s|0,1073741823}function OLe(s,l){s=s|0,l=l|0;var c=0;if((b9(s)|0)>>>0<l>>>0&&Jr(s),l>>>0>1073741823)Tt();else{c=Kt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function ULe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(Dr(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function b9(s){return s=s|0,1073741823}function _Le(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Kt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function HLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function qLe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&>(s)}function x9(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Kt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function k9(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Q9(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&>(s)}function jLe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0;if(Qe=C,C=C+32|0,M=Qe+20|0,j=Qe+12|0,O=Qe+16|0,se=Qe+4|0,je=Qe,Oe=Qe+8|0,k=E9()|0,m=n[k>>2]|0,B=n[m>>2]|0,B|0)for(Q=n[k+8>>2]|0,k=n[k+4>>2]|0;xc(M,B),GLe(s,M,k,Q),m=m+4|0,B=n[m>>2]|0,B;)Q=Q+1|0,k=k+1|0;if(m=C9()|0,B=n[m>>2]|0,B|0)do xc(M,B),n[j>>2]=n[m+4>>2],YLe(l,M,j),m=m+8|0,B=n[m>>2]|0;while(B|0);if(m=n[(Fd()|0)>>2]|0,m|0)do l=n[m+4>>2]|0,xc(M,n[(Rd(l)|0)>>2]|0),n[j>>2]=$F(l)|0,WLe(c,M,j),m=n[m>>2]|0;while(m|0);if(xc(O,0),m=eR()|0,n[M>>2]=n[O>>2],w9(M,m,d),m=n[(Fd()|0)>>2]|0,m|0){s=M+4|0,l=M+8|0,c=M+8|0;do{if(Q=n[m+4>>2]|0,xc(j,n[(Rd(Q)|0)>>2]|0),KLe(se,F9(Q)|0),B=n[se>>2]|0,B|0){n[M>>2]=0,n[s>>2]=0,n[l>>2]=0;do xc(je,n[(Rd(n[B+4>>2]|0)|0)>>2]|0),k=n[s>>2]|0,k>>>0<(n[c>>2]|0)>>>0?(n[k>>2]=n[je>>2],n[s>>2]=(n[s>>2]|0)+4):rR(M,je),B=n[B>>2]|0;while(B|0);VLe(f,j,M),$A(M)}n[Oe>>2]=n[j>>2],O=R9(Q)|0,n[M>>2]=n[Oe>>2],w9(M,O,d),tG(se),m=n[m>>2]|0}while(m|0)}C=Qe}function GLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,oMe(s,l,c,f)}function YLe(s,l,c){s=s|0,l=l|0,c=c|0,sMe(s,l,c)}function Rd(s){return s=s|0,s|0}function WLe(s,l,c){s=s|0,l=l|0,c=c|0,tMe(s,l,c)}function F9(s){return s=s|0,s+16|0}function KLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;if(m=C,C=C+16|0,d=m+8|0,c=m,n[s>>2]=0,f=n[l>>2]|0,n[d>>2]=f,n[c>>2]=s,c=eMe(c)|0,f|0){if(f=Kt(12)|0,B=(T9(d)|0)+4|0,s=n[B+4>>2]|0,l=f+4|0,n[l>>2]=n[B>>2],n[l+4>>2]=s,l=n[n[d>>2]>>2]|0,n[d>>2]=l,!l)s=f;else for(l=f;s=Kt(12)|0,Q=(T9(d)|0)+4|0,k=n[Q+4>>2]|0,B=s+4|0,n[B>>2]=n[Q>>2],n[B+4>>2]=k,n[l>>2]=s,B=n[n[d>>2]>>2]|0,n[d>>2]=B,B;)l=s;n[s>>2]=n[c>>2],n[c>>2]=f}C=m}function VLe(s,l,c){s=s|0,l=l|0,c=c|0,zLe(s,l,c)}function R9(s){return s=s|0,s+24|0}function zLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,B=f+24|0,d=f+16|0,k=f+12|0,m=f,za(d),s=ya(s)|0,n[k>>2]=n[l>>2],iR(m,c),n[B>>2]=n[k>>2],JLe(s,B,m),$A(m),Ja(d),C=f}function JLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,B=f+16|0,k=f+12|0,d=f,m=Pl(XLe()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=b0(B)|0,n[d>>2]=n[c>>2],B=c+4|0,n[d+4>>2]=n[B>>2],k=c+8|0,n[d+8>>2]=n[k>>2],n[k>>2]=0,n[B>>2]=0,n[c>>2]=0,oo(0,m|0,s|0,l|0,oR(d)|0)|0,$A(d),C=f}function XLe(){var s=0;return o[7976]|0||(ZLe(10720),s=7976,n[s>>2]=1,n[s+4>>2]=0),10720}function ZLe(s){s=s|0,Sl(s,$Le()|0,2)}function $Le(){return 1732}function eMe(s){return s=s|0,n[s>>2]|0}function T9(s){return s=s|0,n[s>>2]|0}function tMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+32|0,m=f+16|0,d=f+8|0,B=f,za(d),s=ya(s)|0,n[B>>2]=n[l>>2],c=n[c>>2]|0,n[m>>2]=n[B>>2],N9(s,m,c),Ja(d),C=f}function N9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,m=f+4|0,B=f,d=Pl(rMe()|0)|0,n[B>>2]=n[l>>2],n[m>>2]=n[B>>2],l=b0(m)|0,oo(0,d|0,s|0,l|0,I9(c)|0)|0,C=f}function rMe(){var s=0;return o[7984]|0||(nMe(10732),s=7984,n[s>>2]=1,n[s+4>>2]=0),10732}function nMe(s){s=s|0,Sl(s,iMe()|0,2)}function iMe(){return 1744}function sMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+32|0,m=f+16|0,d=f+8|0,B=f,za(d),s=ya(s)|0,n[B>>2]=n[l>>2],c=n[c>>2]|0,n[m>>2]=n[B>>2],N9(s,m,c),Ja(d),C=f}function oMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+32|0,B=d+16|0,m=d+8|0,k=d,za(m),s=ya(s)|0,n[k>>2]=n[l>>2],c=o[c>>0]|0,f=o[f>>0]|0,n[B>>2]=n[k>>2],aMe(s,B,c,f),Ja(m),C=d}function aMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,B=d+4|0,k=d,m=Pl(lMe()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=b0(B)|0,c=Td(c)|0,hc(0,m|0,s|0,l|0,c|0,Td(f)|0)|0,C=d}function lMe(){var s=0;return o[7992]|0||(uMe(10744),s=7992,n[s>>2]=1,n[s+4>>2]=0),10744}function Td(s){return s=s|0,cMe(s)|0}function cMe(s){return s=s|0,s&255|0}function uMe(s){s=s|0,Sl(s,AMe()|0,3)}function AMe(){return 1756}function fMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;switch(se=C,C=C+32|0,k=se+8|0,Q=se+4|0,O=se+20|0,M=se,DF(s,0),f=cUe(l)|0,n[k>>2]=0,j=k+4|0,n[j>>2]=0,n[k+8>>2]=0,f<<24>>24){case 0:{o[O>>0]=0,pMe(Q,c,O),Kv(s,Q)|0,jA(Q);break}case 8:{j=fR(l)|0,o[O>>0]=8,xc(M,n[j+4>>2]|0),hMe(Q,c,O,M,j+8|0),Kv(s,Q)|0,jA(Q);break}case 9:{if(m=fR(l)|0,l=n[m+4>>2]|0,l|0)for(B=k+8|0,d=m+12|0;l=l+-1|0,xc(Q,n[d>>2]|0),f=n[j>>2]|0,f>>>0<(n[B>>2]|0)>>>0?(n[f>>2]=n[Q>>2],n[j>>2]=(n[j>>2]|0)+4):rR(k,Q),l;)d=d+4|0;o[O>>0]=9,xc(M,n[m+8>>2]|0),gMe(Q,c,O,M,k),Kv(s,Q)|0,jA(Q);break}default:j=fR(l)|0,o[O>>0]=f,xc(M,n[j+4>>2]|0),dMe(Q,c,O,M),Kv(s,Q)|0,jA(Q)}$A(k),C=se}function pMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,za(d),l=ya(l)|0,xMe(s,l,o[c>>0]|0),Ja(d),C=f}function Kv(s,l){s=s|0,l=l|0;var c=0;return c=n[s>>2]|0,c|0&&PA(c|0),n[s>>2]=n[l>>2],n[l>>2]=0,s|0}function hMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0;m=C,C=C+32|0,k=m+16|0,B=m+8|0,Q=m,za(B),l=ya(l)|0,c=o[c>>0]|0,n[Q>>2]=n[f>>2],d=n[d>>2]|0,n[k>>2]=n[Q>>2],DMe(s,l,c,k,d),Ja(B),C=m}function gMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0,O=0;m=C,C=C+32|0,Q=m+24|0,B=m+16|0,O=m+12|0,k=m,za(B),l=ya(l)|0,c=o[c>>0]|0,n[O>>2]=n[f>>2],iR(k,d),n[Q>>2]=n[O>>2],wMe(s,l,c,Q,k),$A(k),Ja(B),C=m}function dMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+32|0,B=d+16|0,m=d+8|0,k=d,za(m),l=ya(l)|0,c=o[c>>0]|0,n[k>>2]=n[f>>2],n[B>>2]=n[k>>2],mMe(s,l,c,B),Ja(m),C=d}function mMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+4|0,k=d,B=Pl(yMe()|0)|0,c=Td(c)|0,n[k>>2]=n[f>>2],n[m>>2]=n[k>>2],Vv(s,oo(0,B|0,l|0,c|0,b0(m)|0)|0),C=d}function yMe(){var s=0;return o[8e3]|0||(EMe(10756),s=8e3,n[s>>2]=1,n[s+4>>2]=0),10756}function Vv(s,l){s=s|0,l=l|0,DF(s,l)}function EMe(s){s=s|0,Sl(s,CMe()|0,2)}function CMe(){return 1772}function wMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0,O=0;m=C,C=C+32|0,Q=m+16|0,O=m+12|0,B=m,k=Pl(IMe()|0)|0,c=Td(c)|0,n[O>>2]=n[f>>2],n[Q>>2]=n[O>>2],f=b0(Q)|0,n[B>>2]=n[d>>2],Q=d+4|0,n[B+4>>2]=n[Q>>2],O=d+8|0,n[B+8>>2]=n[O>>2],n[O>>2]=0,n[Q>>2]=0,n[d>>2]=0,Vv(s,hc(0,k|0,l|0,c|0,f|0,oR(B)|0)|0),$A(B),C=m}function IMe(){var s=0;return o[8008]|0||(BMe(10768),s=8008,n[s>>2]=1,n[s+4>>2]=0),10768}function BMe(s){s=s|0,Sl(s,vMe()|0,3)}function vMe(){return 1784}function DMe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0;m=C,C=C+16|0,k=m+4|0,Q=m,B=Pl(PMe()|0)|0,c=Td(c)|0,n[Q>>2]=n[f>>2],n[k>>2]=n[Q>>2],f=b0(k)|0,Vv(s,hc(0,B|0,l|0,c|0,f|0,sR(d)|0)|0),C=m}function PMe(){var s=0;return o[8016]|0||(SMe(10780),s=8016,n[s>>2]=1,n[s+4>>2]=0),10780}function SMe(s){s=s|0,Sl(s,bMe()|0,3)}function bMe(){return 1800}function xMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=Pl(kMe()|0)|0,Vv(s,Qn(0,f|0,l|0,Td(c)|0)|0)}function kMe(){var s=0;return o[8024]|0||(QMe(10792),s=8024,n[s>>2]=1,n[s+4>>2]=0),10792}function QMe(s){s=s|0,Sl(s,FMe()|0,1)}function FMe(){return 1816}function RMe(){TMe(),NMe(),LMe()}function TMe(){n[2702]=c7(65536)|0}function NMe(){rOe(10856)}function LMe(){MMe(10816)}function MMe(s){s=s|0,OMe(s,5044),UMe(s)|0}function OMe(s,l){s=s|0,l=l|0;var c=0;c=D9()|0,n[s>>2]=c,JMe(c,l),Pp(n[s>>2]|0)}function UMe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,_Me()|0),s|0}function _Me(){var s=0;return o[8032]|0||(L9(10820),ir(64,10820,U|0)|0,s=8032,n[s>>2]=1,n[s+4>>2]=0),Rr(10820)|0||L9(10820),10820}function L9(s){s=s|0,jMe(s),S0(s,25)}function HMe(s){s=s|0,qMe(s+24|0)}function qMe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function jMe(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,18,l,KMe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function GMe(s,l){s=s|0,l=l|0,YMe(s,l)}function YMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;c=C,C=C+16|0,f=c,d=c+4|0,v0(d,l),n[f>>2]=D0(d,l)|0,WMe(s,f),C=c}function WMe(s,l){s=s|0,l=l|0,M9(s+4|0,n[l>>2]|0),o[s+8>>0]=1}function M9(s,l){s=s|0,l=l|0,n[s>>2]=l}function KMe(){return 1824}function VMe(s){return s=s|0,zMe(s)|0}function zMe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Va(8)|0,l=f,k=Kt(4)|0,v0(d,s),M9(k,D0(d,s)|0),m=l+4|0,n[m>>2]=k,s=Kt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],P9(s,m,d),n[f>>2]=s,C=c,l|0}function Va(s){s=s|0;var l=0,c=0;return s=s+7&-8,s>>>0<=32768&&(l=n[2701]|0,s>>>0<=(65536-l|0)>>>0)?(c=(n[2702]|0)+l|0,n[2701]=l+s,s=c):(s=c7(s+8|0)|0,n[s>>2]=n[2703],n[2703]=s,s=s+8|0),s|0}function JMe(s,l){s=s|0,l=l|0,n[s>>2]=XMe()|0,n[s+4>>2]=ZMe()|0,n[s+12>>2]=l,n[s+8>>2]=$Me()|0,n[s+32>>2]=9}function XMe(){return 11744}function ZMe(){return 1832}function $Me(){return Yv()|0}function eOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(tOe(c),gt(c)):l|0&>(l)}function tOe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function rOe(s){s=s|0,nOe(s,5052),iOe(s)|0,sOe(s,5058,26)|0,oOe(s,5069,1)|0,aOe(s,5077,10)|0,lOe(s,5087,19)|0,cOe(s,5094,27)|0}function nOe(s,l){s=s|0,l=l|0;var c=0;c=tUe()|0,n[s>>2]=c,rUe(c,l),Pp(n[s>>2]|0)}function iOe(s){s=s|0;var l=0;return l=n[s>>2]|0,P0(l,H4e()|0),s|0}function sOe(s,l,c){return s=s|0,l=l|0,c=c|0,B4e(s,pn(l)|0,c,0),s|0}function oOe(s,l,c){return s=s|0,l=l|0,c=c|0,l4e(s,pn(l)|0,c,0),s|0}function aOe(s,l,c){return s=s|0,l=l|0,c=c|0,_Oe(s,pn(l)|0,c,0),s|0}function lOe(s,l,c){return s=s|0,l=l|0,c=c|0,DOe(s,pn(l)|0,c,0),s|0}function O9(s,l){s=s|0,l=l|0;var c=0,f=0;e:for(;;){for(c=n[2703]|0;;){if((c|0)==(l|0))break e;if(f=n[c>>2]|0,n[2703]=f,!c)c=f;else break}gt(c)}n[2701]=s}function cOe(s,l,c){return s=s|0,l=l|0,c=c|0,uOe(s,pn(l)|0,c,0),s|0}function uOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=aR()|0,s=AOe(c)|0,hn(m,l,d,s,fOe(c,f)|0,f)}function aR(){var s=0,l=0;if(o[8040]|0||(_9(10860),ir(65,10860,U|0)|0,l=8040,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10860)|0)){s=10860,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));_9(10860)}return 10860}function AOe(s){return s=s|0,s|0}function fOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=aR()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(U9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(pOe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function U9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function pOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=hOe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,gOe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,U9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,dOe(s,d),mOe(d),C=k;return}}function hOe(s){return s=s|0,536870911}function gOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function dOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function mOe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function _9(s){s=s|0,COe(s)}function yOe(s){s=s|0,EOe(s+24|0)}function EOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function COe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,11,l,wOe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function wOe(){return 1840}function IOe(s,l,c){s=s|0,l=l|0,c=c|0,vOe(n[(BOe(s)|0)>>2]|0,l,c)}function BOe(s){return s=s|0,(n[(aR()|0)+24>>2]|0)+(s<<3)|0}function vOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;f=C,C=C+16|0,m=f+1|0,d=f,v0(m,l),l=D0(m,l)|0,v0(d,c),c=D0(d,c)|0,tf[s&31](l,c),C=f}function DOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=lR()|0,s=POe(c)|0,hn(m,l,d,s,SOe(c,f)|0,f)}function lR(){var s=0,l=0;if(o[8048]|0||(q9(10896),ir(66,10896,U|0)|0,l=8048,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10896)|0)){s=10896,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));q9(10896)}return 10896}function POe(s){return s=s|0,s|0}function SOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=lR()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(H9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(bOe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function H9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function bOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=xOe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,kOe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,H9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,QOe(s,d),FOe(d),C=k;return}}function xOe(s){return s=s|0,536870911}function kOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function QOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function FOe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function q9(s){s=s|0,NOe(s)}function ROe(s){s=s|0,TOe(s+24|0)}function TOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function NOe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,11,l,LOe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function LOe(){return 1852}function MOe(s,l){return s=s|0,l=l|0,UOe(n[(OOe(s)|0)>>2]|0,l)|0}function OOe(s){return s=s|0,(n[(lR()|0)+24>>2]|0)+(s<<3)|0}function UOe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,v0(f,l),l=D0(f,l)|0,l=jv(F0[s&31](l)|0)|0,C=c,l|0}function _Oe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=cR()|0,s=HOe(c)|0,hn(m,l,d,s,qOe(c,f)|0,f)}function cR(){var s=0,l=0;if(o[8056]|0||(G9(10932),ir(67,10932,U|0)|0,l=8056,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10932)|0)){s=10932,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));G9(10932)}return 10932}function HOe(s){return s=s|0,s|0}function qOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=cR()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(j9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(jOe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function j9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function jOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=GOe(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,YOe(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,j9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,WOe(s,d),KOe(d),C=k;return}}function GOe(s){return s=s|0,536870911}function YOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function WOe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function KOe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function G9(s){s=s|0,JOe(s)}function VOe(s){s=s|0,zOe(s+24|0)}function zOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function JOe(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,7,l,XOe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function XOe(){return 1860}function ZOe(s,l,c){return s=s|0,l=l|0,c=c|0,e4e(n[($Oe(s)|0)>>2]|0,l,c)|0}function $Oe(s){return s=s|0,(n[(cR()|0)+24>>2]|0)+(s<<3)|0}function e4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0;return f=C,C=C+32|0,B=f+12|0,m=f+8|0,k=f,Q=f+16|0,d=f+4|0,t4e(Q,l),r4e(k,Q,l),Ip(d,c),c=Bp(d,c)|0,n[B>>2]=n[k>>2],vw[s&15](m,B,c),c=n4e(m)|0,jA(m),vp(d),C=f,c|0}function t4e(s,l){s=s|0,l=l|0}function r4e(s,l,c){s=s|0,l=l|0,c=c|0,i4e(s,c)}function n4e(s){return s=s|0,ya(s)|0}function i4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+16|0,c=d,f=l,f&1?(s4e(c,0),ii(f|0,c|0)|0,o4e(s,c),a4e(c)):n[s>>2]=n[l>>2],C=d}function s4e(s,l){s=s|0,l=l|0,K5(s,l),n[s+4>>2]=0,o[s+8>>0]=0}function o4e(s,l){s=s|0,l=l|0,n[s>>2]=n[l+4>>2]}function a4e(s){s=s|0,o[s+8>>0]=0}function l4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=uR()|0,s=c4e(c)|0,hn(m,l,d,s,u4e(c,f)|0,f)}function uR(){var s=0,l=0;if(o[8064]|0||(W9(10968),ir(68,10968,U|0)|0,l=8064,n[l>>2]=1,n[l+4>>2]=0),!(Rr(10968)|0)){s=10968,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));W9(10968)}return 10968}function c4e(s){return s=s|0,s|0}function u4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=uR()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(Y9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(A4e(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function Y9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function A4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=f4e(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,p4e(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,Y9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,h4e(s,d),g4e(d),C=k;return}}function f4e(s){return s=s|0,536870911}function p4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function h4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function g4e(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function W9(s){s=s|0,y4e(s)}function d4e(s){s=s|0,m4e(s+24|0)}function m4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function y4e(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,1,l,E4e()|0,5),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function E4e(){return 1872}function C4e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,I4e(n[(w4e(s)|0)>>2]|0,l,c,f,d,m)}function w4e(s){return s=s|0,(n[(uR()|0)+24>>2]|0)+(s<<3)|0}function I4e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,Q=0,O=0,M=0,j=0;B=C,C=C+32|0,k=B+16|0,Q=B+12|0,O=B+8|0,M=B+4|0,j=B,Ip(k,l),l=Bp(k,l)|0,Ip(Q,c),c=Bp(Q,c)|0,Ip(O,f),f=Bp(O,f)|0,Ip(M,d),d=Bp(M,d)|0,Ip(j,m),m=Bp(j,m)|0,h7[s&1](l,c,f,d,m),vp(j),vp(M),vp(O),vp(Q),vp(k),C=B}function B4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=AR()|0,s=v4e(c)|0,hn(m,l,d,s,D4e(c,f)|0,f)}function AR(){var s=0,l=0;if(o[8072]|0||(V9(11004),ir(69,11004,U|0)|0,l=8072,n[l>>2]=1,n[l+4>>2]=0),!(Rr(11004)|0)){s=11004,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));V9(11004)}return 11004}function v4e(s){return s=s|0,s|0}function D4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,Q=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,Q=AR()|0,B=Q+24|0,l=gr(l,4)|0,n[m>>2]=l,c=Q+28|0,f=n[c>>2]|0,f>>>0<(n[Q+32>>2]|0)>>>0?(K9(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(P4e(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function K9(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function P4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=S4e(s)|0,f>>>0<B>>>0)Jr(s);else{Q=n[s>>2]|0,M=(n[s+8>>2]|0)-Q|0,O=M>>2,b4e(d,M>>3>>>0<f>>>1>>>0?O>>>0<B>>>0?B:O:f,(n[m>>2]|0)-Q>>3,s+8|0),B=d+8|0,K9(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,x4e(s,d),k4e(d),C=k;return}}function S4e(s){return s=s|0,536870911}function b4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Kt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function x4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(Dr(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function k4e(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&>(s)}function V9(s){s=s|0,R4e(s)}function Q4e(s){s=s|0,F4e(s+24|0)}function F4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function R4e(s){s=s|0;var l=0;l=Vr()|0,zr(s,1,12,l,T4e()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function T4e(){return 1896}function N4e(s,l,c){s=s|0,l=l|0,c=c|0,M4e(n[(L4e(s)|0)>>2]|0,l,c)}function L4e(s){return s=s|0,(n[(AR()|0)+24>>2]|0)+(s<<3)|0}function M4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;f=C,C=C+16|0,m=f+4|0,d=f,O4e(m,l),l=U4e(m,l)|0,Ip(d,c),c=Bp(d,c)|0,tf[s&31](l,c),vp(d),C=f}function O4e(s,l){s=s|0,l=l|0}function U4e(s,l){return s=s|0,l=l|0,_4e(l)|0}function _4e(s){return s=s|0,s|0}function H4e(){var s=0;return o[8080]|0||(z9(11040),ir(70,11040,U|0)|0,s=8080,n[s>>2]=1,n[s+4>>2]=0),Rr(11040)|0||z9(11040),11040}function z9(s){s=s|0,G4e(s),S0(s,71)}function q4e(s){s=s|0,j4e(s+24|0)}function j4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),gt(c))}function G4e(s){s=s|0;var l=0;l=Vr()|0,zr(s,5,7,l,V4e()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Y4e(s){s=s|0,W4e(s)}function W4e(s){s=s|0,K4e(s)}function K4e(s){s=s|0,o[s+8>>0]=1}function V4e(){return 1936}function z4e(){return J4e()|0}function J4e(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Va(8)|0,s=c,m=s+4|0,n[m>>2]=Kt(1)|0,f=Kt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],X4e(f,m,d),n[c>>2]=f,C=l,s|0}function X4e(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Kt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1916,n[c+12>>2]=l,n[s+4>>2]=c}function Z4e(s){s=s|0,Md(s),gt(s)}function $4e(s){s=s|0,s=n[s+12>>2]|0,s|0&>(s)}function eUe(s){s=s|0,gt(s)}function tUe(){var s=0;return o[8088]|0||(lUe(11076),ir(25,11076,U|0)|0,s=8088,n[s>>2]=1,n[s+4>>2]=0),11076}function rUe(s,l){s=s|0,l=l|0,n[s>>2]=nUe()|0,n[s+4>>2]=iUe()|0,n[s+12>>2]=l,n[s+8>>2]=sUe()|0,n[s+32>>2]=10}function nUe(){return 11745}function iUe(){return 1940}function sUe(){return Gv()|0}function oUe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Dp(f,896)|0)==512?c|0&&(aUe(c),gt(c)):l|0&>(l)}function aUe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Sp(s)}function lUe(s){s=s|0,wp(s)}function xc(s,l){s=s|0,l=l|0,n[s>>2]=l}function fR(s){return s=s|0,n[s>>2]|0}function cUe(s){return s=s|0,o[n[s>>2]>>0]|0}function uUe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,n[f>>2]=n[s>>2],AUe(l,f)|0,C=c}function AUe(s,l){s=s|0,l=l|0;var c=0;return c=fUe(n[s>>2]|0,l)|0,l=s+4|0,n[(n[l>>2]|0)+8>>2]=c,n[(n[l>>2]|0)+8>>2]|0}function fUe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,za(f),s=ya(s)|0,l=pUe(s,n[l>>2]|0)|0,Ja(f),C=c,l|0}function za(s){s=s|0,n[s>>2]=n[2701],n[s+4>>2]=n[2703]}function pUe(s,l){s=s|0,l=l|0;var c=0;return c=Pl(hUe()|0)|0,Qn(0,c|0,s|0,sR(l)|0)|0}function Ja(s){s=s|0,O9(n[s>>2]|0,n[s+4>>2]|0)}function hUe(){var s=0;return o[8096]|0||(gUe(11120),s=8096,n[s>>2]=1,n[s+4>>2]=0),11120}function gUe(s){s=s|0,Sl(s,dUe()|0,1)}function dUe(){return 1948}function mUe(){yUe()}function yUe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0;if(Oe=C,C=C+16|0,M=Oe+4|0,j=Oe,Ti(65536,10804,n[2702]|0,10812),c=E9()|0,l=n[c>>2]|0,s=n[l>>2]|0,s|0)for(f=n[c+8>>2]|0,c=n[c+4>>2]|0;Ac(s|0,u[c>>0]|0|0,o[f>>0]|0),l=l+4|0,s=n[l>>2]|0,s;)f=f+1|0,c=c+1|0;if(s=C9()|0,l=n[s>>2]|0,l|0)do fu(l|0,n[s+4>>2]|0),s=s+8|0,l=n[s>>2]|0;while(l|0);fu(EUe()|0,5167),O=Fd()|0,s=n[O>>2]|0;e:do if(s|0){do CUe(n[s+4>>2]|0),s=n[s>>2]|0;while(s|0);if(s=n[O>>2]|0,s|0){Q=O;do{for(;d=s,s=n[s>>2]|0,d=n[d+4>>2]|0,!!(wUe(d)|0);)if(n[j>>2]=Q,n[M>>2]=n[j>>2],IUe(O,M)|0,!s)break e;if(BUe(d),Q=n[Q>>2]|0,l=J9(d)|0,m=Hi()|0,B=C,C=C+((1*(l<<2)|0)+15&-16)|0,k=C,C=C+((1*(l<<2)|0)+15&-16)|0,l=n[(F9(d)|0)>>2]|0,l|0)for(c=B,f=k;n[c>>2]=n[(Rd(n[l+4>>2]|0)|0)>>2],n[f>>2]=n[l+8>>2],l=n[l>>2]|0,l;)c=c+4|0,f=f+4|0;Qe=Rd(d)|0,l=vUe(d)|0,c=J9(d)|0,f=DUe(d)|0,pu(Qe|0,l|0,B|0,k|0,c|0,f|0,$F(d)|0),_i(m|0)}while(s|0)}}while(!1);if(s=n[(eR()|0)>>2]|0,s|0)do Qe=s+4|0,O=tR(Qe)|0,d=Cw(O)|0,m=yw(O)|0,B=(Ew(O)|0)+1|0,k=zv(O)|0,Q=X9(Qe)|0,O=Rr(O)|0,M=Wv(Qe)|0,j=pR(Qe)|0,El(0,d|0,m|0,B|0,k|0,Q|0,O|0,M|0,j|0,hR(Qe)|0),s=n[s>>2]|0;while(s|0);s=n[(Fd()|0)>>2]|0;e:do if(s|0){t:for(;;){if(l=n[s+4>>2]|0,l|0&&(se=n[(Rd(l)|0)>>2]|0,je=n[(R9(l)|0)>>2]|0,je|0)){c=je;do{l=c+4|0,f=tR(l)|0;r:do if(f|0)switch(Rr(f)|0){case 0:break t;case 4:case 3:case 2:{k=Cw(f)|0,Q=yw(f)|0,O=(Ew(f)|0)+1|0,M=zv(f)|0,j=Rr(f)|0,Qe=Wv(l)|0,El(se|0,k|0,Q|0,O|0,M|0,0,j|0,Qe|0,pR(l)|0,hR(l)|0);break r}case 1:{B=Cw(f)|0,k=yw(f)|0,Q=(Ew(f)|0)+1|0,O=zv(f)|0,M=X9(l)|0,j=Rr(f)|0,Qe=Wv(l)|0,El(se|0,B|0,k|0,Q|0,O|0,M|0,j|0,Qe|0,pR(l)|0,hR(l)|0);break r}case 5:{O=Cw(f)|0,M=yw(f)|0,j=(Ew(f)|0)+1|0,Qe=zv(f)|0,El(se|0,O|0,M|0,j|0,Qe|0,PUe(f)|0,Rr(f)|0,0,0,0);break r}default:break r}while(!1);c=n[c>>2]|0}while(c|0)}if(s=n[s>>2]|0,!s)break e}Tt()}while(!1);Ie(),C=Oe}function EUe(){return 11703}function CUe(s){s=s|0,o[s+40>>0]=0}function wUe(s){return s=s|0,(o[s+40>>0]|0)!=0|0}function IUe(s,l){return s=s|0,l=l|0,l=SUe(l)|0,s=n[l>>2]|0,n[l>>2]=n[s>>2],gt(s),n[l>>2]|0}function BUe(s){s=s|0,o[s+40>>0]=1}function J9(s){return s=s|0,n[s+20>>2]|0}function vUe(s){return s=s|0,n[s+8>>2]|0}function DUe(s){return s=s|0,n[s+32>>2]|0}function zv(s){return s=s|0,n[s+4>>2]|0}function X9(s){return s=s|0,n[s+4>>2]|0}function pR(s){return s=s|0,n[s+8>>2]|0}function hR(s){return s=s|0,n[s+16>>2]|0}function PUe(s){return s=s|0,n[s+20>>2]|0}function SUe(s){return s=s|0,n[s>>2]|0}function Jv(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0,$e=0,Je=0,lt=0,_e=0,qe=0,Lt=0;Lt=C,C=C+16|0,se=Lt;do if(s>>>0<245){if(O=s>>>0<11?16:s+11&-8,s=O>>>3,j=n[2783]|0,c=j>>>s,c&3|0)return l=(c&1^1)+s|0,s=11172+(l<<1<<2)|0,c=s+8|0,f=n[c>>2]|0,d=f+8|0,m=n[d>>2]|0,(s|0)==(m|0)?n[2783]=j&~(1<<l):(n[m+12>>2]=s,n[c>>2]=m),qe=l<<3,n[f+4>>2]=qe|3,qe=f+qe+4|0,n[qe>>2]=n[qe>>2]|1,qe=d,C=Lt,qe|0;if(M=n[2785]|0,O>>>0>M>>>0){if(c|0)return l=2<<s,l=c<<s&(l|0-l),l=(l&0-l)+-1|0,B=l>>>12&16,l=l>>>B,c=l>>>5&8,l=l>>>c,d=l>>>2&4,l=l>>>d,s=l>>>1&2,l=l>>>s,f=l>>>1&1,f=(c|B|d|s|f)+(l>>>f)|0,l=11172+(f<<1<<2)|0,s=l+8|0,d=n[s>>2]|0,B=d+8|0,c=n[B>>2]|0,(l|0)==(c|0)?(s=j&~(1<<f),n[2783]=s):(n[c+12>>2]=l,n[s>>2]=c,s=j),m=(f<<3)-O|0,n[d+4>>2]=O|3,f=d+O|0,n[f+4>>2]=m|1,n[f+m>>2]=m,M|0&&(d=n[2788]|0,l=M>>>3,c=11172+(l<<1<<2)|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=d,n[l+12>>2]=d,n[d+8>>2]=l,n[d+12>>2]=c),n[2785]=m,n[2788]=f,qe=B,C=Lt,qe|0;if(k=n[2784]|0,k){if(c=(k&0-k)+-1|0,B=c>>>12&16,c=c>>>B,m=c>>>5&8,c=c>>>m,Q=c>>>2&4,c=c>>>Q,f=c>>>1&2,c=c>>>f,s=c>>>1&1,s=n[11436+((m|B|Q|f|s)+(c>>>s)<<2)>>2]|0,c=(n[s+4>>2]&-8)-O|0,f=n[s+16+(((n[s+16>>2]|0)==0&1)<<2)>>2]|0,!f)Q=s,m=c;else{do B=(n[f+4>>2]&-8)-O|0,Q=B>>>0<c>>>0,c=Q?B:c,s=Q?f:s,f=n[f+16+(((n[f+16>>2]|0)==0&1)<<2)>>2]|0;while(f|0);Q=s,m=c}if(B=Q+O|0,Q>>>0<B>>>0){d=n[Q+24>>2]|0,l=n[Q+12>>2]|0;do if((l|0)==(Q|0)){if(s=Q+20|0,l=n[s>>2]|0,!l&&(s=Q+16|0,l=n[s>>2]|0,!l)){c=0;break}for(;;){if(c=l+20|0,f=n[c>>2]|0,f|0){l=f,s=c;continue}if(c=l+16|0,f=n[c>>2]|0,f)l=f,s=c;else break}n[s>>2]=0,c=l}else c=n[Q+8>>2]|0,n[c+12>>2]=l,n[l+8>>2]=c,c=l;while(!1);do if(d|0){if(l=n[Q+28>>2]|0,s=11436+(l<<2)|0,(Q|0)==(n[s>>2]|0)){if(n[s>>2]=c,!c){n[2784]=k&~(1<<l);break}}else if(n[d+16+(((n[d+16>>2]|0)!=(Q|0)&1)<<2)>>2]=c,!c)break;n[c+24>>2]=d,l=n[Q+16>>2]|0,l|0&&(n[c+16>>2]=l,n[l+24>>2]=c),l=n[Q+20>>2]|0,l|0&&(n[c+20>>2]=l,n[l+24>>2]=c)}while(!1);return m>>>0<16?(qe=m+O|0,n[Q+4>>2]=qe|3,qe=Q+qe+4|0,n[qe>>2]=n[qe>>2]|1):(n[Q+4>>2]=O|3,n[B+4>>2]=m|1,n[B+m>>2]=m,M|0&&(f=n[2788]|0,l=M>>>3,c=11172+(l<<1<<2)|0,l=1<<l,j&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=j|l,l=c,s=c+8|0),n[s>>2]=f,n[l+12>>2]=f,n[f+8>>2]=l,n[f+12>>2]=c),n[2785]=m,n[2788]=B),qe=Q+8|0,C=Lt,qe|0}else j=O}else j=O}else j=O}else if(s>>>0<=4294967231)if(s=s+11|0,O=s&-8,Q=n[2784]|0,Q){f=0-O|0,s=s>>>8,s?O>>>0>16777215?k=31:(j=(s+1048320|0)>>>16&8,_e=s<<j,M=(_e+520192|0)>>>16&4,_e=_e<<M,k=(_e+245760|0)>>>16&2,k=14-(M|j|k)+(_e<<k>>>15)|0,k=O>>>(k+7|0)&1|k<<1):k=0,c=n[11436+(k<<2)>>2]|0;e:do if(!c)c=0,s=0,_e=57;else for(s=0,B=O<<((k|0)==31?0:25-(k>>>1)|0),m=0;;){if(d=(n[c+4>>2]&-8)-O|0,d>>>0<f>>>0)if(d)s=c,f=d;else{s=c,f=0,d=c,_e=61;break e}if(d=n[c+20>>2]|0,c=n[c+16+(B>>>31<<2)>>2]|0,m=(d|0)==0|(d|0)==(c|0)?m:d,d=(c|0)==0,d){c=m,_e=57;break}else B=B<<((d^1)&1)}while(!1);if((_e|0)==57){if((c|0)==0&(s|0)==0){if(s=2<<k,s=Q&(s|0-s),!s){j=O;break}j=(s&0-s)+-1|0,B=j>>>12&16,j=j>>>B,m=j>>>5&8,j=j>>>m,k=j>>>2&4,j=j>>>k,M=j>>>1&2,j=j>>>M,c=j>>>1&1,s=0,c=n[11436+((m|B|k|M|c)+(j>>>c)<<2)>>2]|0}c?(d=c,_e=61):(k=s,B=f)}if((_e|0)==61)for(;;)if(_e=0,c=(n[d+4>>2]&-8)-O|0,j=c>>>0<f>>>0,c=j?c:f,s=j?d:s,d=n[d+16+(((n[d+16>>2]|0)==0&1)<<2)>>2]|0,d)f=c,_e=61;else{k=s,B=c;break}if(k|0&&B>>>0<((n[2785]|0)-O|0)>>>0){if(m=k+O|0,k>>>0>=m>>>0)return qe=0,C=Lt,qe|0;d=n[k+24>>2]|0,l=n[k+12>>2]|0;do if((l|0)==(k|0)){if(s=k+20|0,l=n[s>>2]|0,!l&&(s=k+16|0,l=n[s>>2]|0,!l)){l=0;break}for(;;){if(c=l+20|0,f=n[c>>2]|0,f|0){l=f,s=c;continue}if(c=l+16|0,f=n[c>>2]|0,f)l=f,s=c;else break}n[s>>2]=0}else qe=n[k+8>>2]|0,n[qe+12>>2]=l,n[l+8>>2]=qe;while(!1);do if(d){if(s=n[k+28>>2]|0,c=11436+(s<<2)|0,(k|0)==(n[c>>2]|0)){if(n[c>>2]=l,!l){f=Q&~(1<<s),n[2784]=f;break}}else if(n[d+16+(((n[d+16>>2]|0)!=(k|0)&1)<<2)>>2]=l,!l){f=Q;break}n[l+24>>2]=d,s=n[k+16>>2]|0,s|0&&(n[l+16>>2]=s,n[s+24>>2]=l),s=n[k+20>>2]|0,s&&(n[l+20>>2]=s,n[s+24>>2]=l),f=Q}else f=Q;while(!1);do if(B>>>0>=16){if(n[k+4>>2]=O|3,n[m+4>>2]=B|1,n[m+B>>2]=B,l=B>>>3,B>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=m,n[l+12>>2]=m,n[m+8>>2]=l,n[m+12>>2]=c;break}if(l=B>>>8,l?B>>>0>16777215?l=31:(_e=(l+1048320|0)>>>16&8,qe=l<<_e,lt=(qe+520192|0)>>>16&4,qe=qe<<lt,l=(qe+245760|0)>>>16&2,l=14-(lt|_e|l)+(qe<<l>>>15)|0,l=B>>>(l+7|0)&1|l<<1):l=0,c=11436+(l<<2)|0,n[m+28>>2]=l,s=m+16|0,n[s+4>>2]=0,n[s>>2]=0,s=1<<l,!(f&s)){n[2784]=f|s,n[c>>2]=m,n[m+24>>2]=c,n[m+12>>2]=m,n[m+8>>2]=m;break}for(s=B<<((l|0)==31?0:25-(l>>>1)|0),c=n[c>>2]|0;;){if((n[c+4>>2]&-8|0)==(B|0)){_e=97;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=96;break}}if((_e|0)==96){n[f>>2]=m,n[m+24>>2]=c,n[m+12>>2]=m,n[m+8>>2]=m;break}else if((_e|0)==97){_e=c+8|0,qe=n[_e>>2]|0,n[qe+12>>2]=m,n[_e>>2]=m,n[m+8>>2]=qe,n[m+12>>2]=c,n[m+24>>2]=0;break}}else qe=B+O|0,n[k+4>>2]=qe|3,qe=k+qe+4|0,n[qe>>2]=n[qe>>2]|1;while(!1);return qe=k+8|0,C=Lt,qe|0}else j=O}else j=O;else j=-1;while(!1);if(c=n[2785]|0,c>>>0>=j>>>0)return l=c-j|0,s=n[2788]|0,l>>>0>15?(qe=s+j|0,n[2788]=qe,n[2785]=l,n[qe+4>>2]=l|1,n[qe+l>>2]=l,n[s+4>>2]=j|3):(n[2785]=0,n[2788]=0,n[s+4>>2]=c|3,qe=s+c+4|0,n[qe>>2]=n[qe>>2]|1),qe=s+8|0,C=Lt,qe|0;if(B=n[2786]|0,B>>>0>j>>>0)return lt=B-j|0,n[2786]=lt,qe=n[2789]|0,_e=qe+j|0,n[2789]=_e,n[_e+4>>2]=lt|1,n[qe+4>>2]=j|3,qe=qe+8|0,C=Lt,qe|0;if(n[2901]|0?s=n[2903]|0:(n[2903]=4096,n[2902]=4096,n[2904]=-1,n[2905]=-1,n[2906]=0,n[2894]=0,s=se&-16^1431655768,n[se>>2]=s,n[2901]=s,s=4096),k=j+48|0,Q=j+47|0,m=s+Q|0,d=0-s|0,O=m&d,O>>>0<=j>>>0||(s=n[2893]|0,s|0&&(M=n[2891]|0,se=M+O|0,se>>>0<=M>>>0|se>>>0>s>>>0)))return qe=0,C=Lt,qe|0;e:do if(n[2894]&4)l=0,_e=133;else{c=n[2789]|0;t:do if(c){for(f=11580;s=n[f>>2]|0,!(s>>>0<=c>>>0&&(Qe=f+4|0,(s+(n[Qe>>2]|0)|0)>>>0>c>>>0));)if(s=n[f+8>>2]|0,s)f=s;else{_e=118;break t}if(l=m-B&d,l>>>0<2147483647)if(s=bp(l|0)|0,(s|0)==((n[f>>2]|0)+(n[Qe>>2]|0)|0)){if((s|0)!=-1){B=l,m=s,_e=135;break e}}else f=s,_e=126;else l=0}else _e=118;while(!1);do if((_e|0)==118)if(c=bp(0)|0,(c|0)!=-1&&(l=c,je=n[2902]|0,Oe=je+-1|0,l=(Oe&l|0?(Oe+l&0-je)-l|0:0)+O|0,je=n[2891]|0,Oe=l+je|0,l>>>0>j>>>0&l>>>0<2147483647)){if(Qe=n[2893]|0,Qe|0&&Oe>>>0<=je>>>0|Oe>>>0>Qe>>>0){l=0;break}if(s=bp(l|0)|0,(s|0)==(c|0)){B=l,m=c,_e=135;break e}else f=s,_e=126}else l=0;while(!1);do if((_e|0)==126){if(c=0-l|0,!(k>>>0>l>>>0&(l>>>0<2147483647&(f|0)!=-1)))if((f|0)==-1){l=0;break}else{B=l,m=f,_e=135;break e}if(s=n[2903]|0,s=Q-l+s&0-s,s>>>0>=2147483647){B=l,m=f,_e=135;break e}if((bp(s|0)|0)==-1){bp(c|0)|0,l=0;break}else{B=s+l|0,m=f,_e=135;break e}}while(!1);n[2894]=n[2894]|4,_e=133}while(!1);if((_e|0)==133&&O>>>0<2147483647&&(lt=bp(O|0)|0,Qe=bp(0)|0,$e=Qe-lt|0,Je=$e>>>0>(j+40|0)>>>0,!((lt|0)==-1|Je^1|lt>>>0<Qe>>>0&((lt|0)!=-1&(Qe|0)!=-1)^1))&&(B=Je?$e:l,m=lt,_e=135),(_e|0)==135){l=(n[2891]|0)+B|0,n[2891]=l,l>>>0>(n[2892]|0)>>>0&&(n[2892]=l),Q=n[2789]|0;do if(Q){for(l=11580;;){if(s=n[l>>2]|0,c=l+4|0,f=n[c>>2]|0,(m|0)==(s+f|0)){_e=145;break}if(d=n[l+8>>2]|0,d)l=d;else break}if((_e|0)==145&&!(n[l+12>>2]&8|0)&&Q>>>0<m>>>0&Q>>>0>=s>>>0){n[c>>2]=f+B,qe=Q+8|0,qe=qe&7|0?0-qe&7:0,_e=Q+qe|0,qe=(n[2786]|0)+(B-qe)|0,n[2789]=_e,n[2786]=qe,n[_e+4>>2]=qe|1,n[_e+qe+4>>2]=40,n[2790]=n[2905];break}for(m>>>0<(n[2787]|0)>>>0&&(n[2787]=m),c=m+B|0,l=11580;;){if((n[l>>2]|0)==(c|0)){_e=153;break}if(s=n[l+8>>2]|0,s)l=s;else break}if((_e|0)==153&&!(n[l+12>>2]&8|0)){n[l>>2]=m,M=l+4|0,n[M>>2]=(n[M>>2]|0)+B,M=m+8|0,M=m+(M&7|0?0-M&7:0)|0,l=c+8|0,l=c+(l&7|0?0-l&7:0)|0,O=M+j|0,k=l-M-j|0,n[M+4>>2]=j|3;do if((l|0)!=(Q|0)){if((l|0)==(n[2788]|0)){qe=(n[2785]|0)+k|0,n[2785]=qe,n[2788]=O,n[O+4>>2]=qe|1,n[O+qe>>2]=qe;break}if(s=n[l+4>>2]|0,(s&3|0)==1){B=s&-8,f=s>>>3;e:do if(s>>>0<256)if(s=n[l+8>>2]|0,c=n[l+12>>2]|0,(c|0)==(s|0)){n[2783]=n[2783]&~(1<<f);break}else{n[s+12>>2]=c,n[c+8>>2]=s;break}else{m=n[l+24>>2]|0,s=n[l+12>>2]|0;do if((s|0)==(l|0)){if(f=l+16|0,c=f+4|0,s=n[c>>2]|0,!s)if(s=n[f>>2]|0,s)c=f;else{s=0;break}for(;;){if(f=s+20|0,d=n[f>>2]|0,d|0){s=d,c=f;continue}if(f=s+16|0,d=n[f>>2]|0,d)s=d,c=f;else break}n[c>>2]=0}else qe=n[l+8>>2]|0,n[qe+12>>2]=s,n[s+8>>2]=qe;while(!1);if(!m)break;c=n[l+28>>2]|0,f=11436+(c<<2)|0;do if((l|0)!=(n[f>>2]|0)){if(n[m+16+(((n[m+16>>2]|0)!=(l|0)&1)<<2)>>2]=s,!s)break e}else{if(n[f>>2]=s,s|0)break;n[2784]=n[2784]&~(1<<c);break e}while(!1);if(n[s+24>>2]=m,c=l+16|0,f=n[c>>2]|0,f|0&&(n[s+16>>2]=f,n[f+24>>2]=s),c=n[c+4>>2]|0,!c)break;n[s+20>>2]=c,n[c+24>>2]=s}while(!1);l=l+B|0,d=B+k|0}else d=k;if(l=l+4|0,n[l>>2]=n[l>>2]&-2,n[O+4>>2]=d|1,n[O+d>>2]=d,l=d>>>3,d>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=O,n[l+12>>2]=O,n[O+8>>2]=l,n[O+12>>2]=c;break}l=d>>>8;do if(!l)l=0;else{if(d>>>0>16777215){l=31;break}_e=(l+1048320|0)>>>16&8,qe=l<<_e,lt=(qe+520192|0)>>>16&4,qe=qe<<lt,l=(qe+245760|0)>>>16&2,l=14-(lt|_e|l)+(qe<<l>>>15)|0,l=d>>>(l+7|0)&1|l<<1}while(!1);if(f=11436+(l<<2)|0,n[O+28>>2]=l,s=O+16|0,n[s+4>>2]=0,n[s>>2]=0,s=n[2784]|0,c=1<<l,!(s&c)){n[2784]=s|c,n[f>>2]=O,n[O+24>>2]=f,n[O+12>>2]=O,n[O+8>>2]=O;break}for(s=d<<((l|0)==31?0:25-(l>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(d|0)){_e=194;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=193;break}}if((_e|0)==193){n[f>>2]=O,n[O+24>>2]=c,n[O+12>>2]=O,n[O+8>>2]=O;break}else if((_e|0)==194){_e=c+8|0,qe=n[_e>>2]|0,n[qe+12>>2]=O,n[_e>>2]=O,n[O+8>>2]=qe,n[O+12>>2]=c,n[O+24>>2]=0;break}}else qe=(n[2786]|0)+k|0,n[2786]=qe,n[2789]=O,n[O+4>>2]=qe|1;while(!1);return qe=M+8|0,C=Lt,qe|0}for(l=11580;s=n[l>>2]|0,!(s>>>0<=Q>>>0&&(qe=s+(n[l+4>>2]|0)|0,qe>>>0>Q>>>0));)l=n[l+8>>2]|0;d=qe+-47|0,s=d+8|0,s=d+(s&7|0?0-s&7:0)|0,d=Q+16|0,s=s>>>0<d>>>0?Q:s,l=s+8|0,c=m+8|0,c=c&7|0?0-c&7:0,_e=m+c|0,c=B+-40-c|0,n[2789]=_e,n[2786]=c,n[_e+4>>2]=c|1,n[_e+c+4>>2]=40,n[2790]=n[2905],c=s+4|0,n[c>>2]=27,n[l>>2]=n[2895],n[l+4>>2]=n[2896],n[l+8>>2]=n[2897],n[l+12>>2]=n[2898],n[2895]=m,n[2896]=B,n[2898]=0,n[2897]=l,l=s+24|0;do _e=l,l=l+4|0,n[l>>2]=7;while((_e+8|0)>>>0<qe>>>0);if((s|0)!=(Q|0)){if(m=s-Q|0,n[c>>2]=n[c>>2]&-2,n[Q+4>>2]=m|1,n[s>>2]=m,l=m>>>3,m>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=Q,n[l+12>>2]=Q,n[Q+8>>2]=l,n[Q+12>>2]=c;break}if(l=m>>>8,l?m>>>0>16777215?c=31:(_e=(l+1048320|0)>>>16&8,qe=l<<_e,lt=(qe+520192|0)>>>16&4,qe=qe<<lt,c=(qe+245760|0)>>>16&2,c=14-(lt|_e|c)+(qe<<c>>>15)|0,c=m>>>(c+7|0)&1|c<<1):c=0,f=11436+(c<<2)|0,n[Q+28>>2]=c,n[Q+20>>2]=0,n[d>>2]=0,l=n[2784]|0,s=1<<c,!(l&s)){n[2784]=l|s,n[f>>2]=Q,n[Q+24>>2]=f,n[Q+12>>2]=Q,n[Q+8>>2]=Q;break}for(s=m<<((c|0)==31?0:25-(c>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(m|0)){_e=216;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=215;break}}if((_e|0)==215){n[f>>2]=Q,n[Q+24>>2]=c,n[Q+12>>2]=Q,n[Q+8>>2]=Q;break}else if((_e|0)==216){_e=c+8|0,qe=n[_e>>2]|0,n[qe+12>>2]=Q,n[_e>>2]=Q,n[Q+8>>2]=qe,n[Q+12>>2]=c,n[Q+24>>2]=0;break}}}else{qe=n[2787]|0,(qe|0)==0|m>>>0<qe>>>0&&(n[2787]=m),n[2895]=m,n[2896]=B,n[2898]=0,n[2792]=n[2901],n[2791]=-1,l=0;do qe=11172+(l<<1<<2)|0,n[qe+12>>2]=qe,n[qe+8>>2]=qe,l=l+1|0;while((l|0)!=32);qe=m+8|0,qe=qe&7|0?0-qe&7:0,_e=m+qe|0,qe=B+-40-qe|0,n[2789]=_e,n[2786]=qe,n[_e+4>>2]=qe|1,n[_e+qe+4>>2]=40,n[2790]=n[2905]}while(!1);if(l=n[2786]|0,l>>>0>j>>>0)return lt=l-j|0,n[2786]=lt,qe=n[2789]|0,_e=qe+j|0,n[2789]=_e,n[_e+4>>2]=lt|1,n[qe+4>>2]=j|3,qe=qe+8|0,C=Lt,qe|0}return n[(Nd()|0)>>2]=12,qe=0,C=Lt,qe|0}function Xv(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,Q=0;if(s){c=s+-8|0,d=n[2787]|0,s=n[s+-4>>2]|0,l=s&-8,Q=c+l|0;do if(s&1)k=c,B=c;else{if(f=n[c>>2]|0,!(s&3)||(B=c+(0-f)|0,m=f+l|0,B>>>0<d>>>0))return;if((B|0)==(n[2788]|0)){if(s=Q+4|0,l=n[s>>2]|0,(l&3|0)!=3){k=B,l=m;break}n[2785]=m,n[s>>2]=l&-2,n[B+4>>2]=m|1,n[B+m>>2]=m;return}if(c=f>>>3,f>>>0<256)if(s=n[B+8>>2]|0,l=n[B+12>>2]|0,(l|0)==(s|0)){n[2783]=n[2783]&~(1<<c),k=B,l=m;break}else{n[s+12>>2]=l,n[l+8>>2]=s,k=B,l=m;break}d=n[B+24>>2]|0,s=n[B+12>>2]|0;do if((s|0)==(B|0)){if(c=B+16|0,l=c+4|0,s=n[l>>2]|0,!s)if(s=n[c>>2]|0,s)l=c;else{s=0;break}for(;;){if(c=s+20|0,f=n[c>>2]|0,f|0){s=f,l=c;continue}if(c=s+16|0,f=n[c>>2]|0,f)s=f,l=c;else break}n[l>>2]=0}else k=n[B+8>>2]|0,n[k+12>>2]=s,n[s+8>>2]=k;while(!1);if(d){if(l=n[B+28>>2]|0,c=11436+(l<<2)|0,(B|0)==(n[c>>2]|0)){if(n[c>>2]=s,!s){n[2784]=n[2784]&~(1<<l),k=B,l=m;break}}else if(n[d+16+(((n[d+16>>2]|0)!=(B|0)&1)<<2)>>2]=s,!s){k=B,l=m;break}n[s+24>>2]=d,l=B+16|0,c=n[l>>2]|0,c|0&&(n[s+16>>2]=c,n[c+24>>2]=s),l=n[l+4>>2]|0,l?(n[s+20>>2]=l,n[l+24>>2]=s,k=B,l=m):(k=B,l=m)}else k=B,l=m}while(!1);if(!(B>>>0>=Q>>>0)&&(s=Q+4|0,f=n[s>>2]|0,!!(f&1))){if(f&2)n[s>>2]=f&-2,n[k+4>>2]=l|1,n[B+l>>2]=l,d=l;else{if(s=n[2788]|0,(Q|0)==(n[2789]|0)){if(Q=(n[2786]|0)+l|0,n[2786]=Q,n[2789]=k,n[k+4>>2]=Q|1,(k|0)!=(s|0))return;n[2788]=0,n[2785]=0;return}if((Q|0)==(s|0)){Q=(n[2785]|0)+l|0,n[2785]=Q,n[2788]=B,n[k+4>>2]=Q|1,n[B+Q>>2]=Q;return}d=(f&-8)+l|0,c=f>>>3;do if(f>>>0<256)if(l=n[Q+8>>2]|0,s=n[Q+12>>2]|0,(s|0)==(l|0)){n[2783]=n[2783]&~(1<<c);break}else{n[l+12>>2]=s,n[s+8>>2]=l;break}else{m=n[Q+24>>2]|0,s=n[Q+12>>2]|0;do if((s|0)==(Q|0)){if(c=Q+16|0,l=c+4|0,s=n[l>>2]|0,!s)if(s=n[c>>2]|0,s)l=c;else{c=0;break}for(;;){if(c=s+20|0,f=n[c>>2]|0,f|0){s=f,l=c;continue}if(c=s+16|0,f=n[c>>2]|0,f)s=f,l=c;else break}n[l>>2]=0,c=s}else c=n[Q+8>>2]|0,n[c+12>>2]=s,n[s+8>>2]=c,c=s;while(!1);if(m|0){if(s=n[Q+28>>2]|0,l=11436+(s<<2)|0,(Q|0)==(n[l>>2]|0)){if(n[l>>2]=c,!c){n[2784]=n[2784]&~(1<<s);break}}else if(n[m+16+(((n[m+16>>2]|0)!=(Q|0)&1)<<2)>>2]=c,!c)break;n[c+24>>2]=m,s=Q+16|0,l=n[s>>2]|0,l|0&&(n[c+16>>2]=l,n[l+24>>2]=c),s=n[s+4>>2]|0,s|0&&(n[c+20>>2]=s,n[s+24>>2]=c)}}while(!1);if(n[k+4>>2]=d|1,n[B+d>>2]=d,(k|0)==(n[2788]|0)){n[2785]=d;return}}if(s=d>>>3,d>>>0<256){c=11172+(s<<1<<2)|0,l=n[2783]|0,s=1<<s,l&s?(l=c+8|0,s=n[l>>2]|0):(n[2783]=l|s,s=c,l=c+8|0),n[l>>2]=k,n[s+12>>2]=k,n[k+8>>2]=s,n[k+12>>2]=c;return}s=d>>>8,s?d>>>0>16777215?s=31:(B=(s+1048320|0)>>>16&8,Q=s<<B,m=(Q+520192|0)>>>16&4,Q=Q<<m,s=(Q+245760|0)>>>16&2,s=14-(m|B|s)+(Q<<s>>>15)|0,s=d>>>(s+7|0)&1|s<<1):s=0,f=11436+(s<<2)|0,n[k+28>>2]=s,n[k+20>>2]=0,n[k+16>>2]=0,l=n[2784]|0,c=1<<s;do if(l&c){for(l=d<<((s|0)==31?0:25-(s>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(d|0)){s=73;break}if(f=c+16+(l>>>31<<2)|0,s=n[f>>2]|0,s)l=l<<1,c=s;else{s=72;break}}if((s|0)==72){n[f>>2]=k,n[k+24>>2]=c,n[k+12>>2]=k,n[k+8>>2]=k;break}else if((s|0)==73){B=c+8|0,Q=n[B>>2]|0,n[Q+12>>2]=k,n[B>>2]=k,n[k+8>>2]=Q,n[k+12>>2]=c,n[k+24>>2]=0;break}}else n[2784]=l|c,n[f>>2]=k,n[k+24>>2]=f,n[k+12>>2]=k,n[k+8>>2]=k;while(!1);if(Q=(n[2791]|0)+-1|0,n[2791]=Q,!Q)s=11588;else return;for(;s=n[s>>2]|0,s;)s=s+8|0;n[2791]=-1}}}function bUe(){return 11628}function xUe(s){s=s|0;var l=0,c=0;return l=C,C=C+16|0,c=l,n[c>>2]=FUe(n[s+60>>2]|0)|0,s=Zv(gc(6,c|0)|0)|0,C=l,s|0}function Z9(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0;j=C,C=C+48|0,O=j+16|0,m=j,d=j+32|0,k=s+28|0,f=n[k>>2]|0,n[d>>2]=f,Q=s+20|0,f=(n[Q>>2]|0)-f|0,n[d+4>>2]=f,n[d+8>>2]=l,n[d+12>>2]=c,f=f+c|0,B=s+60|0,n[m>>2]=n[B>>2],n[m+4>>2]=d,n[m+8>>2]=2,m=Zv(Ni(146,m|0)|0)|0;e:do if((f|0)!=(m|0)){for(l=2;!((m|0)<0);)if(f=f-m|0,je=n[d+4>>2]|0,se=m>>>0>je>>>0,d=se?d+8|0:d,l=(se<<31>>31)+l|0,je=m-(se?je:0)|0,n[d>>2]=(n[d>>2]|0)+je,se=d+4|0,n[se>>2]=(n[se>>2]|0)-je,n[O>>2]=n[B>>2],n[O+4>>2]=d,n[O+8>>2]=l,m=Zv(Ni(146,O|0)|0)|0,(f|0)==(m|0)){M=3;break e}n[s+16>>2]=0,n[k>>2]=0,n[Q>>2]=0,n[s>>2]=n[s>>2]|32,(l|0)==2?c=0:c=c-(n[d+4>>2]|0)|0}else M=3;while(!1);return(M|0)==3&&(je=n[s+44>>2]|0,n[s+16>>2]=je+(n[s+48>>2]|0),n[k>>2]=je,n[Q>>2]=je),C=j,c|0}function kUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return d=C,C=C+32|0,m=d,f=d+20|0,n[m>>2]=n[s+60>>2],n[m+4>>2]=0,n[m+8>>2]=l,n[m+12>>2]=f,n[m+16>>2]=c,(Zv(aa(140,m|0)|0)|0)<0?(n[f>>2]=-1,s=-1):s=n[f>>2]|0,C=d,s|0}function Zv(s){return s=s|0,s>>>0>4294963200&&(n[(Nd()|0)>>2]=0-s,s=-1),s|0}function Nd(){return(QUe()|0)+64|0}function QUe(){return gR()|0}function gR(){return 2084}function FUe(s){return s=s|0,s|0}function RUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;return d=C,C=C+32|0,f=d,n[s+36>>2]=1,!(n[s>>2]&64|0)&&(n[f>>2]=n[s+60>>2],n[f+4>>2]=21523,n[f+8>>2]=d+16,hu(54,f|0)|0)&&(o[s+75>>0]=-1),f=Z9(s,l,c)|0,C=d,f|0}function $9(s,l){s=s|0,l=l|0;var c=0,f=0;if(c=o[s>>0]|0,f=o[l>>0]|0,!(c<<24>>24)||c<<24>>24!=f<<24>>24)s=f;else{do s=s+1|0,l=l+1|0,c=o[s>>0]|0,f=o[l>>0]|0;while(!(!(c<<24>>24)||c<<24>>24!=f<<24>>24));s=f}return(c&255)-(s&255)|0}function TUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;e:do if(!c)s=0;else{for(;f=o[s>>0]|0,d=o[l>>0]|0,f<<24>>24==d<<24>>24;)if(c=c+-1|0,c)s=s+1|0,l=l+1|0;else{s=0;break e}s=(f&255)-(d&255)|0}while(!1);return s|0}function e7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0;Qe=C,C=C+224|0,M=Qe+120|0,j=Qe+80|0,je=Qe,Oe=Qe+136|0,f=j,d=f+40|0;do n[f>>2]=0,f=f+4|0;while((f|0)<(d|0));return n[M>>2]=n[c>>2],(dR(0,l,M,je,j)|0)<0?c=-1:((n[s+76>>2]|0)>-1?se=NUe(s)|0:se=0,c=n[s>>2]|0,O=c&32,(o[s+74>>0]|0)<1&&(n[s>>2]=c&-33),f=s+48|0,n[f>>2]|0?c=dR(s,l,M,je,j)|0:(d=s+44|0,m=n[d>>2]|0,n[d>>2]=Oe,B=s+28|0,n[B>>2]=Oe,k=s+20|0,n[k>>2]=Oe,n[f>>2]=80,Q=s+16|0,n[Q>>2]=Oe+80,c=dR(s,l,M,je,j)|0,m&&(rD[n[s+36>>2]&7](s,0,0)|0,c=n[k>>2]|0?c:-1,n[d>>2]=m,n[f>>2]=0,n[Q>>2]=0,n[B>>2]=0,n[k>>2]=0)),f=n[s>>2]|0,n[s>>2]=f|O,se|0&&LUe(s),c=f&32|0?-1:c),C=Qe,c|0}function dR(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0,$e=0,Je=0,lt=0,_e=0,qe=0,Lt=0,Or=0,cr=0,Xt=0,Pr=0,Tr=0,ar=0;ar=C,C=C+64|0,cr=ar+16|0,Xt=ar,Lt=ar+24|0,Pr=ar+8|0,Tr=ar+20|0,n[cr>>2]=l,lt=(s|0)!=0,_e=Lt+40|0,qe=_e,Lt=Lt+39|0,Or=Pr+4|0,B=0,m=0,M=0;e:for(;;){do if((m|0)>-1)if((B|0)>(2147483647-m|0)){n[(Nd()|0)>>2]=75,m=-1;break}else{m=B+m|0;break}while(!1);if(B=o[l>>0]|0,B<<24>>24)k=l;else{Je=87;break}t:for(;;){switch(B<<24>>24){case 37:{B=k,Je=9;break t}case 0:{B=k;break t}default:}$e=k+1|0,n[cr>>2]=$e,B=o[$e>>0]|0,k=$e}t:do if((Je|0)==9)for(;;){if(Je=0,(o[k+1>>0]|0)!=37)break t;if(B=B+1|0,k=k+2|0,n[cr>>2]=k,(o[k>>0]|0)==37)Je=9;else break}while(!1);if(B=B-l|0,lt&&as(s,l,B),B|0){l=k;continue}Q=k+1|0,B=(o[Q>>0]|0)+-48|0,B>>>0<10?($e=(o[k+2>>0]|0)==36,Qe=$e?B:-1,M=$e?1:M,Q=$e?k+3|0:Q):Qe=-1,n[cr>>2]=Q,B=o[Q>>0]|0,k=(B<<24>>24)+-32|0;t:do if(k>>>0<32)for(O=0,j=B;;){if(B=1<<k,!(B&75913)){B=j;break t}if(O=B|O,Q=Q+1|0,n[cr>>2]=Q,B=o[Q>>0]|0,k=(B<<24>>24)+-32|0,k>>>0>=32)break;j=B}else O=0;while(!1);if(B<<24>>24==42){if(k=Q+1|0,B=(o[k>>0]|0)+-48|0,B>>>0<10&&(o[Q+2>>0]|0)==36)n[d+(B<<2)>>2]=10,B=n[f+((o[k>>0]|0)+-48<<3)>>2]|0,M=1,Q=Q+3|0;else{if(M|0){m=-1;break}lt?(M=(n[c>>2]|0)+3&-4,B=n[M>>2]|0,n[c>>2]=M+4,M=0,Q=k):(B=0,M=0,Q=k)}n[cr>>2]=Q,$e=(B|0)<0,B=$e?0-B|0:B,O=$e?O|8192:O}else{if(B=t7(cr)|0,(B|0)<0){m=-1;break}Q=n[cr>>2]|0}do if((o[Q>>0]|0)==46){if((o[Q+1>>0]|0)!=42){n[cr>>2]=Q+1,k=t7(cr)|0,Q=n[cr>>2]|0;break}if(j=Q+2|0,k=(o[j>>0]|0)+-48|0,k>>>0<10&&(o[Q+3>>0]|0)==36){n[d+(k<<2)>>2]=10,k=n[f+((o[j>>0]|0)+-48<<3)>>2]|0,Q=Q+4|0,n[cr>>2]=Q;break}if(M|0){m=-1;break e}lt?($e=(n[c>>2]|0)+3&-4,k=n[$e>>2]|0,n[c>>2]=$e+4):k=0,n[cr>>2]=j,Q=j}else k=-1;while(!1);for(Oe=0;;){if(((o[Q>>0]|0)+-65|0)>>>0>57){m=-1;break e}if($e=Q+1|0,n[cr>>2]=$e,j=o[(o[Q>>0]|0)+-65+(5178+(Oe*58|0))>>0]|0,se=j&255,(se+-1|0)>>>0<8)Oe=se,Q=$e;else break}if(!(j<<24>>24)){m=-1;break}je=(Qe|0)>-1;do if(j<<24>>24==19)if(je){m=-1;break e}else Je=49;else{if(je){n[d+(Qe<<2)>>2]=se,je=f+(Qe<<3)|0,Qe=n[je+4>>2]|0,Je=Xt,n[Je>>2]=n[je>>2],n[Je+4>>2]=Qe,Je=49;break}if(!lt){m=0;break e}r7(Xt,se,c)}while(!1);if((Je|0)==49&&(Je=0,!lt)){B=0,l=$e;continue}Q=o[Q>>0]|0,Q=(Oe|0)!=0&(Q&15|0)==3?Q&-33:Q,je=O&-65537,Qe=O&8192|0?je:O;t:do switch(Q|0){case 110:switch((Oe&255)<<24>>24){case 0:{n[n[Xt>>2]>>2]=m,B=0,l=$e;continue e}case 1:{n[n[Xt>>2]>>2]=m,B=0,l=$e;continue e}case 2:{B=n[Xt>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=$e;continue e}case 3:{a[n[Xt>>2]>>1]=m,B=0,l=$e;continue e}case 4:{o[n[Xt>>2]>>0]=m,B=0,l=$e;continue e}case 6:{n[n[Xt>>2]>>2]=m,B=0,l=$e;continue e}case 7:{B=n[Xt>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=$e;continue e}default:{B=0,l=$e;continue e}}case 112:{Q=120,k=k>>>0>8?k:8,l=Qe|8,Je=61;break}case 88:case 120:{l=Qe,Je=61;break}case 111:{Q=Xt,l=n[Q>>2]|0,Q=n[Q+4>>2]|0,se=OUe(l,Q,_e)|0,je=qe-se|0,O=0,j=5642,k=(Qe&8|0)==0|(k|0)>(je|0)?k:je+1|0,je=Qe,Je=67;break}case 105:case 100:if(Q=Xt,l=n[Q>>2]|0,Q=n[Q+4>>2]|0,(Q|0)<0){l=$v(0,0,l|0,Q|0)|0,Q=we,O=Xt,n[O>>2]=l,n[O+4>>2]=Q,O=1,j=5642,Je=66;break t}else{O=(Qe&2049|0)!=0&1,j=Qe&2048|0?5643:Qe&1|0?5644:5642,Je=66;break t}case 117:{Q=Xt,O=0,j=5642,l=n[Q>>2]|0,Q=n[Q+4>>2]|0,Je=66;break}case 99:{o[Lt>>0]=n[Xt>>2],l=Lt,O=0,j=5642,se=_e,Q=1,k=je;break}case 109:{Q=UUe(n[(Nd()|0)>>2]|0)|0,Je=71;break}case 115:{Q=n[Xt>>2]|0,Q=Q|0?Q:5652,Je=71;break}case 67:{n[Pr>>2]=n[Xt>>2],n[Or>>2]=0,n[Xt>>2]=Pr,se=-1,Q=Pr,Je=75;break}case 83:{l=n[Xt>>2]|0,k?(se=k,Q=l,Je=75):(Ds(s,32,B,0,Qe),l=0,Je=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{B=HUe(s,+E[Xt>>3],B,k,Qe,Q)|0,l=$e;continue e}default:O=0,j=5642,se=_e,Q=k,k=Qe}while(!1);t:do if((Je|0)==61)Qe=Xt,Oe=n[Qe>>2]|0,Qe=n[Qe+4>>2]|0,se=MUe(Oe,Qe,_e,Q&32)|0,j=(l&8|0)==0|(Oe|0)==0&(Qe|0)==0,O=j?0:2,j=j?5642:5642+(Q>>4)|0,je=l,l=Oe,Q=Qe,Je=67;else if((Je|0)==66)se=Ld(l,Q,_e)|0,je=Qe,Je=67;else if((Je|0)==71)Je=0,Qe=_Ue(Q,0,k)|0,Oe=(Qe|0)==0,l=Q,O=0,j=5642,se=Oe?Q+k|0:Qe,Q=Oe?k:Qe-Q|0,k=je;else if((Je|0)==75){for(Je=0,j=Q,l=0,k=0;O=n[j>>2]|0,!(!O||(k=n7(Tr,O)|0,(k|0)<0|k>>>0>(se-l|0)>>>0));)if(l=k+l|0,se>>>0>l>>>0)j=j+4|0;else break;if((k|0)<0){m=-1;break e}if(Ds(s,32,B,l,Qe),!l)l=0,Je=84;else for(O=0;;){if(k=n[Q>>2]|0,!k){Je=84;break t}if(k=n7(Tr,k)|0,O=k+O|0,(O|0)>(l|0)){Je=84;break t}if(as(s,Tr,k),O>>>0>=l>>>0){Je=84;break}else Q=Q+4|0}}while(!1);if((Je|0)==67)Je=0,Q=(l|0)!=0|(Q|0)!=0,Qe=(k|0)!=0|Q,Q=((Q^1)&1)+(qe-se)|0,l=Qe?se:_e,se=_e,Q=Qe?(k|0)>(Q|0)?k:Q:k,k=(k|0)>-1?je&-65537:je;else if((Je|0)==84){Je=0,Ds(s,32,B,l,Qe^8192),B=(B|0)>(l|0)?B:l,l=$e;continue}Oe=se-l|0,je=(Q|0)<(Oe|0)?Oe:Q,Qe=je+O|0,B=(B|0)<(Qe|0)?Qe:B,Ds(s,32,B,Qe,k),as(s,j,O),Ds(s,48,B,Qe,k^65536),Ds(s,48,je,Oe,0),as(s,l,Oe),Ds(s,32,B,Qe,k^8192),l=$e}e:do if((Je|0)==87&&!s)if(!M)m=0;else{for(m=1;l=n[d+(m<<2)>>2]|0,!!l;)if(r7(f+(m<<3)|0,l,c),m=m+1|0,(m|0)>=10){m=1;break e}for(;;){if(n[d+(m<<2)>>2]|0){m=-1;break e}if(m=m+1|0,(m|0)>=10){m=1;break}}}while(!1);return C=ar,m|0}function NUe(s){return s=s|0,0}function LUe(s){s=s|0}function as(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]&32||JUe(l,c,s)|0}function t7(s){s=s|0;var l=0,c=0,f=0;if(c=n[s>>2]|0,f=(o[c>>0]|0)+-48|0,f>>>0<10){l=0;do l=f+(l*10|0)|0,c=c+1|0,n[s>>2]=c,f=(o[c>>0]|0)+-48|0;while(f>>>0<10)}else l=0;return l|0}function r7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;e:do if(l>>>0<=20)do switch(l|0){case 9:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,n[s>>2]=l;break e}case 10:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,f=s,n[f>>2]=l,n[f+4>>2]=((l|0)<0)<<31>>31;break e}case 11:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,f=s,n[f>>2]=l,n[f+4>>2]=0;break e}case 12:{f=(n[c>>2]|0)+7&-8,l=f,d=n[l>>2]|0,l=n[l+4>>2]|0,n[c>>2]=f+8,f=s,n[f>>2]=d,n[f+4>>2]=l;break e}case 13:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,f=(f&65535)<<16>>16,d=s,n[d>>2]=f,n[d+4>>2]=((f|0)<0)<<31>>31;break e}case 14:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,d=s,n[d>>2]=f&65535,n[d+4>>2]=0;break e}case 15:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,f=(f&255)<<24>>24,d=s,n[d>>2]=f,n[d+4>>2]=((f|0)<0)<<31>>31;break e}case 16:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,d=s,n[d>>2]=f&255,n[d+4>>2]=0;break e}case 17:{d=(n[c>>2]|0)+7&-8,m=+E[d>>3],n[c>>2]=d+8,E[s>>3]=m;break e}case 18:{d=(n[c>>2]|0)+7&-8,m=+E[d>>3],n[c>>2]=d+8,E[s>>3]=m;break e}default:break e}while(!1);while(!1)}function MUe(s,l,c,f){if(s=s|0,l=l|0,c=c|0,f=f|0,!((s|0)==0&(l|0)==0))do c=c+-1|0,o[c>>0]=u[5694+(s&15)>>0]|0|f,s=eD(s|0,l|0,4)|0,l=we;while(!((s|0)==0&(l|0)==0));return c|0}function OUe(s,l,c){if(s=s|0,l=l|0,c=c|0,!((s|0)==0&(l|0)==0))do c=c+-1|0,o[c>>0]=s&7|48,s=eD(s|0,l|0,3)|0,l=we;while(!((s|0)==0&(l|0)==0));return c|0}function Ld(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;if(l>>>0>0|(l|0)==0&s>>>0>4294967295){for(;f=CR(s|0,l|0,10,0)|0,c=c+-1|0,o[c>>0]=f&255|48,f=s,s=ER(s|0,l|0,10,0)|0,l>>>0>9|(l|0)==9&f>>>0>4294967295;)l=we;l=s}else l=s;if(l)for(;c=c+-1|0,o[c>>0]=(l>>>0)%10|0|48,!(l>>>0<10);)l=(l>>>0)/10|0;return c|0}function UUe(s){return s=s|0,WUe(s,n[(YUe()|0)+188>>2]|0)|0}function _Ue(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;m=l&255,f=(c|0)!=0;e:do if(f&(s&3|0)!=0)for(d=l&255;;){if((o[s>>0]|0)==d<<24>>24){B=6;break e}if(s=s+1|0,c=c+-1|0,f=(c|0)!=0,!(f&(s&3|0)!=0)){B=5;break}}else B=5;while(!1);(B|0)==5&&(f?B=6:c=0);e:do if((B|0)==6&&(d=l&255,(o[s>>0]|0)!=d<<24>>24)){f=Ue(m,16843009)|0;t:do if(c>>>0>3){for(;m=n[s>>2]^f,!((m&-2139062144^-2139062144)&m+-16843009|0);)if(s=s+4|0,c=c+-4|0,c>>>0<=3){B=11;break t}}else B=11;while(!1);if((B|0)==11&&!c){c=0;break}for(;;){if((o[s>>0]|0)==d<<24>>24)break e;if(s=s+1|0,c=c+-1|0,!c){c=0;break}}}while(!1);return(c|0?s:0)|0}function Ds(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0;if(B=C,C=C+256|0,m=B,(c|0)>(f|0)&(d&73728|0)==0){if(d=c-f|0,Od(m|0,l|0,(d>>>0<256?d:256)|0)|0,d>>>0>255){l=c-f|0;do as(s,m,256),d=d+-256|0;while(d>>>0>255);d=l&255}as(s,m,d)}C=B}function n7(s,l){return s=s|0,l=l|0,s?s=jUe(s,l,0)|0:s=0,s|0}function HUe(s,l,c,f,d,m){s=s|0,l=+l,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0,Qe=0,$e=0,Je=0,lt=0,_e=0,qe=0,Lt=0,Or=0,cr=0,Xt=0,Pr=0,Tr=0,ar=0,xn=0;xn=C,C=C+560|0,Q=xn+8|0,$e=xn,ar=xn+524|0,Tr=ar,O=xn+512|0,n[$e>>2]=0,Pr=O+12|0,i7(l)|0,(we|0)<0?(l=-l,cr=1,Or=5659):(cr=(d&2049|0)!=0&1,Or=d&2048|0?5662:d&1|0?5665:5660),i7(l)|0,Xt=we&2146435072;do if(Xt>>>0<2146435072|(Xt|0)==2146435072&!1){if(je=+qUe(l,$e)*2,B=je!=0,B&&(n[$e>>2]=(n[$e>>2]|0)+-1),lt=m|32,(lt|0)==97){Oe=m&32,se=Oe|0?Or+9|0:Or,j=cr|2,B=12-f|0;do if(f>>>0>11|(B|0)==0)l=je;else{l=8;do B=B+-1|0,l=l*16;while(B|0);if((o[se>>0]|0)==45){l=-(l+(-je-l));break}else{l=je+l-l;break}}while(!1);k=n[$e>>2]|0,B=(k|0)<0?0-k|0:k,B=Ld(B,((B|0)<0)<<31>>31,Pr)|0,(B|0)==(Pr|0)&&(B=O+11|0,o[B>>0]=48),o[B+-1>>0]=(k>>31&2)+43,M=B+-2|0,o[M>>0]=m+15,O=(f|0)<1,Q=(d&8|0)==0,B=ar;do Xt=~~l,k=B+1|0,o[B>>0]=u[5694+Xt>>0]|Oe,l=(l-+(Xt|0))*16,(k-Tr|0)==1&&!(Q&(O&l==0))?(o[k>>0]=46,B=B+2|0):B=k;while(l!=0);Xt=B-Tr|0,Tr=Pr-M|0,Pr=(f|0)!=0&(Xt+-2|0)<(f|0)?f+2|0:Xt,B=Tr+j+Pr|0,Ds(s,32,c,B,d),as(s,se,j),Ds(s,48,c,B,d^65536),as(s,ar,Xt),Ds(s,48,Pr-Xt|0,0,0),as(s,M,Tr),Ds(s,32,c,B,d^8192);break}k=(f|0)<0?6:f,B?(B=(n[$e>>2]|0)+-28|0,n[$e>>2]=B,l=je*268435456):(l=je,B=n[$e>>2]|0),Xt=(B|0)<0?Q:Q+288|0,Q=Xt;do qe=~~l>>>0,n[Q>>2]=qe,Q=Q+4|0,l=(l-+(qe>>>0))*1e9;while(l!=0);if((B|0)>0)for(O=Xt,j=Q;;){if(M=(B|0)<29?B:29,B=j+-4|0,B>>>0>=O>>>0){Q=0;do _e=u7(n[B>>2]|0,0,M|0)|0,_e=yR(_e|0,we|0,Q|0,0)|0,qe=we,Je=CR(_e|0,qe|0,1e9,0)|0,n[B>>2]=Je,Q=ER(_e|0,qe|0,1e9,0)|0,B=B+-4|0;while(B>>>0>=O>>>0);Q&&(O=O+-4|0,n[O>>2]=Q)}for(Q=j;!(Q>>>0<=O>>>0);)if(B=Q+-4|0,!(n[B>>2]|0))Q=B;else break;if(B=(n[$e>>2]|0)-M|0,n[$e>>2]=B,(B|0)>0)j=Q;else break}else O=Xt;if((B|0)<0){f=((k+25|0)/9|0)+1|0,Qe=(lt|0)==102;do{if(Oe=0-B|0,Oe=(Oe|0)<9?Oe:9,O>>>0<Q>>>0){M=(1<<Oe)+-1|0,j=1e9>>>Oe,se=0,B=O;do qe=n[B>>2]|0,n[B>>2]=(qe>>>Oe)+se,se=Ue(qe&M,j)|0,B=B+4|0;while(B>>>0<Q>>>0);B=n[O>>2]|0?O:O+4|0,se?(n[Q>>2]=se,O=B,B=Q+4|0):(O=B,B=Q)}else O=n[O>>2]|0?O:O+4|0,B=Q;Q=Qe?Xt:O,Q=(B-Q>>2|0)>(f|0)?Q+(f<<2)|0:B,B=(n[$e>>2]|0)+Oe|0,n[$e>>2]=B}while((B|0)<0);B=O,f=Q}else B=O,f=Q;if(qe=Xt,B>>>0<f>>>0){if(Q=(qe-B>>2)*9|0,M=n[B>>2]|0,M>>>0>=10){O=10;do O=O*10|0,Q=Q+1|0;while(M>>>0>=O>>>0)}}else Q=0;if(Qe=(lt|0)==103,Je=(k|0)!=0,O=k-((lt|0)!=102?Q:0)+((Je&Qe)<<31>>31)|0,(O|0)<(((f-qe>>2)*9|0)+-9|0)){if(O=O+9216|0,Oe=Xt+4+(((O|0)/9|0)+-1024<<2)|0,O=((O|0)%9|0)+1|0,(O|0)<9){M=10;do M=M*10|0,O=O+1|0;while((O|0)!=9)}else M=10;if(j=n[Oe>>2]|0,se=(j>>>0)%(M>>>0)|0,O=(Oe+4|0)==(f|0),O&(se|0)==0)O=Oe;else if(je=((j>>>0)/(M>>>0)|0)&1|0?9007199254740994:9007199254740992,_e=(M|0)/2|0,l=se>>>0<_e>>>0?.5:O&(se|0)==(_e|0)?1:1.5,cr&&(_e=(o[Or>>0]|0)==45,l=_e?-l:l,je=_e?-je:je),O=j-se|0,n[Oe>>2]=O,je+l!=je){if(_e=O+M|0,n[Oe>>2]=_e,_e>>>0>999999999)for(Q=Oe;O=Q+-4|0,n[Q>>2]=0,O>>>0<B>>>0&&(B=B+-4|0,n[B>>2]=0),_e=(n[O>>2]|0)+1|0,n[O>>2]=_e,_e>>>0>999999999;)Q=O;else O=Oe;if(Q=(qe-B>>2)*9|0,j=n[B>>2]|0,j>>>0>=10){M=10;do M=M*10|0,Q=Q+1|0;while(j>>>0>=M>>>0)}}else O=Oe;O=O+4|0,O=f>>>0>O>>>0?O:f,_e=B}else O=f,_e=B;for(lt=O;;){if(lt>>>0<=_e>>>0){$e=0;break}if(B=lt+-4|0,!(n[B>>2]|0))lt=B;else{$e=1;break}}f=0-Q|0;do if(Qe)if(B=((Je^1)&1)+k|0,(B|0)>(Q|0)&(Q|0)>-5?(M=m+-1|0,k=B+-1-Q|0):(M=m+-2|0,k=B+-1|0),B=d&8,B)Oe=B;else{if($e&&(Lt=n[lt+-4>>2]|0,(Lt|0)!=0))if((Lt>>>0)%10|0)O=0;else{O=0,B=10;do B=B*10|0,O=O+1|0;while(!((Lt>>>0)%(B>>>0)|0|0))}else O=9;if(B=((lt-qe>>2)*9|0)+-9|0,(M|32|0)==102){Oe=B-O|0,Oe=(Oe|0)>0?Oe:0,k=(k|0)<(Oe|0)?k:Oe,Oe=0;break}else{Oe=B+Q-O|0,Oe=(Oe|0)>0?Oe:0,k=(k|0)<(Oe|0)?k:Oe,Oe=0;break}}else M=m,Oe=d&8;while(!1);if(Qe=k|Oe,j=(Qe|0)!=0&1,se=(M|32|0)==102,se)Je=0,B=(Q|0)>0?Q:0;else{if(B=(Q|0)<0?f:Q,B=Ld(B,((B|0)<0)<<31>>31,Pr)|0,O=Pr,(O-B|0)<2)do B=B+-1|0,o[B>>0]=48;while((O-B|0)<2);o[B+-1>>0]=(Q>>31&2)+43,B=B+-2|0,o[B>>0]=M,Je=B,B=O-B|0}if(B=cr+1+k+j+B|0,Ds(s,32,c,B,d),as(s,Or,cr),Ds(s,48,c,B,d^65536),se){M=_e>>>0>Xt>>>0?Xt:_e,Oe=ar+9|0,j=Oe,se=ar+8|0,O=M;do{if(Q=Ld(n[O>>2]|0,0,Oe)|0,(O|0)==(M|0))(Q|0)==(Oe|0)&&(o[se>>0]=48,Q=se);else if(Q>>>0>ar>>>0){Od(ar|0,48,Q-Tr|0)|0;do Q=Q+-1|0;while(Q>>>0>ar>>>0)}as(s,Q,j-Q|0),O=O+4|0}while(O>>>0<=Xt>>>0);if(Qe|0&&as(s,5710,1),O>>>0<lt>>>0&(k|0)>0)for(;;){if(Q=Ld(n[O>>2]|0,0,Oe)|0,Q>>>0>ar>>>0){Od(ar|0,48,Q-Tr|0)|0;do Q=Q+-1|0;while(Q>>>0>ar>>>0)}if(as(s,Q,(k|0)<9?k:9),O=O+4|0,Q=k+-9|0,O>>>0<lt>>>0&(k|0)>9)k=Q;else{k=Q;break}}Ds(s,48,k+9|0,9,0)}else{if(Qe=$e?lt:_e+4|0,(k|0)>-1){$e=ar+9|0,Oe=(Oe|0)==0,f=$e,j=0-Tr|0,se=ar+8|0,M=_e;do{Q=Ld(n[M>>2]|0,0,$e)|0,(Q|0)==($e|0)&&(o[se>>0]=48,Q=se);do if((M|0)==(_e|0)){if(O=Q+1|0,as(s,Q,1),Oe&(k|0)<1){Q=O;break}as(s,5710,1),Q=O}else{if(Q>>>0<=ar>>>0)break;Od(ar|0,48,Q+j|0)|0;do Q=Q+-1|0;while(Q>>>0>ar>>>0)}while(!1);Tr=f-Q|0,as(s,Q,(k|0)>(Tr|0)?Tr:k),k=k-Tr|0,M=M+4|0}while(M>>>0<Qe>>>0&(k|0)>-1)}Ds(s,48,k+18|0,18,0),as(s,Je,Pr-Je|0)}Ds(s,32,c,B,d^8192)}else ar=(m&32|0)!=0,B=cr+3|0,Ds(s,32,c,B,d&-65537),as(s,Or,cr),as(s,l!=l|!1?ar?5686:5690:ar?5678:5682,3),Ds(s,32,c,B,d^8192);while(!1);return C=xn,((B|0)<(c|0)?c:B)|0}function i7(s){s=+s;var l=0;return E[v>>3]=s,l=n[v>>2]|0,we=n[v+4>>2]|0,l|0}function qUe(s,l){return s=+s,l=l|0,+ +s7(s,l)}function s7(s,l){s=+s,l=l|0;var c=0,f=0,d=0;switch(E[v>>3]=s,c=n[v>>2]|0,f=n[v+4>>2]|0,d=eD(c|0,f|0,52)|0,d&2047){case 0:{s!=0?(s=+s7(s*18446744073709552e3,l),c=(n[l>>2]|0)+-64|0):c=0,n[l>>2]=c;break}case 2047:break;default:n[l>>2]=(d&2047)+-1022,n[v>>2]=c,n[v+4>>2]=f&-2146435073|1071644672,s=+E[v>>3]}return+s}function jUe(s,l,c){s=s|0,l=l|0,c=c|0;do if(s){if(l>>>0<128){o[s>>0]=l,s=1;break}if(!(n[n[(GUe()|0)+188>>2]>>2]|0))if((l&-128|0)==57216){o[s>>0]=l,s=1;break}else{n[(Nd()|0)>>2]=84,s=-1;break}if(l>>>0<2048){o[s>>0]=l>>>6|192,o[s+1>>0]=l&63|128,s=2;break}if(l>>>0<55296|(l&-8192|0)==57344){o[s>>0]=l>>>12|224,o[s+1>>0]=l>>>6&63|128,o[s+2>>0]=l&63|128,s=3;break}if((l+-65536|0)>>>0<1048576){o[s>>0]=l>>>18|240,o[s+1>>0]=l>>>12&63|128,o[s+2>>0]=l>>>6&63|128,o[s+3>>0]=l&63|128,s=4;break}else{n[(Nd()|0)>>2]=84,s=-1;break}}else s=1;while(!1);return s|0}function GUe(){return gR()|0}function YUe(){return gR()|0}function WUe(s,l){s=s|0,l=l|0;var c=0,f=0;for(f=0;;){if((u[5712+f>>0]|0)==(s|0)){s=2;break}if(c=f+1|0,(c|0)==87){c=5800,f=87,s=5;break}else f=c}if((s|0)==2&&(f?(c=5800,s=5):c=5800),(s|0)==5)for(;;){do s=c,c=c+1|0;while(o[s>>0]|0);if(f=f+-1|0,f)s=5;else break}return KUe(c,n[l+20>>2]|0)|0}function KUe(s,l){return s=s|0,l=l|0,VUe(s,l)|0}function VUe(s,l){return s=s|0,l=l|0,l?l=zUe(n[l>>2]|0,n[l+4>>2]|0,s)|0:l=0,(l|0?l:s)|0}function zUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0;se=(n[s>>2]|0)+1794895138|0,m=x0(n[s+8>>2]|0,se)|0,f=x0(n[s+12>>2]|0,se)|0,d=x0(n[s+16>>2]|0,se)|0;e:do if(m>>>0<l>>>2>>>0&&(j=l-(m<<2)|0,f>>>0<j>>>0&d>>>0<j>>>0)&&!((d|f)&3|0)){for(j=f>>>2,M=d>>>2,O=0;;){if(k=m>>>1,Q=O+k|0,B=Q<<1,d=B+j|0,f=x0(n[s+(d<<2)>>2]|0,se)|0,d=x0(n[s+(d+1<<2)>>2]|0,se)|0,!(d>>>0<l>>>0&f>>>0<(l-d|0)>>>0)){f=0;break e}if(o[s+(d+f)>>0]|0){f=0;break e}if(f=$9(c,s+d|0)|0,!f)break;if(f=(f|0)<0,(m|0)==1){f=0;break e}else O=f?O:Q,m=f?k:m-k|0}f=B+M|0,d=x0(n[s+(f<<2)>>2]|0,se)|0,f=x0(n[s+(f+1<<2)>>2]|0,se)|0,f>>>0<l>>>0&d>>>0<(l-f|0)>>>0?f=o[s+(f+d)>>0]|0?0:s+f|0:f=0}else f=0;while(!1);return f|0}function x0(s,l){s=s|0,l=l|0;var c=0;return c=p7(s|0)|0,(l|0?c:s)|0}function JUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=c+16|0,d=n[f>>2]|0,d?m=5:XUe(c)|0?f=0:(d=n[f>>2]|0,m=5);e:do if((m|0)==5){if(k=c+20|0,B=n[k>>2]|0,f=B,(d-B|0)>>>0<l>>>0){f=rD[n[c+36>>2]&7](c,s,l)|0;break}t:do if((o[c+75>>0]|0)>-1){for(B=l;;){if(!B){m=0,d=s;break t}if(d=B+-1|0,(o[s+d>>0]|0)==10)break;B=d}if(f=rD[n[c+36>>2]&7](c,s,B)|0,f>>>0<B>>>0)break e;m=B,d=s+B|0,l=l-B|0,f=n[k>>2]|0}else m=0,d=s;while(!1);Dr(f|0,d|0,l|0)|0,n[k>>2]=(n[k>>2]|0)+l,f=m+l|0}while(!1);return f|0}function XUe(s){s=s|0;var l=0,c=0;return l=s+74|0,c=o[l>>0]|0,o[l>>0]=c+255|c,l=n[s>>2]|0,l&8?(n[s>>2]=l|32,s=-1):(n[s+8>>2]=0,n[s+4>>2]=0,c=n[s+44>>2]|0,n[s+28>>2]=c,n[s+20>>2]=c,n[s+16>>2]=c+(n[s+48>>2]|0),s=0),s|0}function _n(s,l){s=y(s),l=y(l);var c=0,f=0;c=o7(s)|0;do if((c&2147483647)>>>0<=2139095040){if(f=o7(l)|0,(f&2147483647)>>>0<=2139095040)if((f^c|0)<0){s=(c|0)<0?l:s;break}else{s=s<l?l:s;break}}else s=l;while(!1);return y(s)}function o7(s){return s=y(s),h[v>>2]=s,n[v>>2]|0|0}function k0(s,l){s=y(s),l=y(l);var c=0,f=0;c=a7(s)|0;do if((c&2147483647)>>>0<=2139095040){if(f=a7(l)|0,(f&2147483647)>>>0<=2139095040)if((f^c|0)<0){s=(c|0)<0?s:l;break}else{s=s<l?s:l;break}}else s=l;while(!1);return y(s)}function a7(s){return s=y(s),h[v>>2]=s,n[v>>2]|0|0}function mR(s,l){s=y(s),l=y(l);var c=0,f=0,d=0,m=0,B=0,k=0,Q=0,O=0;m=(h[v>>2]=s,n[v>>2]|0),k=(h[v>>2]=l,n[v>>2]|0),c=m>>>23&255,B=k>>>23&255,Q=m&-2147483648,d=k<<1;e:do if(d|0&&!((c|0)==255|((ZUe(l)|0)&2147483647)>>>0>2139095040)){if(f=m<<1,f>>>0<=d>>>0)return l=y(s*y(0)),y((f|0)==(d|0)?l:s);if(c)f=m&8388607|8388608;else{if(c=m<<9,(c|0)>-1){f=c,c=0;do c=c+-1|0,f=f<<1;while((f|0)>-1)}else c=0;f=m<<1-c}if(B)k=k&8388607|8388608;else{if(m=k<<9,(m|0)>-1){d=0;do d=d+-1|0,m=m<<1;while((m|0)>-1)}else d=0;B=d,k=k<<1-d}d=f-k|0,m=(d|0)>-1;t:do if((c|0)>(B|0)){for(;;){if(m)if(d)f=d;else break;if(f=f<<1,c=c+-1|0,d=f-k|0,m=(d|0)>-1,(c|0)<=(B|0))break t}l=y(s*y(0));break e}while(!1);if(m)if(d)f=d;else{l=y(s*y(0));break}if(f>>>0<8388608)do f=f<<1,c=c+-1|0;while(f>>>0<8388608);(c|0)>0?c=f+-8388608|c<<23:c=f>>>(1-c|0),l=(n[v>>2]=c|Q,y(h[v>>2]))}else O=3;while(!1);return(O|0)==3&&(l=y(s*l),l=y(l/l)),y(l)}function ZUe(s){return s=y(s),h[v>>2]=s,n[v>>2]|0|0}function $Ue(s,l){return s=s|0,l=l|0,e7(n[582]|0,s,l)|0}function Jr(s){s=s|0,Tt()}function Md(s){s=s|0}function e3e(s,l){return s=s|0,l=l|0,0}function t3e(s){return s=s|0,(l7(s+4|0)|0)==-1?(ef[n[(n[s>>2]|0)+8>>2]&127](s),s=1):s=0,s|0}function l7(s){s=s|0;var l=0;return l=n[s>>2]|0,n[s>>2]=l+-1,l+-1|0}function Sp(s){s=s|0,t3e(s)|0&&r3e(s)}function r3e(s){s=s|0;var l=0;l=s+8|0,n[l>>2]|0&&(l7(l)|0)!=-1||ef[n[(n[s>>2]|0)+16>>2]&127](s)}function Kt(s){s=s|0;var l=0;for(l=s|0?s:1;s=Jv(l)|0,!(s|0);){if(s=i3e()|0,!s){s=0;break}B7[s&0]()}return s|0}function c7(s){return s=s|0,Kt(s)|0}function gt(s){s=s|0,Xv(s)}function n3e(s){s=s|0,(o[s+11>>0]|0)<0&>(n[s>>2]|0)}function i3e(){var s=0;return s=n[2923]|0,n[2923]=s+0,s|0}function s3e(){}function $v(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,f=l-f-(c>>>0>s>>>0|0)>>>0,we=f,s-c>>>0|0|0}function yR(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,c=s+c>>>0,we=l+f+(c>>>0<s>>>0|0)>>>0,c|0|0}function Od(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;if(m=s+c|0,l=l&255,(c|0)>=67){for(;s&3;)o[s>>0]=l,s=s+1|0;for(f=m&-4|0,d=f-64|0,B=l|l<<8|l<<16|l<<24;(s|0)<=(d|0);)n[s>>2]=B,n[s+4>>2]=B,n[s+8>>2]=B,n[s+12>>2]=B,n[s+16>>2]=B,n[s+20>>2]=B,n[s+24>>2]=B,n[s+28>>2]=B,n[s+32>>2]=B,n[s+36>>2]=B,n[s+40>>2]=B,n[s+44>>2]=B,n[s+48>>2]=B,n[s+52>>2]=B,n[s+56>>2]=B,n[s+60>>2]=B,s=s+64|0;for(;(s|0)<(f|0);)n[s>>2]=B,s=s+4|0}for(;(s|0)<(m|0);)o[s>>0]=l,s=s+1|0;return m-c|0}function u7(s,l,c){return s=s|0,l=l|0,c=c|0,(c|0)<32?(we=l<<c|(s&(1<<c)-1<<32-c)>>>32-c,s<<c):(we=s<<c-32,0)}function eD(s,l,c){return s=s|0,l=l|0,c=c|0,(c|0)<32?(we=l>>>c,s>>>c|(l&(1<<c)-1)<<32-c):(we=0,l>>>c-32|0)}function Dr(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;if((c|0)>=8192)return fc(s|0,l|0,c|0)|0;if(m=s|0,d=s+c|0,(s&3)==(l&3)){for(;s&3;){if(!c)return m|0;o[s>>0]=o[l>>0]|0,s=s+1|0,l=l+1|0,c=c-1|0}for(c=d&-4|0,f=c-64|0;(s|0)<=(f|0);)n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2],n[s+16>>2]=n[l+16>>2],n[s+20>>2]=n[l+20>>2],n[s+24>>2]=n[l+24>>2],n[s+28>>2]=n[l+28>>2],n[s+32>>2]=n[l+32>>2],n[s+36>>2]=n[l+36>>2],n[s+40>>2]=n[l+40>>2],n[s+44>>2]=n[l+44>>2],n[s+48>>2]=n[l+48>>2],n[s+52>>2]=n[l+52>>2],n[s+56>>2]=n[l+56>>2],n[s+60>>2]=n[l+60>>2],s=s+64|0,l=l+64|0;for(;(s|0)<(c|0);)n[s>>2]=n[l>>2],s=s+4|0,l=l+4|0}else for(c=d-4|0;(s|0)<(c|0);)o[s>>0]=o[l>>0]|0,o[s+1>>0]=o[l+1>>0]|0,o[s+2>>0]=o[l+2>>0]|0,o[s+3>>0]=o[l+3>>0]|0,s=s+4|0,l=l+4|0;for(;(s|0)<(d|0);)o[s>>0]=o[l>>0]|0,s=s+1|0,l=l+1|0;return m|0}function A7(s){s=s|0;var l=0;return l=o[L+(s&255)>>0]|0,(l|0)<8?l|0:(l=o[L+(s>>8&255)>>0]|0,(l|0)<8?l+8|0:(l=o[L+(s>>16&255)>>0]|0,(l|0)<8?l+16|0:(o[L+(s>>>24)>>0]|0)+24|0))}function f7(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,Q=0,O=0,M=0,j=0,se=0,je=0,Oe=0;if(M=s,Q=l,O=Q,B=c,se=f,k=se,!O)return m=(d|0)!=0,k?m?(n[d>>2]=s|0,n[d+4>>2]=l&0,se=0,d=0,we=se,d|0):(se=0,d=0,we=se,d|0):(m&&(n[d>>2]=(M>>>0)%(B>>>0),n[d+4>>2]=0),se=0,d=(M>>>0)/(B>>>0)>>>0,we=se,d|0);m=(k|0)==0;do if(B){if(!m){if(m=(S(k|0)|0)-(S(O|0)|0)|0,m>>>0<=31){j=m+1|0,k=31-m|0,l=m-31>>31,B=j,s=M>>>(j>>>0)&l|O<<k,l=O>>>(j>>>0)&l,m=0,k=M<<k;break}return d?(n[d>>2]=s|0,n[d+4>>2]=Q|l&0,se=0,d=0,we=se,d|0):(se=0,d=0,we=se,d|0)}if(m=B-1|0,m&B|0){k=(S(B|0)|0)+33-(S(O|0)|0)|0,Oe=64-k|0,j=32-k|0,Q=j>>31,je=k-32|0,l=je>>31,B=k,s=j-1>>31&O>>>(je>>>0)|(O<<j|M>>>(k>>>0))&l,l=l&O>>>(k>>>0),m=M<<Oe&Q,k=(O<<Oe|M>>>(je>>>0))&Q|M<<j&k-33>>31;break}return d|0&&(n[d>>2]=m&M,n[d+4>>2]=0),(B|0)==1?(je=Q|l&0,Oe=s|0|0,we=je,Oe|0):(Oe=A7(B|0)|0,je=O>>>(Oe>>>0)|0,Oe=O<<32-Oe|M>>>(Oe>>>0)|0,we=je,Oe|0)}else{if(m)return d|0&&(n[d>>2]=(O>>>0)%(B>>>0),n[d+4>>2]=0),je=0,Oe=(O>>>0)/(B>>>0)>>>0,we=je,Oe|0;if(!M)return d|0&&(n[d>>2]=0,n[d+4>>2]=(O>>>0)%(k>>>0)),je=0,Oe=(O>>>0)/(k>>>0)>>>0,we=je,Oe|0;if(m=k-1|0,!(m&k))return d|0&&(n[d>>2]=s|0,n[d+4>>2]=m&O|l&0),je=0,Oe=O>>>((A7(k|0)|0)>>>0),we=je,Oe|0;if(m=(S(k|0)|0)-(S(O|0)|0)|0,m>>>0<=30){l=m+1|0,k=31-m|0,B=l,s=O<<k|M>>>(l>>>0),l=O>>>(l>>>0),m=0,k=M<<k;break}return d?(n[d>>2]=s|0,n[d+4>>2]=Q|l&0,je=0,Oe=0,we=je,Oe|0):(je=0,Oe=0,we=je,Oe|0)}while(!1);if(!B)O=k,Q=0,k=0;else{j=c|0|0,M=se|f&0,O=yR(j|0,M|0,-1,-1)|0,c=we,Q=k,k=0;do f=Q,Q=m>>>31|Q<<1,m=k|m<<1,f=s<<1|f>>>31|0,se=s>>>31|l<<1|0,$v(O|0,c|0,f|0,se|0)|0,Oe=we,je=Oe>>31|((Oe|0)<0?-1:0)<<1,k=je&1,s=$v(f|0,se|0,je&j|0,(((Oe|0)<0?-1:0)>>31|((Oe|0)<0?-1:0)<<1)&M|0)|0,l=we,B=B-1|0;while(B|0);O=Q,Q=0}return B=0,d|0&&(n[d>>2]=s,n[d+4>>2]=l),je=(m|0)>>>31|(O|B)<<1|(B<<1|m>>>31)&0|Q,Oe=(m<<1|0)&-2|k,we=je,Oe|0}function ER(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,f7(s,l,c,f,0)|0}function bp(s){s=s|0;var l=0,c=0;return c=s+15&-16|0,l=n[I>>2]|0,s=l+c|0,(c|0)>0&(s|0)<(l|0)|(s|0)<0?(ie()|0,vA(12),-1):(n[I>>2]=s,(s|0)>($()|0)&&!(X()|0)?(n[I>>2]=l,vA(12),-1):l|0)}function ww(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;if((l|0)<(s|0)&(s|0)<(l+c|0)){for(f=s,l=l+c|0,s=s+c|0;(c|0)>0;)s=s-1|0,l=l-1|0,c=c-1|0,o[s>>0]=o[l>>0]|0;s=f}else Dr(s,l,c)|0;return s|0}function CR(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;return m=C,C=C+16|0,d=m|0,f7(s,l,c,f,d)|0,C=m,we=n[d+4>>2]|0,n[d>>2]|0|0}function p7(s){return s=s|0,(s&255)<<24|(s>>8&255)<<16|(s>>16&255)<<8|s>>>24|0}function o3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,h7[s&1](l|0,c|0,f|0,d|0,m|0)}function a3e(s,l,c){s=s|0,l=l|0,c=y(c),g7[s&1](l|0,y(c))}function l3e(s,l,c){s=s|0,l=l|0,c=+c,d7[s&31](l|0,+c)}function c3e(s,l,c,f){return s=s|0,l=l|0,c=y(c),f=y(f),y(m7[s&0](l|0,y(c),y(f)))}function u3e(s,l){s=s|0,l=l|0,ef[s&127](l|0)}function A3e(s,l,c){s=s|0,l=l|0,c=c|0,tf[s&31](l|0,c|0)}function f3e(s,l){return s=s|0,l=l|0,F0[s&31](l|0)|0}function p3e(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0,y7[s&1](l|0,+c,+f,d|0)}function h3e(s,l,c,f){s=s|0,l=l|0,c=+c,f=+f,V3e[s&1](l|0,+c,+f)}function g3e(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,rD[s&7](l|0,c|0,f|0)|0}function d3e(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,+z3e[s&1](l|0,c|0,f|0)}function m3e(s,l){return s=s|0,l=l|0,+E7[s&15](l|0)}function y3e(s,l,c){return s=s|0,l=l|0,c=+c,J3e[s&1](l|0,+c)|0}function E3e(s,l,c){return s=s|0,l=l|0,c=c|0,IR[s&15](l|0,c|0)|0}function C3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=+f,d=+d,m=m|0,X3e[s&1](l|0,c|0,+f,+d,m|0)}function w3e(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,Z3e[s&1](l|0,c|0,f|0,d|0,m|0,B|0)}function I3e(s,l,c){return s=s|0,l=l|0,c=c|0,+C7[s&7](l|0,c|0)}function B3e(s){return s=s|0,nD[s&7]()|0}function v3e(s,l,c,f,d,m){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,w7[s&1](l|0,c|0,f|0,d|0,m|0)|0}function D3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=+d,$3e[s&1](l|0,c|0,f|0,+d)}function P3e(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=y(f),d=d|0,m=y(m),B=B|0,I7[s&1](l|0,c|0,y(f),d|0,y(m),B|0)}function S3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,vw[s&15](l|0,c|0,f|0)}function b3e(s){s=s|0,B7[s&0]()}function x3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f,v7[s&15](l|0,c|0,+f)}function k3e(s,l,c){return s=s|0,l=+l,c=+c,e_e[s&1](+l,+c)|0}function Q3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,BR[s&15](l|0,c|0,f|0,d|0)}function F3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,F(0)}function R3e(s,l){s=s|0,l=y(l),F(1)}function Ea(s,l){s=s|0,l=+l,F(2)}function T3e(s,l,c){return s=s|0,l=y(l),c=y(c),F(3),Xe}function Er(s){s=s|0,F(4)}function Iw(s,l){s=s|0,l=l|0,F(5)}function Xa(s){return s=s|0,F(6),0}function N3e(s,l,c,f){s=s|0,l=+l,c=+c,f=f|0,F(7)}function L3e(s,l,c){s=s|0,l=+l,c=+c,F(8)}function M3e(s,l,c){return s=s|0,l=l|0,c=c|0,F(9),0}function O3e(s,l,c){return s=s|0,l=l|0,c=c|0,F(10),0}function Q0(s){return s=s|0,F(11),0}function U3e(s,l){return s=s|0,l=+l,F(12),0}function Bw(s,l){return s=s|0,l=l|0,F(13),0}function _3e(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0,F(14)}function H3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,F(15)}function wR(s,l){return s=s|0,l=l|0,F(16),0}function q3e(){return F(17),0}function j3e(s,l,c,f,d){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,F(18),0}function G3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f,F(19)}function Y3e(s,l,c,f,d,m){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0,F(20)}function tD(s,l,c){s=s|0,l=l|0,c=c|0,F(21)}function W3e(){F(22)}function Ud(s,l,c){s=s|0,l=l|0,c=+c,F(23)}function K3e(s,l){return s=+s,l=+l,F(24),0}function _d(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,F(25)}var h7=[F3e,jLe],g7=[R3e,fo],d7=[Ea,fw,pw,lF,cF,Dl,hw,uF,xd,ku,dw,AF,Lv,WA,Mv,kd,Ov,Uv,Qd,Ea,Ea,Ea,Ea,Ea,Ea,Ea,Ea,Ea,Ea,Ea,Ea,Ea],m7=[T3e],ef=[Er,Md,BDe,vDe,DDe,exe,txe,rxe,yNe,ENe,CNe,kLe,QLe,FLe,Z4e,$4e,eUe,ds,Qv,bd,YA,gw,Eve,Cve,pDe,RDe,YDe,cPe,DPe,qPe,sSe,CSe,NSe,XSe,pbe,xbe,Ybe,Exe,Nxe,Xxe,pke,xke,Yke,uQe,DQe,UQe,tFe,bc,FFe,VFe,pRe,QRe,WRe,pTe,BTe,PTe,jTe,WTe,cNe,INe,DNe,qNe,oLe,eG,HMe,yOe,ROe,VOe,d4e,Q4e,q4e,Y4e,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er,Er],tf=[Iw,tF,rF,Aw,xu,nF,iF,Cp,sF,oF,aF,Nv,KA,Ve,At,Wt,vr,Sn,Qr,pF,ove,xve,hQe,bQe,NRe,GMe,hLe,O9,Iw,Iw,Iw,Iw],F0=[Xa,xUe,eF,D,fe,De,vt,wt,bt,_r,di,po,nve,ive,wve,iFe,JRe,YNe,VMe,Va,Xa,Xa,Xa,Xa,Xa,Xa,Xa,Xa,Xa,Xa,Xa,Xa],y7=[N3e,Ive],V3e=[L3e,fNe],rD=[M3e,Z9,kUe,RUe,WPe,Bxe,LFe,ZOe],z3e=[O3e,mbe],E7=[Q0,Yo,nt,bn,Bve,vve,Dve,Pve,Sve,bve,Q0,Q0,Q0,Q0,Q0,Q0],J3e=[U3e,CTe],IR=[Bw,e3e,sve,mDe,pPe,lSe,BSe,zbe,Uxe,jQe,xv,MOe,Bw,Bw,Bw,Bw],X3e=[_3e,zDe],Z3e=[H3e,C4e],C7=[wR,ai,kve,Qve,Fve,Rbe,wR,wR],nD=[q3e,Rve,cw,ma,kTe,JTe,xNe,z4e],w7=[j3e,nw],$3e=[G3e,mke],I7=[Y3e,ave],vw=[tD,T,os,tn,ho,xPe,OSe,Rke,zke,Sd,fMe,IOe,N4e,tD,tD,tD],B7=[W3e],v7=[Ud,Fv,Rv,Tv,GA,_v,fF,P,tke,ZFe,dTe,Ud,Ud,Ud,Ud,Ud],e_e=[K3e,dNe],BR=[_d,tbe,fFe,mRe,sTe,LTe,rNe,LNe,ALe,eOe,oUe,_d,_d,_d,_d,_d];return{_llvm_bswap_i32:p7,dynCall_idd:k3e,dynCall_i:B3e,_i64Subtract:$v,___udivdi3:ER,dynCall_vif:a3e,setThrew:du,dynCall_viii:S3e,_bitshift64Lshr:eD,_bitshift64Shl:u7,dynCall_vi:u3e,dynCall_viiddi:C3e,dynCall_diii:d3e,dynCall_iii:E3e,_memset:Od,_sbrk:bp,_memcpy:Dr,__GLOBAL__sub_I_Yoga_cpp:Pd,dynCall_vii:A3e,___uremdi3:CR,dynCall_vid:l3e,stackAlloc:lo,_nbind_init:mUe,getTempRet0:qa,dynCall_di:m3e,dynCall_iid:y3e,setTempRet0:bA,_i64Add:yR,dynCall_fiff:c3e,dynCall_iiii:g3e,_emscripten_get_global_libc:bUe,dynCall_viid:x3e,dynCall_viiid:D3e,dynCall_viififi:P3e,dynCall_ii:f3e,__GLOBAL__sub_I_Binding_cc:RMe,dynCall_viiii:Q3e,dynCall_iiiiii:v3e,stackSave:dc,dynCall_viiiii:o3e,__GLOBAL__sub_I_nbind_cc:Tve,dynCall_vidd:h3e,_free:Xv,runPostSets:s3e,dynCall_viiiiii:w3e,establishStackSpace:qi,_memmove:ww,stackRestore:gu,_malloc:Jv,__GLOBAL__sub_I_common_cc:$Ne,dynCall_viddi:p3e,dynCall_dii:I3e,dynCall_v:b3e}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(t){this.name="ExitStatus",this.message="Program terminated with exit("+t+")",this.status=t}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function t(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=t)},Module.callMain=Module.callMain=function t(e){e=e||[],ensureInitRuntime();var r=e.length+1;function o(){for(var p=0;p<3;p++)a.push(0)}var a=[allocate(intArrayFromString(Module.thisProgram),"i8",ALLOC_NORMAL)];o();for(var n=0;n<r-1;n=n+1)a.push(allocate(intArrayFromString(e[n]),"i8",ALLOC_NORMAL)),o();a.push(0),a=allocate(a,"i32",ALLOC_NORMAL);try{var u=Module._main(r,a,0);exit(u,!0)}catch(p){if(p instanceof ExitStatus)return;if(p=="SimulateInfiniteLoop"){Module.noExitRuntime=!0;return}else{var A=p;p&&typeof p=="object"&&p.stack&&(A=[p,p.stack]),Module.printErr("exception thrown: "+A),Module.quit(1,p)}}finally{calledMain=!0}};function run(t){if(t=t||Module.arguments,preloadStartTime===null&&(preloadStartTime=Date.now()),runDependencies>0||(preRun(),runDependencies>0)||Module.calledRun)return;function e(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(t),postRun()))}Module.setStatus?(Module.setStatus("Running..."),setTimeout(function(){setTimeout(function(){Module.setStatus("")},1),e()},1)):e()}Module.run=Module.run=run;function exit(t,e){e&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=t,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(t)),ENVIRONMENT_IS_NODE&&process.exit(t),Module.quit(t,new ExitStatus(t)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(t){Module.onAbort&&Module.onAbort(t),t!==void 0?(Module.print(t),Module.printErr(t),t=JSON.stringify(t)):t="",ABORT=!0,EXITSTATUS=1;var e=` +If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,r="abort("+t+") at "+stackTrace()+e;throw abortDecorators&&abortDecorators.forEach(function(o){r=o(r,t)}),r}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit=="function"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var Jg=_((SKt,_Ee)=>{"use strict";var Jyt=OEe(),Xyt=UEe(),v6=!1,D6=null;Xyt({},function(t,e){if(!v6){if(v6=!0,t)throw t;D6=e}});if(!v6)throw new Error("Failed to load the yoga module - it needed to be loaded synchronously, but didn't");_Ee.exports=Jyt(D6.bind,D6.lib)});var S6=_((bKt,P6)=>{"use strict";var HEe=t=>Number.isNaN(t)?!1:t>=4352&&(t<=4447||t===9001||t===9002||11904<=t&&t<=12871&&t!==12351||12880<=t&&t<=19903||19968<=t&&t<=42182||43360<=t&&t<=43388||44032<=t&&t<=55203||63744<=t&&t<=64255||65040<=t&&t<=65049||65072<=t&&t<=65131||65281<=t&&t<=65376||65504<=t&&t<=65510||110592<=t&&t<=110593||127488<=t&&t<=127569||131072<=t&&t<=262141);P6.exports=HEe;P6.exports.default=HEe});var jEe=_((xKt,qEe)=>{"use strict";qEe.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g}});var Lk=_((kKt,b6)=>{"use strict";var Zyt=BP(),$yt=S6(),eEt=jEe(),GEe=t=>{if(typeof t!="string"||t.length===0||(t=Zyt(t),t.length===0))return 0;t=t.replace(eEt()," ");let e=0;for(let r=0;r<t.length;r++){let o=t.codePointAt(r);o<=31||o>=127&&o<=159||o>=768&&o<=879||(o>65535&&r++,e+=$yt(o)?2:1)}return e};b6.exports=GEe;b6.exports.default=GEe});var k6=_((QKt,x6)=>{"use strict";var tEt=Lk(),YEe=t=>{let e=0;for(let r of t.split(` +`))e=Math.max(e,tEt(r));return e};x6.exports=YEe;x6.exports.default=YEe});var WEe=_(W2=>{"use strict";var rEt=W2&&W2.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(W2,"__esModule",{value:!0});var nEt=rEt(k6()),Q6={};W2.default=t=>{if(t.length===0)return{width:0,height:0};if(Q6[t])return Q6[t];let e=nEt.default(t),r=t.split(` +`).length;return Q6[t]={width:e,height:r},{width:e,height:r}}});var KEe=_(K2=>{"use strict";var iEt=K2&&K2.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(K2,"__esModule",{value:!0});var dn=iEt(Jg()),sEt=(t,e)=>{"position"in e&&t.setPositionType(e.position==="absolute"?dn.default.POSITION_TYPE_ABSOLUTE:dn.default.POSITION_TYPE_RELATIVE)},oEt=(t,e)=>{"marginLeft"in e&&t.setMargin(dn.default.EDGE_START,e.marginLeft||0),"marginRight"in e&&t.setMargin(dn.default.EDGE_END,e.marginRight||0),"marginTop"in e&&t.setMargin(dn.default.EDGE_TOP,e.marginTop||0),"marginBottom"in e&&t.setMargin(dn.default.EDGE_BOTTOM,e.marginBottom||0)},aEt=(t,e)=>{"paddingLeft"in e&&t.setPadding(dn.default.EDGE_LEFT,e.paddingLeft||0),"paddingRight"in e&&t.setPadding(dn.default.EDGE_RIGHT,e.paddingRight||0),"paddingTop"in e&&t.setPadding(dn.default.EDGE_TOP,e.paddingTop||0),"paddingBottom"in e&&t.setPadding(dn.default.EDGE_BOTTOM,e.paddingBottom||0)},lEt=(t,e)=>{var r;"flexGrow"in e&&t.setFlexGrow((r=e.flexGrow)!==null&&r!==void 0?r:0),"flexShrink"in e&&t.setFlexShrink(typeof e.flexShrink=="number"?e.flexShrink:1),"flexDirection"in e&&(e.flexDirection==="row"&&t.setFlexDirection(dn.default.FLEX_DIRECTION_ROW),e.flexDirection==="row-reverse"&&t.setFlexDirection(dn.default.FLEX_DIRECTION_ROW_REVERSE),e.flexDirection==="column"&&t.setFlexDirection(dn.default.FLEX_DIRECTION_COLUMN),e.flexDirection==="column-reverse"&&t.setFlexDirection(dn.default.FLEX_DIRECTION_COLUMN_REVERSE)),"flexBasis"in e&&(typeof e.flexBasis=="number"?t.setFlexBasis(e.flexBasis):typeof e.flexBasis=="string"?t.setFlexBasisPercent(Number.parseInt(e.flexBasis,10)):t.setFlexBasis(NaN)),"alignItems"in e&&((e.alignItems==="stretch"||!e.alignItems)&&t.setAlignItems(dn.default.ALIGN_STRETCH),e.alignItems==="flex-start"&&t.setAlignItems(dn.default.ALIGN_FLEX_START),e.alignItems==="center"&&t.setAlignItems(dn.default.ALIGN_CENTER),e.alignItems==="flex-end"&&t.setAlignItems(dn.default.ALIGN_FLEX_END)),"alignSelf"in e&&((e.alignSelf==="auto"||!e.alignSelf)&&t.setAlignSelf(dn.default.ALIGN_AUTO),e.alignSelf==="flex-start"&&t.setAlignSelf(dn.default.ALIGN_FLEX_START),e.alignSelf==="center"&&t.setAlignSelf(dn.default.ALIGN_CENTER),e.alignSelf==="flex-end"&&t.setAlignSelf(dn.default.ALIGN_FLEX_END)),"justifyContent"in e&&((e.justifyContent==="flex-start"||!e.justifyContent)&&t.setJustifyContent(dn.default.JUSTIFY_FLEX_START),e.justifyContent==="center"&&t.setJustifyContent(dn.default.JUSTIFY_CENTER),e.justifyContent==="flex-end"&&t.setJustifyContent(dn.default.JUSTIFY_FLEX_END),e.justifyContent==="space-between"&&t.setJustifyContent(dn.default.JUSTIFY_SPACE_BETWEEN),e.justifyContent==="space-around"&&t.setJustifyContent(dn.default.JUSTIFY_SPACE_AROUND))},cEt=(t,e)=>{var r,o;"width"in e&&(typeof e.width=="number"?t.setWidth(e.width):typeof e.width=="string"?t.setWidthPercent(Number.parseInt(e.width,10)):t.setWidthAuto()),"height"in e&&(typeof e.height=="number"?t.setHeight(e.height):typeof e.height=="string"?t.setHeightPercent(Number.parseInt(e.height,10)):t.setHeightAuto()),"minWidth"in e&&(typeof e.minWidth=="string"?t.setMinWidthPercent(Number.parseInt(e.minWidth,10)):t.setMinWidth((r=e.minWidth)!==null&&r!==void 0?r:0)),"minHeight"in e&&(typeof e.minHeight=="string"?t.setMinHeightPercent(Number.parseInt(e.minHeight,10)):t.setMinHeight((o=e.minHeight)!==null&&o!==void 0?o:0))},uEt=(t,e)=>{"display"in e&&t.setDisplay(e.display==="flex"?dn.default.DISPLAY_FLEX:dn.default.DISPLAY_NONE)},AEt=(t,e)=>{if("borderStyle"in e){let r=typeof e.borderStyle=="string"?1:0;t.setBorder(dn.default.EDGE_TOP,r),t.setBorder(dn.default.EDGE_BOTTOM,r),t.setBorder(dn.default.EDGE_LEFT,r),t.setBorder(dn.default.EDGE_RIGHT,r)}};K2.default=(t,e={})=>{sEt(t,e),oEt(t,e),aEt(t,e),lEt(t,e),cEt(t,e),uEt(t,e),AEt(t,e)}});var JEe=_((TKt,zEe)=>{"use strict";var V2=Lk(),fEt=BP(),pEt=aI(),R6=new Set(["\x1B","\x9B"]),hEt=39,VEe=t=>`${R6.values().next().value}[${t}m`,gEt=t=>t.split(" ").map(e=>V2(e)),F6=(t,e,r)=>{let o=[...e],a=!1,n=V2(fEt(t[t.length-1]));for(let[u,A]of o.entries()){let p=V2(A);if(n+p<=r?t[t.length-1]+=A:(t.push(A),n=0),R6.has(A))a=!0;else if(a&&A==="m"){a=!1;continue}a||(n+=p,n===r&&u<o.length-1&&(t.push(""),n=0))}!n&&t[t.length-1].length>0&&t.length>1&&(t[t.length-2]+=t.pop())},dEt=t=>{let e=t.split(" "),r=e.length;for(;r>0&&!(V2(e[r-1])>0);)r--;return r===e.length?t:e.slice(0,r).join(" ")+e.slice(r).join("")},mEt=(t,e,r={})=>{if(r.trim!==!1&&t.trim()==="")return"";let o="",a="",n,u=gEt(t),A=[""];for(let[p,h]of t.split(" ").entries()){r.trim!==!1&&(A[A.length-1]=A[A.length-1].trimLeft());let E=V2(A[A.length-1]);if(p!==0&&(E>=e&&(r.wordWrap===!1||r.trim===!1)&&(A.push(""),E=0),(E>0||r.trim===!1)&&(A[A.length-1]+=" ",E++)),r.hard&&u[p]>e){let I=e-E,v=1+Math.floor((u[p]-I-1)/e);Math.floor((u[p]-1)/e)<v&&A.push(""),F6(A,h,e);continue}if(E+u[p]>e&&E>0&&u[p]>0){if(r.wordWrap===!1&&E<e){F6(A,h,e);continue}A.push("")}if(E+u[p]>e&&r.wordWrap===!1){F6(A,h,e);continue}A[A.length-1]+=h}r.trim!==!1&&(A=A.map(dEt)),o=A.join(` +`);for(let[p,h]of[...o].entries()){if(a+=h,R6.has(h)){let I=parseFloat(/\d[^m]*/.exec(o.slice(p,p+4)));n=I===hEt?null:I}let E=pEt.codes.get(Number(n));n&&E&&(o[p+1]===` +`?a+=VEe(E):h===` +`&&(a+=VEe(n)))}return a};zEe.exports=(t,e,r)=>String(t).normalize().replace(/\r\n/g,` +`).split(` +`).map(o=>mEt(o,e,r)).join(` +`)});var $Ee=_((NKt,ZEe)=>{"use strict";var XEe="[\uD800-\uDBFF][\uDC00-\uDFFF]",yEt=t=>t&&t.exact?new RegExp(`^${XEe}$`):new RegExp(XEe,"g");ZEe.exports=yEt});var T6=_((LKt,nCe)=>{"use strict";var EEt=S6(),CEt=$Ee(),eCe=aI(),rCe=["\x1B","\x9B"],Mk=t=>`${rCe[0]}[${t}m`,tCe=(t,e,r)=>{let o=[];t=[...t];for(let a of t){let n=a;a.match(";")&&(a=a.split(";")[0][0]+"0");let u=eCe.codes.get(parseInt(a,10));if(u){let A=t.indexOf(u.toString());A>=0?t.splice(A,1):o.push(Mk(e?u:n))}else if(e){o.push(Mk(0));break}else o.push(Mk(n))}if(e&&(o=o.filter((a,n)=>o.indexOf(a)===n),r!==void 0)){let a=Mk(eCe.codes.get(parseInt(r,10)));o=o.reduce((n,u)=>u===a?[u,...n]:[...n,u],[])}return o.join("")};nCe.exports=(t,e,r)=>{let o=[...t.normalize()],a=[];r=typeof r=="number"?r:o.length;let n=!1,u,A=0,p="";for(let[h,E]of o.entries()){let I=!1;if(rCe.includes(E)){let v=/\d[^m]*/.exec(t.slice(h,h+18));u=v&&v.length>0?v[0]:void 0,A<r&&(n=!0,u!==void 0&&a.push(u))}else n&&E==="m"&&(n=!1,I=!0);if(!n&&!I&&++A,!CEt({exact:!0}).test(E)&&EEt(E.codePointAt())&&++A,A>e&&A<=r)p+=E;else if(A===e&&!n&&u!==void 0)p=tCe(a);else if(A>=r){p+=tCe(a,!0,u);break}}return p}});var sCe=_((MKt,iCe)=>{"use strict";var Nh=T6(),wEt=Lk();function Ok(t,e,r){if(t.charAt(e)===" ")return e;for(let o=1;o<=3;o++)if(r){if(t.charAt(e+o)===" ")return e+o}else if(t.charAt(e-o)===" ")return e-o;return e}iCe.exports=(t,e,r)=>{r={position:"end",preferTruncationOnSpace:!1,...r};let{position:o,space:a,preferTruncationOnSpace:n}=r,u="\u2026",A=1;if(typeof t!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof t}`);if(typeof e!="number")throw new TypeError(`Expected \`columns\` to be a number, got ${typeof e}`);if(e<1)return"";if(e===1)return u;let p=wEt(t);if(p<=e)return t;if(o==="start"){if(n){let h=Ok(t,p-e+1,!0);return u+Nh(t,h,p).trim()}return a===!0&&(u+=" ",A=2),u+Nh(t,p-e+A,p)}if(o==="middle"){a===!0&&(u=" "+u+" ",A=3);let h=Math.floor(e/2);if(n){let E=Ok(t,h),I=Ok(t,p-(e-h)+1,!0);return Nh(t,0,E)+u+Nh(t,I,p).trim()}return Nh(t,0,h)+u+Nh(t,p-(e-h)+A,p)}if(o==="end"){if(n){let h=Ok(t,e-1);return Nh(t,0,h)+u}return a===!0&&(u=" "+u,A=2),Nh(t,0,e-A)+u}throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${o}`)}});var L6=_(z2=>{"use strict";var oCe=z2&&z2.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(z2,"__esModule",{value:!0});var IEt=oCe(JEe()),BEt=oCe(sCe()),N6={};z2.default=(t,e,r)=>{let o=t+String(e)+String(r);if(N6[o])return N6[o];let a=t;if(r==="wrap"&&(a=IEt.default(t,e,{trim:!1,hard:!0})),r.startsWith("truncate")){let n="end";r==="truncate-middle"&&(n="middle"),r==="truncate-start"&&(n="start"),a=BEt.default(t,e,{position:n})}return N6[o]=a,a}});var O6=_(M6=>{"use strict";Object.defineProperty(M6,"__esModule",{value:!0});var aCe=t=>{let e="";if(t.childNodes.length>0)for(let r of t.childNodes){let o="";r.nodeName==="#text"?o=r.nodeValue:((r.nodeName==="ink-text"||r.nodeName==="ink-virtual-text")&&(o=aCe(r)),o.length>0&&typeof r.internal_transform=="function"&&(o=r.internal_transform(o))),e+=o}return e};M6.default=aCe});var U6=_(pi=>{"use strict";var J2=pi&&pi.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(pi,"__esModule",{value:!0});pi.setTextNodeValue=pi.createTextNode=pi.setStyle=pi.setAttribute=pi.removeChildNode=pi.insertBeforeNode=pi.appendChildNode=pi.createNode=pi.TEXT_NAME=void 0;var vEt=J2(Jg()),lCe=J2(WEe()),DEt=J2(KEe()),PEt=J2(L6()),SEt=J2(O6());pi.TEXT_NAME="#text";pi.createNode=t=>{var e;let r={nodeName:t,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:t==="ink-virtual-text"?void 0:vEt.default.Node.create()};return t==="ink-text"&&((e=r.yogaNode)===null||e===void 0||e.setMeasureFunc(bEt.bind(null,r))),r};pi.appendChildNode=(t,e)=>{var r;e.parentNode&&pi.removeChildNode(e.parentNode,e),e.parentNode=t,t.childNodes.push(e),e.yogaNode&&((r=t.yogaNode)===null||r===void 0||r.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&Uk(t)};pi.insertBeforeNode=(t,e,r)=>{var o,a;e.parentNode&&pi.removeChildNode(e.parentNode,e),e.parentNode=t;let n=t.childNodes.indexOf(r);if(n>=0){t.childNodes.splice(n,0,e),e.yogaNode&&((o=t.yogaNode)===null||o===void 0||o.insertChild(e.yogaNode,n));return}t.childNodes.push(e),e.yogaNode&&((a=t.yogaNode)===null||a===void 0||a.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&Uk(t)};pi.removeChildNode=(t,e)=>{var r,o;e.yogaNode&&((o=(r=e.parentNode)===null||r===void 0?void 0:r.yogaNode)===null||o===void 0||o.removeChild(e.yogaNode)),e.parentNode=null;let a=t.childNodes.indexOf(e);a>=0&&t.childNodes.splice(a,1),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&Uk(t)};pi.setAttribute=(t,e,r)=>{t.attributes[e]=r};pi.setStyle=(t,e)=>{t.style=e,t.yogaNode&&DEt.default(t.yogaNode,e)};pi.createTextNode=t=>{let e={nodeName:"#text",nodeValue:t,yogaNode:void 0,parentNode:null,style:{}};return pi.setTextNodeValue(e,t),e};var bEt=function(t,e){var r,o;let a=t.nodeName==="#text"?t.nodeValue:SEt.default(t),n=lCe.default(a);if(n.width<=e||n.width>=1&&e>0&&e<1)return n;let u=(o=(r=t.style)===null||r===void 0?void 0:r.textWrap)!==null&&o!==void 0?o:"wrap",A=PEt.default(a,e,u);return lCe.default(A)},cCe=t=>{var e;if(!(!t||!t.parentNode))return(e=t.yogaNode)!==null&&e!==void 0?e:cCe(t.parentNode)},Uk=t=>{let e=cCe(t);e?.markDirty()};pi.setTextNodeValue=(t,e)=>{typeof e!="string"&&(e=String(e)),t.nodeValue=e,Uk(t)}});var hCe=_(X2=>{"use strict";var pCe=X2&&X2.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(X2,"__esModule",{value:!0});var uCe=w6(),xEt=pCe(FEe()),ACe=pCe(Jg()),Mo=U6(),fCe=t=>{t?.unsetMeasureFunc(),t?.freeRecursive()};X2.default=xEt.default({schedulePassiveEffects:uCe.unstable_scheduleCallback,cancelPassiveEffects:uCe.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>{},resetAfterCommit:t=>{if(t.isStaticDirty){t.isStaticDirty=!1,typeof t.onImmediateRender=="function"&&t.onImmediateRender();return}typeof t.onRender=="function"&&t.onRender()},getChildHostContext:(t,e)=>{let r=t.isInsideText,o=e==="ink-text"||e==="ink-virtual-text";return r===o?t:{isInsideText:o}},shouldSetTextContent:()=>!1,createInstance:(t,e,r,o)=>{if(o.isInsideText&&t==="ink-box")throw new Error("<Box> can\u2019t be nested inside <Text> component");let a=t==="ink-text"&&o.isInsideText?"ink-virtual-text":t,n=Mo.createNode(a);for(let[u,A]of Object.entries(e))u!=="children"&&(u==="style"?Mo.setStyle(n,A):u==="internal_transform"?n.internal_transform=A:u==="internal_static"?n.internal_static=!0:Mo.setAttribute(n,u,A));return n},createTextInstance:(t,e,r)=>{if(!r.isInsideText)throw new Error(`Text string "${t}" must be rendered inside <Text> component`);return Mo.createTextNode(t)},resetTextContent:()=>{},hideTextInstance:t=>{Mo.setTextNodeValue(t,"")},unhideTextInstance:(t,e)=>{Mo.setTextNodeValue(t,e)},getPublicInstance:t=>t,hideInstance:t=>{var e;(e=t.yogaNode)===null||e===void 0||e.setDisplay(ACe.default.DISPLAY_NONE)},unhideInstance:t=>{var e;(e=t.yogaNode)===null||e===void 0||e.setDisplay(ACe.default.DISPLAY_FLEX)},appendInitialChild:Mo.appendChildNode,appendChild:Mo.appendChildNode,insertBefore:Mo.insertBeforeNode,finalizeInitialChildren:(t,e,r,o)=>(t.internal_static&&(o.isStaticDirty=!0,o.staticNode=t),!1),supportsMutation:!0,appendChildToContainer:Mo.appendChildNode,insertInContainerBefore:Mo.insertBeforeNode,removeChildFromContainer:(t,e)=>{Mo.removeChildNode(t,e),fCe(e.yogaNode)},prepareUpdate:(t,e,r,o,a)=>{t.internal_static&&(a.isStaticDirty=!0);let n={},u=Object.keys(o);for(let A of u)if(o[A]!==r[A]){if(A==="style"&&typeof o.style=="object"&&typeof r.style=="object"){let h=o.style,E=r.style,I=Object.keys(h);for(let v of I){if(v==="borderStyle"||v==="borderColor"){if(typeof n.style!="object"){let x={};n.style=x}n.style.borderStyle=h.borderStyle,n.style.borderColor=h.borderColor}if(h[v]!==E[v]){if(typeof n.style!="object"){let x={};n.style=x}n.style[v]=h[v]}}continue}n[A]=o[A]}return n},commitUpdate:(t,e)=>{for(let[r,o]of Object.entries(e))r!=="children"&&(r==="style"?Mo.setStyle(t,o):r==="internal_transform"?t.internal_transform=o:r==="internal_static"?t.internal_static=!0:Mo.setAttribute(t,r,o))},commitTextUpdate:(t,e,r)=>{Mo.setTextNodeValue(t,r)},removeChild:(t,e)=>{Mo.removeChildNode(t,e),fCe(e.yogaNode)}})});var dCe=_((qKt,gCe)=>{"use strict";gCe.exports=(t,e=1,r)=>{if(r={indent:" ",includeEmptyLines:!1,...r},typeof t!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof t}\``);if(typeof e!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof e}\``);if(typeof r.indent!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof r.indent}\``);if(e===0)return t;let o=r.includeEmptyLines?/^/gm:/^(?!\s*$)/gm;return t.replace(o,r.indent.repeat(e))}});var mCe=_(Z2=>{"use strict";var kEt=Z2&&Z2.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Z2,"__esModule",{value:!0});var _k=kEt(Jg());Z2.default=t=>t.getComputedWidth()-t.getComputedPadding(_k.default.EDGE_LEFT)-t.getComputedPadding(_k.default.EDGE_RIGHT)-t.getComputedBorder(_k.default.EDGE_LEFT)-t.getComputedBorder(_k.default.EDGE_RIGHT)});var yCe=_((GKt,QEt)=>{QEt.exports={single:{topLeft:"\u250C",topRight:"\u2510",bottomRight:"\u2518",bottomLeft:"\u2514",vertical:"\u2502",horizontal:"\u2500"},double:{topLeft:"\u2554",topRight:"\u2557",bottomRight:"\u255D",bottomLeft:"\u255A",vertical:"\u2551",horizontal:"\u2550"},round:{topLeft:"\u256D",topRight:"\u256E",bottomRight:"\u256F",bottomLeft:"\u2570",vertical:"\u2502",horizontal:"\u2500"},bold:{topLeft:"\u250F",topRight:"\u2513",bottomRight:"\u251B",bottomLeft:"\u2517",vertical:"\u2503",horizontal:"\u2501"},singleDouble:{topLeft:"\u2553",topRight:"\u2556",bottomRight:"\u255C",bottomLeft:"\u2559",vertical:"\u2551",horizontal:"\u2500"},doubleSingle:{topLeft:"\u2552",topRight:"\u2555",bottomRight:"\u255B",bottomLeft:"\u2558",vertical:"\u2502",horizontal:"\u2550"},classic:{topLeft:"+",topRight:"+",bottomRight:"+",bottomLeft:"+",vertical:"|",horizontal:"-"}}});var CCe=_((YKt,_6)=>{"use strict";var ECe=yCe();_6.exports=ECe;_6.exports.default=ECe});var ICe=_((WKt,wCe)=>{"use strict";var FEt=(t,e,r)=>{let o=t.indexOf(e);if(o===-1)return t;let a=e.length,n=0,u="";do u+=t.substr(n,o-n)+e+r,n=o+a,o=t.indexOf(e,n);while(o!==-1);return u+=t.substr(n),u},REt=(t,e,r,o)=>{let a=0,n="";do{let u=t[o-1]==="\r";n+=t.substr(a,(u?o-1:o)-a)+e+(u?`\r +`:` +`)+r,a=o+1,o=t.indexOf(` +`,a)}while(o!==-1);return n+=t.substr(a),n};wCe.exports={stringReplaceAll:FEt,stringEncaseCRLFWithFirstIndex:REt}});var SCe=_((KKt,PCe)=>{"use strict";var TEt=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,BCe=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,NEt=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,LEt=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,MEt=new Map([["n",` +`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function DCe(t){let e=t[0]==="u",r=t[1]==="{";return e&&!r&&t.length===5||t[0]==="x"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):MEt.get(t)||t}function OEt(t,e){let r=[],o=e.trim().split(/\s*,\s*/g),a;for(let n of o){let u=Number(n);if(!Number.isNaN(u))r.push(u);else if(a=n.match(NEt))r.push(a[2].replace(LEt,(A,p,h)=>p?DCe(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function UEt(t){BCe.lastIndex=0;let e=[],r;for(;(r=BCe.exec(t))!==null;){let o=r[1];if(r[2]){let a=OEt(o,r[2]);e.push([o].concat(a))}else e.push([o])}return e}function vCe(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let o=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in o))throw new Error(`Unknown Chalk style: ${a}`);o=n.length>0?o[a](...n):o[a]}return o}PCe.exports=(t,e)=>{let r=[],o=[],a=[];if(e.replace(TEt,(n,u,A,p,h,E)=>{if(u)a.push(DCe(u));else if(p){let I=a.join("");a=[],o.push(r.length===0?I:vCe(t,r)(I)),r.push({inverse:A,styles:UEt(p)})}else if(h){if(r.length===0)throw new Error("Found extraneous } in Chalk template literal");o.push(vCe(t,r)(a.join(""))),a=[],r.pop()}else a.push(E)}),o.push(a.join("")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?"":"s"} (\`}\`)`;throw new Error(n)}return o.join("")}});var Yk=_((VKt,RCe)=>{"use strict";var $2=aI(),{stdout:q6,stderr:j6}=aN(),{stringReplaceAll:_Et,stringEncaseCRLFWithFirstIndex:HEt}=ICe(),{isArray:Hk}=Array,xCe=["ansi","ansi","ansi256","ansi16m"],nC=Object.create(null),qEt=(t,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let r=q6?q6.level:0;t.level=e.level===void 0?r:e.level},G6=class{constructor(e){return kCe(e)}},kCe=t=>{let e={};return qEt(e,t),e.template=(...r)=>FCe(e.template,...r),Object.setPrototypeOf(e,qk.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},e.template.Instance=G6,e.template};function qk(t){return kCe(t)}for(let[t,e]of Object.entries($2))nC[t]={get(){let r=jk(this,Y6(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};nC.visible={get(){let t=jk(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:t}),t}};var QCe=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let t of QCe)nC[t]={get(){let{level:e}=this;return function(...r){let o=Y6($2.color[xCe[e]][t](...r),$2.color.close,this._styler);return jk(this,o,this._isEmpty)}}};for(let t of QCe){let e="bg"+t[0].toUpperCase()+t.slice(1);nC[e]={get(){let{level:r}=this;return function(...o){let a=Y6($2.bgColor[xCe[r]][t](...o),$2.bgColor.close,this._styler);return jk(this,a,this._isEmpty)}}}}var jEt=Object.defineProperties(()=>{},{...nC,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),Y6=(t,e,r)=>{let o,a;return r===void 0?(o=t,a=e):(o=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:a,parent:r}},jk=(t,e,r)=>{let o=(...a)=>Hk(a[0])&&Hk(a[0].raw)?bCe(o,FCe(o,...a)):bCe(o,a.length===1?""+a[0]:a.join(" "));return Object.setPrototypeOf(o,jEt),o._generator=t,o._styler=e,o._isEmpty=r,o},bCe=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?"":e;let r=t._styler;if(r===void 0)return e;let{openAll:o,closeAll:a}=r;if(e.indexOf("\x1B")!==-1)for(;r!==void 0;)e=_Et(e,r.close,r.open),r=r.parent;let n=e.indexOf(` +`);return n!==-1&&(e=HEt(e,a,o,n)),o+e+a},H6,FCe=(t,...e)=>{let[r]=e;if(!Hk(r)||!Hk(r.raw))return e.join(" ");let o=e.slice(1),a=[r.raw[0]];for(let n=1;n<r.length;n++)a.push(String(o[n-1]).replace(/[{}\\]/g,"\\$&"),String(r.raw[n]));return H6===void 0&&(H6=SCe()),H6(t,a.join(""))};Object.defineProperties(qk.prototype,nC);var Gk=qk();Gk.supportsColor=q6;Gk.stderr=qk({level:j6?j6.level:0});Gk.stderr.supportsColor=j6;RCe.exports=Gk});var W6=_(tB=>{"use strict";var GEt=tB&&tB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(tB,"__esModule",{value:!0});var eB=GEt(Yk()),YEt=/^(rgb|hsl|hsv|hwb)\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/,WEt=/^(ansi|ansi256)\(\s?(\d+)\s?\)$/,Wk=(t,e)=>e==="foreground"?t:"bg"+t[0].toUpperCase()+t.slice(1);tB.default=(t,e,r)=>{if(!e)return t;if(e in eB.default){let a=Wk(e,r);return eB.default[a](t)}if(e.startsWith("#")){let a=Wk("hex",r);return eB.default[a](e)(t)}if(e.startsWith("ansi")){let a=WEt.exec(e);if(!a)return t;let n=Wk(a[1],r),u=Number(a[2]);return eB.default[n](u)(t)}if(e.startsWith("rgb")||e.startsWith("hsl")||e.startsWith("hsv")||e.startsWith("hwb")){let a=YEt.exec(e);if(!a)return t;let n=Wk(a[1],r),u=Number(a[2]),A=Number(a[3]),p=Number(a[4]);return eB.default[n](u,A,p)(t)}return t}});var NCe=_(rB=>{"use strict";var TCe=rB&&rB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(rB,"__esModule",{value:!0});var KEt=TCe(CCe()),K6=TCe(W6());rB.default=(t,e,r,o)=>{if(typeof r.style.borderStyle=="string"){let a=r.yogaNode.getComputedWidth(),n=r.yogaNode.getComputedHeight(),u=r.style.borderColor,A=KEt.default[r.style.borderStyle],p=K6.default(A.topLeft+A.horizontal.repeat(a-2)+A.topRight,u,"foreground"),h=(K6.default(A.vertical,u,"foreground")+` +`).repeat(n-2),E=K6.default(A.bottomLeft+A.horizontal.repeat(a-2)+A.bottomRight,u,"foreground");o.write(t,e,p,{transformers:[]}),o.write(t,e+1,h,{transformers:[]}),o.write(t+a-1,e+1,h,{transformers:[]}),o.write(t,e+n-1,E,{transformers:[]})}}});var MCe=_(nB=>{"use strict";var Xg=nB&&nB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(nB,"__esModule",{value:!0});var VEt=Xg(Jg()),zEt=Xg(k6()),JEt=Xg(dCe()),XEt=Xg(L6()),ZEt=Xg(mCe()),$Et=Xg(O6()),eCt=Xg(NCe()),tCt=(t,e)=>{var r;let o=(r=t.childNodes[0])===null||r===void 0?void 0:r.yogaNode;if(o){let a=o.getComputedLeft(),n=o.getComputedTop();e=` +`.repeat(n)+JEt.default(e,a)}return e},LCe=(t,e,r)=>{var o;let{offsetX:a=0,offsetY:n=0,transformers:u=[],skipStaticElements:A}=r;if(A&&t.internal_static)return;let{yogaNode:p}=t;if(p){if(p.getDisplay()===VEt.default.DISPLAY_NONE)return;let h=a+p.getComputedLeft(),E=n+p.getComputedTop(),I=u;if(typeof t.internal_transform=="function"&&(I=[t.internal_transform,...u]),t.nodeName==="ink-text"){let v=$Et.default(t);if(v.length>0){let x=zEt.default(v),C=ZEt.default(p);if(x>C){let R=(o=t.style.textWrap)!==null&&o!==void 0?o:"wrap";v=XEt.default(v,C,R)}v=tCt(t,v),e.write(h,E,v,{transformers:I})}return}if(t.nodeName==="ink-box"&&eCt.default(h,E,t,e),t.nodeName==="ink-root"||t.nodeName==="ink-box")for(let v of t.childNodes)LCe(v,e,{offsetX:h,offsetY:E,transformers:I,skipStaticElements:A})}};nB.default=LCe});var UCe=_((ZKt,OCe)=>{"use strict";OCe.exports=t=>{t=Object.assign({onlyFirst:!1},t);let e=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(e,t.onlyFirst?void 0:"g")}});var HCe=_(($Kt,V6)=>{"use strict";var rCt=UCe(),_Ce=t=>typeof t=="string"?t.replace(rCt(),""):t;V6.exports=_Ce;V6.exports.default=_Ce});var GCe=_((eVt,jCe)=>{"use strict";var qCe="[\uD800-\uDBFF][\uDC00-\uDFFF]";jCe.exports=t=>t&&t.exact?new RegExp(`^${qCe}$`):new RegExp(qCe,"g")});var WCe=_((tVt,z6)=>{"use strict";var nCt=HCe(),iCt=GCe(),YCe=t=>nCt(t).replace(iCt()," ").length;z6.exports=YCe;z6.exports.default=YCe});var zCe=_(iB=>{"use strict";var VCe=iB&&iB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(iB,"__esModule",{value:!0});var KCe=VCe(T6()),sCt=VCe(WCe()),J6=class{constructor(e){this.writes=[];let{width:r,height:o}=e;this.width=r,this.height=o}write(e,r,o,a){let{transformers:n}=a;o&&this.writes.push({x:e,y:r,text:o,transformers:n})}get(){let e=[];for(let o=0;o<this.height;o++)e.push(" ".repeat(this.width));for(let o of this.writes){let{x:a,y:n,text:u,transformers:A}=o,p=u.split(` +`),h=0;for(let E of p){let I=e[n+h];if(!I)continue;let v=sCt.default(E);for(let x of A)E=x(E);e[n+h]=KCe.default(I,0,a)+E+KCe.default(I,a+v),h++}}return{output:e.map(o=>o.trimRight()).join(` +`),height:e.length}}};iB.default=J6});var ZCe=_(sB=>{"use strict";var X6=sB&&sB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(sB,"__esModule",{value:!0});var oCt=X6(Jg()),JCe=X6(MCe()),XCe=X6(zCe());sB.default=(t,e)=>{var r;if(t.yogaNode.setWidth(e),t.yogaNode){t.yogaNode.calculateLayout(void 0,void 0,oCt.default.DIRECTION_LTR);let o=new XCe.default({width:t.yogaNode.getComputedWidth(),height:t.yogaNode.getComputedHeight()});JCe.default(t,o,{skipStaticElements:!0});let a;!((r=t.staticNode)===null||r===void 0)&&r.yogaNode&&(a=new XCe.default({width:t.staticNode.yogaNode.getComputedWidth(),height:t.staticNode.yogaNode.getComputedHeight()}),JCe.default(t.staticNode,a,{skipStaticElements:!1}));let{output:n,height:u}=o.get();return{output:n,outputHeight:u,staticOutput:a?`${a.get().output} +`:""}}return{output:"",outputHeight:0,staticOutput:""}}});var rwe=_((iVt,twe)=>{"use strict";var $Ce=ve("stream"),ewe=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"],Z6={},aCt=t=>{let e=new $Ce.PassThrough,r=new $Ce.PassThrough;e.write=a=>t("stdout",a),r.write=a=>t("stderr",a);let o=new console.Console(e,r);for(let a of ewe)Z6[a]=console[a],console[a]=o[a];return()=>{for(let a of ewe)console[a]=Z6[a];Z6={}}};twe.exports=aCt});var eq=_($6=>{"use strict";Object.defineProperty($6,"__esModule",{value:!0});$6.default=new WeakMap});var rq=_(tq=>{"use strict";Object.defineProperty(tq,"__esModule",{value:!0});var lCt=an(),nwe=lCt.createContext({exit:()=>{}});nwe.displayName="InternalAppContext";tq.default=nwe});var iq=_(nq=>{"use strict";Object.defineProperty(nq,"__esModule",{value:!0});var cCt=an(),iwe=cCt.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});iwe.displayName="InternalStdinContext";nq.default=iwe});var oq=_(sq=>{"use strict";Object.defineProperty(sq,"__esModule",{value:!0});var uCt=an(),swe=uCt.createContext({stdout:void 0,write:()=>{}});swe.displayName="InternalStdoutContext";sq.default=swe});var lq=_(aq=>{"use strict";Object.defineProperty(aq,"__esModule",{value:!0});var ACt=an(),owe=ACt.createContext({stderr:void 0,write:()=>{}});owe.displayName="InternalStderrContext";aq.default=owe});var Kk=_(cq=>{"use strict";Object.defineProperty(cq,"__esModule",{value:!0});var fCt=an(),awe=fCt.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{}});awe.displayName="InternalFocusContext";cq.default=awe});var cwe=_((AVt,lwe)=>{"use strict";var pCt=/[|\\{}()[\]^$+*?.-]/g;lwe.exports=t=>{if(typeof t!="string")throw new TypeError("Expected a string");return t.replace(pCt,"\\$&")}});var pwe=_((fVt,fwe)=>{"use strict";var hCt=cwe(),gCt=typeof process=="object"&&process&&typeof process.cwd=="function"?process.cwd():".",Awe=[].concat(ve("module").builtinModules,"bootstrap_node","node").map(t=>new RegExp(`(?:\\((?:node:)?${t}(?:\\.js)?:\\d+:\\d+\\)$|^\\s*at (?:node:)?${t}(?:\\.js)?:\\d+:\\d+$)`));Awe.push(/\((?:node:)?internal\/[^:]+:\d+:\d+\)$/,/\s*at (?:node:)?internal\/[^:]+:\d+:\d+$/,/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/);var uq=class t{constructor(e){e={ignoredPackages:[],...e},"internals"in e||(e.internals=t.nodeInternals()),"cwd"in e||(e.cwd=gCt),this._cwd=e.cwd.replace(/\\/g,"/"),this._internals=[].concat(e.internals,dCt(e.ignoredPackages)),this._wrapCallSite=e.wrapCallSite||!1}static nodeInternals(){return[...Awe]}clean(e,r=0){r=" ".repeat(r),Array.isArray(e)||(e=e.split(` +`)),!/^\s*at /.test(e[0])&&/^\s*at /.test(e[1])&&(e=e.slice(1));let o=!1,a=null,n=[];return e.forEach(u=>{if(u=u.replace(/\\/g,"/"),this._internals.some(p=>p.test(u)))return;let A=/^\s*at /.test(u);o?u=u.trimEnd().replace(/^(\s+)at /,"$1"):(u=u.trim(),A&&(u=u.slice(3))),u=u.replace(`${this._cwd}/`,""),u&&(A?(a&&(n.push(a),a=null),n.push(u)):(o=!0,a=u))}),n.map(u=>`${r}${u} +`).join("")}captureString(e,r=this.captureString){typeof e=="function"&&(r=e,e=1/0);let{stackTraceLimit:o}=Error;e&&(Error.stackTraceLimit=e);let a={};Error.captureStackTrace(a,r);let{stack:n}=a;return Error.stackTraceLimit=o,this.clean(n)}capture(e,r=this.capture){typeof e=="function"&&(r=e,e=1/0);let{prepareStackTrace:o,stackTraceLimit:a}=Error;Error.prepareStackTrace=(A,p)=>this._wrapCallSite?p.map(this._wrapCallSite):p,e&&(Error.stackTraceLimit=e);let n={};Error.captureStackTrace(n,r);let{stack:u}=n;return Object.assign(Error,{prepareStackTrace:o,stackTraceLimit:a}),u}at(e=this.at){let[r]=this.capture(1,e);if(!r)return{};let o={line:r.getLineNumber(),column:r.getColumnNumber()};uwe(o,r.getFileName(),this._cwd),r.isConstructor()&&(o.constructor=!0),r.isEval()&&(o.evalOrigin=r.getEvalOrigin()),r.isNative()&&(o.native=!0);let a;try{a=r.getTypeName()}catch{}a&&a!=="Object"&&a!=="[object Object]"&&(o.type=a);let n=r.getFunctionName();n&&(o.function=n);let u=r.getMethodName();return u&&n!==u&&(o.method=u),o}parseLine(e){let r=e&&e.match(mCt);if(!r)return null;let o=r[1]==="new",a=r[2],n=r[3],u=r[4],A=Number(r[5]),p=Number(r[6]),h=r[7],E=r[8],I=r[9],v=r[10]==="native",x=r[11]===")",C,R={};if(E&&(R.line=Number(E)),I&&(R.column=Number(I)),x&&h){let L=0;for(let U=h.length-1;U>0;U--)if(h.charAt(U)===")")L++;else if(h.charAt(U)==="("&&h.charAt(U-1)===" "&&(L--,L===-1&&h.charAt(U-1)===" ")){let z=h.slice(0,U-1);h=h.slice(U+1),a+=` (${z}`;break}}if(a){let L=a.match(yCt);L&&(a=L[1],C=L[2])}return uwe(R,h,this._cwd),o&&(R.constructor=!0),n&&(R.evalOrigin=n,R.evalLine=A,R.evalColumn=p,R.evalFile=u&&u.replace(/\\/g,"/")),v&&(R.native=!0),a&&(R.function=a),C&&a!==C&&(R.method=C),R}};function uwe(t,e,r){e&&(e=e.replace(/\\/g,"/"),e.startsWith(`${r}/`)&&(e=e.slice(r.length+1)),t.file=e)}function dCt(t){if(t.length===0)return[];let e=t.map(r=>hCt(r));return new RegExp(`[/\\\\]node_modules[/\\\\](?:${e.join("|")})[/\\\\][^:]+:\\d+:\\d+`)}var mCt=new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$"),yCt=/^(.*?) \[as (.*?)\]$/;fwe.exports=uq});var gwe=_((pVt,hwe)=>{"use strict";hwe.exports=(t,e)=>t.replace(/^\t+/gm,r=>" ".repeat(r.length*(e||2)))});var mwe=_((hVt,dwe)=>{"use strict";var ECt=gwe(),CCt=(t,e)=>{let r=[],o=t-e,a=t+e;for(let n=o;n<=a;n++)r.push(n);return r};dwe.exports=(t,e,r)=>{if(typeof t!="string")throw new TypeError("Source code is missing.");if(!e||e<1)throw new TypeError("Line number must start from `1`.");if(t=ECt(t).split(/\r?\n/),!(e>t.length))return r={around:3,...r},CCt(e,r.around).filter(o=>t[o-1]!==void 0).map(o=>({line:o,value:t[o-1]}))}});var Vk=_(iu=>{"use strict";var wCt=iu&&iu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ICt=iu&&iu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),BCt=iu&&iu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&wCt(e,t,r);return ICt(e,t),e},vCt=iu&&iu.__rest||function(t,e){var r={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.indexOf(o)<0&&(r[o]=t[o]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var a=0,o=Object.getOwnPropertySymbols(t);a<o.length;a++)e.indexOf(o[a])<0&&Object.prototype.propertyIsEnumerable.call(t,o[a])&&(r[o[a]]=t[o[a]]);return r};Object.defineProperty(iu,"__esModule",{value:!0});var ywe=BCt(an()),Aq=ywe.forwardRef((t,e)=>{var{children:r}=t,o=vCt(t,["children"]);let a=Object.assign(Object.assign({},o),{marginLeft:o.marginLeft||o.marginX||o.margin||0,marginRight:o.marginRight||o.marginX||o.margin||0,marginTop:o.marginTop||o.marginY||o.margin||0,marginBottom:o.marginBottom||o.marginY||o.margin||0,paddingLeft:o.paddingLeft||o.paddingX||o.padding||0,paddingRight:o.paddingRight||o.paddingX||o.padding||0,paddingTop:o.paddingTop||o.paddingY||o.padding||0,paddingBottom:o.paddingBottom||o.paddingY||o.padding||0});return ywe.default.createElement("ink-box",{ref:e,style:a},r)});Aq.displayName="Box";Aq.defaultProps={flexDirection:"row",flexGrow:0,flexShrink:1};iu.default=Aq});var hq=_(oB=>{"use strict";var fq=oB&&oB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(oB,"__esModule",{value:!0});var DCt=fq(an()),iC=fq(Yk()),Ewe=fq(W6()),pq=({color:t,backgroundColor:e,dimColor:r,bold:o,italic:a,underline:n,strikethrough:u,inverse:A,wrap:p,children:h})=>{if(h==null)return null;let E=I=>(r&&(I=iC.default.dim(I)),t&&(I=Ewe.default(I,t,"foreground")),e&&(I=Ewe.default(I,e,"background")),o&&(I=iC.default.bold(I)),a&&(I=iC.default.italic(I)),n&&(I=iC.default.underline(I)),u&&(I=iC.default.strikethrough(I)),A&&(I=iC.default.inverse(I)),I);return DCt.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row",textWrap:p},internal_transform:E},h)};pq.displayName="Text";pq.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:"wrap"};oB.default=pq});var Bwe=_(su=>{"use strict";var PCt=su&&su.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),SCt=su&&su.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),bCt=su&&su.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&PCt(e,t,r);return SCt(e,t),e},aB=su&&su.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(su,"__esModule",{value:!0});var Cwe=bCt(ve("fs")),hs=aB(an()),wwe=aB(pwe()),xCt=aB(mwe()),Vf=aB(Vk()),hA=aB(hq()),Iwe=new wwe.default({cwd:process.cwd(),internals:wwe.default.nodeInternals()}),kCt=({error:t})=>{let e=t.stack?t.stack.split(` +`).slice(1):void 0,r=e?Iwe.parseLine(e[0]):void 0,o,a=0;if(r?.file&&r?.line&&Cwe.existsSync(r.file)){let n=Cwe.readFileSync(r.file,"utf8");if(o=xCt.default(n,r.line),o)for(let{line:u}of o)a=Math.max(a,String(u).length)}return hs.default.createElement(Vf.default,{flexDirection:"column",padding:1},hs.default.createElement(Vf.default,null,hs.default.createElement(hA.default,{backgroundColor:"red",color:"white"}," ","ERROR"," "),hs.default.createElement(hA.default,null," ",t.message)),r&&hs.default.createElement(Vf.default,{marginTop:1},hs.default.createElement(hA.default,{dimColor:!0},r.file,":",r.line,":",r.column)),r&&o&&hs.default.createElement(Vf.default,{marginTop:1,flexDirection:"column"},o.map(({line:n,value:u})=>hs.default.createElement(Vf.default,{key:n},hs.default.createElement(Vf.default,{width:a+1},hs.default.createElement(hA.default,{dimColor:n!==r.line,backgroundColor:n===r.line?"red":void 0,color:n===r.line?"white":void 0},String(n).padStart(a," "),":")),hs.default.createElement(hA.default,{key:n,backgroundColor:n===r.line?"red":void 0,color:n===r.line?"white":void 0}," "+u)))),t.stack&&hs.default.createElement(Vf.default,{marginTop:1,flexDirection:"column"},t.stack.split(` +`).slice(1).map(n=>{let u=Iwe.parseLine(n);return u?hs.default.createElement(Vf.default,{key:n},hs.default.createElement(hA.default,{dimColor:!0},"- "),hs.default.createElement(hA.default,{dimColor:!0,bold:!0},u.function),hs.default.createElement(hA.default,{dimColor:!0,color:"gray"}," ","(",u.file,":",u.line,":",u.column,")")):hs.default.createElement(Vf.default,{key:n},hs.default.createElement(hA.default,{dimColor:!0},"- "),hs.default.createElement(hA.default,{dimColor:!0,bold:!0},n))})))};su.default=kCt});var Dwe=_(ou=>{"use strict";var QCt=ou&&ou.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),FCt=ou&&ou.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),RCt=ou&&ou.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&QCt(e,t,r);return FCt(e,t),e},$g=ou&&ou.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ou,"__esModule",{value:!0});var Zg=RCt(an()),vwe=$g(u6()),TCt=$g(rq()),NCt=$g(iq()),LCt=$g(oq()),MCt=$g(lq()),OCt=$g(Kk()),UCt=$g(Bwe()),_Ct=" ",HCt="\x1B[Z",qCt="\x1B",zk=class extends Zg.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=e=>{let{stdin:r}=this.props;if(!this.isRawModeSupported())throw r===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(r.setEncoding("utf8"),e){this.rawModeEnabledCount===0&&(r.addListener("data",this.handleInput),r.resume(),r.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(r.setRawMode(!1),r.removeListener("data",this.handleInput),r.pause())},this.handleInput=e=>{e===""&&this.props.exitOnCtrlC&&this.handleExit(),e===qCt&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(e===_Ct&&this.focusNext(),e===HCt&&this.focusPrevious())},this.handleExit=e=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(e)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focusNext=()=>{this.setState(e=>{let r=e.focusables[0].id;return{activeFocusId:this.findNextFocusable(e)||r}})},this.focusPrevious=()=>{this.setState(e=>{let r=e.focusables[e.focusables.length-1].id;return{activeFocusId:this.findPreviousFocusable(e)||r}})},this.addFocusable=(e,{autoFocus:r})=>{this.setState(o=>{let a=o.activeFocusId;return!a&&r&&(a=e),{activeFocusId:a,focusables:[...o.focusables,{id:e,isActive:!0}]}})},this.removeFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.filter(o=>o.id!==e)}))},this.activateFocusable=e=>{this.setState(r=>({focusables:r.focusables.map(o=>o.id!==e?o:{id:e,isActive:!0})}))},this.deactivateFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.map(o=>o.id!==e?o:{id:e,isActive:!1})}))},this.findNextFocusable=e=>{let r=e.focusables.findIndex(o=>o.id===e.activeFocusId);for(let o=r+1;o<e.focusables.length;o++)if(e.focusables[o].isActive)return e.focusables[o].id},this.findPreviousFocusable=e=>{let r=e.focusables.findIndex(o=>o.id===e.activeFocusId);for(let o=r-1;o>=0;o--)if(e.focusables[o].isActive)return e.focusables[o].id}}static getDerivedStateFromError(e){return{error:e}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return Zg.default.createElement(TCt.default.Provider,{value:{exit:this.handleExit}},Zg.default.createElement(NCt.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},Zg.default.createElement(LCt.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},Zg.default.createElement(MCt.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},Zg.default.createElement(OCt.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious}},this.state.error?Zg.default.createElement(UCt.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){vwe.default.hide(this.props.stdout)}componentWillUnmount(){vwe.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(e){this.handleExit(e)}};ou.default=zk;zk.displayName="InternalApp"});var bwe=_(au=>{"use strict";var jCt=au&&au.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),GCt=au&&au.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),YCt=au&&au.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&jCt(e,t,r);return GCt(e,t),e},lu=au&&au.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(au,"__esModule",{value:!0});var WCt=lu(an()),Pwe=eO(),KCt=lu(pEe()),VCt=lu(s6()),zCt=lu(EEe()),JCt=lu(wEe()),gq=lu(hCe()),XCt=lu(ZCe()),ZCt=lu(c6()),$Ct=lu(rwe()),ewt=YCt(U6()),twt=lu(eq()),rwt=lu(Dwe()),sC=process.env.CI==="false"?!1:zCt.default,Swe=()=>{},dq=class{constructor(e){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:r,outputHeight:o,staticOutput:a}=XCt.default(this.rootNode,this.options.stdout.columns||80),n=a&&a!==` +`;if(this.options.debug){n&&(this.fullStaticOutput+=a),this.options.stdout.write(this.fullStaticOutput+r);return}if(sC){n&&this.options.stdout.write(a),this.lastOutput=r;return}if(n&&(this.fullStaticOutput+=a),o>=this.options.stdout.rows){this.options.stdout.write(VCt.default.clearTerminal+this.fullStaticOutput+r),this.lastOutput=r;return}n&&(this.log.clear(),this.options.stdout.write(a),this.log(r)),!n&&r!==this.lastOutput&&this.throttledLog(r),this.lastOutput=r},JCt.default(this),this.options=e,this.rootNode=ewt.createNode("ink-root"),this.rootNode.onRender=e.debug?this.onRender:Pwe(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=KCt.default.create(e.stdout),this.throttledLog=e.debug?this.log:Pwe(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput="",this.fullStaticOutput="",this.container=gq.default.createContainer(this.rootNode,!1,!1),this.unsubscribeExit=ZCt.default(this.unmount,{alwaysLast:!1}),e.patchConsole&&this.patchConsole(),sC||(e.stdout.on("resize",this.onRender),this.unsubscribeResize=()=>{e.stdout.off("resize",this.onRender)})}render(e){let r=WCt.default.createElement(rwt.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},e);gq.default.updateContainer(r,this.container,null,Swe)}writeToStdout(e){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(e+this.fullStaticOutput+this.lastOutput);return}if(sC){this.options.stdout.write(e);return}this.log.clear(),this.options.stdout.write(e),this.log(this.lastOutput)}}writeToStderr(e){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(e),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(sC){this.options.stderr.write(e);return}this.log.clear(),this.options.stderr.write(e),this.log(this.lastOutput)}}unmount(e){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole=="function"&&this.restoreConsole(),typeof this.unsubscribeResize=="function"&&this.unsubscribeResize(),sC?this.options.stdout.write(this.lastOutput+` +`):this.options.debug||this.log.done(),this.isUnmounted=!0,gq.default.updateContainer(null,this.container,null,Swe),twt.default.delete(this.options.stdout),e instanceof Error?this.rejectExitPromise(e):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((e,r)=>{this.resolveExitPromise=e,this.rejectExitPromise=r})),this.exitPromise}clear(){!sC&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=$Ct.default((e,r)=>{e==="stdout"&&this.writeToStdout(r),e==="stderr"&&(r.startsWith("The above error occurred")||this.writeToStderr(r))}))}};au.default=dq});var kwe=_(lB=>{"use strict";var xwe=lB&&lB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(lB,"__esModule",{value:!0});var nwt=xwe(bwe()),Jk=xwe(eq()),iwt=ve("stream"),swt=(t,e)=>{let r=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},owt(e)),o=awt(r.stdout,()=>new nwt.default(r));return o.render(t),{rerender:o.render,unmount:()=>o.unmount(),waitUntilExit:o.waitUntilExit,cleanup:()=>Jk.default.delete(r.stdout),clear:o.clear}};lB.default=swt;var owt=(t={})=>t instanceof iwt.Stream?{stdout:t,stdin:process.stdin}:t,awt=(t,e)=>{let r;return Jk.default.has(t)?r=Jk.default.get(t):(r=e(),Jk.default.set(t,r)),r}});var Fwe=_(zf=>{"use strict";var lwt=zf&&zf.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),cwt=zf&&zf.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),uwt=zf&&zf.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&lwt(e,t,r);return cwt(e,t),e};Object.defineProperty(zf,"__esModule",{value:!0});var cB=uwt(an()),Qwe=t=>{let{items:e,children:r,style:o}=t,[a,n]=cB.useState(0),u=cB.useMemo(()=>e.slice(a),[e,a]);cB.useLayoutEffect(()=>{n(e.length)},[e.length]);let A=u.map((h,E)=>r(h,a+E)),p=cB.useMemo(()=>Object.assign({position:"absolute",flexDirection:"column"},o),[o]);return cB.default.createElement("ink-box",{internal_static:!0,style:p},A)};Qwe.displayName="Static";zf.default=Qwe});var Twe=_(uB=>{"use strict";var Awt=uB&&uB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(uB,"__esModule",{value:!0});var fwt=Awt(an()),Rwe=({children:t,transform:e})=>t==null?null:fwt.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row"},internal_transform:e},t);Rwe.displayName="Transform";uB.default=Rwe});var Lwe=_(AB=>{"use strict";var pwt=AB&&AB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(AB,"__esModule",{value:!0});var hwt=pwt(an()),Nwe=({count:t=1})=>hwt.default.createElement("ink-text",null,` +`.repeat(t));Nwe.displayName="Newline";AB.default=Nwe});var Uwe=_(fB=>{"use strict";var Mwe=fB&&fB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(fB,"__esModule",{value:!0});var gwt=Mwe(an()),dwt=Mwe(Vk()),Owe=()=>gwt.default.createElement(dwt.default,{flexGrow:1});Owe.displayName="Spacer";fB.default=Owe});var Xk=_(pB=>{"use strict";var mwt=pB&&pB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(pB,"__esModule",{value:!0});var ywt=an(),Ewt=mwt(iq()),Cwt=()=>ywt.useContext(Ewt.default);pB.default=Cwt});var Hwe=_(hB=>{"use strict";var wwt=hB&&hB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(hB,"__esModule",{value:!0});var _we=an(),Iwt=wwt(Xk()),Bwt=(t,e={})=>{let{stdin:r,setRawMode:o,internal_exitOnCtrlC:a}=Iwt.default();_we.useEffect(()=>{if(e.isActive!==!1)return o(!0),()=>{o(!1)}},[e.isActive,o]),_we.useEffect(()=>{if(e.isActive===!1)return;let n=u=>{let A=String(u),p={upArrow:A==="\x1B[A",downArrow:A==="\x1B[B",leftArrow:A==="\x1B[D",rightArrow:A==="\x1B[C",pageDown:A==="\x1B[6~",pageUp:A==="\x1B[5~",return:A==="\r",escape:A==="\x1B",ctrl:!1,shift:!1,tab:A===" "||A==="\x1B[Z",backspace:A==="\b",delete:A==="\x7F"||A==="\x1B[3~",meta:!1};A<=""&&!p.return&&(A=String.fromCharCode(A.charCodeAt(0)+97-1),p.ctrl=!0),A.startsWith("\x1B")&&(A=A.slice(1),p.meta=!0);let h=A>="A"&&A<="Z",E=A>="\u0410"&&A<="\u042F";A.length===1&&(h||E)&&(p.shift=!0),p.tab&&A==="[Z"&&(p.shift=!0),(p.tab||p.backspace||p.delete)&&(A=""),(!(A==="c"&&p.ctrl)||!a)&&t(A,p)};return r?.on("data",n),()=>{r?.off("data",n)}},[e.isActive,r,a,t])};hB.default=Bwt});var qwe=_(gB=>{"use strict";var vwt=gB&&gB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(gB,"__esModule",{value:!0});var Dwt=an(),Pwt=vwt(rq()),Swt=()=>Dwt.useContext(Pwt.default);gB.default=Swt});var jwe=_(dB=>{"use strict";var bwt=dB&&dB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(dB,"__esModule",{value:!0});var xwt=an(),kwt=bwt(oq()),Qwt=()=>xwt.useContext(kwt.default);dB.default=Qwt});var Gwe=_(mB=>{"use strict";var Fwt=mB&&mB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(mB,"__esModule",{value:!0});var Rwt=an(),Twt=Fwt(lq()),Nwt=()=>Rwt.useContext(Twt.default);mB.default=Nwt});var Wwe=_(EB=>{"use strict";var Ywe=EB&&EB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(EB,"__esModule",{value:!0});var yB=an(),Lwt=Ywe(Kk()),Mwt=Ywe(Xk()),Owt=({isActive:t=!0,autoFocus:e=!1}={})=>{let{isRawModeSupported:r,setRawMode:o}=Mwt.default(),{activeId:a,add:n,remove:u,activate:A,deactivate:p}=yB.useContext(Lwt.default),h=yB.useMemo(()=>Math.random().toString().slice(2,7),[]);return yB.useEffect(()=>(n(h,{autoFocus:e}),()=>{u(h)}),[h,e]),yB.useEffect(()=>{t?A(h):p(h)},[t,h]),yB.useEffect(()=>{if(!(!r||!t))return o(!0),()=>{o(!1)}},[t]),{isFocused:!!h&&a===h}};EB.default=Owt});var Kwe=_(CB=>{"use strict";var Uwt=CB&&CB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(CB,"__esModule",{value:!0});var _wt=an(),Hwt=Uwt(Kk()),qwt=()=>{let t=_wt.useContext(Hwt.default);return{enableFocus:t.enableFocus,disableFocus:t.disableFocus,focusNext:t.focusNext,focusPrevious:t.focusPrevious}};CB.default=qwt});var Vwe=_(mq=>{"use strict";Object.defineProperty(mq,"__esModule",{value:!0});mq.default=t=>{var e,r,o,a;return{width:(r=(e=t.yogaNode)===null||e===void 0?void 0:e.getComputedWidth())!==null&&r!==void 0?r:0,height:(a=(o=t.yogaNode)===null||o===void 0?void 0:o.getComputedHeight())!==null&&a!==void 0?a:0}}});var ic=_(ro=>{"use strict";Object.defineProperty(ro,"__esModule",{value:!0});var jwt=kwe();Object.defineProperty(ro,"render",{enumerable:!0,get:function(){return jwt.default}});var Gwt=Vk();Object.defineProperty(ro,"Box",{enumerable:!0,get:function(){return Gwt.default}});var Ywt=hq();Object.defineProperty(ro,"Text",{enumerable:!0,get:function(){return Ywt.default}});var Wwt=Fwe();Object.defineProperty(ro,"Static",{enumerable:!0,get:function(){return Wwt.default}});var Kwt=Twe();Object.defineProperty(ro,"Transform",{enumerable:!0,get:function(){return Kwt.default}});var Vwt=Lwe();Object.defineProperty(ro,"Newline",{enumerable:!0,get:function(){return Vwt.default}});var zwt=Uwe();Object.defineProperty(ro,"Spacer",{enumerable:!0,get:function(){return zwt.default}});var Jwt=Hwe();Object.defineProperty(ro,"useInput",{enumerable:!0,get:function(){return Jwt.default}});var Xwt=qwe();Object.defineProperty(ro,"useApp",{enumerable:!0,get:function(){return Xwt.default}});var Zwt=Xk();Object.defineProperty(ro,"useStdin",{enumerable:!0,get:function(){return Zwt.default}});var $wt=jwe();Object.defineProperty(ro,"useStdout",{enumerable:!0,get:function(){return $wt.default}});var eIt=Gwe();Object.defineProperty(ro,"useStderr",{enumerable:!0,get:function(){return eIt.default}});var tIt=Wwe();Object.defineProperty(ro,"useFocus",{enumerable:!0,get:function(){return tIt.default}});var rIt=Kwe();Object.defineProperty(ro,"useFocusManager",{enumerable:!0,get:function(){return rIt.default}});var nIt=Vwe();Object.defineProperty(ro,"measureElement",{enumerable:!0,get:function(){return nIt.default}})});var Eq={};Vt(Eq,{Gem:()=>yq});var zwe,ed,yq,Zk=Et(()=>{zwe=Ze(ic()),ed=Ze(an()),yq=(0,ed.memo)(({active:t})=>{let e=(0,ed.useMemo)(()=>t?"\u25C9":"\u25EF",[t]),r=(0,ed.useMemo)(()=>t?"green":"yellow",[t]);return ed.default.createElement(zwe.Text,{color:r},e)})});var Xwe={};Vt(Xwe,{useKeypress:()=>td});function td({active:t},e,r){let{stdin:o}=(0,Jwe.useStdin)(),a=(0,$k.useCallback)((n,u)=>e(n,u),r);(0,$k.useEffect)(()=>{if(!(!t||!o))return o.on("keypress",a),()=>{o.off("keypress",a)}},[t,a,o])}var Jwe,$k,wB=Et(()=>{Jwe=Ze(ic()),$k=Ze(an())});var $we={};Vt($we,{FocusRequest:()=>Zwe,useFocusRequest:()=>Cq});var Zwe,Cq,wq=Et(()=>{wB();Zwe=(r=>(r.BEFORE="before",r.AFTER="after",r))(Zwe||{}),Cq=function({active:t},e,r){td({active:t},(o,a)=>{a.name==="tab"&&(a.shift?e("before"):e("after"))},r)}});var eIe={};Vt(eIe,{useListInput:()=>IB});var IB,eQ=Et(()=>{wB();IB=function(t,e,{active:r,minus:o,plus:a,set:n,loop:u=!0}){td({active:r},(A,p)=>{let h=e.indexOf(t);switch(p.name){case o:{let E=h-1;if(u){n(e[(e.length+E)%e.length]);return}if(E<0)return;n(e[E])}break;case a:{let E=h+1;if(u){n(e[E%e.length]);return}if(E>=e.length)return;n(e[E])}break}},[e,t,a,n,u])}});var tQ={};Vt(tQ,{ScrollableItems:()=>iIt});var Lh,Oa,iIt,rQ=Et(()=>{Lh=Ze(ic()),Oa=Ze(an());wq();eQ();iIt=({active:t=!0,children:e=[],radius:r=10,size:o=1,loop:a=!0,onFocusRequest:n,willReachEnd:u})=>{let A=L=>{if(L.key===null)throw new Error("Expected all children to have a key");return L.key},p=Oa.default.Children.map(e,L=>A(L)),h=p[0],[E,I]=(0,Oa.useState)(h),v=p.indexOf(E);(0,Oa.useEffect)(()=>{p.includes(E)||I(h)},[e]),(0,Oa.useEffect)(()=>{u&&v>=p.length-2&&u()},[v]),Cq({active:t&&!!n},L=>{n?.(L)},[n]),IB(E,p,{active:t,minus:"up",plus:"down",set:I,loop:a});let x=v-r,C=v+r;C>p.length&&(x-=C-p.length,C=p.length),x<0&&(C+=-x,x=0),C>=p.length&&(C=p.length-1);let R=[];for(let L=x;L<=C;++L){let U=p[L],z=t&&U===E;R.push(Oa.default.createElement(Lh.Box,{key:U,height:o},Oa.default.createElement(Lh.Box,{marginLeft:1,marginRight:1},Oa.default.createElement(Lh.Text,null,z?Oa.default.createElement(Lh.Text,{color:"cyan",bold:!0},">"):" ")),Oa.default.createElement(Lh.Box,null,Oa.default.cloneElement(e[L],{active:z}))))}return Oa.default.createElement(Lh.Box,{flexDirection:"column",width:"100%"},R)}});var tIe,Jf,rIe,Iq,nIe,Bq=Et(()=>{tIe=Ze(ic()),Jf=Ze(an()),rIe=ve("readline"),Iq=Jf.default.createContext(null),nIe=({children:t})=>{let{stdin:e,setRawMode:r}=(0,tIe.useStdin)();(0,Jf.useEffect)(()=>{r&&r(!0),e&&(0,rIe.emitKeypressEvents)(e)},[e,r]);let[o,a]=(0,Jf.useState)(new Map),n=(0,Jf.useMemo)(()=>({getAll:()=>o,get:u=>o.get(u),set:(u,A)=>a(new Map([...o,[u,A]]))}),[o,a]);return Jf.default.createElement(Iq.Provider,{value:n,children:t})}});var vq={};Vt(vq,{useMinistore:()=>sIt});function sIt(t,e){let r=(0,nQ.useContext)(Iq);if(r===null)throw new Error("Expected this hook to run with a ministore context attached");if(typeof t>"u")return r.getAll();let o=(0,nQ.useCallback)(n=>{r.set(t,n)},[t,r.set]),a=r.get(t);return typeof a>"u"&&(a=e),[a,o]}var nQ,Dq=Et(()=>{nQ=Ze(an());Bq()});var sQ={};Vt(sQ,{renderForm:()=>oIt});async function oIt(t,e,{stdin:r,stdout:o,stderr:a}){let n,u=p=>{let{exit:h}=(0,iQ.useApp)();td({active:!0},(E,I)=>{I.name==="return"&&(n=p,h())},[h,p])},{waitUntilExit:A}=(0,iQ.render)(Pq.default.createElement(nIe,null,Pq.default.createElement(t,{...e,useSubmit:u})),{stdin:r,stdout:o,stderr:a});return await A(),n}var iQ,Pq,oQ=Et(()=>{iQ=Ze(ic()),Pq=Ze(an());Bq();wB()});var aIe=_(BB=>{"use strict";Object.defineProperty(BB,"__esModule",{value:!0});BB.UncontrolledTextInput=void 0;var sIe=an(),Sq=an(),iIe=ic(),rd=Yk(),oIe=({value:t,placeholder:e="",focus:r=!0,mask:o,highlightPastedText:a=!1,showCursor:n=!0,onChange:u,onSubmit:A})=>{let[{cursorOffset:p,cursorWidth:h},E]=Sq.useState({cursorOffset:(t||"").length,cursorWidth:0});Sq.useEffect(()=>{E(R=>{if(!r||!n)return R;let L=t||"";return R.cursorOffset>L.length-1?{cursorOffset:L.length,cursorWidth:0}:R})},[t,r,n]);let I=a?h:0,v=o?o.repeat(t.length):t,x=v,C=e?rd.grey(e):void 0;if(n&&r){C=e.length>0?rd.inverse(e[0])+rd.grey(e.slice(1)):rd.inverse(" "),x=v.length>0?"":rd.inverse(" ");let R=0;for(let L of v)R>=p-I&&R<=p?x+=rd.inverse(L):x+=L,R++;v.length>0&&p===v.length&&(x+=rd.inverse(" "))}return iIe.useInput((R,L)=>{if(L.upArrow||L.downArrow||L.ctrl&&R==="c"||L.tab||L.shift&&L.tab)return;if(L.return){A&&A(t);return}let U=p,z=t,te=0;L.leftArrow?n&&U--:L.rightArrow?n&&U++:L.backspace||L.delete?p>0&&(z=t.slice(0,p-1)+t.slice(p,t.length),U--):(z=t.slice(0,p)+R+t.slice(p,t.length),U+=R.length,R.length>1&&(te=R.length)),p<0&&(U=0),p>t.length&&(U=t.length),E({cursorOffset:U,cursorWidth:te}),z!==t&&u(z)},{isActive:r}),sIe.createElement(iIe.Text,null,e?v.length>0?x:C:x)};BB.default=oIe;BB.UncontrolledTextInput=t=>{let[e,r]=Sq.useState("");return sIe.createElement(oIe,Object.assign({},t,{value:e,onChange:r}))}});var uIe={};Vt(uIe,{Pad:()=>bq});var lIe,cIe,bq,xq=Et(()=>{lIe=Ze(ic()),cIe=Ze(an()),bq=({length:t,active:e})=>{if(t===0)return null;let r=t>1?` ${"-".repeat(t-1)}`:" ";return cIe.default.createElement(lIe.Text,{dimColor:!e},r)}});var AIe={};Vt(AIe,{ItemOptions:()=>aIt});var DB,Mh,aIt,fIe=Et(()=>{DB=Ze(ic()),Mh=Ze(an());eQ();Zk();xq();aIt=function({active:t,skewer:e,options:r,value:o,onChange:a,sizes:n=[]}){let u=r.filter(({label:p})=>!!p).map(({value:p})=>p),A=r.findIndex(p=>p.value===o&&p.label!="");return IB(o,u,{active:t,minus:"left",plus:"right",set:a}),Mh.default.createElement(Mh.default.Fragment,null,r.map(({label:p},h)=>{let E=h===A,I=n[h]-1||0,v=p.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),x=Math.max(0,I-v.length-2);return p?Mh.default.createElement(DB.Box,{key:p,width:I,marginLeft:1},Mh.default.createElement(DB.Text,{wrap:"truncate"},Mh.default.createElement(yq,{active:E})," ",p),e?Mh.default.createElement(bq,{active:t,length:x}):null):Mh.default.createElement(DB.Box,{key:`spacer-${h}`,width:I,marginLeft:1})}))}});var SIe=_((rJt,PIe)=>{var Oq;PIe.exports=()=>(typeof Oq>"u"&&(Oq=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),Oq)});var VIe=_((SJt,KIe)=>{var Kq=Symbol("arg flag"),sc=class t extends Error{constructor(e,r){super(e),this.name="ArgError",this.code=r,Object.setPrototypeOf(this,t.prototype)}};function HB(t,{argv:e=process.argv.slice(2),permissive:r=!1,stopAtPositional:o=!1}={}){if(!t)throw new sc("argument specification object is required","ARG_CONFIG_NO_SPEC");let a={_:[]},n={},u={};for(let A of Object.keys(t)){if(!A)throw new sc("argument key cannot be an empty string","ARG_CONFIG_EMPTY_KEY");if(A[0]!=="-")throw new sc(`argument key must start with '-' but found: '${A}'`,"ARG_CONFIG_NONOPT_KEY");if(A.length===1)throw new sc(`argument key must have a name; singular '-' keys are not allowed: ${A}`,"ARG_CONFIG_NONAME_KEY");if(typeof t[A]=="string"){n[A]=t[A];continue}let p=t[A],h=!1;if(Array.isArray(p)&&p.length===1&&typeof p[0]=="function"){let[E]=p;p=(I,v,x=[])=>(x.push(E(I,v,x[x.length-1])),x),h=E===Boolean||E[Kq]===!0}else if(typeof p=="function")h=p===Boolean||p[Kq]===!0;else throw new sc(`type missing or not a function or valid array type: ${A}`,"ARG_CONFIG_VAD_TYPE");if(A[1]!=="-"&&A.length>2)throw new sc(`short argument keys (with a single hyphen) must have only one character: ${A}`,"ARG_CONFIG_SHORTOPT_TOOLONG");u[A]=[p,h]}for(let A=0,p=e.length;A<p;A++){let h=e[A];if(o&&a._.length>0){a._=a._.concat(e.slice(A));break}if(h==="--"){a._=a._.concat(e.slice(A+1));break}if(h.length>1&&h[0]==="-"){let E=h[1]==="-"||h.length===2?[h]:h.slice(1).split("").map(I=>`-${I}`);for(let I=0;I<E.length;I++){let v=E[I],[x,C]=v[1]==="-"?v.split(/=(.*)/,2):[v,void 0],R=x;for(;R in n;)R=n[R];if(!(R in u))if(r){a._.push(v);continue}else throw new sc(`unknown or unexpected option: ${x}`,"ARG_UNKNOWN_OPTION");let[L,U]=u[R];if(!U&&I+1<E.length)throw new sc(`option requires argument (but was followed by another short argument): ${x}`,"ARG_MISSING_REQUIRED_SHORTARG");if(U)a[R]=L(!0,R,a[R]);else if(C===void 0){if(e.length<A+2||e[A+1].length>1&&e[A+1][0]==="-"&&!(e[A+1].match(/^-?\d*(\.(?=\d))?\d*$/)&&(L===Number||typeof BigInt<"u"&&L===BigInt))){let z=x===R?"":` (alias for ${R})`;throw new sc(`option requires argument: ${x}${z}`,"ARG_MISSING_REQUIRED_LONGARG")}a[R]=L(e[A+1],R,a[R]),++A}else a[R]=L(C,R,a[R])}}else a._.push(h)}return a}HB.flag=t=>(t[Kq]=!0,t);HB.COUNT=HB.flag((t,e,r)=>(r||0)+1);HB.ArgError=sc;KIe.exports=HB});var r1e=_((nXt,t1e)=>{var Xq;t1e.exports=()=>(typeof Xq>"u"&&(Xq=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),Xq)});var a1e=_((nj,ij)=>{(function(t){nj&&typeof nj=="object"&&typeof ij<"u"?ij.exports=t():typeof define=="function"&&define.amd?define([],t):typeof window<"u"?window.isWindows=t():typeof global<"u"?global.isWindows=t():typeof self<"u"?self.isWindows=t():this.isWindows=t()})(function(){"use strict";return function(){return process&&(process.platform==="win32"||/^(msys|cygwin)$/.test(process.env.OSTYPE))}})});var A1e=_((tZt,u1e)=>{"use strict";sj.ifExists=i1t;var uC=ve("util"),oc=ve("path"),l1e=a1e(),t1t=/^#!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+)(.*)$/,r1t={createPwshFile:!0,createCmdFile:l1e(),fs:ve("fs")},n1t=new Map([[".js","node"],[".cjs","node"],[".mjs","node"],[".cmd","cmd"],[".bat","cmd"],[".ps1","pwsh"],[".sh","sh"]]);function c1e(t){let e={...r1t,...t},r=e.fs;return e.fs_={chmod:r.chmod?uC.promisify(r.chmod):async()=>{},mkdir:uC.promisify(r.mkdir),readFile:uC.promisify(r.readFile),stat:uC.promisify(r.stat),unlink:uC.promisify(r.unlink),writeFile:uC.promisify(r.writeFile)},e}async function sj(t,e,r){let o=c1e(r);await o.fs_.stat(t),await o1t(t,e,o)}function i1t(t,e,r){return sj(t,e,r).catch(()=>{})}function s1t(t,e){return e.fs_.unlink(t).catch(()=>{})}async function o1t(t,e,r){let o=await A1t(t,r);return await a1t(e,r),l1t(t,e,o,r)}function a1t(t,e){return e.fs_.mkdir(oc.dirname(t),{recursive:!0})}function l1t(t,e,r,o){let a=c1e(o),n=[{generator:h1t,extension:""}];return a.createCmdFile&&n.push({generator:p1t,extension:".cmd"}),a.createPwshFile&&n.push({generator:g1t,extension:".ps1"}),Promise.all(n.map(u=>f1t(t,e+u.extension,r,u.generator,a)))}function c1t(t,e){return s1t(t,e)}function u1t(t,e){return d1t(t,e)}async function A1t(t,e){let a=(await e.fs_.readFile(t,"utf8")).trim().split(/\r*\n/)[0].match(t1t);if(!a){let n=oc.extname(t).toLowerCase();return{program:n1t.get(n)||null,additionalArgs:""}}return{program:a[1],additionalArgs:a[2]}}async function f1t(t,e,r,o,a){let n=a.preserveSymlinks?"--preserve-symlinks":"",u=[r.additionalArgs,n].filter(A=>A).join(" ");return a=Object.assign({},a,{prog:r.program,args:u}),await c1t(e,a),await a.fs_.writeFile(e,o(t,e,a),"utf8"),u1t(e,a)}function p1t(t,e,r){let a=oc.relative(oc.dirname(e),t).split("/").join("\\"),n=oc.isAbsolute(a)?`"${a}"`:`"%~dp0\\${a}"`,u,A=r.prog,p=r.args||"",h=oj(r.nodePath).win32;A?(u=`"%~dp0\\${A}.exe"`,a=n):(A=n,p="",a="");let E=r.progArgs?`${r.progArgs.join(" ")} `:"",I=h?`@SET NODE_PATH=${h}\r +`:"";return u?I+=`@IF EXIST ${u} (\r + ${u} ${p} ${a} ${E}%*\r +) ELSE (\r + @SETLOCAL\r + @SET PATHEXT=%PATHEXT:;.JS;=;%\r + ${A} ${p} ${a} ${E}%*\r +)\r +`:I+=`@${A} ${p} ${a} ${E}%*\r +`,I}function h1t(t,e,r){let o=oc.relative(oc.dirname(e),t),a=r.prog&&r.prog.split("\\").join("/"),n;o=o.split("\\").join("/");let u=oc.isAbsolute(o)?`"${o}"`:`"$basedir/${o}"`,A=r.args||"",p=oj(r.nodePath).posix;a?(n=`"$basedir/${r.prog}"`,o=u):(a=u,A="",o="");let h=r.progArgs?`${r.progArgs.join(" ")} `:"",E=`#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") + +case \`uname\` in + *CYGWIN*) basedir=\`cygpath -w "$basedir"\`;; +esac + +`,I=r.nodePath?`export NODE_PATH="${p}" +`:"";return n?E+=`${I}if [ -x ${n} ]; then + exec ${n} ${A} ${o} ${h}"$@" +else + exec ${a} ${A} ${o} ${h}"$@" +fi +`:E+=`${I}${a} ${A} ${o} ${h}"$@" +exit $? +`,E}function g1t(t,e,r){let o=oc.relative(oc.dirname(e),t),a=r.prog&&r.prog.split("\\").join("/"),n=a&&`"${a}$exe"`,u;o=o.split("\\").join("/");let A=oc.isAbsolute(o)?`"${o}"`:`"$basedir/${o}"`,p=r.args||"",h=oj(r.nodePath),E=h.win32,I=h.posix;n?(u=`"$basedir/${r.prog}$exe"`,o=A):(n=A,p="",o="");let v=r.progArgs?`${r.progArgs.join(" ")} `:"",x=`#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +${r.nodePath?`$env_node_path=$env:NODE_PATH +$env:NODE_PATH="${E}" +`:""}if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +}`;return r.nodePath&&(x+=` else { + $env:NODE_PATH="${I}" +}`),u?x+=` +$ret=0 +if (Test-Path ${u}) { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & ${u} ${p} ${o} ${v}$args + } else { + & ${u} ${p} ${o} ${v}$args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & ${n} ${p} ${o} ${v}$args + } else { + & ${n} ${p} ${o} ${v}$args + } + $ret=$LASTEXITCODE +} +${r.nodePath?`$env:NODE_PATH=$env_node_path +`:""}exit $ret +`:x+=` +# Support pipeline input +if ($MyInvocation.ExpectingInput) { + $input | & ${n} ${p} ${o} ${v}$args +} else { + & ${n} ${p} ${o} ${v}$args +} +${r.nodePath?`$env:NODE_PATH=$env_node_path +`:""}exit $LASTEXITCODE +`,x}function d1t(t,e){return e.fs_.chmod(t,493)}function oj(t){if(!t)return{win32:"",posix:""};let e=typeof t=="string"?t.split(oc.delimiter):Array.from(t),r={};for(let o=0;o<e.length;o++){let a=e[o].split("/").join("\\"),n=l1e()?e[o].split("\\").join("/").replace(/^([^:\\/]*):/,(u,A)=>`/mnt/${A.toLowerCase()}`):e[o];r.win32=r.win32?`${r.win32};${a}`:a,r.posix=r.posix?`${r.posix}:${n}`:n,r[o]={win32:a,posix:n}}return r}u1e.exports=sj});var Cj=_((I$t,Q1e)=>{Q1e.exports=ve("stream")});var N1e=_((B$t,T1e)=>{"use strict";function F1e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,o)}return r}function j1t(t){for(var e=1;e<arguments.length;e++){var r=arguments[e]!=null?arguments[e]:{};e%2?F1e(Object(r),!0).forEach(function(o){G1t(t,o,r[o])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):F1e(Object(r)).forEach(function(o){Object.defineProperty(t,o,Object.getOwnPropertyDescriptor(r,o))})}return t}function G1t(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function Y1t(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function R1e(t,e){for(var r=0;r<e.length;r++){var o=e[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function W1t(t,e,r){return e&&R1e(t.prototype,e),r&&R1e(t,r),t}var K1t=ve("buffer"),yQ=K1t.Buffer,V1t=ve("util"),wj=V1t.inspect,z1t=wj&&wj.custom||"inspect";function J1t(t,e,r){yQ.prototype.copy.call(t,e,r)}T1e.exports=function(){function t(){Y1t(this,t),this.head=null,this.tail=null,this.length=0}return W1t(t,[{key:"push",value:function(r){var o={data:r,next:null};this.length>0?this.tail.next=o:this.head=o,this.tail=o,++this.length}},{key:"unshift",value:function(r){var o={data:r,next:this.head};this.length===0&&(this.tail=o),this.head=o,++this.length}},{key:"shift",value:function(){if(this.length!==0){var r=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,r}}},{key:"clear",value:function(){this.head=this.tail=null,this.length=0}},{key:"join",value:function(r){if(this.length===0)return"";for(var o=this.head,a=""+o.data;o=o.next;)a+=r+o.data;return a}},{key:"concat",value:function(r){if(this.length===0)return yQ.alloc(0);for(var o=yQ.allocUnsafe(r>>>0),a=this.head,n=0;a;)J1t(a.data,o,n),n+=a.data.length,a=a.next;return o}},{key:"consume",value:function(r,o){var a;return r<this.head.data.length?(a=this.head.data.slice(0,r),this.head.data=this.head.data.slice(r)):r===this.head.data.length?a=this.shift():a=o?this._getString(r):this._getBuffer(r),a}},{key:"first",value:function(){return this.head.data}},{key:"_getString",value:function(r){var o=this.head,a=1,n=o.data;for(r-=n.length;o=o.next;){var u=o.data,A=r>u.length?u.length:r;if(A===u.length?n+=u:n+=u.slice(0,r),r-=A,r===0){A===u.length?(++a,o.next?this.head=o.next:this.head=this.tail=null):(this.head=o,o.data=u.slice(A));break}++a}return this.length-=a,n}},{key:"_getBuffer",value:function(r){var o=yQ.allocUnsafe(r),a=this.head,n=1;for(a.data.copy(o),r-=a.data.length;a=a.next;){var u=a.data,A=r>u.length?u.length:r;if(u.copy(o,o.length-r,0,A),r-=A,r===0){A===u.length?(++n,a.next?this.head=a.next:this.head=this.tail=null):(this.head=a,a.data=u.slice(A));break}++n}return this.length-=n,o}},{key:z1t,value:function(r,o){return wj(this,j1t({},o,{depth:0,customInspect:!1}))}}]),t}()});var Bj=_((v$t,M1e)=>{"use strict";function X1t(t,e){var r=this,o=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return o||a?(e?e(t):t&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(Ij,this,t)):process.nextTick(Ij,this,t)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(t||null,function(n){!e&&n?r._writableState?r._writableState.errorEmitted?process.nextTick(EQ,r):(r._writableState.errorEmitted=!0,process.nextTick(L1e,r,n)):process.nextTick(L1e,r,n):e?(process.nextTick(EQ,r),e(n)):process.nextTick(EQ,r)}),this)}function L1e(t,e){Ij(t,e),EQ(t)}function EQ(t){t._writableState&&!t._writableState.emitClose||t._readableState&&!t._readableState.emitClose||t.emit("close")}function Z1t(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function Ij(t,e){t.emit("error",e)}function $1t(t,e){var r=t._readableState,o=t._writableState;r&&r.autoDestroy||o&&o.autoDestroy?t.destroy(e):t.emit("error",e)}M1e.exports={destroy:X1t,undestroy:Z1t,errorOrDestroy:$1t}});var Gh=_((D$t,_1e)=>{"use strict";var U1e={};function lc(t,e,r){r||(r=Error);function o(n,u,A){return typeof e=="string"?e:e(n,u,A)}class a extends r{constructor(u,A,p){super(o(u,A,p))}}a.prototype.name=r.name,a.prototype.code=t,U1e[t]=a}function O1e(t,e){if(Array.isArray(t)){let r=t.length;return t=t.map(o=>String(o)),r>2?`one of ${e} ${t.slice(0,r-1).join(", ")}, or `+t[r-1]:r===2?`one of ${e} ${t[0]} or ${t[1]}`:`of ${e} ${t[0]}`}else return`of ${e} ${String(t)}`}function e2t(t,e,r){return t.substr(!r||r<0?0:+r,e.length)===e}function t2t(t,e,r){return(r===void 0||r>t.length)&&(r=t.length),t.substring(r-e.length,r)===e}function r2t(t,e,r){return typeof r!="number"&&(r=0),r+e.length>t.length?!1:t.indexOf(e,r)!==-1}lc("ERR_INVALID_OPT_VALUE",function(t,e){return'The value "'+e+'" is invalid for option "'+t+'"'},TypeError);lc("ERR_INVALID_ARG_TYPE",function(t,e,r){let o;typeof e=="string"&&e2t(e,"not ")?(o="must not be",e=e.replace(/^not /,"")):o="must be";let a;if(t2t(t," argument"))a=`The ${t} ${o} ${O1e(e,"type")}`;else{let n=r2t(t,".")?"property":"argument";a=`The "${t}" ${n} ${o} ${O1e(e,"type")}`}return a+=`. Received type ${typeof r}`,a},TypeError);lc("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF");lc("ERR_METHOD_NOT_IMPLEMENTED",function(t){return"The "+t+" method is not implemented"});lc("ERR_STREAM_PREMATURE_CLOSE","Premature close");lc("ERR_STREAM_DESTROYED",function(t){return"Cannot call "+t+" after a stream was destroyed"});lc("ERR_MULTIPLE_CALLBACK","Callback called multiple times");lc("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable");lc("ERR_STREAM_WRITE_AFTER_END","write after end");lc("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError);lc("ERR_UNKNOWN_ENCODING",function(t){return"Unknown encoding: "+t},TypeError);lc("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event");_1e.exports.codes=U1e});var vj=_((P$t,H1e)=>{"use strict";var n2t=Gh().codes.ERR_INVALID_OPT_VALUE;function i2t(t,e,r){return t.highWaterMark!=null?t.highWaterMark:e?t[r]:null}function s2t(t,e,r,o){var a=i2t(e,o,r);if(a!=null){if(!(isFinite(a)&&Math.floor(a)===a)||a<0){var n=o?r:"highWaterMark";throw new n2t(n,a)}return Math.floor(a)}return t.objectMode?16:16*1024}H1e.exports={getHighWaterMark:s2t}});var q1e=_((S$t,Dj)=>{typeof Object.create=="function"?Dj.exports=function(e,r){r&&(e.super_=r,e.prototype=Object.create(r.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:Dj.exports=function(e,r){if(r){e.super_=r;var o=function(){};o.prototype=r.prototype,e.prototype=new o,e.prototype.constructor=e}}});var Yh=_((b$t,Sj)=>{try{if(Pj=ve("util"),typeof Pj.inherits!="function")throw"";Sj.exports=Pj.inherits}catch{Sj.exports=q1e()}var Pj});var G1e=_((x$t,j1e)=>{j1e.exports=ve("util").deprecate});var kj=_((k$t,J1e)=>{"use strict";J1e.exports=Fi;function W1e(t){var e=this;this.next=null,this.entry=null,this.finish=function(){F2t(e,t)}}var gC;Fi.WritableState=$B;var o2t={deprecate:G1e()},K1e=Cj(),wQ=ve("buffer").Buffer,a2t=global.Uint8Array||function(){};function l2t(t){return wQ.from(t)}function c2t(t){return wQ.isBuffer(t)||t instanceof a2t}var xj=Bj(),u2t=vj(),A2t=u2t.getHighWaterMark,Wh=Gh().codes,f2t=Wh.ERR_INVALID_ARG_TYPE,p2t=Wh.ERR_METHOD_NOT_IMPLEMENTED,h2t=Wh.ERR_MULTIPLE_CALLBACK,g2t=Wh.ERR_STREAM_CANNOT_PIPE,d2t=Wh.ERR_STREAM_DESTROYED,m2t=Wh.ERR_STREAM_NULL_VALUES,y2t=Wh.ERR_STREAM_WRITE_AFTER_END,E2t=Wh.ERR_UNKNOWN_ENCODING,dC=xj.errorOrDestroy;Yh()(Fi,K1e);function C2t(){}function $B(t,e,r){gC=gC||ld(),t=t||{},typeof r!="boolean"&&(r=e instanceof gC),this.objectMode=!!t.objectMode,r&&(this.objectMode=this.objectMode||!!t.writableObjectMode),this.highWaterMark=A2t(this,t,"writableHighWaterMark",r),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var o=t.decodeStrings===!1;this.decodeStrings=!o,this.defaultEncoding=t.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(a){S2t(e,a)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=t.emitClose!==!1,this.autoDestroy=!!t.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new W1e(this)}$B.prototype.getBuffer=function(){for(var e=this.bufferedRequest,r=[];e;)r.push(e),e=e.next;return r};(function(){try{Object.defineProperty($B.prototype,"buffer",{get:o2t.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch{}})();var CQ;typeof Symbol=="function"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]=="function"?(CQ=Function.prototype[Symbol.hasInstance],Object.defineProperty(Fi,Symbol.hasInstance,{value:function(e){return CQ.call(this,e)?!0:this!==Fi?!1:e&&e._writableState instanceof $B}})):CQ=function(e){return e instanceof this};function Fi(t){gC=gC||ld();var e=this instanceof gC;if(!e&&!CQ.call(Fi,this))return new Fi(t);this._writableState=new $B(t,this,e),this.writable=!0,t&&(typeof t.write=="function"&&(this._write=t.write),typeof t.writev=="function"&&(this._writev=t.writev),typeof t.destroy=="function"&&(this._destroy=t.destroy),typeof t.final=="function"&&(this._final=t.final)),K1e.call(this)}Fi.prototype.pipe=function(){dC(this,new g2t)};function w2t(t,e){var r=new y2t;dC(t,r),process.nextTick(e,r)}function I2t(t,e,r,o){var a;return r===null?a=new m2t:typeof r!="string"&&!e.objectMode&&(a=new f2t("chunk",["string","Buffer"],r)),a?(dC(t,a),process.nextTick(o,a),!1):!0}Fi.prototype.write=function(t,e,r){var o=this._writableState,a=!1,n=!o.objectMode&&c2t(t);return n&&!wQ.isBuffer(t)&&(t=l2t(t)),typeof e=="function"&&(r=e,e=null),n?e="buffer":e||(e=o.defaultEncoding),typeof r!="function"&&(r=C2t),o.ending?w2t(this,r):(n||I2t(this,o,t,r))&&(o.pendingcb++,a=v2t(this,o,n,t,e,r)),a};Fi.prototype.cork=function(){this._writableState.corked++};Fi.prototype.uncork=function(){var t=this._writableState;t.corked&&(t.corked--,!t.writing&&!t.corked&&!t.bufferProcessing&&t.bufferedRequest&&V1e(this,t))};Fi.prototype.setDefaultEncoding=function(e){if(typeof e=="string"&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new E2t(e);return this._writableState.defaultEncoding=e,this};Object.defineProperty(Fi.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});function B2t(t,e,r){return!t.objectMode&&t.decodeStrings!==!1&&typeof e=="string"&&(e=wQ.from(e,r)),e}Object.defineProperty(Fi.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function v2t(t,e,r,o,a,n){if(!r){var u=B2t(e,o,a);o!==u&&(r=!0,a="buffer",o=u)}var A=e.objectMode?1:o.length;e.length+=A;var p=e.length<e.highWaterMark;if(p||(e.needDrain=!0),e.writing||e.corked){var h=e.lastBufferedRequest;e.lastBufferedRequest={chunk:o,encoding:a,isBuf:r,callback:n,next:null},h?h.next=e.lastBufferedRequest:e.bufferedRequest=e.lastBufferedRequest,e.bufferedRequestCount+=1}else bj(t,e,!1,A,o,a,n);return p}function bj(t,e,r,o,a,n,u){e.writelen=o,e.writecb=u,e.writing=!0,e.sync=!0,e.destroyed?e.onwrite(new d2t("write")):r?t._writev(a,e.onwrite):t._write(a,n,e.onwrite),e.sync=!1}function D2t(t,e,r,o,a){--e.pendingcb,r?(process.nextTick(a,o),process.nextTick(ZB,t,e),t._writableState.errorEmitted=!0,dC(t,o)):(a(o),t._writableState.errorEmitted=!0,dC(t,o),ZB(t,e))}function P2t(t){t.writing=!1,t.writecb=null,t.length-=t.writelen,t.writelen=0}function S2t(t,e){var r=t._writableState,o=r.sync,a=r.writecb;if(typeof a!="function")throw new h2t;if(P2t(r),e)D2t(t,r,o,e,a);else{var n=z1e(r)||t.destroyed;!n&&!r.corked&&!r.bufferProcessing&&r.bufferedRequest&&V1e(t,r),o?process.nextTick(Y1e,t,r,n,a):Y1e(t,r,n,a)}}function Y1e(t,e,r,o){r||b2t(t,e),e.pendingcb--,o(),ZB(t,e)}function b2t(t,e){e.length===0&&e.needDrain&&(e.needDrain=!1,t.emit("drain"))}function V1e(t,e){e.bufferProcessing=!0;var r=e.bufferedRequest;if(t._writev&&r&&r.next){var o=e.bufferedRequestCount,a=new Array(o),n=e.corkedRequestsFree;n.entry=r;for(var u=0,A=!0;r;)a[u]=r,r.isBuf||(A=!1),r=r.next,u+=1;a.allBuffers=A,bj(t,e,!0,e.length,a,"",n.finish),e.pendingcb++,e.lastBufferedRequest=null,n.next?(e.corkedRequestsFree=n.next,n.next=null):e.corkedRequestsFree=new W1e(e),e.bufferedRequestCount=0}else{for(;r;){var p=r.chunk,h=r.encoding,E=r.callback,I=e.objectMode?1:p.length;if(bj(t,e,!1,I,p,h,E),r=r.next,e.bufferedRequestCount--,e.writing)break}r===null&&(e.lastBufferedRequest=null)}e.bufferedRequest=r,e.bufferProcessing=!1}Fi.prototype._write=function(t,e,r){r(new p2t("_write()"))};Fi.prototype._writev=null;Fi.prototype.end=function(t,e,r){var o=this._writableState;return typeof t=="function"?(r=t,t=null,e=null):typeof e=="function"&&(r=e,e=null),t!=null&&this.write(t,e),o.corked&&(o.corked=1,this.uncork()),o.ending||Q2t(this,o,r),this};Object.defineProperty(Fi.prototype,"writableLength",{enumerable:!1,get:function(){return this._writableState.length}});function z1e(t){return t.ending&&t.length===0&&t.bufferedRequest===null&&!t.finished&&!t.writing}function x2t(t,e){t._final(function(r){e.pendingcb--,r&&dC(t,r),e.prefinished=!0,t.emit("prefinish"),ZB(t,e)})}function k2t(t,e){!e.prefinished&&!e.finalCalled&&(typeof t._final=="function"&&!e.destroyed?(e.pendingcb++,e.finalCalled=!0,process.nextTick(x2t,t,e)):(e.prefinished=!0,t.emit("prefinish")))}function ZB(t,e){var r=z1e(e);if(r&&(k2t(t,e),e.pendingcb===0&&(e.finished=!0,t.emit("finish"),e.autoDestroy))){var o=t._readableState;(!o||o.autoDestroy&&o.endEmitted)&&t.destroy()}return r}function Q2t(t,e,r){e.ending=!0,ZB(t,e),r&&(e.finished?process.nextTick(r):t.once("finish",r)),e.ended=!0,t.writable=!1}function F2t(t,e,r){var o=t.entry;for(t.entry=null;o;){var a=o.callback;e.pendingcb--,a(r),o=o.next}e.corkedRequestsFree.next=t}Object.defineProperty(Fi.prototype,"destroyed",{enumerable:!1,get:function(){return this._writableState===void 0?!1:this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}});Fi.prototype.destroy=xj.destroy;Fi.prototype._undestroy=xj.undestroy;Fi.prototype._destroy=function(t,e){e(t)}});var ld=_((Q$t,Z1e)=>{"use strict";var R2t=Object.keys||function(t){var e=[];for(var r in t)e.push(r);return e};Z1e.exports=yA;var X1e=Rj(),Fj=kj();Yh()(yA,X1e);for(Qj=R2t(Fj.prototype),IQ=0;IQ<Qj.length;IQ++)BQ=Qj[IQ],yA.prototype[BQ]||(yA.prototype[BQ]=Fj.prototype[BQ]);var Qj,BQ,IQ;function yA(t){if(!(this instanceof yA))return new yA(t);X1e.call(this,t),Fj.call(this,t),this.allowHalfOpen=!0,t&&(t.readable===!1&&(this.readable=!1),t.writable===!1&&(this.writable=!1),t.allowHalfOpen===!1&&(this.allowHalfOpen=!1,this.once("end",T2t)))}Object.defineProperty(yA.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});Object.defineProperty(yA.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});Object.defineProperty(yA.prototype,"writableLength",{enumerable:!1,get:function(){return this._writableState.length}});function T2t(){this._writableState.ended||process.nextTick(N2t,this)}function N2t(t){t.end()}Object.defineProperty(yA.prototype,"destroyed",{enumerable:!1,get:function(){return this._readableState===void 0||this._writableState===void 0?!1:this._readableState.destroyed&&this._writableState.destroyed},set:function(e){this._readableState===void 0||this._writableState===void 0||(this._readableState.destroyed=e,this._writableState.destroyed=e)}})});var t2e=_((Tj,e2e)=>{var vQ=ve("buffer"),rp=vQ.Buffer;function $1e(t,e){for(var r in t)e[r]=t[r]}rp.from&&rp.alloc&&rp.allocUnsafe&&rp.allocUnsafeSlow?e2e.exports=vQ:($1e(vQ,Tj),Tj.Buffer=mC);function mC(t,e,r){return rp(t,e,r)}$1e(rp,mC);mC.from=function(t,e,r){if(typeof t=="number")throw new TypeError("Argument must not be a number");return rp(t,e,r)};mC.alloc=function(t,e,r){if(typeof t!="number")throw new TypeError("Argument must be a number");var o=rp(t);return e!==void 0?typeof r=="string"?o.fill(e,r):o.fill(e):o.fill(0),o};mC.allocUnsafe=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return rp(t)};mC.allocUnsafeSlow=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return vQ.SlowBuffer(t)}});var Mj=_(n2e=>{"use strict";var Lj=t2e().Buffer,r2e=Lj.isEncoding||function(t){switch(t=""+t,t&&t.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function L2t(t){if(!t)return"utf8";for(var e;;)switch(t){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return t;default:if(e)return;t=(""+t).toLowerCase(),e=!0}}function M2t(t){var e=L2t(t);if(typeof e!="string"&&(Lj.isEncoding===r2e||!r2e(t)))throw new Error("Unknown encoding: "+t);return e||t}n2e.StringDecoder=ev;function ev(t){this.encoding=M2t(t);var e;switch(this.encoding){case"utf16le":this.text=j2t,this.end=G2t,e=4;break;case"utf8":this.fillLast=_2t,e=4;break;case"base64":this.text=Y2t,this.end=W2t,e=3;break;default:this.write=K2t,this.end=V2t;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=Lj.allocUnsafe(e)}ev.prototype.write=function(t){if(t.length===0)return"";var e,r;if(this.lastNeed){if(e=this.fillLast(t),e===void 0)return"";r=this.lastNeed,this.lastNeed=0}else r=0;return r<t.length?e?e+this.text(t,r):this.text(t,r):e||""};ev.prototype.end=q2t;ev.prototype.text=H2t;ev.prototype.fillLast=function(t){if(this.lastNeed<=t.length)return t.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);t.copy(this.lastChar,this.lastTotal-this.lastNeed,0,t.length),this.lastNeed-=t.length};function Nj(t){return t<=127?0:t>>5===6?2:t>>4===14?3:t>>3===30?4:t>>6===2?-1:-2}function O2t(t,e,r){var o=e.length-1;if(o<r)return 0;var a=Nj(e[o]);return a>=0?(a>0&&(t.lastNeed=a-1),a):--o<r||a===-2?0:(a=Nj(e[o]),a>=0?(a>0&&(t.lastNeed=a-2),a):--o<r||a===-2?0:(a=Nj(e[o]),a>=0?(a>0&&(a===2?a=0:t.lastNeed=a-3),a):0))}function U2t(t,e,r){if((e[0]&192)!==128)return t.lastNeed=0,"\uFFFD";if(t.lastNeed>1&&e.length>1){if((e[1]&192)!==128)return t.lastNeed=1,"\uFFFD";if(t.lastNeed>2&&e.length>2&&(e[2]&192)!==128)return t.lastNeed=2,"\uFFFD"}}function _2t(t){var e=this.lastTotal-this.lastNeed,r=U2t(this,t,e);if(r!==void 0)return r;if(this.lastNeed<=t.length)return t.copy(this.lastChar,e,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);t.copy(this.lastChar,e,0,t.length),this.lastNeed-=t.length}function H2t(t,e){var r=O2t(this,t,e);if(!this.lastNeed)return t.toString("utf8",e);this.lastTotal=r;var o=t.length-(r-this.lastNeed);return t.copy(this.lastChar,0,o),t.toString("utf8",e,o)}function q2t(t){var e=t&&t.length?this.write(t):"";return this.lastNeed?e+"\uFFFD":e}function j2t(t,e){if((t.length-e)%2===0){var r=t.toString("utf16le",e);if(r){var o=r.charCodeAt(r.length-1);if(o>=55296&&o<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=t[t.length-1],t.toString("utf16le",e,t.length-1)}function G2t(t){var e=t&&t.length?this.write(t):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return e+this.lastChar.toString("utf16le",0,r)}return e}function Y2t(t,e){var r=(t.length-e)%3;return r===0?t.toString("base64",e):(this.lastNeed=3-r,this.lastTotal=3,r===1?this.lastChar[0]=t[t.length-1]:(this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1]),t.toString("base64",e,t.length-r))}function W2t(t){var e=t&&t.length?this.write(t):"";return this.lastNeed?e+this.lastChar.toString("base64",0,3-this.lastNeed):e}function K2t(t){return t.toString(this.encoding)}function V2t(t){return t&&t.length?this.write(t):""}});var DQ=_((R$t,o2e)=>{"use strict";var i2e=Gh().codes.ERR_STREAM_PREMATURE_CLOSE;function z2t(t){var e=!1;return function(){if(!e){e=!0;for(var r=arguments.length,o=new Array(r),a=0;a<r;a++)o[a]=arguments[a];t.apply(this,o)}}}function J2t(){}function X2t(t){return t.setHeader&&typeof t.abort=="function"}function s2e(t,e,r){if(typeof e=="function")return s2e(t,null,e);e||(e={}),r=z2t(r||J2t);var o=e.readable||e.readable!==!1&&t.readable,a=e.writable||e.writable!==!1&&t.writable,n=function(){t.writable||A()},u=t._writableState&&t._writableState.finished,A=function(){a=!1,u=!0,o||r.call(t)},p=t._readableState&&t._readableState.endEmitted,h=function(){o=!1,p=!0,a||r.call(t)},E=function(C){r.call(t,C)},I=function(){var C;if(o&&!p)return(!t._readableState||!t._readableState.ended)&&(C=new i2e),r.call(t,C);if(a&&!u)return(!t._writableState||!t._writableState.ended)&&(C=new i2e),r.call(t,C)},v=function(){t.req.on("finish",A)};return X2t(t)?(t.on("complete",A),t.on("abort",I),t.req?v():t.on("request",v)):a&&!t._writableState&&(t.on("end",n),t.on("close",n)),t.on("end",h),t.on("finish",A),e.error!==!1&&t.on("error",E),t.on("close",I),function(){t.removeListener("complete",A),t.removeListener("abort",I),t.removeListener("request",v),t.req&&t.req.removeListener("finish",A),t.removeListener("end",n),t.removeListener("close",n),t.removeListener("finish",A),t.removeListener("end",h),t.removeListener("error",E),t.removeListener("close",I)}}o2e.exports=s2e});var l2e=_((T$t,a2e)=>{"use strict";var PQ;function Kh(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var Z2t=DQ(),Vh=Symbol("lastResolve"),cd=Symbol("lastReject"),tv=Symbol("error"),SQ=Symbol("ended"),ud=Symbol("lastPromise"),Oj=Symbol("handlePromise"),Ad=Symbol("stream");function zh(t,e){return{value:t,done:e}}function $2t(t){var e=t[Vh];if(e!==null){var r=t[Ad].read();r!==null&&(t[ud]=null,t[Vh]=null,t[cd]=null,e(zh(r,!1)))}}function eBt(t){process.nextTick($2t,t)}function tBt(t,e){return function(r,o){t.then(function(){if(e[SQ]){r(zh(void 0,!0));return}e[Oj](r,o)},o)}}var rBt=Object.getPrototypeOf(function(){}),nBt=Object.setPrototypeOf((PQ={get stream(){return this[Ad]},next:function(){var e=this,r=this[tv];if(r!==null)return Promise.reject(r);if(this[SQ])return Promise.resolve(zh(void 0,!0));if(this[Ad].destroyed)return new Promise(function(u,A){process.nextTick(function(){e[tv]?A(e[tv]):u(zh(void 0,!0))})});var o=this[ud],a;if(o)a=new Promise(tBt(o,this));else{var n=this[Ad].read();if(n!==null)return Promise.resolve(zh(n,!1));a=new Promise(this[Oj])}return this[ud]=a,a}},Kh(PQ,Symbol.asyncIterator,function(){return this}),Kh(PQ,"return",function(){var e=this;return new Promise(function(r,o){e[Ad].destroy(null,function(a){if(a){o(a);return}r(zh(void 0,!0))})})}),PQ),rBt),iBt=function(e){var r,o=Object.create(nBt,(r={},Kh(r,Ad,{value:e,writable:!0}),Kh(r,Vh,{value:null,writable:!0}),Kh(r,cd,{value:null,writable:!0}),Kh(r,tv,{value:null,writable:!0}),Kh(r,SQ,{value:e._readableState.endEmitted,writable:!0}),Kh(r,Oj,{value:function(n,u){var A=o[Ad].read();A?(o[ud]=null,o[Vh]=null,o[cd]=null,n(zh(A,!1))):(o[Vh]=n,o[cd]=u)},writable:!0}),r));return o[ud]=null,Z2t(e,function(a){if(a&&a.code!=="ERR_STREAM_PREMATURE_CLOSE"){var n=o[cd];n!==null&&(o[ud]=null,o[Vh]=null,o[cd]=null,n(a)),o[tv]=a;return}var u=o[Vh];u!==null&&(o[ud]=null,o[Vh]=null,o[cd]=null,u(zh(void 0,!0))),o[SQ]=!0}),e.on("readable",eBt.bind(null,o)),o};a2e.exports=iBt});var f2e=_((N$t,A2e)=>{"use strict";function c2e(t,e,r,o,a,n,u){try{var A=t[n](u),p=A.value}catch(h){r(h);return}A.done?e(p):Promise.resolve(p).then(o,a)}function sBt(t){return function(){var e=this,r=arguments;return new Promise(function(o,a){var n=t.apply(e,r);function u(p){c2e(n,o,a,u,A,"next",p)}function A(p){c2e(n,o,a,u,A,"throw",p)}u(void 0)})}}function u2e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,o)}return r}function oBt(t){for(var e=1;e<arguments.length;e++){var r=arguments[e]!=null?arguments[e]:{};e%2?u2e(Object(r),!0).forEach(function(o){aBt(t,o,r[o])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):u2e(Object(r)).forEach(function(o){Object.defineProperty(t,o,Object.getOwnPropertyDescriptor(r,o))})}return t}function aBt(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var lBt=Gh().codes.ERR_INVALID_ARG_TYPE;function cBt(t,e,r){var o;if(e&&typeof e.next=="function")o=e;else if(e&&e[Symbol.asyncIterator])o=e[Symbol.asyncIterator]();else if(e&&e[Symbol.iterator])o=e[Symbol.iterator]();else throw new lBt("iterable",["Iterable"],e);var a=new t(oBt({objectMode:!0},r)),n=!1;a._read=function(){n||(n=!0,u())};function u(){return A.apply(this,arguments)}function A(){return A=sBt(function*(){try{var p=yield o.next(),h=p.value,E=p.done;E?a.push(null):a.push(yield h)?u():n=!1}catch(I){a.destroy(I)}}),A.apply(this,arguments)}return a}A2e.exports=cBt});var Rj=_((M$t,I2e)=>{"use strict";I2e.exports=mn;var yC;mn.ReadableState=d2e;var L$t=ve("events").EventEmitter,g2e=function(e,r){return e.listeners(r).length},nv=Cj(),bQ=ve("buffer").Buffer,uBt=global.Uint8Array||function(){};function ABt(t){return bQ.from(t)}function fBt(t){return bQ.isBuffer(t)||t instanceof uBt}var Uj=ve("util"),en;Uj&&Uj.debuglog?en=Uj.debuglog("stream"):en=function(){};var pBt=N1e(),Wj=Bj(),hBt=vj(),gBt=hBt.getHighWaterMark,xQ=Gh().codes,dBt=xQ.ERR_INVALID_ARG_TYPE,mBt=xQ.ERR_STREAM_PUSH_AFTER_EOF,yBt=xQ.ERR_METHOD_NOT_IMPLEMENTED,EBt=xQ.ERR_STREAM_UNSHIFT_AFTER_END_EVENT,EC,_j,Hj;Yh()(mn,nv);var rv=Wj.errorOrDestroy,qj=["error","close","destroy","pause","resume"];function CBt(t,e,r){if(typeof t.prependListener=="function")return t.prependListener(e,r);!t._events||!t._events[e]?t.on(e,r):Array.isArray(t._events[e])?t._events[e].unshift(r):t._events[e]=[r,t._events[e]]}function d2e(t,e,r){yC=yC||ld(),t=t||{},typeof r!="boolean"&&(r=e instanceof yC),this.objectMode=!!t.objectMode,r&&(this.objectMode=this.objectMode||!!t.readableObjectMode),this.highWaterMark=gBt(this,t,"readableHighWaterMark",r),this.buffer=new pBt,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=t.emitClose!==!1,this.autoDestroy=!!t.autoDestroy,this.destroyed=!1,this.defaultEncoding=t.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,t.encoding&&(EC||(EC=Mj().StringDecoder),this.decoder=new EC(t.encoding),this.encoding=t.encoding)}function mn(t){if(yC=yC||ld(),!(this instanceof mn))return new mn(t);var e=this instanceof yC;this._readableState=new d2e(t,this,e),this.readable=!0,t&&(typeof t.read=="function"&&(this._read=t.read),typeof t.destroy=="function"&&(this._destroy=t.destroy)),nv.call(this)}Object.defineProperty(mn.prototype,"destroyed",{enumerable:!1,get:function(){return this._readableState===void 0?!1:this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}});mn.prototype.destroy=Wj.destroy;mn.prototype._undestroy=Wj.undestroy;mn.prototype._destroy=function(t,e){e(t)};mn.prototype.push=function(t,e){var r=this._readableState,o;return r.objectMode?o=!0:typeof t=="string"&&(e=e||r.defaultEncoding,e!==r.encoding&&(t=bQ.from(t,e),e=""),o=!0),m2e(this,t,e,!1,o)};mn.prototype.unshift=function(t){return m2e(this,t,null,!0,!1)};function m2e(t,e,r,o,a){en("readableAddChunk",e);var n=t._readableState;if(e===null)n.reading=!1,BBt(t,n);else{var u;if(a||(u=wBt(n,e)),u)rv(t,u);else if(n.objectMode||e&&e.length>0)if(typeof e!="string"&&!n.objectMode&&Object.getPrototypeOf(e)!==bQ.prototype&&(e=ABt(e)),o)n.endEmitted?rv(t,new EBt):jj(t,n,e,!0);else if(n.ended)rv(t,new mBt);else{if(n.destroyed)return!1;n.reading=!1,n.decoder&&!r?(e=n.decoder.write(e),n.objectMode||e.length!==0?jj(t,n,e,!1):Yj(t,n)):jj(t,n,e,!1)}else o||(n.reading=!1,Yj(t,n))}return!n.ended&&(n.length<n.highWaterMark||n.length===0)}function jj(t,e,r,o){e.flowing&&e.length===0&&!e.sync?(e.awaitDrain=0,t.emit("data",r)):(e.length+=e.objectMode?1:r.length,o?e.buffer.unshift(r):e.buffer.push(r),e.needReadable&&kQ(t)),Yj(t,e)}function wBt(t,e){var r;return!fBt(e)&&typeof e!="string"&&e!==void 0&&!t.objectMode&&(r=new dBt("chunk",["string","Buffer","Uint8Array"],e)),r}mn.prototype.isPaused=function(){return this._readableState.flowing===!1};mn.prototype.setEncoding=function(t){EC||(EC=Mj().StringDecoder);var e=new EC(t);this._readableState.decoder=e,this._readableState.encoding=this._readableState.decoder.encoding;for(var r=this._readableState.buffer.head,o="";r!==null;)o+=e.write(r.data),r=r.next;return this._readableState.buffer.clear(),o!==""&&this._readableState.buffer.push(o),this._readableState.length=o.length,this};var p2e=1073741824;function IBt(t){return t>=p2e?t=p2e:(t--,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,t|=t>>>16,t++),t}function h2e(t,e){return t<=0||e.length===0&&e.ended?0:e.objectMode?1:t!==t?e.flowing&&e.length?e.buffer.head.data.length:e.length:(t>e.highWaterMark&&(e.highWaterMark=IBt(t)),t<=e.length?t:e.ended?e.length:(e.needReadable=!0,0))}mn.prototype.read=function(t){en("read",t),t=parseInt(t,10);var e=this._readableState,r=t;if(t!==0&&(e.emittedReadable=!1),t===0&&e.needReadable&&((e.highWaterMark!==0?e.length>=e.highWaterMark:e.length>0)||e.ended))return en("read: emitReadable",e.length,e.ended),e.length===0&&e.ended?Gj(this):kQ(this),null;if(t=h2e(t,e),t===0&&e.ended)return e.length===0&&Gj(this),null;var o=e.needReadable;en("need readable",o),(e.length===0||e.length-t<e.highWaterMark)&&(o=!0,en("length less than watermark",o)),e.ended||e.reading?(o=!1,en("reading or ended",o)):o&&(en("do read"),e.reading=!0,e.sync=!0,e.length===0&&(e.needReadable=!0),this._read(e.highWaterMark),e.sync=!1,e.reading||(t=h2e(r,e)));var a;return t>0?a=C2e(t,e):a=null,a===null?(e.needReadable=e.length<=e.highWaterMark,t=0):(e.length-=t,e.awaitDrain=0),e.length===0&&(e.ended||(e.needReadable=!0),r!==t&&e.ended&&Gj(this)),a!==null&&this.emit("data",a),a};function BBt(t,e){if(en("onEofChunk"),!e.ended){if(e.decoder){var r=e.decoder.end();r&&r.length&&(e.buffer.push(r),e.length+=e.objectMode?1:r.length)}e.ended=!0,e.sync?kQ(t):(e.needReadable=!1,e.emittedReadable||(e.emittedReadable=!0,y2e(t)))}}function kQ(t){var e=t._readableState;en("emitReadable",e.needReadable,e.emittedReadable),e.needReadable=!1,e.emittedReadable||(en("emitReadable",e.flowing),e.emittedReadable=!0,process.nextTick(y2e,t))}function y2e(t){var e=t._readableState;en("emitReadable_",e.destroyed,e.length,e.ended),!e.destroyed&&(e.length||e.ended)&&(t.emit("readable"),e.emittedReadable=!1),e.needReadable=!e.flowing&&!e.ended&&e.length<=e.highWaterMark,Kj(t)}function Yj(t,e){e.readingMore||(e.readingMore=!0,process.nextTick(vBt,t,e))}function vBt(t,e){for(;!e.reading&&!e.ended&&(e.length<e.highWaterMark||e.flowing&&e.length===0);){var r=e.length;if(en("maybeReadMore read 0"),t.read(0),r===e.length)break}e.readingMore=!1}mn.prototype._read=function(t){rv(this,new yBt("_read()"))};mn.prototype.pipe=function(t,e){var r=this,o=this._readableState;switch(o.pipesCount){case 0:o.pipes=t;break;case 1:o.pipes=[o.pipes,t];break;default:o.pipes.push(t);break}o.pipesCount+=1,en("pipe count=%d opts=%j",o.pipesCount,e);var a=(!e||e.end!==!1)&&t!==process.stdout&&t!==process.stderr,n=a?A:R;o.endEmitted?process.nextTick(n):r.once("end",n),t.on("unpipe",u);function u(L,U){en("onunpipe"),L===r&&U&&U.hasUnpiped===!1&&(U.hasUnpiped=!0,E())}function A(){en("onend"),t.end()}var p=DBt(r);t.on("drain",p);var h=!1;function E(){en("cleanup"),t.removeListener("close",x),t.removeListener("finish",C),t.removeListener("drain",p),t.removeListener("error",v),t.removeListener("unpipe",u),r.removeListener("end",A),r.removeListener("end",R),r.removeListener("data",I),h=!0,o.awaitDrain&&(!t._writableState||t._writableState.needDrain)&&p()}r.on("data",I);function I(L){en("ondata");var U=t.write(L);en("dest.write",U),U===!1&&((o.pipesCount===1&&o.pipes===t||o.pipesCount>1&&w2e(o.pipes,t)!==-1)&&!h&&(en("false write response, pause",o.awaitDrain),o.awaitDrain++),r.pause())}function v(L){en("onerror",L),R(),t.removeListener("error",v),g2e(t,"error")===0&&rv(t,L)}CBt(t,"error",v);function x(){t.removeListener("finish",C),R()}t.once("close",x);function C(){en("onfinish"),t.removeListener("close",x),R()}t.once("finish",C);function R(){en("unpipe"),r.unpipe(t)}return t.emit("pipe",r),o.flowing||(en("pipe resume"),r.resume()),t};function DBt(t){return function(){var r=t._readableState;en("pipeOnDrain",r.awaitDrain),r.awaitDrain&&r.awaitDrain--,r.awaitDrain===0&&g2e(t,"data")&&(r.flowing=!0,Kj(t))}}mn.prototype.unpipe=function(t){var e=this._readableState,r={hasUnpiped:!1};if(e.pipesCount===0)return this;if(e.pipesCount===1)return t&&t!==e.pipes?this:(t||(t=e.pipes),e.pipes=null,e.pipesCount=0,e.flowing=!1,t&&t.emit("unpipe",this,r),this);if(!t){var o=e.pipes,a=e.pipesCount;e.pipes=null,e.pipesCount=0,e.flowing=!1;for(var n=0;n<a;n++)o[n].emit("unpipe",this,{hasUnpiped:!1});return this}var u=w2e(e.pipes,t);return u===-1?this:(e.pipes.splice(u,1),e.pipesCount-=1,e.pipesCount===1&&(e.pipes=e.pipes[0]),t.emit("unpipe",this,r),this)};mn.prototype.on=function(t,e){var r=nv.prototype.on.call(this,t,e),o=this._readableState;return t==="data"?(o.readableListening=this.listenerCount("readable")>0,o.flowing!==!1&&this.resume()):t==="readable"&&!o.endEmitted&&!o.readableListening&&(o.readableListening=o.needReadable=!0,o.flowing=!1,o.emittedReadable=!1,en("on readable",o.length,o.reading),o.length?kQ(this):o.reading||process.nextTick(PBt,this)),r};mn.prototype.addListener=mn.prototype.on;mn.prototype.removeListener=function(t,e){var r=nv.prototype.removeListener.call(this,t,e);return t==="readable"&&process.nextTick(E2e,this),r};mn.prototype.removeAllListeners=function(t){var e=nv.prototype.removeAllListeners.apply(this,arguments);return(t==="readable"||t===void 0)&&process.nextTick(E2e,this),e};function E2e(t){var e=t._readableState;e.readableListening=t.listenerCount("readable")>0,e.resumeScheduled&&!e.paused?e.flowing=!0:t.listenerCount("data")>0&&t.resume()}function PBt(t){en("readable nexttick read 0"),t.read(0)}mn.prototype.resume=function(){var t=this._readableState;return t.flowing||(en("resume"),t.flowing=!t.readableListening,SBt(this,t)),t.paused=!1,this};function SBt(t,e){e.resumeScheduled||(e.resumeScheduled=!0,process.nextTick(bBt,t,e))}function bBt(t,e){en("resume",e.reading),e.reading||t.read(0),e.resumeScheduled=!1,t.emit("resume"),Kj(t),e.flowing&&!e.reading&&t.read(0)}mn.prototype.pause=function(){return en("call pause flowing=%j",this._readableState.flowing),this._readableState.flowing!==!1&&(en("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState.paused=!0,this};function Kj(t){var e=t._readableState;for(en("flow",e.flowing);e.flowing&&t.read()!==null;);}mn.prototype.wrap=function(t){var e=this,r=this._readableState,o=!1;t.on("end",function(){if(en("wrapped end"),r.decoder&&!r.ended){var u=r.decoder.end();u&&u.length&&e.push(u)}e.push(null)}),t.on("data",function(u){if(en("wrapped data"),r.decoder&&(u=r.decoder.write(u)),!(r.objectMode&&u==null)&&!(!r.objectMode&&(!u||!u.length))){var A=e.push(u);A||(o=!0,t.pause())}});for(var a in t)this[a]===void 0&&typeof t[a]=="function"&&(this[a]=function(A){return function(){return t[A].apply(t,arguments)}}(a));for(var n=0;n<qj.length;n++)t.on(qj[n],this.emit.bind(this,qj[n]));return this._read=function(u){en("wrapped _read",u),o&&(o=!1,t.resume())},this};typeof Symbol=="function"&&(mn.prototype[Symbol.asyncIterator]=function(){return _j===void 0&&(_j=l2e()),_j(this)});Object.defineProperty(mn.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}});Object.defineProperty(mn.prototype,"readableBuffer",{enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}});Object.defineProperty(mn.prototype,"readableFlowing",{enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}});mn._fromList=C2e;Object.defineProperty(mn.prototype,"readableLength",{enumerable:!1,get:function(){return this._readableState.length}});function C2e(t,e){if(e.length===0)return null;var r;return e.objectMode?r=e.buffer.shift():!t||t>=e.length?(e.decoder?r=e.buffer.join(""):e.buffer.length===1?r=e.buffer.first():r=e.buffer.concat(e.length),e.buffer.clear()):r=e.buffer.consume(t,e.decoder),r}function Gj(t){var e=t._readableState;en("endReadable",e.endEmitted),e.endEmitted||(e.ended=!0,process.nextTick(xBt,e,t))}function xBt(t,e){if(en("endReadableNT",t.endEmitted,t.length),!t.endEmitted&&t.length===0&&(t.endEmitted=!0,e.readable=!1,e.emit("end"),t.autoDestroy)){var r=e._writableState;(!r||r.autoDestroy&&r.finished)&&e.destroy()}}typeof Symbol=="function"&&(mn.from=function(t,e){return Hj===void 0&&(Hj=f2e()),Hj(mn,t,e)});function w2e(t,e){for(var r=0,o=t.length;r<o;r++)if(t[r]===e)return r;return-1}});var Vj=_((O$t,v2e)=>{"use strict";v2e.exports=np;var QQ=Gh().codes,kBt=QQ.ERR_METHOD_NOT_IMPLEMENTED,QBt=QQ.ERR_MULTIPLE_CALLBACK,FBt=QQ.ERR_TRANSFORM_ALREADY_TRANSFORMING,RBt=QQ.ERR_TRANSFORM_WITH_LENGTH_0,FQ=ld();Yh()(np,FQ);function TBt(t,e){var r=this._transformState;r.transforming=!1;var o=r.writecb;if(o===null)return this.emit("error",new QBt);r.writechunk=null,r.writecb=null,e!=null&&this.push(e),o(t);var a=this._readableState;a.reading=!1,(a.needReadable||a.length<a.highWaterMark)&&this._read(a.highWaterMark)}function np(t){if(!(this instanceof np))return new np(t);FQ.call(this,t),this._transformState={afterTransform:TBt.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,t&&(typeof t.transform=="function"&&(this._transform=t.transform),typeof t.flush=="function"&&(this._flush=t.flush)),this.on("prefinish",NBt)}function NBt(){var t=this;typeof this._flush=="function"&&!this._readableState.destroyed?this._flush(function(e,r){B2e(t,e,r)}):B2e(this,null,null)}np.prototype.push=function(t,e){return this._transformState.needTransform=!1,FQ.prototype.push.call(this,t,e)};np.prototype._transform=function(t,e,r){r(new kBt("_transform()"))};np.prototype._write=function(t,e,r){var o=this._transformState;if(o.writecb=r,o.writechunk=t,o.writeencoding=e,!o.transforming){var a=this._readableState;(o.needTransform||a.needReadable||a.length<a.highWaterMark)&&this._read(a.highWaterMark)}};np.prototype._read=function(t){var e=this._transformState;e.writechunk!==null&&!e.transforming?(e.transforming=!0,this._transform(e.writechunk,e.writeencoding,e.afterTransform)):e.needTransform=!0};np.prototype._destroy=function(t,e){FQ.prototype._destroy.call(this,t,function(r){e(r)})};function B2e(t,e,r){if(e)return t.emit("error",e);if(r!=null&&t.push(r),t._writableState.length)throw new RBt;if(t._transformState.transforming)throw new FBt;return t.push(null)}});var S2e=_((U$t,P2e)=>{"use strict";P2e.exports=iv;var D2e=Vj();Yh()(iv,D2e);function iv(t){if(!(this instanceof iv))return new iv(t);D2e.call(this,t)}iv.prototype._transform=function(t,e,r){r(null,t)}});var F2e=_((_$t,Q2e)=>{"use strict";var zj;function LBt(t){var e=!1;return function(){e||(e=!0,t.apply(void 0,arguments))}}var k2e=Gh().codes,MBt=k2e.ERR_MISSING_ARGS,OBt=k2e.ERR_STREAM_DESTROYED;function b2e(t){if(t)throw t}function UBt(t){return t.setHeader&&typeof t.abort=="function"}function _Bt(t,e,r,o){o=LBt(o);var a=!1;t.on("close",function(){a=!0}),zj===void 0&&(zj=DQ()),zj(t,{readable:e,writable:r},function(u){if(u)return o(u);a=!0,o()});var n=!1;return function(u){if(!a&&!n){if(n=!0,UBt(t))return t.abort();if(typeof t.destroy=="function")return t.destroy();o(u||new OBt("pipe"))}}}function x2e(t){t()}function HBt(t,e){return t.pipe(e)}function qBt(t){return!t.length||typeof t[t.length-1]!="function"?b2e:t.pop()}function jBt(){for(var t=arguments.length,e=new Array(t),r=0;r<t;r++)e[r]=arguments[r];var o=qBt(e);if(Array.isArray(e[0])&&(e=e[0]),e.length<2)throw new MBt("streams");var a,n=e.map(function(u,A){var p=A<e.length-1,h=A>0;return _Bt(u,p,h,function(E){a||(a=E),E&&n.forEach(x2e),!p&&(n.forEach(x2e),o(a))})});return e.reduce(HBt)}Q2e.exports=jBt});var CC=_((cc,ov)=>{var sv=ve("stream");process.env.READABLE_STREAM==="disable"&&sv?(ov.exports=sv.Readable,Object.assign(ov.exports,sv),ov.exports.Stream=sv):(cc=ov.exports=Rj(),cc.Stream=sv||cc,cc.Readable=cc,cc.Writable=kj(),cc.Duplex=ld(),cc.Transform=Vj(),cc.PassThrough=S2e(),cc.finished=DQ(),cc.pipeline=F2e())});var N2e=_((H$t,T2e)=>{"use strict";var{Buffer:uu}=ve("buffer"),R2e=Symbol.for("BufferList");function ni(t){if(!(this instanceof ni))return new ni(t);ni._init.call(this,t)}ni._init=function(e){Object.defineProperty(this,R2e,{value:!0}),this._bufs=[],this.length=0,e&&this.append(e)};ni.prototype._new=function(e){return new ni(e)};ni.prototype._offset=function(e){if(e===0)return[0,0];let r=0;for(let o=0;o<this._bufs.length;o++){let a=r+this._bufs[o].length;if(e<a||o===this._bufs.length-1)return[o,e-r];r=a}};ni.prototype._reverseOffset=function(t){let e=t[0],r=t[1];for(let o=0;o<e;o++)r+=this._bufs[o].length;return r};ni.prototype.get=function(e){if(e>this.length||e<0)return;let r=this._offset(e);return this._bufs[r[0]][r[1]]};ni.prototype.slice=function(e,r){return typeof e=="number"&&e<0&&(e+=this.length),typeof r=="number"&&r<0&&(r+=this.length),this.copy(null,0,e,r)};ni.prototype.copy=function(e,r,o,a){if((typeof o!="number"||o<0)&&(o=0),(typeof a!="number"||a>this.length)&&(a=this.length),o>=this.length||a<=0)return e||uu.alloc(0);let n=!!e,u=this._offset(o),A=a-o,p=A,h=n&&r||0,E=u[1];if(o===0&&a===this.length){if(!n)return this._bufs.length===1?this._bufs[0]:uu.concat(this._bufs,this.length);for(let I=0;I<this._bufs.length;I++)this._bufs[I].copy(e,h),h+=this._bufs[I].length;return e}if(p<=this._bufs[u[0]].length-E)return n?this._bufs[u[0]].copy(e,r,E,E+p):this._bufs[u[0]].slice(E,E+p);n||(e=uu.allocUnsafe(A));for(let I=u[0];I<this._bufs.length;I++){let v=this._bufs[I].length-E;if(p>v)this._bufs[I].copy(e,h,E),h+=v;else{this._bufs[I].copy(e,h,E,E+p),h+=v;break}p-=v,E&&(E=0)}return e.length>h?e.slice(0,h):e};ni.prototype.shallowSlice=function(e,r){if(e=e||0,r=typeof r!="number"?this.length:r,e<0&&(e+=this.length),r<0&&(r+=this.length),e===r)return this._new();let o=this._offset(e),a=this._offset(r),n=this._bufs.slice(o[0],a[0]+1);return a[1]===0?n.pop():n[n.length-1]=n[n.length-1].slice(0,a[1]),o[1]!==0&&(n[0]=n[0].slice(o[1])),this._new(n)};ni.prototype.toString=function(e,r,o){return this.slice(r,o).toString(e)};ni.prototype.consume=function(e){if(e=Math.trunc(e),Number.isNaN(e)||e<=0)return this;for(;this._bufs.length;)if(e>=this._bufs[0].length)e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift();else{this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}return this};ni.prototype.duplicate=function(){let e=this._new();for(let r=0;r<this._bufs.length;r++)e.append(this._bufs[r]);return e};ni.prototype.append=function(e){if(e==null)return this;if(e.buffer)this._appendBuffer(uu.from(e.buffer,e.byteOffset,e.byteLength));else if(Array.isArray(e))for(let r=0;r<e.length;r++)this.append(e[r]);else if(this._isBufferList(e))for(let r=0;r<e._bufs.length;r++)this.append(e._bufs[r]);else typeof e=="number"&&(e=e.toString()),this._appendBuffer(uu.from(e));return this};ni.prototype._appendBuffer=function(e){this._bufs.push(e),this.length+=e.length};ni.prototype.indexOf=function(t,e,r){if(r===void 0&&typeof e=="string"&&(r=e,e=void 0),typeof t=="function"||Array.isArray(t))throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.');if(typeof t=="number"?t=uu.from([t]):typeof t=="string"?t=uu.from(t,r):this._isBufferList(t)?t=t.slice():Array.isArray(t.buffer)?t=uu.from(t.buffer,t.byteOffset,t.byteLength):uu.isBuffer(t)||(t=uu.from(t)),e=Number(e||0),isNaN(e)&&(e=0),e<0&&(e=this.length+e),e<0&&(e=0),t.length===0)return e>this.length?this.length:e;let o=this._offset(e),a=o[0],n=o[1];for(;a<this._bufs.length;a++){let u=this._bufs[a];for(;n<u.length;)if(u.length-n>=t.length){let p=u.indexOf(t,n);if(p!==-1)return this._reverseOffset([a,p]);n=u.length-t.length+1}else{let p=this._reverseOffset([a,n]);if(this._match(p,t))return p;n++}n=0}return-1};ni.prototype._match=function(t,e){if(this.length-t<e.length)return!1;for(let r=0;r<e.length;r++)if(this.get(t+r)!==e[r])return!1;return!0};(function(){let t={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1,readIntBE:null,readIntLE:null,readUIntBE:null,readUIntLE:null};for(let e in t)(function(r){t[r]===null?ni.prototype[r]=function(o,a){return this.slice(o,o+a)[r](0,a)}:ni.prototype[r]=function(o=0){return this.slice(o,o+t[r])[r](0)}})(e)})();ni.prototype._isBufferList=function(e){return e instanceof ni||ni.isBufferList(e)};ni.isBufferList=function(e){return e!=null&&e[R2e]};T2e.exports=ni});var L2e=_((q$t,RQ)=>{"use strict";var Jj=CC().Duplex,GBt=Yh(),av=N2e();function Uo(t){if(!(this instanceof Uo))return new Uo(t);if(typeof t=="function"){this._callback=t;let e=function(o){this._callback&&(this._callback(o),this._callback=null)}.bind(this);this.on("pipe",function(o){o.on("error",e)}),this.on("unpipe",function(o){o.removeListener("error",e)}),t=null}av._init.call(this,t),Jj.call(this)}GBt(Uo,Jj);Object.assign(Uo.prototype,av.prototype);Uo.prototype._new=function(e){return new Uo(e)};Uo.prototype._write=function(e,r,o){this._appendBuffer(e),typeof o=="function"&&o()};Uo.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)};Uo.prototype.end=function(e){Jj.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)};Uo.prototype._destroy=function(e,r){this._bufs.length=0,this.length=0,r(e)};Uo.prototype._isBufferList=function(e){return e instanceof Uo||e instanceof av||Uo.isBufferList(e)};Uo.isBufferList=av.isBufferList;RQ.exports=Uo;RQ.exports.BufferListStream=Uo;RQ.exports.BufferList=av});var $j=_(IC=>{var YBt=Buffer.alloc,WBt="0000000000000000000",KBt="7777777777777777777",M2e=48,O2e=Buffer.from("ustar\0","binary"),VBt=Buffer.from("00","binary"),zBt=Buffer.from("ustar ","binary"),JBt=Buffer.from(" \0","binary"),XBt=parseInt("7777",8),lv=257,Zj=263,ZBt=function(t,e,r){return typeof t!="number"?r:(t=~~t,t>=e?e:t>=0||(t+=e,t>=0)?t:0)},$Bt=function(t){switch(t){case 0:return"file";case 1:return"link";case 2:return"symlink";case 3:return"character-device";case 4:return"block-device";case 5:return"directory";case 6:return"fifo";case 7:return"contiguous-file";case 72:return"pax-header";case 55:return"pax-global-header";case 27:return"gnu-long-link-path";case 28:case 30:return"gnu-long-path"}return null},evt=function(t){switch(t){case"file":return 0;case"link":return 1;case"symlink":return 2;case"character-device":return 3;case"block-device":return 4;case"directory":return 5;case"fifo":return 6;case"contiguous-file":return 7;case"pax-header":return 72}return 0},U2e=function(t,e,r,o){for(;r<o;r++)if(t[r]===e)return r;return o},_2e=function(t){for(var e=256,r=0;r<148;r++)e+=t[r];for(var o=156;o<512;o++)e+=t[o];return e},Jh=function(t,e){return t=t.toString(8),t.length>e?KBt.slice(0,e)+" ":WBt.slice(0,e-t.length)+t+" "};function tvt(t){var e;if(t[0]===128)e=!0;else if(t[0]===255)e=!1;else return null;for(var r=[],o=t.length-1;o>0;o--){var a=t[o];e?r.push(a):r.push(255-a)}var n=0,u=r.length;for(o=0;o<u;o++)n+=r[o]*Math.pow(256,o);return e?n:-1*n}var Xh=function(t,e,r){if(t=t.slice(e,e+r),e=0,t[e]&128)return tvt(t);for(;e<t.length&&t[e]===32;)e++;for(var o=ZBt(U2e(t,32,e,t.length),t.length,t.length);e<o&&t[e]===0;)e++;return o===e?0:parseInt(t.slice(e,o).toString(),8)},wC=function(t,e,r,o){return t.slice(e,U2e(t,0,e,e+r)).toString(o)},Xj=function(t){var e=Buffer.byteLength(t),r=Math.floor(Math.log(e)/Math.log(10))+1;return e+r>=Math.pow(10,r)&&r++,e+r+t};IC.decodeLongPath=function(t,e){return wC(t,0,t.length,e)};IC.encodePax=function(t){var e="";t.name&&(e+=Xj(" path="+t.name+` +`)),t.linkname&&(e+=Xj(" linkpath="+t.linkname+` +`));var r=t.pax;if(r)for(var o in r)e+=Xj(" "+o+"="+r[o]+` +`);return Buffer.from(e)};IC.decodePax=function(t){for(var e={};t.length;){for(var r=0;r<t.length&&t[r]!==32;)r++;var o=parseInt(t.slice(0,r).toString(),10);if(!o)return e;var a=t.slice(r+1,o-1).toString(),n=a.indexOf("=");if(n===-1)return e;e[a.slice(0,n)]=a.slice(n+1),t=t.slice(o)}return e};IC.encode=function(t){var e=YBt(512),r=t.name,o="";if(t.typeflag===5&&r[r.length-1]!=="/"&&(r+="/"),Buffer.byteLength(r)!==r.length)return null;for(;Buffer.byteLength(r)>100;){var a=r.indexOf("/");if(a===-1)return null;o+=o?"/"+r.slice(0,a):r.slice(0,a),r=r.slice(a+1)}return Buffer.byteLength(r)>100||Buffer.byteLength(o)>155||t.linkname&&Buffer.byteLength(t.linkname)>100?null:(e.write(r),e.write(Jh(t.mode&XBt,6),100),e.write(Jh(t.uid,6),108),e.write(Jh(t.gid,6),116),e.write(Jh(t.size,11),124),e.write(Jh(t.mtime.getTime()/1e3|0,11),136),e[156]=M2e+evt(t.type),t.linkname&&e.write(t.linkname,157),O2e.copy(e,lv),VBt.copy(e,Zj),t.uname&&e.write(t.uname,265),t.gname&&e.write(t.gname,297),e.write(Jh(t.devmajor||0,6),329),e.write(Jh(t.devminor||0,6),337),o&&e.write(o,345),e.write(Jh(_2e(e),6),148),e)};IC.decode=function(t,e,r){var o=t[156]===0?0:t[156]-M2e,a=wC(t,0,100,e),n=Xh(t,100,8),u=Xh(t,108,8),A=Xh(t,116,8),p=Xh(t,124,12),h=Xh(t,136,12),E=$Bt(o),I=t[157]===0?null:wC(t,157,100,e),v=wC(t,265,32),x=wC(t,297,32),C=Xh(t,329,8),R=Xh(t,337,8),L=_2e(t);if(L===8*32)return null;if(L!==Xh(t,148,8))throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");if(O2e.compare(t,lv,lv+6)===0)t[345]&&(a=wC(t,345,155,e)+"/"+a);else if(!(zBt.compare(t,lv,lv+6)===0&&JBt.compare(t,Zj,Zj+2)===0)){if(!r)throw new Error("Invalid tar header: unknown format.")}return o===0&&a&&a[a.length-1]==="/"&&(o=5),{name:a,mode:n,uid:u,gid:A,size:p,mtime:new Date(1e3*h),type:E,linkname:I,uname:v,gname:x,devmajor:C,devminor:R}}});var K2e=_((G$t,W2e)=>{var q2e=ve("util"),rvt=L2e(),cv=$j(),j2e=CC().Writable,G2e=CC().PassThrough,Y2e=function(){},H2e=function(t){return t&=511,t&&512-t},nvt=function(t,e){var r=new TQ(t,e);return r.end(),r},ivt=function(t,e){return e.path&&(t.name=e.path),e.linkpath&&(t.linkname=e.linkpath),e.size&&(t.size=parseInt(e.size,10)),t.pax=e,t},TQ=function(t,e){this._parent=t,this.offset=e,G2e.call(this,{autoDestroy:!1})};q2e.inherits(TQ,G2e);TQ.prototype.destroy=function(t){this._parent.destroy(t)};var ip=function(t){if(!(this instanceof ip))return new ip(t);j2e.call(this,t),t=t||{},this._offset=0,this._buffer=rvt(),this._missing=0,this._partial=!1,this._onparse=Y2e,this._header=null,this._stream=null,this._overflow=null,this._cb=null,this._locked=!1,this._destroyed=!1,this._pax=null,this._paxGlobal=null,this._gnuLongPath=null,this._gnuLongLinkPath=null;var e=this,r=e._buffer,o=function(){e._continue()},a=function(v){if(e._locked=!1,v)return e.destroy(v);e._stream||o()},n=function(){e._stream=null;var v=H2e(e._header.size);v?e._parse(v,u):e._parse(512,I),e._locked||o()},u=function(){e._buffer.consume(H2e(e._header.size)),e._parse(512,I),o()},A=function(){var v=e._header.size;e._paxGlobal=cv.decodePax(r.slice(0,v)),r.consume(v),n()},p=function(){var v=e._header.size;e._pax=cv.decodePax(r.slice(0,v)),e._paxGlobal&&(e._pax=Object.assign({},e._paxGlobal,e._pax)),r.consume(v),n()},h=function(){var v=e._header.size;this._gnuLongPath=cv.decodeLongPath(r.slice(0,v),t.filenameEncoding),r.consume(v),n()},E=function(){var v=e._header.size;this._gnuLongLinkPath=cv.decodeLongPath(r.slice(0,v),t.filenameEncoding),r.consume(v),n()},I=function(){var v=e._offset,x;try{x=e._header=cv.decode(r.slice(0,512),t.filenameEncoding,t.allowUnknownFormat)}catch(C){e.emit("error",C)}if(r.consume(512),!x){e._parse(512,I),o();return}if(x.type==="gnu-long-path"){e._parse(x.size,h),o();return}if(x.type==="gnu-long-link-path"){e._parse(x.size,E),o();return}if(x.type==="pax-global-header"){e._parse(x.size,A),o();return}if(x.type==="pax-header"){e._parse(x.size,p),o();return}if(e._gnuLongPath&&(x.name=e._gnuLongPath,e._gnuLongPath=null),e._gnuLongLinkPath&&(x.linkname=e._gnuLongLinkPath,e._gnuLongLinkPath=null),e._pax&&(e._header=x=ivt(x,e._pax),e._pax=null),e._locked=!0,!x.size||x.type==="directory"){e._parse(512,I),e.emit("entry",x,nvt(e,v),a);return}e._stream=new TQ(e,v),e.emit("entry",x,e._stream,a),e._parse(x.size,n),o()};this._onheader=I,this._parse(512,I)};q2e.inherits(ip,j2e);ip.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit("error",t),this.emit("close"),this._stream&&this._stream.emit("close"))};ip.prototype._parse=function(t,e){this._destroyed||(this._offset+=t,this._missing=t,e===this._onheader&&(this._partial=!1),this._onparse=e)};ip.prototype._continue=function(){if(!this._destroyed){var t=this._cb;this._cb=Y2e,this._overflow?this._write(this._overflow,void 0,t):t()}};ip.prototype._write=function(t,e,r){if(!this._destroyed){var o=this._stream,a=this._buffer,n=this._missing;if(t.length&&(this._partial=!0),t.length<n)return this._missing-=t.length,this._overflow=null,o?o.write(t,r):(a.append(t),r());this._cb=r,this._missing=0;var u=null;t.length>n&&(u=t.slice(n),t=t.slice(0,n)),o?o.end(t):a.append(t),this._overflow=u,this._onparse()}};ip.prototype._final=function(t){if(this._partial)return this.destroy(new Error("Unexpected end of data"));t()};W2e.exports=ip});var z2e=_((Y$t,V2e)=>{V2e.exports=ve("fs").constants||ve("constants")});var eBe=_((W$t,$2e)=>{var BC=z2e(),J2e=bO(),LQ=Yh(),svt=Buffer.alloc,X2e=CC().Readable,vC=CC().Writable,ovt=ve("string_decoder").StringDecoder,NQ=$j(),avt=parseInt("755",8),lvt=parseInt("644",8),Z2e=svt(1024),t5=function(){},e5=function(t,e){e&=511,e&&t.push(Z2e.slice(0,512-e))};function cvt(t){switch(t&BC.S_IFMT){case BC.S_IFBLK:return"block-device";case BC.S_IFCHR:return"character-device";case BC.S_IFDIR:return"directory";case BC.S_IFIFO:return"fifo";case BC.S_IFLNK:return"symlink"}return"file"}var MQ=function(t){vC.call(this),this.written=0,this._to=t,this._destroyed=!1};LQ(MQ,vC);MQ.prototype._write=function(t,e,r){if(this.written+=t.length,this._to.push(t))return r();this._to._drain=r};MQ.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var OQ=function(){vC.call(this),this.linkname="",this._decoder=new ovt("utf-8"),this._destroyed=!1};LQ(OQ,vC);OQ.prototype._write=function(t,e,r){this.linkname+=this._decoder.write(t),r()};OQ.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var uv=function(){vC.call(this),this._destroyed=!1};LQ(uv,vC);uv.prototype._write=function(t,e,r){r(new Error("No body allowed for this entry"))};uv.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var EA=function(t){if(!(this instanceof EA))return new EA(t);X2e.call(this,t),this._drain=t5,this._finalized=!1,this._finalizing=!1,this._destroyed=!1,this._stream=null};LQ(EA,X2e);EA.prototype.entry=function(t,e,r){if(this._stream)throw new Error("already piping an entry");if(!(this._finalized||this._destroyed)){typeof e=="function"&&(r=e,e=null),r||(r=t5);var o=this;if((!t.size||t.type==="symlink")&&(t.size=0),t.type||(t.type=cvt(t.mode)),t.mode||(t.mode=t.type==="directory"?avt:lvt),t.uid||(t.uid=0),t.gid||(t.gid=0),t.mtime||(t.mtime=new Date),typeof e=="string"&&(e=Buffer.from(e)),Buffer.isBuffer(e)){t.size=e.length,this._encode(t);var a=this.push(e);return e5(o,t.size),a?process.nextTick(r):this._drain=r,new uv}if(t.type==="symlink"&&!t.linkname){var n=new OQ;return J2e(n,function(A){if(A)return o.destroy(),r(A);t.linkname=n.linkname,o._encode(t),r()}),n}if(this._encode(t),t.type!=="file"&&t.type!=="contiguous-file")return process.nextTick(r),new uv;var u=new MQ(this);return this._stream=u,J2e(u,function(A){if(o._stream=null,A)return o.destroy(),r(A);if(u.written!==t.size)return o.destroy(),r(new Error("size mismatch"));e5(o,t.size),o._finalizing&&o.finalize(),r()}),u}};EA.prototype.finalize=function(){if(this._stream){this._finalizing=!0;return}this._finalized||(this._finalized=!0,this.push(Z2e),this.push(null))};EA.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit("error",t),this.emit("close"),this._stream&&this._stream.destroy&&this._stream.destroy())};EA.prototype._encode=function(t){if(!t.pax){var e=NQ.encode(t);if(e){this.push(e);return}}this._encodePax(t)};EA.prototype._encodePax=function(t){var e=NQ.encodePax({name:t.name,linkname:t.linkname,pax:t.pax}),r={name:"PaxHeader",mode:t.mode,uid:t.uid,gid:t.gid,size:e.length,mtime:t.mtime,type:"pax-header",linkname:t.linkname&&"PaxHeader",uname:t.uname,gname:t.gname,devmajor:t.devmajor,devminor:t.devminor};this.push(NQ.encode(r)),this.push(e),e5(this,e.length),r.size=t.size,r.type=t.type,this.push(NQ.encode(r))};EA.prototype._read=function(t){var e=this._drain;this._drain=t5,e()};$2e.exports=EA});var tBe=_(r5=>{r5.extract=K2e();r5.pack=eBe()});var pBe=_((fer,fBe)=>{"use strict";var Av=class t{constructor(e,r,o){this.__specs=e||{},Object.keys(this.__specs).forEach(a=>{if(typeof this.__specs[a]=="string"){let n=this.__specs[a],u=this.__specs[n];if(u){let A=u.aliases||[];A.push(a,n),u.aliases=[...new Set(A)],this.__specs[a]=u}else throw new Error(`Alias refers to invalid key: ${n} -> ${a}`)}}),this.__opts=r||{},this.__providers=uBe(o.filter(a=>a!=null&&typeof a=="object")),this.__isFiggyPudding=!0}get(e){return l5(this,e,!0)}get[Symbol.toStringTag](){return"FiggyPudding"}forEach(e,r=this){for(let[o,a]of this.entries())e.call(r,a,o,this)}toJSON(){let e={};return this.forEach((r,o)=>{e[o]=r}),e}*entries(e){for(let o of Object.keys(this.__specs))yield[o,this.get(o)];let r=e||this.__opts.other;if(r){let o=new Set;for(let a of this.__providers){let n=a.entries?a.entries(r):vvt(a);for(let[u,A]of n)r(u)&&!o.has(u)&&(o.add(u),yield[u,A])}}}*[Symbol.iterator](){for(let[e,r]of this.entries())yield[e,r]}*keys(){for(let[e]of this.entries())yield e}*values(){for(let[,e]of this.entries())yield e}concat(...e){return new Proxy(new t(this.__specs,this.__opts,uBe(this.__providers).concat(e)),ABe)}};try{let t=ve("util");Av.prototype[t.inspect.custom]=function(e,r){return this[Symbol.toStringTag]+" "+t.inspect(this.toJSON(),r)}}catch{}function Ivt(t){throw Object.assign(new Error(`invalid config key requested: ${t}`),{code:"EBADKEY"})}function l5(t,e,r){let o=t.__specs[e];if(r&&!o&&(!t.__opts.other||!t.__opts.other(e)))Ivt(e);else{o||(o={});let a;for(let n of t.__providers){if(a=cBe(e,n),a===void 0&&o.aliases&&o.aliases.length){for(let u of o.aliases)if(u!==e&&(a=cBe(u,n),a!==void 0))break}if(a!==void 0)break}return a===void 0&&o.default!==void 0?typeof o.default=="function"?o.default(t):o.default:a}}function cBe(t,e){let r;return e.__isFiggyPudding?r=l5(e,t,!1):typeof e.get=="function"?r=e.get(t):r=e[t],r}var ABe={has(t,e){return e in t.__specs&&l5(t,e,!1)!==void 0},ownKeys(t){return Object.keys(t.__specs)},get(t,e){return typeof e=="symbol"||e.slice(0,2)==="__"||e in Av.prototype?t[e]:t.get(e)},set(t,e,r){if(typeof e=="symbol"||e.slice(0,2)==="__")return t[e]=r,!0;throw new Error("figgyPudding options cannot be modified. Use .concat() instead.")},deleteProperty(){throw new Error("figgyPudding options cannot be deleted. Use .concat() and shadow them instead.")}};fBe.exports=Bvt;function Bvt(t,e){function r(...o){return new Proxy(new Av(t,e,o),ABe)}return r}function uBe(t){let e=[];return t.forEach(r=>e.unshift(r)),e}function vvt(t){return Object.keys(t).map(e=>[e,t[e]])}});var dBe=_((per,IA)=>{"use strict";var pv=ve("crypto"),Dvt=pBe(),Pvt=ve("stream").Transform,hBe=["sha256","sha384","sha512"],Svt=/^[a-z0-9+/]+(?:=?=?)$/i,bvt=/^([^-]+)-([^?]+)([?\S*]*)$/,xvt=/^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/,kvt=/^[\x21-\x7E]+$/,oa=Dvt({algorithms:{default:["sha512"]},error:{default:!1},integrity:{},options:{default:[]},pickAlgorithm:{default:()=>Ovt},Promise:{default:()=>Promise},sep:{default:" "},single:{default:!1},size:{},strict:{default:!1}}),Zh=class{get isHash(){return!0}constructor(e,r){r=oa(r);let o=!!r.strict;this.source=e.trim();let a=this.source.match(o?xvt:bvt);if(!a||o&&!hBe.some(u=>u===a[1]))return;this.algorithm=a[1],this.digest=a[2];let n=a[3];this.options=n?n.slice(1).split("?"):[]}hexDigest(){return this.digest&&Buffer.from(this.digest,"base64").toString("hex")}toJSON(){return this.toString()}toString(e){if(e=oa(e),e.strict&&!(hBe.some(o=>o===this.algorithm)&&this.digest.match(Svt)&&(this.options||[]).every(o=>o.match(kvt))))return"";let r=this.options&&this.options.length?`?${this.options.join("?")}`:"";return`${this.algorithm}-${this.digest}${r}`}},fd=class{get isIntegrity(){return!0}toJSON(){return this.toString()}toString(e){e=oa(e);let r=e.sep||" ";return e.strict&&(r=r.replace(/\S+/g," ")),Object.keys(this).map(o=>this[o].map(a=>Zh.prototype.toString.call(a,e)).filter(a=>a.length).join(r)).filter(o=>o.length).join(r)}concat(e,r){r=oa(r);let o=typeof e=="string"?e:fv(e,r);return wA(`${this.toString(r)} ${o}`,r)}hexDigest(){return wA(this,{single:!0}).hexDigest()}match(e,r){r=oa(r);let o=wA(e,r),a=o.pickAlgorithm(r);return this[a]&&o[a]&&this[a].find(n=>o[a].find(u=>n.digest===u.digest))||!1}pickAlgorithm(e){e=oa(e);let r=e.pickAlgorithm,o=Object.keys(this);if(!o.length)throw new Error(`No algorithms available for ${JSON.stringify(this.toString())}`);return o.reduce((a,n)=>r(a,n)||a)}};IA.exports.parse=wA;function wA(t,e){if(e=oa(e),typeof t=="string")return c5(t,e);if(t.algorithm&&t.digest){let r=new fd;return r[t.algorithm]=[t],c5(fv(r,e),e)}else return c5(fv(t,e),e)}function c5(t,e){return e.single?new Zh(t,e):t.trim().split(/\s+/).reduce((r,o)=>{let a=new Zh(o,e);if(a.algorithm&&a.digest){let n=a.algorithm;r[n]||(r[n]=[]),r[n].push(a)}return r},new fd)}IA.exports.stringify=fv;function fv(t,e){return e=oa(e),t.algorithm&&t.digest?Zh.prototype.toString.call(t,e):typeof t=="string"?fv(wA(t,e),e):fd.prototype.toString.call(t,e)}IA.exports.fromHex=Qvt;function Qvt(t,e,r){r=oa(r);let o=r.options&&r.options.length?`?${r.options.join("?")}`:"";return wA(`${e}-${Buffer.from(t,"hex").toString("base64")}${o}`,r)}IA.exports.fromData=Fvt;function Fvt(t,e){e=oa(e);let r=e.algorithms,o=e.options&&e.options.length?`?${e.options.join("?")}`:"";return r.reduce((a,n)=>{let u=pv.createHash(n).update(t).digest("base64"),A=new Zh(`${n}-${u}${o}`,e);if(A.algorithm&&A.digest){let p=A.algorithm;a[p]||(a[p]=[]),a[p].push(A)}return a},new fd)}IA.exports.fromStream=Rvt;function Rvt(t,e){e=oa(e);let r=e.Promise||Promise,o=u5(e);return new r((a,n)=>{t.pipe(o),t.on("error",n),o.on("error",n);let u;o.on("integrity",A=>{u=A}),o.on("end",()=>a(u)),o.on("data",()=>{})})}IA.exports.checkData=Tvt;function Tvt(t,e,r){if(r=oa(r),e=wA(e,r),!Object.keys(e).length){if(r.error)throw Object.assign(new Error("No valid integrity hashes to check against"),{code:"EINTEGRITY"});return!1}let o=e.pickAlgorithm(r),a=pv.createHash(o).update(t).digest("base64"),n=wA({algorithm:o,digest:a}),u=n.match(e,r);if(u||!r.error)return u;if(typeof r.size=="number"&&t.length!==r.size){let A=new Error(`data size mismatch when checking ${e}. + Wanted: ${r.size} + Found: ${t.length}`);throw A.code="EBADSIZE",A.found=t.length,A.expected=r.size,A.sri=e,A}else{let A=new Error(`Integrity checksum failed when using ${o}: Wanted ${e}, but got ${n}. (${t.length} bytes)`);throw A.code="EINTEGRITY",A.found=n,A.expected=e,A.algorithm=o,A.sri=e,A}}IA.exports.checkStream=Nvt;function Nvt(t,e,r){r=oa(r);let o=r.Promise||Promise,a=u5(r.concat({integrity:e}));return new o((n,u)=>{t.pipe(a),t.on("error",u),a.on("error",u);let A;a.on("verified",p=>{A=p}),a.on("end",()=>n(A)),a.on("data",()=>{})})}IA.exports.integrityStream=u5;function u5(t){t=oa(t);let e=t.integrity&&wA(t.integrity,t),r=e&&Object.keys(e).length,o=r&&e.pickAlgorithm(t),a=r&&e[o],n=Array.from(new Set(t.algorithms.concat(o?[o]:[]))),u=n.map(pv.createHash),A=0,p=new Pvt({transform(h,E,I){A+=h.length,u.forEach(v=>v.update(h,E)),I(null,h,E)}}).on("end",()=>{let h=t.options&&t.options.length?`?${t.options.join("?")}`:"",E=wA(u.map((v,x)=>`${n[x]}-${v.digest("base64")}${h}`).join(" "),t),I=r&&E.match(e,t);if(typeof t.size=="number"&&A!==t.size){let v=new Error(`stream size mismatch when checking ${e}. + Wanted: ${t.size} + Found: ${A}`);v.code="EBADSIZE",v.found=A,v.expected=t.size,v.sri=e,p.emit("error",v)}else if(t.integrity&&!I){let v=new Error(`${e} integrity checksum failed when using ${o}: wanted ${a} but got ${E}. (${A} bytes)`);v.code="EINTEGRITY",v.found=E,v.expected=a,v.algorithm=o,v.sri=e,p.emit("error",v)}else p.emit("size",A),p.emit("integrity",E),I&&p.emit("verified",I)});return p}IA.exports.create=Lvt;function Lvt(t){t=oa(t);let e=t.algorithms,r=t.options.length?`?${t.options.join("?")}`:"",o=e.map(pv.createHash);return{update:function(a,n){return o.forEach(u=>u.update(a,n)),this},digest:function(a){return e.reduce((u,A)=>{let p=o.shift().digest("base64"),h=new Zh(`${A}-${p}${r}`,t);if(h.algorithm&&h.digest){let E=h.algorithm;u[E]||(u[E]=[]),u[E].push(h)}return u},new fd)}}}var Mvt=new Set(pv.getHashes()),gBe=["md5","whirlpool","sha1","sha224","sha256","sha384","sha512","sha3","sha3-256","sha3-384","sha3-512","sha3_256","sha3_384","sha3_512"].filter(t=>Mvt.has(t));function Ovt(t,e){return gBe.indexOf(t.toLowerCase())>=gBe.indexOf(e.toLowerCase())?t:e}});var YBe=_((dir,GBe)=>{var ODt=$N();function UDt(t){return ODt(t)?void 0:t}GBe.exports=UDt});var KBe=_((mir,WBe)=>{var _Dt=kb(),HDt=B8(),qDt=S8(),jDt=Mg(),GDt=Ag(),YDt=YBe(),WDt=m_(),KDt=I8(),VDt=1,zDt=2,JDt=4,XDt=WDt(function(t,e){var r={};if(t==null)return r;var o=!1;e=_Dt(e,function(n){return n=jDt(n,t),o||(o=n.length>1),n}),GDt(t,KDt(t),r),o&&(r=HDt(r,VDt|zDt|JDt,YDt));for(var a=e.length;a--;)qDt(r,e[a]);return r});WBe.exports=XDt});Pt();Ge();Pt();var ZBe=ve("child_process"),$Be=Ze(X0());qt();var Uy=new Map([]);var W1={};Vt(W1,{BaseCommand:()=>ut,WorkspaceRequiredError:()=>sr,getCli:()=>ihe,getDynamicLibs:()=>nhe,getPluginConfiguration:()=>Hy,openWorkspace:()=>_y,pluginCommands:()=>Uy,runExit:()=>Wx});qt();var ut=class extends it{constructor(){super(...arguments);this.cwd=ge.String("--cwd",{hidden:!0})}validateAndExecute(){if(typeof this.cwd<"u")throw new st("The --cwd option is ambiguous when used anywhere else than the very first parameter provided in the command line, before even the command path");return super.validateAndExecute()}};Ge();Pt();qt();var sr=class extends st{constructor(e,r){let o=K.relative(e,r),a=K.join(e,Ut.fileName);super(`This command can only be run from within a workspace of your project (${o} isn't a workspace of ${a}).`)}};Ge();Pt();nA();Nl();g1();qt();var OAt=Ze(Jn());el();var nhe=()=>new Map([["@yarnpkg/cli",W1],["@yarnpkg/core",Y1],["@yarnpkg/fslib",kw],["@yarnpkg/libzip",p1],["@yarnpkg/parsers",Ow],["@yarnpkg/shell",E1],["clipanion",Jw],["semver",OAt],["typanion",Vo]]);Ge();async function _y(t,e){let{project:r,workspace:o}=await kt.find(t,e);if(!o)throw new sr(r.cwd,e);return o}Ge();Pt();nA();Nl();g1();qt();var oPt=Ze(Jn());el();var K8={};Vt(K8,{AddCommand:()=>Yy,BinCommand:()=>Wy,CacheCleanCommand:()=>Ky,ClipanionCommand:()=>$y,ConfigCommand:()=>Xy,ConfigGetCommand:()=>Vy,ConfigSetCommand:()=>zy,ConfigUnsetCommand:()=>Jy,DedupeCommand:()=>Zy,EntryCommand:()=>tE,ExecCommand:()=>nE,ExplainCommand:()=>oE,ExplainPeerRequirementsCommand:()=>iE,HelpCommand:()=>eE,InfoCommand:()=>aE,LinkCommand:()=>cE,NodeCommand:()=>uE,PluginCheckCommand:()=>AE,PluginImportCommand:()=>hE,PluginImportSourcesCommand:()=>gE,PluginListCommand:()=>fE,PluginRemoveCommand:()=>dE,PluginRuntimeCommand:()=>mE,RebuildCommand:()=>yE,RemoveCommand:()=>EE,RunCommand:()=>wE,RunIndexCommand:()=>CE,SetResolutionCommand:()=>IE,SetVersionCommand:()=>sE,SetVersionSourcesCommand:()=>pE,UnlinkCommand:()=>BE,UpCommand:()=>vE,VersionCommand:()=>rE,WhyCommand:()=>DE,WorkspaceCommand:()=>kE,WorkspacesListCommand:()=>xE,YarnCommand:()=>lE,dedupeUtils:()=>rk,default:()=>Fgt,suggestUtils:()=>Zc});var Nde=Ze(X0());Ge();Ge();Ge();qt();var Y0e=Ze(J1());el();var Zc={};Vt(Zc,{Modifier:()=>m8,Strategy:()=>$x,Target:()=>X1,WorkspaceModifier:()=>_0e,applyModifier:()=>ipt,extractDescriptorFromPath:()=>y8,extractRangeModifier:()=>H0e,fetchDescriptorFrom:()=>E8,findProjectDescriptors:()=>G0e,getModifier:()=>Z1,getSuggestedDescriptors:()=>$1,makeWorkspaceDescriptor:()=>j0e,toWorkspaceModifier:()=>q0e});Ge();Ge();Pt();var d8=Ze(Jn()),rpt="workspace:",X1=(o=>(o.REGULAR="dependencies",o.DEVELOPMENT="devDependencies",o.PEER="peerDependencies",o))(X1||{}),m8=(o=>(o.CARET="^",o.TILDE="~",o.EXACT="",o))(m8||{}),_0e=(o=>(o.CARET="^",o.TILDE="~",o.EXACT="*",o))(_0e||{}),$x=(n=>(n.KEEP="keep",n.REUSE="reuse",n.PROJECT="project",n.LATEST="latest",n.CACHE="cache",n))($x||{});function Z1(t,e){return t.exact?"":t.caret?"^":t.tilde?"~":e.configuration.get("defaultSemverRangePrefix")}var npt=/^([\^~]?)[0-9]+(?:\.[0-9]+){0,2}(?:-\S+)?$/;function H0e(t,{project:e}){let r=t.match(npt);return r?r[1]:e.configuration.get("defaultSemverRangePrefix")}function ipt(t,e){let{protocol:r,source:o,params:a,selector:n}=G.parseRange(t.range);return d8.default.valid(n)&&(n=`${e}${t.range}`),G.makeDescriptor(t,G.makeRange({protocol:r,source:o,params:a,selector:n}))}function q0e(t){switch(t){case"^":return"^";case"~":return"~";case"":return"*";default:throw new Error(`Assertion failed: Unknown modifier: "${t}"`)}}function j0e(t,e){return G.makeDescriptor(t.anchoredDescriptor,`${rpt}${q0e(e)}`)}async function G0e(t,{project:e,target:r}){let o=new Map,a=n=>{let u=o.get(n.descriptorHash);return u||o.set(n.descriptorHash,u={descriptor:n,locators:[]}),u};for(let n of e.workspaces)if(r==="peerDependencies"){let u=n.manifest.peerDependencies.get(t.identHash);u!==void 0&&a(u).locators.push(n.anchoredLocator)}else{let u=n.manifest.dependencies.get(t.identHash),A=n.manifest.devDependencies.get(t.identHash);r==="devDependencies"?A!==void 0?a(A).locators.push(n.anchoredLocator):u!==void 0&&a(u).locators.push(n.anchoredLocator):u!==void 0?a(u).locators.push(n.anchoredLocator):A!==void 0&&a(A).locators.push(n.anchoredLocator)}return o}async function y8(t,{cwd:e,workspace:r}){return await spt(async o=>{K.isAbsolute(t)||(t=K.relative(r.cwd,K.resolve(e,t)),t.match(/^\.{0,2}\//)||(t=`./${t}`));let{project:a}=r,n=await E8(G.makeIdent(null,"archive"),t,{project:r.project,cache:o,workspace:r});if(!n)throw new Error("Assertion failed: The descriptor should have been found");let u=new ki,A=a.configuration.makeResolver(),p=a.configuration.makeFetcher(),h={checksums:a.storedChecksums,project:a,cache:o,fetcher:p,report:u,resolver:A},E=A.bindDescriptor(n,r.anchoredLocator,h),I=G.convertDescriptorToLocator(E),v=await p.fetch(I,h),x=await Ut.find(v.prefixPath,{baseFs:v.packageFs});if(!x.name)throw new Error("Target path doesn't have a name");return G.makeDescriptor(x.name,t)})}async function $1(t,{project:e,workspace:r,cache:o,target:a,fixed:n,modifier:u,strategies:A,maxResults:p=1/0}){if(!(p>=0))throw new Error(`Invalid maxResults (${p})`);let[h,E]=t.range!=="unknown"?n||Lr.validRange(t.range)||!t.range.match(/^[a-z0-9._-]+$/i)?[t.range,"latest"]:["unknown",t.range]:["unknown","latest"];if(h!=="unknown")return{suggestions:[{descriptor:t,name:`Use ${G.prettyDescriptor(e.configuration,t)}`,reason:"(unambiguous explicit request)"}],rejections:[]};let I=typeof r<"u"&&r!==null&&r.manifest[a].get(t.identHash)||null,v=[],x=[],C=async R=>{try{await R()}catch(L){x.push(L)}};for(let R of A){if(v.length>=p)break;switch(R){case"keep":await C(async()=>{I&&v.push({descriptor:I,name:`Keep ${G.prettyDescriptor(e.configuration,I)}`,reason:"(no changes)"})});break;case"reuse":await C(async()=>{for(let{descriptor:L,locators:U}of(await G0e(t,{project:e,target:a})).values()){if(U.length===1&&U[0].locatorHash===r.anchoredLocator.locatorHash&&A.includes("keep"))continue;let z=`(originally used by ${G.prettyLocator(e.configuration,U[0])}`;z+=U.length>1?` and ${U.length-1} other${U.length>2?"s":""})`:")",v.push({descriptor:L,name:`Reuse ${G.prettyDescriptor(e.configuration,L)}`,reason:z})}});break;case"cache":await C(async()=>{for(let L of e.storedDescriptors.values())L.identHash===t.identHash&&v.push({descriptor:L,name:`Reuse ${G.prettyDescriptor(e.configuration,L)}`,reason:"(already used somewhere in the lockfile)"})});break;case"project":await C(async()=>{if(r.manifest.name!==null&&t.identHash===r.manifest.name.identHash)return;let L=e.tryWorkspaceByIdent(t);if(L===null)return;let U=j0e(L,u);v.push({descriptor:U,name:`Attach ${G.prettyDescriptor(e.configuration,U)}`,reason:`(local workspace at ${pe.pretty(e.configuration,L.relativeCwd,pe.Type.PATH)})`})});break;case"latest":{let L=e.configuration.get("enableNetwork"),U=e.configuration.get("enableOfflineMode");await C(async()=>{if(a==="peerDependencies")v.push({descriptor:G.makeDescriptor(t,"*"),name:"Use *",reason:"(catch-all peer dependency pattern)"});else if(!L&&!U)v.push({descriptor:null,name:"Resolve from latest",reason:pe.pretty(e.configuration,"(unavailable because enableNetwork is toggled off)","grey")});else{let z=await E8(t,E,{project:e,cache:o,workspace:r,modifier:u});z&&v.push({descriptor:z,name:`Use ${G.prettyDescriptor(e.configuration,z)}`,reason:`(resolved from ${U?"the cache":"latest"})`})}})}break}}return{suggestions:v.slice(0,p),rejections:x.slice(0,p)}}async function E8(t,e,{project:r,cache:o,workspace:a,preserveModifier:n=!0,modifier:u}){let A=r.configuration.normalizeDependency(G.makeDescriptor(t,e)),p=new ki,h=r.configuration.makeFetcher(),E=r.configuration.makeResolver(),I={project:r,fetcher:h,cache:o,checksums:r.storedChecksums,report:p,cacheOptions:{skipIntegrityCheck:!0}},v={...I,resolver:E,fetchOptions:I},x=E.bindDescriptor(A,a.anchoredLocator,v),C=await E.getCandidates(x,{},v);if(C.length===0)return null;let R=C[0],{protocol:L,source:U,params:z,selector:te}=G.parseRange(G.convertToManifestRange(R.reference));if(L===r.configuration.get("defaultProtocol")&&(L=null),d8.default.valid(te)){let ae=te;if(typeof u<"u")te=u+te;else if(n!==!1){let Ce=typeof n=="string"?n:A.range;te=H0e(Ce,{project:r})+te}let le=G.makeDescriptor(R,G.makeRange({protocol:L,source:U,params:z,selector:te}));(await E.getCandidates(r.configuration.normalizeDependency(le),{},v)).length!==1&&(te=ae)}return G.makeDescriptor(R,G.makeRange({protocol:L,source:U,params:z,selector:te}))}async function spt(t){return await oe.mktempPromise(async e=>{let r=Ke.create(e);return r.useWithSource(e,{enableMirror:!1,compressionLevel:0},e,{overwrite:!0}),await t(new Gr(e,{configuration:r,check:!1,immutable:!1}))})}var Yy=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.fixed=ge.Boolean("-F,--fixed",!1,{description:"Store dependency tags as-is instead of resolving them"});this.exact=ge.Boolean("-E,--exact",!1,{description:"Don't use any semver modifier on the resolved range"});this.tilde=ge.Boolean("-T,--tilde",!1,{description:"Use the `~` semver modifier on the resolved range"});this.caret=ge.Boolean("-C,--caret",!1,{description:"Use the `^` semver modifier on the resolved range"});this.dev=ge.Boolean("-D,--dev",!1,{description:"Add a package as a dev dependency"});this.peer=ge.Boolean("-P,--peer",!1,{description:"Add a package as a peer dependency"});this.optional=ge.Boolean("-O,--optional",!1,{description:"Add / upgrade a package to an optional regular / peer dependency"});this.preferDev=ge.Boolean("--prefer-dev",!1,{description:"Add / upgrade a package to a dev dependency"});this.interactive=ge.Boolean("-i,--interactive",{description:"Reuse the specified package from other workspaces in the project"});this.cached=ge.Boolean("--cached",!1,{description:"Reuse the highest version already used somewhere within the project"});this.mode=ge.String("--mode",{description:"Change what artifacts installs generate",validator:Js(hl)});this.silent=ge.Boolean("--silent",{hidden:!0});this.packages=ge.Rest()}static{this.paths=[["add"]]}static{this.usage=it.Usage({description:"add dependencies to the project",details:"\n This command adds a package to the package.json for the nearest workspace.\n\n - If it didn't exist before, the package will by default be added to the regular `dependencies` field, but this behavior can be overriden thanks to the `-D,--dev` flag (which will cause the dependency to be added to the `devDependencies` field instead) and the `-P,--peer` flag (which will do the same but for `peerDependencies`).\n\n - If the package was already listed in your dependencies, it will by default be upgraded whether it's part of your `dependencies` or `devDependencies` (it won't ever update `peerDependencies`, though).\n\n - If set, the `--prefer-dev` flag will operate as a more flexible `-D,--dev` in that it will add the package to your `devDependencies` if it isn't already listed in either `dependencies` or `devDependencies`, but it will also happily upgrade your `dependencies` if that's what you already use (whereas `-D,--dev` would throw an exception).\n\n - If set, the `-O,--optional` flag will add the package to the `optionalDependencies` field and, in combination with the `-P,--peer` flag, it will add the package as an optional peer dependency. If the package was already listed in your `dependencies`, it will be upgraded to `optionalDependencies`. If the package was already listed in your `peerDependencies`, in combination with the `-P,--peer` flag, it will be upgraded to an optional peer dependency: `\"peerDependenciesMeta\": { \"<package>\": { \"optional\": true } }`\n\n - If the added package doesn't specify a range at all its `latest` tag will be resolved and the returned version will be used to generate a new semver range (using the `^` modifier by default unless otherwise configured via the `defaultSemverRangePrefix` configuration, or the `~` modifier if `-T,--tilde` is specified, or no modifier at all if `-E,--exact` is specified). Two exceptions to this rule: the first one is that if the package is a workspace then its local version will be used, and the second one is that if you use `-P,--peer` the default range will be `*` and won't be resolved at all.\n\n - If the added package specifies a range (such as `^1.0.0`, `latest`, or `rc`), Yarn will add this range as-is in the resulting package.json entry (in particular, tags such as `rc` will be encoded as-is rather than being converted into a semver range).\n\n If the `--cached` option is used, Yarn will preferably reuse the highest version already used somewhere within the project, even if through a transitive dependency.\n\n If the `-i,--interactive` option is used (or if the `preferInteractive` settings is toggled on) the command will first try to check whether other workspaces in the project use the specified package and, if so, will offer to reuse them.\n\n If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n For a compilation of all the supported protocols, please consult the dedicated page from our website: https://yarnpkg.com/protocols.\n ",examples:[["Add a regular package to the current workspace","$0 add lodash"],["Add a specific version for a package to the current workspace","$0 add lodash@1.2.3"],["Add a package from a GitHub repository (the master branch) to the current workspace using a URL","$0 add lodash@https://github.com/lodash/lodash"],["Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol","$0 add lodash@github:lodash/lodash"],["Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol (shorthand)","$0 add lodash@lodash/lodash"],["Add a package from a specific branch of a GitHub repository to the current workspace using the GitHub protocol (shorthand)","$0 add lodash-es@lodash/lodash#es"],["Add a local package (gzipped tarball format) to the current workspace","$0 add local-package-name@file:../path/to/local-package-name-v0.1.2.tgz"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.fixed,A=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=A||r.get("preferReuse"),h=Z1(this,o),E=[p?"reuse":void 0,"project",this.cached?"cache":void 0,"latest"].filter(U=>typeof U<"u"),I=A?1/0:1,v=await Promise.all(this.packages.map(async U=>{let z=U.match(/^\.{0,2}\//)?await y8(U,{cwd:this.context.cwd,workspace:a}):G.tryParseDescriptor(U),te=U.match(/^(https?:|git@github)/);if(te)throw new st(`It seems you are trying to add a package using a ${pe.pretty(r,`${te[0]}...`,pe.Type.RANGE)} url; we now require package names to be explicitly specified. +Try running the command again with the package name prefixed: ${pe.pretty(r,"yarn add",pe.Type.CODE)} ${pe.pretty(r,G.makeDescriptor(G.makeIdent(null,"my-package"),`${te[0]}...`),pe.Type.DESCRIPTOR)}`);if(!z)throw new st(`The ${pe.pretty(r,U,pe.Type.CODE)} string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name?`);let ae=opt(a,z,{dev:this.dev,peer:this.peer,preferDev:this.preferDev,optional:this.optional});return await Promise.all(ae.map(async ce=>{let Ce=await $1(z,{project:o,workspace:a,cache:n,fixed:u,target:ce,modifier:h,strategies:E,maxResults:I});return{request:z,suggestedDescriptors:Ce,target:ce}}))})).then(U=>U.flat()),x=await AA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async U=>{for(let{request:z,suggestedDescriptors:{suggestions:te,rejections:ae}}of v)if(te.filter(ce=>ce.descriptor!==null).length===0){let[ce]=ae;if(typeof ce>"u")throw new Error("Assertion failed: Expected an error to have been set");o.configuration.get("enableNetwork")?U.reportError(27,`${G.prettyDescriptor(r,z)} can't be resolved to a satisfying range`):U.reportError(27,`${G.prettyDescriptor(r,z)} can't be resolved to a satisfying range (note: network resolution has been disabled)`),U.reportSeparator(),U.reportExceptionOnce(ce)}});if(x.hasErrors())return x.exitCode();let C=!1,R=[],L=[];for(let{suggestedDescriptors:{suggestions:U},target:z}of v){let te,ae=U.filter(de=>de.descriptor!==null),le=ae[0].descriptor,ce=ae.every(de=>G.areDescriptorsEqual(de.descriptor,le));ae.length===1||ce?te=le:(C=!0,{answer:te}=await(0,Y0e.prompt)({type:"select",name:"answer",message:"Which range do you want to use?",choices:U.map(({descriptor:de,name:Be,reason:Ee})=>de?{name:Be,hint:Ee,descriptor:de}:{name:Be,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(de){return this.find(de,"descriptor")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ce=a.manifest[z].get(te.identHash);(typeof Ce>"u"||Ce.descriptorHash!==te.descriptorHash)&&(a.manifest[z].set(te.identHash,te),this.optional&&(z==="dependencies"?a.manifest.ensureDependencyMeta({...te,range:"unknown"}).optional=!0:z==="peerDependencies"&&(a.manifest.ensurePeerDependencyMeta({...te,range:"unknown"}).optional=!0)),typeof Ce>"u"?R.push([a,z,te,E]):L.push([a,z,Ce,te]))}return await r.triggerMultipleHooks(U=>U.afterWorkspaceDependencyAddition,R),await r.triggerMultipleHooks(U=>U.afterWorkspaceDependencyReplacement,L),C&&this.context.stdout.write(` +`),await o.installWithNewReport({json:this.json,stdout:this.context.stdout,quiet:this.context.quiet},{cache:n,mode:this.mode})}};function opt(t,e,{dev:r,peer:o,preferDev:a,optional:n}){let u=t.manifest.dependencies.has(e.identHash),A=t.manifest.devDependencies.has(e.identHash),p=t.manifest.peerDependencies.has(e.identHash);if((r||o)&&u)throw new st(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a regular dependency - remove the -D,-P flags or remove it from your dependencies first`);if(!r&&!o&&p)throw new st(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a peer dependency - use either of -D or -P, or remove it from your peer dependencies first`);if(n&&A)throw new st(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a dev dependency - remove the -O flag or remove it from your dev dependencies first`);if(n&&!o&&p)throw new st(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a peer dependency - remove the -O flag or add the -P flag or remove it from your peer dependencies first`);if((r||a)&&n)throw new st(`Package "${G.prettyIdent(t.project.configuration,e)}" cannot simultaneously be a dev dependency and an optional dependency`);let h=[];return o&&h.push("peerDependencies"),(r||a)&&h.push("devDependencies"),n&&h.push("dependencies"),h.length>0?h:A?["devDependencies"]:p?["peerDependencies"]:["dependencies"]}Ge();Ge();qt();var Wy=class extends ut{constructor(){super(...arguments);this.verbose=ge.Boolean("-v,--verbose",!1,{description:"Print both the binary name and the locator of the package that provides the binary"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.name=ge.String({required:!1})}static{this.paths=[["bin"]]}static{this.usage=it.Usage({description:"get the path to a binary script",details:` + When used without arguments, this command will print the list of all the binaries available in the current workspace. Adding the \`-v,--verbose\` flag will cause the output to contain both the binary name and the locator of the package that provides the binary. + + When an argument is specified, this command will just print the path to the binary on the standard output and exit. Note that the reported path may be stored within a zip archive. + `,examples:[["List all the available binaries","$0 bin"],["Print the path to a specific binary","$0 bin eslint"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,locator:a}=await kt.find(r,this.context.cwd);if(await o.restoreInstallState(),this.name){let A=(await An.getPackageAccessibleBinaries(a,{project:o})).get(this.name);if(!A)throw new st(`Couldn't find a binary named "${this.name}" for package "${G.prettyLocator(r,a)}"`);let[,p]=A;return this.context.stdout.write(`${p} +`),0}return(await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async u=>{let A=await An.getPackageAccessibleBinaries(a,{project:o}),h=Array.from(A.keys()).reduce((E,I)=>Math.max(E,I.length),0);for(let[E,[I,v]]of A)u.reportJson({name:E,source:G.stringifyIdent(I),path:v});if(this.verbose)for(let[E,[I]]of A)u.reportInfo(null,`${E.padEnd(h," ")} ${G.prettyLocator(r,I)}`);else for(let E of A.keys())u.reportInfo(null,E)})).exitCode()}};Ge();Pt();qt();var Ky=class extends ut{constructor(){super(...arguments);this.mirror=ge.Boolean("--mirror",!1,{description:"Remove the global cache files instead of the local cache files"});this.all=ge.Boolean("--all",!1,{description:"Remove both the global cache files and the local cache files of the current project"})}static{this.paths=[["cache","clean"],["cache","clear"]]}static{this.usage=it.Usage({description:"remove the shared cache files",details:` + This command will remove all the files from the cache. + `,examples:[["Remove all the local archives","$0 cache clean"],["Remove all the archives stored in the ~/.yarn directory","$0 cache clean --mirror"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=await Gr.find(r);return(await Rt.start({configuration:r,stdout:this.context.stdout},async()=>{let n=(this.all||this.mirror)&&o.mirrorCwd!==null,u=!this.mirror;n&&(await oe.removePromise(o.mirrorCwd),await r.triggerHook(A=>A.cleanGlobalArtifacts,r)),u&&await oe.removePromise(o.cwd)})).exitCode()}};Ge();qt();var K0e=Ze(e2()),C8=ve("util"),Vy=class extends ut{constructor(){super(...arguments);this.why=ge.Boolean("--why",!1,{description:"Print the explanation for why a setting has its value"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.unsafe=ge.Boolean("--no-redacted",!1,{description:"Don't redact secrets (such as tokens) from the output"});this.name=ge.String()}static{this.paths=[["config","get"]]}static{this.usage=it.Usage({description:"read a configuration settings",details:` + This command will print a configuration setting. + + Secrets (such as tokens) will be redacted from the output by default. If this behavior isn't desired, set the \`--no-redacted\` to get the untransformed value. + `,examples:[["Print a simple configuration setting","yarn config get yarnPath"],["Print a complex configuration setting","yarn config get packageExtensions"],["Print a nested field from the configuration",`yarn config get 'npmScopes["my-company"].npmRegistryServer'`],["Print a token from the configuration","yarn config get npmAuthToken --no-redacted"],["Print a configuration setting as JSON","yarn config get packageExtensions --json"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=this.name.replace(/[.[].*$/,""),a=this.name.replace(/^[^.[]*/,"");if(typeof r.settings.get(o)>"u")throw new st(`Couldn't find a configuration settings named "${o}"`);let u=r.getSpecial(o,{hideSecrets:!this.unsafe,getNativePaths:!0}),A=He.convertMapsToIndexableObjects(u),p=a?(0,K0e.default)(A,a):A,h=await Rt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async E=>{E.reportJson(p)});if(!this.json){if(typeof p=="string")return this.context.stdout.write(`${p} +`),h.exitCode();C8.inspect.styles.name="cyan",this.context.stdout.write(`${(0,C8.inspect)(p,{depth:1/0,colors:r.get("enableColors"),compact:!1})} +`)}return h.exitCode()}};Ge();qt();var Mge=Ze(v8()),Oge=Ze(e2()),Uge=Ze(D8()),P8=ve("util"),zy=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Set complex configuration settings to JSON values"});this.home=ge.Boolean("-H,--home",!1,{description:"Update the home configuration instead of the project configuration"});this.name=ge.String();this.value=ge.String()}static{this.paths=[["config","set"]]}static{this.usage=it.Usage({description:"change a configuration settings",details:` + This command will set a configuration setting. + + When used without the \`--json\` flag, it can only set a simple configuration setting (a string, a number, or a boolean). + + When used with the \`--json\` flag, it can set both simple and complex configuration settings, including Arrays and Objects. + `,examples:[["Set a simple configuration setting (a string, a number, or a boolean)","yarn config set initScope myScope"],["Set a simple configuration setting (a string, a number, or a boolean) using the `--json` flag",'yarn config set initScope --json \\"myScope\\"'],["Set a complex configuration setting (an Array) using the `--json` flag",`yarn config set unsafeHttpWhitelist --json '["*.example.com", "example.com"]'`],["Set a complex configuration setting (an Object) using the `--json` flag",`yarn config set packageExtensions --json '{ "@babel/parser@*": { "dependencies": { "@babel/types": "*" } } }'`],["Set a nested configuration setting",'yarn config set npmScopes.company.npmRegistryServer "https://npm.example.com"'],["Set a nested configuration setting using indexed access for non-simple keys",`yarn config set 'npmRegistries["//npm.example.com"].npmAuthToken' "ffffffff-ffff-ffff-ffff-ffffffffffff"`]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=()=>{if(!r.projectCwd)throw new st("This command must be run from within a project folder");return r.projectCwd},a=this.name.replace(/[.[].*$/,""),n=this.name.replace(/^[^.[]*\.?/,"");if(typeof r.settings.get(a)>"u")throw new st(`Couldn't find a configuration settings named "${a}"`);if(a==="enableStrictSettings")throw new st("This setting only affects the file it's in, and thus cannot be set from the CLI");let A=this.json?JSON.parse(this.value):this.value;await(this.home?C=>Ke.updateHomeConfiguration(C):C=>Ke.updateConfiguration(o(),C))(C=>{if(n){let R=(0,Mge.default)(C);return(0,Uge.default)(R,this.name,A),R}else return{...C,[a]:A}});let E=(await Ke.find(this.context.cwd,this.context.plugins)).getSpecial(a,{hideSecrets:!0,getNativePaths:!0}),I=He.convertMapsToIndexableObjects(E),v=n?(0,Oge.default)(I,n):I;return(await Rt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async C=>{P8.inspect.styles.name="cyan",C.reportInfo(0,`Successfully set ${this.name} to ${(0,P8.inspect)(v,{depth:1/0,colors:r.get("enableColors"),compact:!1})}`)})).exitCode()}};Ge();qt();var Jge=Ze(v8()),Xge=Ze(jge()),Zge=Ze(b8()),Jy=class extends ut{constructor(){super(...arguments);this.home=ge.Boolean("-H,--home",!1,{description:"Update the home configuration instead of the project configuration"});this.name=ge.String()}static{this.paths=[["config","unset"]]}static{this.usage=it.Usage({description:"unset a configuration setting",details:` + This command will unset a configuration setting. + `,examples:[["Unset a simple configuration setting","yarn config unset initScope"],["Unset a complex configuration setting","yarn config unset packageExtensions"],["Unset a nested configuration setting","yarn config unset npmScopes.company.npmRegistryServer"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=()=>{if(!r.projectCwd)throw new st("This command must be run from within a project folder");return r.projectCwd},a=this.name.replace(/[.[].*$/,""),n=this.name.replace(/^[^.[]*\.?/,"");if(typeof r.settings.get(a)>"u")throw new st(`Couldn't find a configuration settings named "${a}"`);let A=this.home?h=>Ke.updateHomeConfiguration(h):h=>Ke.updateConfiguration(o(),h);return(await Rt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async h=>{let E=!1;await A(I=>{if(!(0,Xge.default)(I,this.name))return h.reportWarning(0,`Configuration doesn't contain setting ${this.name}; there is nothing to unset`),E=!0,I;let v=n?(0,Jge.default)(I):{...I};return(0,Zge.default)(v,this.name),v}),E||h.reportInfo(0,`Successfully unset ${this.name}`)})).exitCode()}};Ge();Pt();qt();var tk=ve("util"),Xy=class extends ut{constructor(){super(...arguments);this.noDefaults=ge.Boolean("--no-defaults",!1,{description:"Omit the default values from the display"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.verbose=ge.Boolean("-v,--verbose",{hidden:!0});this.why=ge.Boolean("--why",{hidden:!0});this.names=ge.Rest()}static{this.paths=[["config"]]}static{this.usage=it.Usage({description:"display the current configuration",details:` + This command prints the current active configuration settings. + `,examples:[["Print the active configuration settings","$0 config"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins,{strict:!1}),o=await uy({configuration:r,stdout:this.context.stdout,forceError:this.json},[{option:this.verbose,message:"The --verbose option is deprecated, the settings' descriptions are now always displayed"},{option:this.why,message:"The --why option is deprecated, the settings' sources are now always displayed"}]);if(o!==null)return o;let a=this.names.length>0?[...new Set(this.names)].sort():[...r.settings.keys()].sort(),n,u=await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async A=>{if(r.invalid.size>0&&!this.json){for(let[p,h]of r.invalid)A.reportError(34,`Invalid configuration key "${p}" in ${h}`);A.reportSeparator()}if(this.json)for(let p of a){let h=r.settings.get(p);typeof h>"u"&&A.reportError(34,`No configuration key named "${p}"`);let E=r.getSpecial(p,{hideSecrets:!0,getNativePaths:!0}),I=r.sources.get(p)??"<default>",v=I&&I[0]!=="<"?ue.fromPortablePath(I):I;A.reportJson({key:p,effective:E,source:v,...h})}else{let p={breakLength:1/0,colors:r.get("enableColors"),maxArrayLength:2},h={},E={children:h};for(let I of a){if(this.noDefaults&&!r.sources.has(I))continue;let v=r.settings.get(I),x=r.sources.get(I)??"<default>",C=r.getSpecial(I,{hideSecrets:!0,getNativePaths:!0}),R={Description:{label:"Description",value:pe.tuple(pe.Type.MARKDOWN,{text:v.description,format:this.cli.format(),paragraphs:!1})},Source:{label:"Source",value:pe.tuple(x[0]==="<"?pe.Type.CODE:pe.Type.PATH,x)}};h[I]={value:pe.tuple(pe.Type.CODE,I),children:R};let L=(U,z)=>{for(let[te,ae]of z)if(ae instanceof Map){let le={};U[te]={children:le},L(le,ae)}else U[te]={label:te,value:pe.tuple(pe.Type.NO_HINT,(0,tk.inspect)(ae,p))}};C instanceof Map?L(R,C):R.Value={label:"Value",value:pe.tuple(pe.Type.NO_HINT,(0,tk.inspect)(C,p))}}a.length!==1&&(n=void 0),fs.emitTree(E,{configuration:r,json:this.json,stdout:this.context.stdout,separators:2})}});if(!this.json&&typeof n<"u"){let A=a[0],p=(0,tk.inspect)(r.getSpecial(A,{hideSecrets:!0,getNativePaths:!0}),{colors:r.get("enableColors")});this.context.stdout.write(` +`),this.context.stdout.write(`${p} +`)}return u.exitCode()}};Ge();qt();el();var rk={};Vt(rk,{Strategy:()=>t2,acceptedStrategies:()=>q0t,dedupe:()=>x8});Ge();Ge();var $ge=Ze($o()),t2=(e=>(e.HIGHEST="highest",e))(t2||{}),q0t=new Set(Object.values(t2)),j0t={highest:async(t,e,{resolver:r,fetcher:o,resolveOptions:a,fetchOptions:n})=>{let u=new Map;for(let[p,h]of t.storedResolutions){let E=t.storedDescriptors.get(p);if(typeof E>"u")throw new Error(`Assertion failed: The descriptor (${p}) should have been registered`);He.getSetWithDefault(u,E.identHash).add(h)}let A=new Map(He.mapAndFilter(t.storedDescriptors.values(),p=>G.isVirtualDescriptor(p)?He.mapAndFilter.skip:[p.descriptorHash,He.makeDeferred()]));for(let p of t.storedDescriptors.values()){let h=A.get(p.descriptorHash);if(typeof h>"u")throw new Error(`Assertion failed: The descriptor (${p.descriptorHash}) should have been registered`);let E=t.storedResolutions.get(p.descriptorHash);if(typeof E>"u")throw new Error(`Assertion failed: The resolution (${p.descriptorHash}) should have been registered`);let I=t.originalPackages.get(E);if(typeof I>"u")throw new Error(`Assertion failed: The package (${E}) should have been registered`);Promise.resolve().then(async()=>{let v=r.getResolutionDependencies(p,a),x=Object.fromEntries(await He.allSettledSafe(Object.entries(v).map(async([te,ae])=>{let le=A.get(ae.descriptorHash);if(typeof le>"u")throw new Error(`Assertion failed: The descriptor (${ae.descriptorHash}) should have been registered`);let ce=await le.promise;if(!ce)throw new Error("Assertion failed: Expected the dependency to have been through the dedupe process itself");return[te,ce.updatedPackage]})));if(e.length&&!$ge.default.isMatch(G.stringifyIdent(p),e)||!r.shouldPersistResolution(I,a))return I;let C=u.get(p.identHash);if(typeof C>"u")throw new Error(`Assertion failed: The resolutions (${p.identHash}) should have been registered`);if(C.size===1)return I;let R=[...C].map(te=>{let ae=t.originalPackages.get(te);if(typeof ae>"u")throw new Error(`Assertion failed: The package (${te}) should have been registered`);return ae}),L=await r.getSatisfying(p,x,R,a),U=L.locators?.[0];if(typeof U>"u"||!L.sorted)return I;let z=t.originalPackages.get(U.locatorHash);if(typeof z>"u")throw new Error(`Assertion failed: The package (${U.locatorHash}) should have been registered`);return z}).then(async v=>{let x=await t.preparePackage(v,{resolver:r,resolveOptions:a});h.resolve({descriptor:p,currentPackage:I,updatedPackage:v,resolvedPackage:x})}).catch(v=>{h.reject(v)})}return[...A.values()].map(p=>p.promise)}};async function x8(t,{strategy:e,patterns:r,cache:o,report:a}){let{configuration:n}=t,u=new ki,A=n.makeResolver(),p=n.makeFetcher(),h={cache:o,checksums:t.storedChecksums,fetcher:p,project:t,report:u,cacheOptions:{skipIntegrityCheck:!0}},E={project:t,resolver:A,report:u,fetchOptions:h};return await a.startTimerPromise("Deduplication step",async()=>{let I=j0t[e],v=await I(t,r,{resolver:A,resolveOptions:E,fetcher:p,fetchOptions:h}),x=Zs.progressViaCounter(v.length);await a.reportProgress(x);let C=0;await Promise.all(v.map(U=>U.then(z=>{if(z===null||z.currentPackage.locatorHash===z.updatedPackage.locatorHash)return;C++;let{descriptor:te,currentPackage:ae,updatedPackage:le}=z;a.reportInfo(0,`${G.prettyDescriptor(n,te)} can be deduped from ${G.prettyLocator(n,ae)} to ${G.prettyLocator(n,le)}`),a.reportJson({descriptor:G.stringifyDescriptor(te),currentResolution:G.stringifyLocator(ae),updatedResolution:G.stringifyLocator(le)}),t.storedResolutions.set(te.descriptorHash,le.locatorHash)}).finally(()=>x.tick())));let R;switch(C){case 0:R="No packages";break;case 1:R="One package";break;default:R=`${C} packages`}let L=pe.pretty(n,e,pe.Type.CODE);return a.reportInfo(0,`${R} can be deduped using the ${L} strategy`),C})}var Zy=class extends ut{constructor(){super(...arguments);this.strategy=ge.String("-s,--strategy","highest",{description:"The strategy to use when deduping dependencies",validator:Js(t2)});this.check=ge.Boolean("-c,--check",!1,{description:"Exit with exit code 1 when duplicates are found, without persisting the dependency tree"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.mode=ge.String("--mode",{description:"Change what artifacts installs generate",validator:Js(hl)});this.patterns=ge.Rest()}static{this.paths=[["dedupe"]]}static{this.usage=it.Usage({description:"deduplicate dependencies with overlapping ranges",details:"\n Duplicates are defined as descriptors with overlapping ranges being resolved and locked to different locators. They are a natural consequence of Yarn's deterministic installs, but they can sometimes pile up and unnecessarily increase the size of your project.\n\n This command dedupes dependencies in the current project using different strategies (only one is implemented at the moment):\n\n - `highest`: Reuses (where possible) the locators with the highest versions. This means that dependencies can only be upgraded, never downgraded. It's also guaranteed that it never takes more than a single pass to dedupe the entire dependency tree.\n\n **Note:** Even though it never produces a wrong dependency tree, this command should be used with caution, as it modifies the dependency tree, which can sometimes cause problems when packages don't strictly follow semver recommendations. Because of this, it is recommended to also review the changes manually.\n\n If set, the `-c,--check` flag will only report the found duplicates, without persisting the modified dependency tree. If changes are found, the command will exit with a non-zero exit code, making it suitable for CI purposes.\n\n If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n ### In-depth explanation:\n\n Yarn doesn't deduplicate dependencies by default, otherwise installs wouldn't be deterministic and the lockfile would be useless. What it actually does is that it tries to not duplicate dependencies in the first place.\n\n **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@*`will cause Yarn to reuse `foo@2.3.4`, even if the latest `foo` is actually `foo@2.10.14`, thus preventing unnecessary duplication.\n\n Duplication happens when Yarn can't unlock dependencies that have already been locked inside the lockfile.\n\n **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@2.10.14` will cause Yarn to install `foo@2.10.14` because the existing resolution doesn't satisfy the range `2.10.14`. This behavior can lead to (sometimes) unwanted duplication, since now the lockfile contains 2 separate resolutions for the 2 `foo` descriptors, even though they have overlapping ranges, which means that the lockfile can be simplified so that both descriptors resolve to `foo@2.10.14`.\n ",examples:[["Dedupe all packages","$0 dedupe"],["Dedupe all packages using a specific strategy","$0 dedupe --strategy highest"],["Dedupe a specific package","$0 dedupe lodash"],["Dedupe all packages with the `@babel/*` scope","$0 dedupe '@babel/*'"],["Check for duplicates (can be used as a CI step)","$0 dedupe --check"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd),a=await Gr.find(r);await o.restoreInstallState({restoreResolutions:!1});let n=0,u=await Rt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout,json:this.json},async A=>{n=await x8(o,{strategy:this.strategy,patterns:this.patterns,cache:a,report:A})});return u.hasErrors()?u.exitCode():this.check?n?1:0:await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:a,mode:this.mode})}};Ge();qt();var $y=class extends ut{static{this.paths=[["--clipanion=definitions"]]}async execute(){let{plugins:e}=await Ke.find(this.context.cwd,this.context.plugins),r=[];for(let u of e){let{commands:A}=u[1];if(A){let h=Jo.from(A).definitions();r.push([u[0],h])}}let o=this.cli.definitions(),a=(u,A)=>u.split(" ").slice(1).join()===A.split(" ").slice(1).join(),n=ede()["@yarnpkg/builder"].bundles.standard;for(let u of r){let A=u[1];for(let p of A)o.find(h=>a(h.path,p.path)).plugin={name:u[0],isDefault:n.includes(u[0])}}this.context.stdout.write(`${JSON.stringify(o,null,2)} +`)}};var eE=class extends ut{static{this.paths=[["help"],["--help"],["-h"]]}async execute(){this.context.stdout.write(this.cli.usage(null))}};Ge();Pt();qt();var tE=class extends ut{constructor(){super(...arguments);this.leadingArgument=ge.String();this.args=ge.Proxy()}async execute(){if(this.leadingArgument.match(/[\\/]/)&&!G.tryParseIdent(this.leadingArgument)){let r=K.resolve(this.context.cwd,ue.toPortablePath(this.leadingArgument));return await this.cli.run(this.args,{cwd:r})}else return await this.cli.run(["run",this.leadingArgument,...this.args])}};Ge();var rE=class extends ut{static{this.paths=[["-v"],["--version"]]}async execute(){this.context.stdout.write(`${nn||"<unknown>"} +`)}};Ge();Ge();qt();var nE=class extends ut{constructor(){super(...arguments);this.commandName=ge.String();this.args=ge.Proxy()}static{this.paths=[["exec"]]}static{this.usage=it.Usage({description:"execute a shell script",details:` + This command simply executes a shell script within the context of the root directory of the active workspace using the portable shell. + + It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment). + `,examples:[["Execute a single shell command","$0 exec echo Hello World"],["Execute a shell script",'$0 exec "tsc & babel src --out-dir lib"']]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,locator:a}=await kt.find(r,this.context.cwd);return await o.restoreInstallState(),await An.executePackageShellcode(a,this.commandName,this.args,{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,project:o})}};Ge();qt();el();var iE=class extends ut{constructor(){super(...arguments);this.hash=ge.String({required:!1,validator:YD(om(),[qw(/^p[0-9a-f]{5}$/)])})}static{this.paths=[["explain","peer-requirements"]]}static{this.usage=it.Usage({description:"explain a set of peer requirements",details:` + A peer requirement represents all peer requests that a subject must satisfy when providing a requested package to requesters. + + When the hash argument is specified, this command prints a detailed explanation of the peer requirement corresponding to the hash and whether it is satisfied or not. + + When used without arguments, this command lists all peer requirements and the corresponding hash that can be used to get detailed information about a given requirement. + + **Note:** A hash is a six-letter p-prefixed code that can be obtained from peer dependency warnings or from the list of all peer requirements (\`yarn explain peer-requirements\`). + `,examples:[["Explain the corresponding peer requirement for a hash","$0 explain peer-requirements p1a4ed"],["List all peer requirements","$0 explain peer-requirements"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd);return await o.restoreInstallState({restoreResolutions:!1}),await o.applyLightResolution(),typeof this.hash<"u"?await Y0t(this.hash,o,{stdout:this.context.stdout}):await W0t(o,{stdout:this.context.stdout})}};async function Y0t(t,e,r){let o=e.peerRequirementNodes.get(t);if(typeof o>"u")throw new Error(`No peerDependency requirements found for hash: "${t}"`);let a=new Set,n=p=>a.has(p.requester.locatorHash)?{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:p.children.size>0?[{value:pe.tuple(pe.Type.NO_HINT,"...")}]:[]}:(a.add(p.requester.locatorHash),{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:Object.fromEntries(Array.from(p.children.values(),h=>[G.stringifyLocator(h.requester),n(h)]))}),u=e.peerWarnings.find(p=>p.hash===t);return(await Rt.start({configuration:e.configuration,stdout:r.stdout,includeFooter:!1,includePrefix:!1},async p=>{let h=pe.mark(e.configuration),E=u?h.Cross:h.Check;if(p.reportInfo(0,`Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} is requested to provide ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)} by its descendants`),p.reportSeparator(),p.reportInfo(0,pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)),fs.emitTree({children:Object.fromEntries(Array.from(o.requests.values(),I=>[G.stringifyLocator(I.requester),n(I)]))},{configuration:e.configuration,stdout:r.stdout,json:!1}),p.reportSeparator(),o.provided.range==="missing:"){let I=u?"":" , but all peer requests are optional";p.reportInfo(0,`${E} Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} does not provide ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)}${I}.`)}else{let I=e.storedResolutions.get(o.provided.descriptorHash);if(!I)throw new Error("Assertion failed: Expected the descriptor to be registered");let v=e.storedPackages.get(I);if(!v)throw new Error("Assertion failed: Expected the package to be registered");p.reportInfo(0,`${E} Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} provides ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)} with version ${G.prettyReference(e.configuration,v.version??"0.0.0")}, ${u?"which does not satisfy all requests.":"which satisfies all requests"}`),u?.type===3&&(u.range?p.reportInfo(0,` The combined requested range is ${pe.pretty(e.configuration,u.range,pe.Type.RANGE)}`):p.reportInfo(0," Unfortunately, the requested ranges have no overlap"))}})).exitCode()}async function W0t(t,e){return(await Rt.start({configuration:t.configuration,stdout:e.stdout,includeFooter:!1,includePrefix:!1},async o=>{let a=pe.mark(t.configuration),n=He.sortMap(t.peerRequirementNodes,[([,u])=>G.stringifyLocator(u.subject),([,u])=>G.stringifyIdent(u.ident)]);for(let[,u]of n.values()){if(!u.root)continue;let A=t.peerWarnings.find(E=>E.hash===u.hash),p=[...G.allPeerRequests(u)],h;if(p.length>2?h=` and ${p.length-1} other dependencies`:p.length===2?h=" and 1 other dependency":h="",u.provided.range!=="missing:"){let E=t.storedResolutions.get(u.provided.descriptorHash);if(!E)throw new Error("Assertion failed: Expected the resolution to have been registered");let I=t.storedPackages.get(E);if(!I)throw new Error("Assertion failed: Expected the provided package to have been registered");let v=`${pe.pretty(t.configuration,u.hash,pe.Type.CODE)} \u2192 ${A?a.Cross:a.Check} ${G.prettyLocator(t.configuration,u.subject)} provides ${G.prettyLocator(t.configuration,I)} to ${G.prettyLocator(t.configuration,p[0].requester)}${h}`;A?o.reportWarning(0,v):o.reportInfo(0,v)}else{let E=`${pe.pretty(t.configuration,u.hash,pe.Type.CODE)} \u2192 ${A?a.Cross:a.Check} ${G.prettyLocator(t.configuration,u.subject)} doesn't provide ${G.prettyIdent(t.configuration,u.ident)} to ${G.prettyLocator(t.configuration,p[0].requester)}${h}`;A?o.reportWarning(0,E):o.reportInfo(0,E)}}})).exitCode()}Ge();qt();el();Ge();Ge();Pt();qt();var tde=Ze(Jn()),sE=class extends ut{constructor(){super(...arguments);this.useYarnPath=ge.Boolean("--yarn-path",{description:"Set the yarnPath setting even if the version can be accessed by Corepack"});this.onlyIfNeeded=ge.Boolean("--only-if-needed",!1,{description:"Only lock the Yarn version if it isn't already locked"});this.version=ge.String()}static{this.paths=[["set","version"]]}static{this.usage=it.Usage({description:"lock the Yarn version used by the project",details:"\n This command will set a specific release of Yarn to be used by Corepack: https://nodejs.org/api/corepack.html.\n\n By default it only will set the `packageManager` field at the root of your project, but if the referenced release cannot be represented this way, if you already have `yarnPath` configured, or if you set the `--yarn-path` command line flag, then the release will also be downloaded from the Yarn GitHub repository, stored inside your project, and referenced via the `yarnPath` settings from your project `.yarnrc.yml` file.\n\n A very good use case for this command is to enforce the version of Yarn used by any single member of your team inside the same project - by doing this you ensure that you have control over Yarn upgrades and downgrades (including on your deployment servers), and get rid of most of the headaches related to someone using a slightly different version and getting different behavior.\n\n The version specifier can be:\n\n - a tag:\n - `latest` / `berry` / `stable` -> the most recent stable berry (`>=2.0.0`) release\n - `canary` -> the most recent canary (release candidate) berry (`>=2.0.0`) release\n - `classic` -> the most recent classic (`^0.x || ^1.x`) release\n\n - a semver range (e.g. `2.x`) -> the most recent version satisfying the range (limited to berry releases)\n\n - a semver version (e.g. `2.4.1`, `1.22.1`)\n\n - a local file referenced through either a relative or absolute path\n\n - `self` -> the version used to invoke the command\n ",examples:[["Download the latest release from the Yarn repository","$0 set version latest"],["Download the latest canary release from the Yarn repository","$0 set version canary"],["Download the latest classic release from the Yarn repository","$0 set version classic"],["Download the most recent Yarn 3 build","$0 set version 3.x"],["Download a specific Yarn 2 build","$0 set version 2.0.0-rc.30"],["Switch back to a specific Yarn 1 release","$0 set version 1.22.1"],["Use a release from the local filesystem","$0 set version ./yarn.cjs"],["Use a release from a URL","$0 set version https://repo.yarnpkg.com/3.1.0/packages/yarnpkg-cli/bin/yarn.js"],["Download the version used to invoke the command","$0 set version self"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins);if(this.onlyIfNeeded&&r.get("yarnPath")){let A=r.sources.get("yarnPath");if(!A)throw new Error("Assertion failed: Expected 'yarnPath' to have a source");let p=r.projectCwd??r.startingCwd;if(K.contains(p,A))return 0}let o=()=>{if(typeof nn>"u")throw new st("The --install flag can only be used without explicit version specifier from the Yarn CLI");return`file://${process.argv[1]}`},a,n=(A,p)=>({version:p,url:A.replace(/\{\}/g,p)});if(this.version==="self")a={url:o(),version:nn??"self"};else if(this.version==="latest"||this.version==="berry"||this.version==="stable")a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",await r2(r,"stable"));else if(this.version==="canary")a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",await r2(r,"canary"));else if(this.version==="classic")a={url:"https://classic.yarnpkg.com/latest.js",version:"classic"};else if(this.version.match(/^https?:/))a={url:this.version,version:"remote"};else if(this.version.match(/^\.{0,2}[\\/]/)||ue.isAbsolute(this.version))a={url:`file://${K.resolve(ue.toPortablePath(this.version))}`,version:"file"};else if(Lr.satisfiesWithPrereleases(this.version,">=2.0.0"))a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",this.version);else if(Lr.satisfiesWithPrereleases(this.version,"^0.x || ^1.x"))a=n("https://github.com/yarnpkg/yarn/releases/download/v{}/yarn-{}.js",this.version);else if(Lr.validRange(this.version))a=n("https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js",await K0t(r,this.version));else throw new st(`Invalid version descriptor "${this.version}"`);return(await Rt.start({configuration:r,stdout:this.context.stdout,includeLogs:!this.context.quiet},async A=>{let p=async()=>{let h="file://";return a.url.startsWith(h)?(A.reportInfo(0,`Retrieving ${pe.pretty(r,a.url,pe.Type.PATH)}`),await oe.readFilePromise(a.url.slice(h.length))):(A.reportInfo(0,`Downloading ${pe.pretty(r,a.url,pe.Type.URL)}`),await sn.get(a.url,{configuration:r}))};await k8(r,a.version,p,{report:A,useYarnPath:this.useYarnPath})})).exitCode()}};async function K0t(t,e){let o=(await sn.get("https://repo.yarnpkg.com/tags",{configuration:t,jsonResponse:!0})).tags.filter(a=>Lr.satisfiesWithPrereleases(a,e));if(o.length===0)throw new st(`No matching release found for range ${pe.pretty(t,e,pe.Type.RANGE)}.`);return o[0]}async function r2(t,e){let r=await sn.get("https://repo.yarnpkg.com/tags",{configuration:t,jsonResponse:!0});if(!r.latest[e])throw new st(`Tag ${pe.pretty(t,e,pe.Type.RANGE)} not found`);return r.latest[e]}async function k8(t,e,r,{report:o,useYarnPath:a}){let n,u=async()=>(typeof n>"u"&&(n=await r()),n);if(e===null){let te=await u();await oe.mktempPromise(async ae=>{let le=K.join(ae,"yarn.cjs");await oe.writeFilePromise(le,te);let{stdout:ce}=await Ur.execvp(process.execPath,[ue.fromPortablePath(le),"--version"],{cwd:ae,env:{...t.env,YARN_IGNORE_PATH:"1"}});if(e=ce.trim(),!tde.default.valid(e))throw new Error(`Invalid semver version. ${pe.pretty(t,"yarn --version",pe.Type.CODE)} returned: +${e}`)})}let A=t.projectCwd??t.startingCwd,p=K.resolve(A,".yarn/releases"),h=K.resolve(p,`yarn-${e}.cjs`),E=K.relative(t.startingCwd,h),I=He.isTaggedYarnVersion(e),v=t.get("yarnPath"),x=!I,C=x||!!v||!!a;if(a===!1){if(x)throw new Jt(0,"You explicitly opted out of yarnPath usage in your command line, but the version you specified cannot be represented by Corepack");C=!1}else!C&&!process.env.COREPACK_ROOT&&(o.reportWarning(0,`You don't seem to have ${pe.applyHyperlink(t,"Corepack","https://nodejs.org/api/corepack.html")} enabled; we'll have to rely on ${pe.applyHyperlink(t,"yarnPath","https://yarnpkg.com/configuration/yarnrc#yarnPath")} instead`),C=!0);if(C){let te=await u();o.reportInfo(0,`Saving the new release in ${pe.pretty(t,E,"magenta")}`),await oe.removePromise(K.dirname(h)),await oe.mkdirPromise(K.dirname(h),{recursive:!0}),await oe.writeFilePromise(h,te,{mode:493}),await Ke.updateConfiguration(A,{yarnPath:K.relative(A,h)})}else await oe.removePromise(K.dirname(h)),await Ke.updateConfiguration(A,{yarnPath:Ke.deleteProperty});let R=await Ut.tryFind(A)||new Ut;R.packageManager=`yarn@${I?e:await r2(t,"stable")}`;let L={};R.exportTo(L);let U=K.join(A,Ut.fileName),z=`${JSON.stringify(L,null,R.indent)} +`;return await oe.changeFilePromise(U,z,{automaticNewlines:!0}),{bundleVersion:e}}function rde(t){return wr[ZD(t)]}var V0t=/## (?<code>YN[0-9]{4}) - `(?<name>[A-Z_]+)`\n\n(?<details>(?:.(?!##))+)/gs;async function z0t(t){let r=`https://repo.yarnpkg.com/${He.isTaggedYarnVersion(nn)?nn:await r2(t,"canary")}/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx`,o=await sn.get(r,{configuration:t});return new Map(Array.from(o.toString().matchAll(V0t),({groups:a})=>{if(!a)throw new Error("Assertion failed: Expected the match to have been successful");let n=rde(a.code);if(a.name!==n)throw new Error(`Assertion failed: Invalid error code data: Expected "${a.name}" to be named "${n}"`);return[a.code,a.details]}))}var oE=class extends ut{constructor(){super(...arguments);this.code=ge.String({required:!1,validator:jw(om(),[qw(/^YN[0-9]{4}$/)])});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["explain"]]}static{this.usage=it.Usage({description:"explain an error code",details:` + When the code argument is specified, this command prints its name and its details. + + When used without arguments, this command lists all error codes and their names. + `,examples:[["Explain an error code","$0 explain YN0006"],["List all error codes","$0 explain"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins);if(typeof this.code<"u"){let o=rde(this.code),a=pe.pretty(r,o,pe.Type.CODE),n=this.cli.format().header(`${this.code} - ${a}`),A=(await z0t(r)).get(this.code),p=typeof A<"u"?pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.MARKDOWN,{text:A,format:this.cli.format(),paragraphs:!0})):`This error code does not have a description. + +You can help us by editing this page on GitHub \u{1F642}: +${pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.URL,"https://github.com/yarnpkg/berry/blob/master/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx"))} +`;this.json?this.context.stdout.write(`${JSON.stringify({code:this.code,name:o,details:p})} +`):this.context.stdout.write(`${n} + +${p} +`)}else{let o={children:He.mapAndFilter(Object.entries(wr),([a,n])=>Number.isNaN(Number(a))?He.mapAndFilter.skip:{label:Ku(Number(a)),value:pe.tuple(pe.Type.CODE,n)})};fs.emitTree(o,{configuration:r,stdout:this.context.stdout,json:this.json})}}};Ge();Pt();qt();var nde=Ze($o()),aE=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("-A,--all",!1,{description:"Print versions of a package from the whole project"});this.recursive=ge.Boolean("-R,--recursive",!1,{description:"Print information for all packages, including transitive dependencies"});this.extra=ge.Array("-X,--extra",[],{description:"An array of requests of extra data provided by plugins"});this.cache=ge.Boolean("--cache",!1,{description:"Print information about the cache entry of a package (path, size, checksum)"});this.dependents=ge.Boolean("--dependents",!1,{description:"Print all dependents for each matching package"});this.manifest=ge.Boolean("--manifest",!1,{description:"Print data obtained by looking at the package archive (license, homepage, ...)"});this.nameOnly=ge.Boolean("--name-only",!1,{description:"Only print the name for the matching packages"});this.virtuals=ge.Boolean("--virtuals",!1,{description:"Print each instance of the virtual packages"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.patterns=ge.Rest()}static{this.paths=[["info"]]}static{this.usage=it.Usage({description:"see information related to packages",details:"\n This command prints various information related to the specified packages, accepting glob patterns.\n\n By default, if the locator reference is missing, Yarn will default to print the information about all the matching direct dependencies of the package for the active workspace. To instead print all versions of the package that are direct dependencies of any of your workspaces, use the `-A,--all` flag. Adding the `-R,--recursive` flag will also report transitive dependencies.\n\n Some fields will be hidden by default in order to keep the output readable, but can be selectively displayed by using additional options (`--dependents`, `--manifest`, `--virtuals`, ...) described in the option descriptions.\n\n Note that this command will only print the information directly related to the selected packages - if you wish to know why the package is there in the first place, use `yarn why` which will do just that (it also provides a `-R,--recursive` flag that may be of some help).\n ",examples:[["Show information about Lodash","$0 info lodash"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a&&!this.all)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState();let u=new Set(this.extra);this.cache&&u.add("cache"),this.dependents&&u.add("dependents"),this.manifest&&u.add("manifest");let A=(ae,{recursive:le})=>{let ce=ae.anchoredLocator.locatorHash,Ce=new Map,de=[ce];for(;de.length>0;){let Be=de.shift();if(Ce.has(Be))continue;let Ee=o.storedPackages.get(Be);if(typeof Ee>"u")throw new Error("Assertion failed: Expected the package to be registered");if(Ce.set(Be,Ee),G.isVirtualLocator(Ee)&&de.push(G.devirtualizeLocator(Ee).locatorHash),!(!le&&Be!==ce))for(let g of Ee.dependencies.values()){let me=o.storedResolutions.get(g.descriptorHash);if(typeof me>"u")throw new Error("Assertion failed: Expected the resolution to be registered");de.push(me)}}return Ce.values()},p=({recursive:ae})=>{let le=new Map;for(let ce of o.workspaces)for(let Ce of A(ce,{recursive:ae}))le.set(Ce.locatorHash,Ce);return le.values()},h=({all:ae,recursive:le})=>ae&&le?o.storedPackages.values():ae?p({recursive:le}):A(a,{recursive:le}),E=({all:ae,recursive:le})=>{let ce=h({all:ae,recursive:le}),Ce=this.patterns.map(Ee=>{let g=G.parseLocator(Ee),me=nde.default.makeRe(G.stringifyIdent(g)),we=G.isVirtualLocator(g),Ae=we?G.devirtualizeLocator(g):g;return ne=>{let Z=G.stringifyIdent(ne);if(!me.test(Z))return!1;if(g.reference==="unknown")return!0;let xe=G.isVirtualLocator(ne),Ne=xe?G.devirtualizeLocator(ne):ne;return!(we&&xe&&g.reference!==ne.reference||Ae.reference!==Ne.reference)}}),de=He.sortMap([...ce],Ee=>G.stringifyLocator(Ee));return{selection:de.filter(Ee=>Ce.length===0||Ce.some(g=>g(Ee))),sortedLookup:de}},{selection:I,sortedLookup:v}=E({all:this.all,recursive:this.recursive});if(I.length===0)throw new st("No package matched your request");let x=new Map;if(this.dependents)for(let ae of v)for(let le of ae.dependencies.values()){let ce=o.storedResolutions.get(le.descriptorHash);if(typeof ce>"u")throw new Error("Assertion failed: Expected the resolution to be registered");He.getArrayWithDefault(x,ce).push(ae)}let C=new Map;for(let ae of v){if(!G.isVirtualLocator(ae))continue;let le=G.devirtualizeLocator(ae);He.getArrayWithDefault(C,le.locatorHash).push(ae)}let R={},L={children:R},U=r.makeFetcher(),z={project:o,fetcher:U,cache:n,checksums:o.storedChecksums,report:new ki,cacheOptions:{skipIntegrityCheck:!0}},te=[async(ae,le,ce)=>{if(!le.has("manifest"))return;let Ce=await U.fetch(ae,z),de;try{de=await Ut.find(Ce.prefixPath,{baseFs:Ce.packageFs})}finally{Ce.releaseFs?.()}ce("Manifest",{License:pe.tuple(pe.Type.NO_HINT,de.license),Homepage:pe.tuple(pe.Type.URL,de.raw.homepage??null)})},async(ae,le,ce)=>{if(!le.has("cache"))return;let Ce=o.storedChecksums.get(ae.locatorHash)??null,de=n.getLocatorPath(ae,Ce),Be;if(de!==null)try{Be=await oe.statPromise(de)}catch{}let Ee=typeof Be<"u"?[Be.size,pe.Type.SIZE]:void 0;ce("Cache",{Checksum:pe.tuple(pe.Type.NO_HINT,Ce),Path:pe.tuple(pe.Type.PATH,de),Size:Ee})}];for(let ae of I){let le=G.isVirtualLocator(ae);if(!this.virtuals&&le)continue;let ce={},Ce={value:[ae,pe.Type.LOCATOR],children:ce};if(R[G.stringifyLocator(ae)]=Ce,this.nameOnly){delete Ce.children;continue}let de=C.get(ae.locatorHash);typeof de<"u"&&(ce.Instances={label:"Instances",value:pe.tuple(pe.Type.NUMBER,de.length)}),ce.Version={label:"Version",value:pe.tuple(pe.Type.NO_HINT,ae.version)};let Be=(g,me)=>{let we={};if(ce[g]=we,Array.isArray(me))we.children=me.map(Ae=>({value:Ae}));else{let Ae={};we.children=Ae;for(let[ne,Z]of Object.entries(me))typeof Z>"u"||(Ae[ne]={label:ne,value:Z})}};if(!le){for(let g of te)await g(ae,u,Be);await r.triggerHook(g=>g.fetchPackageInfo,ae,u,Be)}ae.bin.size>0&&!le&&Be("Exported Binaries",[...ae.bin.keys()].map(g=>pe.tuple(pe.Type.PATH,g)));let Ee=x.get(ae.locatorHash);typeof Ee<"u"&&Ee.length>0&&Be("Dependents",Ee.map(g=>pe.tuple(pe.Type.LOCATOR,g))),ae.dependencies.size>0&&!le&&Be("Dependencies",[...ae.dependencies.values()].map(g=>{let me=o.storedResolutions.get(g.descriptorHash),we=typeof me<"u"?o.storedPackages.get(me)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:we})})),ae.peerDependencies.size>0&&le&&Be("Peer dependencies",[...ae.peerDependencies.values()].map(g=>{let me=ae.dependencies.get(g.identHash),we=typeof me<"u"?o.storedResolutions.get(me.descriptorHash)??null:null,Ae=we!==null?o.storedPackages.get(we)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:Ae})}))}fs.emitTree(L,{configuration:r,json:this.json,stdout:this.context.stdout,separators:this.nameOnly?0:2})}};Ge();Pt();Nl();var nk=Ze(X0());qt();var Q8=Ze(Jn());el();var J0t=[{selector:t=>t===-1,name:"nodeLinker",value:"node-modules"},{selector:t=>t!==-1&&t<8,name:"enableGlobalCache",value:!1},{selector:t=>t!==-1&&t<8,name:"compressionLevel",value:"mixed"}],lE=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.immutable=ge.Boolean("--immutable",{description:"Abort with an error exit code if the lockfile was to be modified"});this.immutableCache=ge.Boolean("--immutable-cache",{description:"Abort with an error exit code if the cache folder was to be modified"});this.refreshLockfile=ge.Boolean("--refresh-lockfile",{description:"Refresh the package metadata stored in the lockfile"});this.checkCache=ge.Boolean("--check-cache",{description:"Always refetch the packages and ensure that their checksums are consistent"});this.checkResolutions=ge.Boolean("--check-resolutions",{description:"Validates that the package resolutions are coherent"});this.inlineBuilds=ge.Boolean("--inline-builds",{description:"Verbosely print the output of the build steps of dependencies"});this.mode=ge.String("--mode",{description:"Change what artifacts installs generate",validator:Js(hl)});this.cacheFolder=ge.String("--cache-folder",{hidden:!0});this.frozenLockfile=ge.Boolean("--frozen-lockfile",{hidden:!0});this.ignoreEngines=ge.Boolean("--ignore-engines",{hidden:!0});this.nonInteractive=ge.Boolean("--non-interactive",{hidden:!0});this.preferOffline=ge.Boolean("--prefer-offline",{hidden:!0});this.production=ge.Boolean("--production",{hidden:!0});this.registry=ge.String("--registry",{hidden:!0});this.silent=ge.Boolean("--silent",{hidden:!0});this.networkTimeout=ge.String("--network-timeout",{hidden:!0})}static{this.paths=[["install"],it.Default]}static{this.usage=it.Usage({description:"install the project dependencies",details:"\n This command sets up your project if needed. The installation is split into four different steps that each have their own characteristics:\n\n - **Resolution:** First the package manager will resolve your dependencies. The exact way a dependency version is privileged over another isn't standardized outside of the regular semver guarantees. If a package doesn't resolve to what you would expect, check that all dependencies are correctly declared (also check our website for more information: ).\n\n - **Fetch:** Then we download all the dependencies if needed, and make sure that they're all stored within our cache (check the value of `cacheFolder` in `yarn config` to see where the cache files are stored).\n\n - **Link:** Then we send the dependency tree information to internal plugins tasked with writing them on the disk in some form (for example by generating the `.pnp.cjs` file you might know).\n\n - **Build:** Once the dependency tree has been written on the disk, the package manager will now be free to run the build scripts for all packages that might need it, in a topological order compatible with the way they depend on one another. See https://yarnpkg.com/advanced/lifecycle-scripts for detail.\n\n Note that running this command is not part of the recommended workflow. Yarn supports zero-installs, which means that as long as you store your cache and your `.pnp.cjs` file inside your repository, everything will work without requiring any install right after cloning your repository or switching branches.\n\n If the `--immutable` option is set (defaults to true on CI), Yarn will abort with an error exit code if the lockfile was to be modified (other paths can be added using the `immutablePatterns` configuration setting). For backward compatibility we offer an alias under the name of `--frozen-lockfile`, but it will be removed in a later release.\n\n If the `--immutable-cache` option is set, Yarn will abort with an error exit code if the cache folder was to be modified (either because files would be added, or because they'd be removed).\n\n If the `--refresh-lockfile` option is set, Yarn will keep the same resolution for the packages currently in the lockfile but will refresh their metadata. If used together with `--immutable`, it can validate that the lockfile information are consistent. This flag is enabled by default when Yarn detects it runs within a pull request context.\n\n If the `--check-cache` option is set, Yarn will always refetch the packages and will ensure that their checksum matches what's 1/ described in the lockfile 2/ inside the existing cache files (if present). This is recommended as part of your CI workflow if you're both following the Zero-Installs model and accepting PRs from third-parties, as they'd otherwise have the ability to alter the checked-in packages before submitting them.\n\n If the `--inline-builds` option is set, Yarn will verbosely print the output of the build steps of your dependencies (instead of writing them into individual files). This is likely useful mostly for debug purposes only when using Docker-like environments.\n\n If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n ",examples:[["Install the project","$0 install"],["Validate a project when using Zero-Installs","$0 install --immutable --immutable-cache"],["Validate a project when using Zero-Installs (slightly safer if you accept external PRs)","$0 install --immutable --immutable-cache --check-cache"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins);typeof this.inlineBuilds<"u"&&r.useWithSource("<cli>",{enableInlineBuilds:this.inlineBuilds},r.startingCwd,{overwrite:!0});let o=!!process.env.FUNCTION_TARGET||!!process.env.GOOGLE_RUNTIME,a=await uy({configuration:r,stdout:this.context.stdout},[{option:this.ignoreEngines,message:"The --ignore-engines option is deprecated; engine checking isn't a core feature anymore",error:!nk.default.VERCEL},{option:this.registry,message:"The --registry option is deprecated; prefer setting npmRegistryServer in your .yarnrc.yml file"},{option:this.preferOffline,message:"The --prefer-offline flag is deprecated; use the --cached flag with 'yarn add' instead",error:!nk.default.VERCEL},{option:this.production,message:"The --production option is deprecated on 'install'; use 'yarn workspaces focus' instead",error:!0},{option:this.nonInteractive,message:"The --non-interactive option is deprecated",error:!o},{option:this.frozenLockfile,message:"The --frozen-lockfile option is deprecated; use --immutable and/or --immutable-cache instead",callback:()=>this.immutable=this.frozenLockfile},{option:this.cacheFolder,message:"The cache-folder option has been deprecated; use rc settings instead",error:!nk.default.NETLIFY}]);if(a!==null)return a;let n=this.mode==="update-lockfile";if(n&&(this.immutable||this.immutableCache))throw new st(`${pe.pretty(r,"--immutable",pe.Type.CODE)} and ${pe.pretty(r,"--immutable-cache",pe.Type.CODE)} cannot be used with ${pe.pretty(r,"--mode=update-lockfile",pe.Type.CODE)}`);let u=(this.immutable??r.get("enableImmutableInstalls"))&&!n,A=this.immutableCache&&!n;if(r.projectCwd!==null){let R=await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async L=>{let U=!1;await $0t(r,u)&&(L.reportInfo(48,"Automatically removed core plugins that are now builtins \u{1F44D}"),U=!0),await Z0t(r,u)&&(L.reportInfo(48,"Automatically fixed merge conflicts \u{1F44D}"),U=!0),U&&L.reportSeparator()});if(R.hasErrors())return R.exitCode()}if(r.projectCwd!==null){let R=await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async L=>{if(Ke.telemetry?.isNew)Ke.telemetry.commitTips(),L.reportInfo(65,"Yarn will periodically gather anonymous telemetry: https://yarnpkg.com/advanced/telemetry"),L.reportInfo(65,`Run ${pe.pretty(r,"yarn config set --home enableTelemetry 0",pe.Type.CODE)} to disable`),L.reportSeparator();else if(Ke.telemetry?.shouldShowTips){let U=await sn.get("https://repo.yarnpkg.com/tags",{configuration:r,jsonResponse:!0}).catch(()=>null);if(U!==null){let z=null;if(nn!==null){let ae=Q8.default.prerelease(nn)?"canary":"stable",le=U.latest[ae];Q8.default.gt(le,nn)&&(z=[ae,le])}if(z)Ke.telemetry.commitTips(),L.reportInfo(88,`${pe.applyStyle(r,`A new ${z[0]} version of Yarn is available:`,pe.Style.BOLD)} ${G.prettyReference(r,z[1])}!`),L.reportInfo(88,`Upgrade now by running ${pe.pretty(r,`yarn set version ${z[1]}`,pe.Type.CODE)}`),L.reportSeparator();else{let te=Ke.telemetry.selectTip(U.tips);te&&(L.reportInfo(89,pe.pretty(r,te.message,pe.Type.MARKDOWN_INLINE)),te.url&&L.reportInfo(89,`Learn more at ${te.url}`),L.reportSeparator())}}}});if(R.hasErrors())return R.exitCode()}let{project:p,workspace:h}=await kt.find(r,this.context.cwd),E=p.lockfileLastVersion;if(E!==null){let R=await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async L=>{let U={};for(let z of J0t)z.selector(E)&&typeof r.sources.get(z.name)>"u"&&(r.use("<compat>",{[z.name]:z.value},p.cwd,{overwrite:!0}),U[z.name]=z.value);Object.keys(U).length>0&&(await Ke.updateConfiguration(p.cwd,U),L.reportInfo(87,"Migrated your project to the latest Yarn version \u{1F680}"),L.reportSeparator())});if(R.hasErrors())return R.exitCode()}let I=await Gr.find(r,{immutable:A,check:this.checkCache});if(!h)throw new sr(p.cwd,this.context.cwd);await p.restoreInstallState({restoreResolutions:!1});let v=r.get("enableHardenedMode");v&&typeof r.sources.get("enableHardenedMode")>"u"&&await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async R=>{R.reportWarning(0,"Yarn detected that the current workflow is executed from a public pull request. For safety the hardened mode has been enabled."),R.reportWarning(0,`It will prevent malicious lockfile manipulations, in exchange for a slower install time. You can opt-out if necessary; check our ${pe.applyHyperlink(r,"documentation","https://yarnpkg.com/features/security#hardened-mode")} for more details.`),R.reportSeparator()}),(this.refreshLockfile??v)&&(p.lockfileNeedsRefresh=!0);let x=this.checkResolutions??v;return(await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout,forceSectionAlignment:!0,includeLogs:!0,includeVersion:!0},async R=>{await p.install({cache:I,report:R,immutable:u,checkResolutions:x,mode:this.mode})})).exitCode()}},X0t="<<<<<<<";async function Z0t(t,e){if(!t.projectCwd)return!1;let r=K.join(t.projectCwd,dr.lockfile);if(!await oe.existsPromise(r)||!(await oe.readFilePromise(r,"utf8")).includes(X0t))return!1;if(e)throw new Jt(47,"Cannot autofix a lockfile when running an immutable install");let a=await Ur.execvp("git",["rev-parse","MERGE_HEAD","HEAD"],{cwd:t.projectCwd});if(a.code!==0&&(a=await Ur.execvp("git",["rev-parse","REBASE_HEAD","HEAD"],{cwd:t.projectCwd})),a.code!==0&&(a=await Ur.execvp("git",["rev-parse","CHERRY_PICK_HEAD","HEAD"],{cwd:t.projectCwd})),a.code!==0)throw new Jt(83,"Git returned an error when trying to find the commits pertaining to the conflict");let n=await Promise.all(a.stdout.trim().split(/\n/).map(async A=>{let p=await Ur.execvp("git",["show",`${A}:./${dr.lockfile}`],{cwd:t.projectCwd});if(p.code!==0)throw new Jt(83,`Git returned an error when trying to access the lockfile content in ${A}`);try{return Ki(p.stdout)}catch{throw new Jt(46,"A variant of the conflicting lockfile failed to parse")}}));n=n.filter(A=>!!A.__metadata);for(let A of n){if(A.__metadata.version<7)for(let p of Object.keys(A)){if(p==="__metadata")continue;let h=G.parseDescriptor(p,!0),E=t.normalizeDependency(h),I=G.stringifyDescriptor(E);I!==p&&(A[I]=A[p],delete A[p])}for(let p of Object.keys(A)){if(p==="__metadata")continue;let h=A[p].checksum;typeof h=="string"&&h.includes("/")||(A[p].checksum=`${A.__metadata.cacheKey}/${h}`)}}let u=Object.assign({},...n);u.__metadata.version=`${Math.min(...n.map(A=>parseInt(A.__metadata.version??0)))}`,u.__metadata.cacheKey="merged";for(let[A,p]of Object.entries(u))typeof p=="string"&&delete u[A];return await oe.changeFilePromise(r,Da(u),{automaticNewlines:!0}),!0}async function $0t(t,e){if(!t.projectCwd)return!1;let r=[],o=K.join(t.projectCwd,".yarn/plugins/@yarnpkg");return await Ke.updateConfiguration(t.projectCwd,{plugins:n=>{if(!Array.isArray(n))return n;let u=n.filter(A=>{if(!A.path)return!0;let p=K.resolve(t.projectCwd,A.path),h=l1.has(A.spec)&&K.contains(o,p);return h&&r.push(p),!h});return u.length===0?Ke.deleteProperty:u.length===n.length?n:u}},{immutable:e})?(await Promise.all(r.map(async n=>{await oe.removePromise(n)})),!0):!1}Ge();Pt();qt();var cE=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("-A,--all",!1,{description:"Link all workspaces belonging to the target projects to the current one"});this.private=ge.Boolean("-p,--private",!1,{description:"Also link private workspaces belonging to the target projects to the current one"});this.relative=ge.Boolean("-r,--relative",!1,{description:"Link workspaces using relative paths instead of absolute paths"});this.destinations=ge.Rest()}static{this.paths=[["link"]]}static{this.usage=it.Usage({description:"connect the local project to another one",details:"\n This command will set a new `resolutions` field in the project-level manifest and point it to the workspace at the specified location (even if part of another project).\n ",examples:[["Register one or more remote workspaces for use in the current project","$0 link ~/ts-loader ~/jest"],["Register all workspaces from a remote project for use in the current project","$0 link ~/jest --all"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=o.topLevelWorkspace,A=[];for(let p of this.destinations){let h=K.resolve(this.context.cwd,ue.toPortablePath(p)),E=await Ke.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:I,workspace:v}=await kt.find(E,h);if(o.cwd===I.cwd)throw new st(`Invalid destination '${p}'; Can't link the project to itself`);if(!v)throw new sr(I.cwd,h);if(this.all){let x=!1;for(let C of I.workspaces)C.manifest.name&&(!C.manifest.private||this.private)&&(A.push(C),x=!0);if(!x)throw new st(`No workspace found to be linked in the target project: ${p}`)}else{if(!v.manifest.name)throw new st(`The target workspace at '${p}' doesn't have a name and thus cannot be linked`);if(v.manifest.private&&!this.private)throw new st(`The target workspace at '${p}' is marked private - use the --private flag to link it anyway`);A.push(v)}}for(let p of A){let h=G.stringifyIdent(p.anchoredLocator),E=this.relative?K.relative(o.cwd,p.cwd):p.cwd;u.manifest.resolutions.push({pattern:{descriptor:{fullName:h}},reference:`portal:${E}`})}return await o.installWithNewReport({stdout:this.context.stdout},{cache:n})}};qt();var uE=class extends ut{constructor(){super(...arguments);this.args=ge.Proxy()}static{this.paths=[["node"]]}static{this.usage=it.Usage({description:"run node with the hook already setup",details:` + This command simply runs Node. It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment). + + The Node process will use the exact same version of Node as the one used to run Yarn itself, which might be a good way to ensure that your commands always use a consistent Node version. + `,examples:[["Run a Node script","$0 node ./my-script.js"]]})}async execute(){return this.cli.run(["exec","node",...this.args])}};Ge();qt();var AE=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","check"]]}static{this.usage=it.Usage({category:"Plugin-related commands",description:"find all third-party plugins that differ from their own spec",details:` + Check only the plugins from https. + + If this command detects any plugin differences in the CI environment, it will throw an error. + `,examples:[["find all third-party plugins that differ from their own spec","$0 plugin check"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=await Ke.findRcFiles(this.context.cwd);return(await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{for(let u of o)if(u.data?.plugins)for(let A of u.data.plugins){if(!A.checksum||!A.spec.match(/^https?:/))continue;let p=await sn.get(A.spec,{configuration:r}),h=wn.makeHash(p);if(A.checksum===h)continue;let E=pe.pretty(r,A.path,pe.Type.PATH),I=pe.pretty(r,A.spec,pe.Type.URL),v=`${E} is different from the file provided by ${I}`;n.reportJson({...A,newChecksum:h}),n.reportError(0,v)}})).exitCode()}};Ge();Ge();Pt();qt();var lde=ve("os");Ge();Pt();qt();var ide=ve("os");Ge();Nl();qt();var egt="https://raw.githubusercontent.com/yarnpkg/berry/master/plugins.yml";async function Hg(t,e){let r=await sn.get(egt,{configuration:t}),o=Ki(r.toString());return Object.fromEntries(Object.entries(o).filter(([a,n])=>!e||Lr.satisfiesWithPrereleases(e,n.range??"<4.0.0-rc.1")))}var fE=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","list"]]}static{this.usage=it.Usage({category:"Plugin-related commands",description:"list the available official plugins",details:"\n This command prints the plugins available directly from the Yarn repository. Only those plugins can be referenced by name in `yarn plugin import`.\n ",examples:[["List the official plugins","$0 plugin list"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins);return(await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{let n=await Hg(r,nn);for(let[u,{experimental:A,...p}]of Object.entries(n)){let h=u;A&&(h+=" [experimental]"),a.reportJson({name:u,experimental:A,...p}),a.reportInfo(null,h)}})).exitCode()}};var tgt=/^[0-9]+$/,rgt=process.platform==="win32";function sde(t){return tgt.test(t)?`pull/${t}/head`:t}var ngt=({repository:t,branch:e},r)=>[["git","init",ue.fromPortablePath(r)],["git","remote","add","origin",t],["git","fetch","origin","--depth=1",sde(e)],["git","reset","--hard","FETCH_HEAD"]],igt=({branch:t})=>[["git","fetch","origin","--depth=1",sde(t),"--force"],["git","reset","--hard","FETCH_HEAD"],["git","clean","-dfx","-e","packages/yarnpkg-cli/bundles"]],sgt=({plugins:t,noMinify:e},r,o)=>[["yarn","build:cli",...new Array().concat(...t.map(a=>["--plugin",K.resolve(o,a)])),...e?["--no-minify"]:[],"|"],[rgt?"move":"mv","packages/yarnpkg-cli/bundles/yarn.js",ue.fromPortablePath(r),"|"]],pE=class extends ut{constructor(){super(...arguments);this.installPath=ge.String("--path",{description:"The path where the repository should be cloned to"});this.repository=ge.String("--repository","https://github.com/yarnpkg/berry.git",{description:"The repository that should be cloned"});this.branch=ge.String("--branch","master",{description:"The branch of the repository that should be cloned"});this.plugins=ge.Array("--plugin",[],{description:"An array of additional plugins that should be included in the bundle"});this.dryRun=ge.Boolean("-n,--dry-run",!1,{description:"If set, the bundle will be built but not added to the project"});this.noMinify=ge.Boolean("--no-minify",!1,{description:"Build a bundle for development (debugging) - non-minified and non-mangled"});this.force=ge.Boolean("-f,--force",!1,{description:"Always clone the repository instead of trying to fetch the latest commits"});this.skipPlugins=ge.Boolean("--skip-plugins",!1,{description:"Skip updating the contrib plugins"})}static{this.paths=[["set","version","from","sources"]]}static{this.usage=it.Usage({description:"build Yarn from master",details:` + This command will clone the Yarn repository into a temporary folder, then build it. The resulting bundle will then be copied into the local project. + + By default, it also updates all contrib plugins to the same commit the bundle is built from. This behavior can be disabled by using the \`--skip-plugins\` flag. + `,examples:[["Build Yarn from master","$0 set version from sources"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd),a=typeof this.installPath<"u"?K.resolve(this.context.cwd,ue.toPortablePath(this.installPath)):K.resolve(ue.toPortablePath((0,ide.tmpdir)()),"yarnpkg-sources",wn.makeHash(this.repository).slice(0,6));return(await Rt.start({configuration:r,stdout:this.context.stdout},async u=>{await F8(this,{configuration:r,report:u,target:a}),u.reportSeparator(),u.reportInfo(0,"Building a fresh bundle"),u.reportSeparator();let A=await Ur.execvp("git",["rev-parse","--short","HEAD"],{cwd:a,strict:!0}),p=K.join(a,`packages/yarnpkg-cli/bundles/yarn-${A.stdout.trim()}.js`);oe.existsSync(p)||(await n2(sgt(this,p,a),{configuration:r,context:this.context,target:a}),u.reportSeparator());let h=await oe.readFilePromise(p);if(!this.dryRun){let{bundleVersion:E}=await k8(r,null,async()=>h,{report:u});this.skipPlugins||await ogt(this,E,{project:o,report:u,target:a})}})).exitCode()}};async function n2(t,{configuration:e,context:r,target:o}){for(let[a,...n]of t){let u=n[n.length-1]==="|";if(u&&n.pop(),u)await Ur.pipevp(a,n,{cwd:o,stdin:r.stdin,stdout:r.stdout,stderr:r.stderr,strict:!0});else{r.stdout.write(`${pe.pretty(e,` $ ${[a,...n].join(" ")}`,"grey")} +`);try{await Ur.execvp(a,n,{cwd:o,strict:!0})}catch(A){throw r.stdout.write(A.stdout||A.stack),A}}}}async function F8(t,{configuration:e,report:r,target:o}){let a=!1;if(!t.force&&oe.existsSync(K.join(o,".git"))){r.reportInfo(0,"Fetching the latest commits"),r.reportSeparator();try{await n2(igt(t),{configuration:e,context:t.context,target:o}),a=!0}catch{r.reportSeparator(),r.reportWarning(0,"Repository update failed; we'll try to regenerate it")}}a||(r.reportInfo(0,"Cloning the remote repository"),r.reportSeparator(),await oe.removePromise(o),await oe.mkdirPromise(o,{recursive:!0}),await n2(ngt(t,o),{configuration:e,context:t.context,target:o}))}async function ogt(t,e,{project:r,report:o,target:a}){let n=await Hg(r.configuration,e),u=new Set(Object.keys(n));for(let A of r.configuration.plugins.keys())u.has(A)&&await R8(A,t,{project:r,report:o,target:a})}Ge();Ge();Pt();qt();var ode=Ze(Jn()),ade=ve("vm");var hE=class extends ut{constructor(){super(...arguments);this.name=ge.String();this.checksum=ge.Boolean("--checksum",!0,{description:"Whether to care if this plugin is modified"})}static{this.paths=[["plugin","import"]]}static{this.usage=it.Usage({category:"Plugin-related commands",description:"download a plugin",details:` + This command downloads the specified plugin from its remote location and updates the configuration to reference it in further CLI invocations. + + Three types of plugin references are accepted: + + - If the plugin is stored within the Yarn repository, it can be referenced by name. + - Third-party plugins can be referenced directly through their public urls. + - Local plugins can be referenced by their path on the disk. + + If the \`--no-checksum\` option is set, Yarn will no longer care if the plugin is modified. + + Plugins cannot be downloaded from the npm registry, and aren't allowed to have dependencies (they need to be bundled into a single file, possibly thanks to the \`@yarnpkg/builder\` package). + `,examples:[['Download and activate the "@yarnpkg/plugin-exec" plugin',"$0 plugin import @yarnpkg/plugin-exec"],['Download and activate the "@yarnpkg/plugin-exec" plugin (shorthand)',"$0 plugin import exec"],["Download and activate a community plugin","$0 plugin import https://example.org/path/to/plugin.js"],["Activate a local plugin","$0 plugin import ./path/to/plugin.js"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins);return(await Rt.start({configuration:r,stdout:this.context.stdout},async a=>{let{project:n}=await kt.find(r,this.context.cwd),u,A;if(this.name.match(/^\.{0,2}[\\/]/)||ue.isAbsolute(this.name)){let p=K.resolve(this.context.cwd,ue.toPortablePath(this.name));a.reportInfo(0,`Reading ${pe.pretty(r,p,pe.Type.PATH)}`),u=K.relative(n.cwd,p),A=await oe.readFilePromise(p)}else{let p;if(this.name.match(/^https?:/)){try{new URL(this.name)}catch{throw new Jt(52,`Plugin specifier "${this.name}" is neither a plugin name nor a valid url`)}u=this.name,p=this.name}else{let h=G.parseLocator(this.name.replace(/^((@yarnpkg\/)?plugin-)?/,"@yarnpkg/plugin-"));if(h.reference!=="unknown"&&!ode.default.valid(h.reference))throw new Jt(0,"Official plugins only accept strict version references. Use an explicit URL if you wish to download them from another location.");let E=G.stringifyIdent(h),I=await Hg(r,nn);if(!Object.hasOwn(I,E)){let v=`Couldn't find a plugin named ${G.prettyIdent(r,h)} on the remote registry. +`;throw r.plugins.has(E)?v+=`A plugin named ${G.prettyIdent(r,h)} is already installed; possibly attempting to import a built-in plugin.`:v+=`Note that only the plugins referenced on our website (${pe.pretty(r,"https://github.com/yarnpkg/berry/blob/master/plugins.yml",pe.Type.URL)}) can be referenced by their name; any other plugin will have to be referenced through its public url (for example ${pe.pretty(r,"https://github.com/yarnpkg/berry/raw/master/packages/plugin-typescript/bin/%40yarnpkg/plugin-typescript.js",pe.Type.URL)}).`,new Jt(51,v)}u=E,p=I[E].url,h.reference!=="unknown"?p=p.replace(/\/master\//,`/${E}/${h.reference}/`):nn!==null&&(p=p.replace(/\/master\//,`/@yarnpkg/cli/${nn}/`))}a.reportInfo(0,`Downloading ${pe.pretty(r,p,"green")}`),A=await sn.get(p,{configuration:r})}await T8(u,A,{checksum:this.checksum,project:n,report:a})})).exitCode()}};async function T8(t,e,{checksum:r=!0,project:o,report:a}){let{configuration:n}=o,u={},A={exports:u};(0,ade.runInNewContext)(e.toString(),{module:A,exports:u});let h=`.yarn/plugins/${A.exports.name}.cjs`,E=K.resolve(o.cwd,h);a.reportInfo(0,`Saving the new plugin in ${pe.pretty(n,h,"magenta")}`),await oe.mkdirPromise(K.dirname(E),{recursive:!0}),await oe.writeFilePromise(E,e);let I={path:h,spec:t};r&&(I.checksum=wn.makeHash(e)),await Ke.addPlugin(o.cwd,[I])}var agt=({pluginName:t,noMinify:e},r)=>[["yarn",`build:${t}`,...e?["--no-minify"]:[],"|"]],gE=class extends ut{constructor(){super(...arguments);this.installPath=ge.String("--path",{description:"The path where the repository should be cloned to"});this.repository=ge.String("--repository","https://github.com/yarnpkg/berry.git",{description:"The repository that should be cloned"});this.branch=ge.String("--branch","master",{description:"The branch of the repository that should be cloned"});this.noMinify=ge.Boolean("--no-minify",!1,{description:"Build a plugin for development (debugging) - non-minified and non-mangled"});this.force=ge.Boolean("-f,--force",!1,{description:"Always clone the repository instead of trying to fetch the latest commits"});this.name=ge.String()}static{this.paths=[["plugin","import","from","sources"]]}static{this.usage=it.Usage({category:"Plugin-related commands",description:"build a plugin from sources",details:` + This command clones the Yarn repository into a temporary folder, builds the specified contrib plugin and updates the configuration to reference it in further CLI invocations. + + The plugins can be referenced by their short name if sourced from the official Yarn repository. + `,examples:[['Build and activate the "@yarnpkg/plugin-exec" plugin',"$0 plugin import from sources @yarnpkg/plugin-exec"],['Build and activate the "@yarnpkg/plugin-exec" plugin (shorthand)',"$0 plugin import from sources exec"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=typeof this.installPath<"u"?K.resolve(this.context.cwd,ue.toPortablePath(this.installPath)):K.resolve(ue.toPortablePath((0,lde.tmpdir)()),"yarnpkg-sources",wn.makeHash(this.repository).slice(0,6));return(await Rt.start({configuration:r,stdout:this.context.stdout},async n=>{let{project:u}=await kt.find(r,this.context.cwd),A=G.parseIdent(this.name.replace(/^((@yarnpkg\/)?plugin-)?/,"@yarnpkg/plugin-")),p=G.stringifyIdent(A),h=await Hg(r,nn);if(!Object.hasOwn(h,p))throw new Jt(51,`Couldn't find a plugin named "${p}" on the remote registry. Note that only the plugins referenced on our website (https://github.com/yarnpkg/berry/blob/master/plugins.yml) can be built and imported from sources.`);let E=p;await F8(this,{configuration:r,report:n,target:o}),await R8(E,this,{project:u,report:n,target:o})})).exitCode()}};async function R8(t,{context:e,noMinify:r},{project:o,report:a,target:n}){let u=t.replace(/@yarnpkg\//,""),{configuration:A}=o;a.reportSeparator(),a.reportInfo(0,`Building a fresh ${u}`),a.reportSeparator(),await n2(agt({pluginName:u,noMinify:r},n),{configuration:A,context:e,target:n}),a.reportSeparator();let p=K.resolve(n,`packages/${u}/bundles/${t}.js`),h=await oe.readFilePromise(p);await T8(t,h,{project:o,report:a})}Ge();Pt();qt();var dE=class extends ut{constructor(){super(...arguments);this.name=ge.String()}static{this.paths=[["plugin","remove"]]}static{this.usage=it.Usage({category:"Plugin-related commands",description:"remove a plugin",details:` + This command deletes the specified plugin from the .yarn/plugins folder and removes it from the configuration. + + **Note:** The plugins have to be referenced by their name property, which can be obtained using the \`yarn plugin runtime\` command. Shorthands are not allowed. + `,examples:[["Remove a plugin imported from the Yarn repository","$0 plugin remove @yarnpkg/plugin-typescript"],["Remove a plugin imported from a local file","$0 plugin remove my-local-plugin"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd);return(await Rt.start({configuration:r,stdout:this.context.stdout},async n=>{let u=this.name,A=G.parseIdent(u);if(!r.plugins.has(u))throw new st(`${G.prettyIdent(r,A)} isn't referenced by the current configuration`);let p=`.yarn/plugins/${u}.cjs`,h=K.resolve(o.cwd,p);oe.existsSync(h)&&(n.reportInfo(0,`Removing ${pe.pretty(r,p,pe.Type.PATH)}...`),await oe.removePromise(h)),n.reportInfo(0,"Updating the configuration..."),await Ke.updateConfiguration(o.cwd,{plugins:E=>{if(!Array.isArray(E))return E;let I=E.filter(v=>v.path!==p);return I.length===0?Ke.deleteProperty:I.length===E.length?E:I}})})).exitCode()}};Ge();qt();var mE=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","runtime"]]}static{this.usage=it.Usage({category:"Plugin-related commands",description:"list the active plugins",details:` + This command prints the currently active plugins. Will be displayed both builtin plugins and external plugins. + `,examples:[["List the currently active plugins","$0 plugin runtime"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins);return(await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{for(let n of r.plugins.keys()){let u=this.context.plugins.plugins.has(n),A=n;u&&(A+=" [builtin]"),a.reportJson({name:n,builtin:u}),a.reportInfo(null,`${A}`)}})).exitCode()}};Ge();Ge();qt();var yE=class extends ut{constructor(){super(...arguments);this.idents=ge.Rest()}static{this.paths=[["rebuild"]]}static{this.usage=it.Usage({description:"rebuild the project's native packages",details:` + This command will automatically cause Yarn to forget about previous compilations of the given packages and to run them again. + + Note that while Yarn forgets the compilation, the previous artifacts aren't erased from the filesystem and may affect the next builds (in good or bad). To avoid this, you may remove the .yarn/unplugged folder, or any other relevant location where packages might have been stored (Yarn may offer a way to do that automatically in the future). + + By default all packages will be rebuilt, but you can filter the list by specifying the names of the packages you want to clear from memory. + `,examples:[["Rebuild all packages","$0 rebuild"],["Rebuild fsevents only","$0 rebuild fsevents"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);let u=new Set;for(let A of this.idents)u.add(G.parseIdent(A).identHash);if(await o.restoreInstallState({restoreResolutions:!1}),await o.resolveEverything({cache:n,report:new ki}),u.size>0)for(let A of o.storedPackages.values())u.has(A.identHash)&&(o.storedBuildState.delete(A.locatorHash),o.skippedBuilds.delete(A.locatorHash));else o.storedBuildState.clear(),o.skippedBuilds.clear();return await o.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};Ge();Ge();Ge();qt();var N8=Ze($o());el();var EE=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("-A,--all",!1,{description:"Apply the operation to all workspaces from the current project"});this.mode=ge.String("--mode",{description:"Change what artifacts installs generate",validator:Js(hl)});this.patterns=ge.Rest()}static{this.paths=[["remove"]]}static{this.usage=it.Usage({description:"remove dependencies from the project",details:` + This command will remove the packages matching the specified patterns from the current workspace. + + If the \`--mode=<mode>\` option is set, Yarn will change which artifacts are generated. The modes currently supported are: + + - \`skip-build\` will not run the build scripts at all. Note that this is different from setting \`enableScripts\` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run. + + - \`update-lockfile\` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost. + + This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them. + `,examples:[["Remove a dependency from the current project","$0 remove lodash"],["Remove a dependency from all workspaces at once","$0 remove lodash --all"],["Remove all dependencies starting with `eslint-`","$0 remove 'eslint-*'"],["Remove all dependencies with the `@babel` scope","$0 remove '@babel/*'"],["Remove all dependencies matching `react-dom` or `react-helmet`","$0 remove 'react-{dom,helmet}'"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.all?o.workspaces:[a],A=["dependencies","devDependencies","peerDependencies"],p=[],h=!1,E=[];for(let C of this.patterns){let R=!1,L=G.parseIdent(C);for(let U of u){let z=[...U.manifest.peerDependenciesMeta.keys()];for(let te of(0,N8.default)(z,C))U.manifest.peerDependenciesMeta.delete(te),h=!0,R=!0;for(let te of A){let ae=U.manifest.getForScope(te),le=[...ae.values()].map(ce=>G.stringifyIdent(ce));for(let ce of(0,N8.default)(le,G.stringifyIdent(L))){let{identHash:Ce}=G.parseIdent(ce),de=ae.get(Ce);if(typeof de>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");U.manifest[te].delete(Ce),E.push([U,te,de]),h=!0,R=!0}}}R||p.push(C)}let I=p.length>1?"Patterns":"Pattern",v=p.length>1?"don't":"doesn't",x=this.all?"any":"this";if(p.length>0)throw new st(`${I} ${pe.prettyList(r,p,pe.Type.CODE)} ${v} match any packages referenced by ${x} workspace`);return h?(await r.triggerMultipleHooks(C=>C.afterWorkspaceDependencyRemoval,E),await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})):0}};Ge();Ge();qt();var cde=ve("util"),CE=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["run"]]}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);return(await Rt.start({configuration:r,stdout:this.context.stdout,json:this.json},async u=>{let A=a.manifest.scripts,p=He.sortMap(A.keys(),I=>I),h={breakLength:1/0,colors:r.get("enableColors"),maxArrayLength:2},E=p.reduce((I,v)=>Math.max(I,v.length),0);for(let[I,v]of A.entries())u.reportInfo(null,`${I.padEnd(E," ")} ${(0,cde.inspect)(v,h)}`),u.reportJson({name:I,script:v})})).exitCode()}};Ge();Ge();qt();var wE=class extends ut{constructor(){super(...arguments);this.inspect=ge.String("--inspect",!1,{tolerateBoolean:!0,description:"Forwarded to the underlying Node process when executing a binary"});this.inspectBrk=ge.String("--inspect-brk",!1,{tolerateBoolean:!0,description:"Forwarded to the underlying Node process when executing a binary"});this.topLevel=ge.Boolean("-T,--top-level",!1,{description:"Check the root workspace for scripts and/or binaries instead of the current one"});this.binariesOnly=ge.Boolean("-B,--binaries-only",!1,{description:"Ignore any user defined scripts and only check for binaries"});this.require=ge.String("--require",{description:"Forwarded to the underlying Node process when executing a binary"});this.silent=ge.Boolean("--silent",{hidden:!0});this.scriptName=ge.String();this.args=ge.Proxy()}static{this.paths=[["run"]]}static{this.usage=it.Usage({description:"run a script defined in the package.json",details:` + This command will run a tool. The exact tool that will be executed will depend on the current state of your workspace: + + - If the \`scripts\` field from your local package.json contains a matching script name, its definition will get executed. + + - Otherwise, if one of the local workspace's dependencies exposes a binary with a matching name, this binary will get executed. + + - Otherwise, if the specified name contains a colon character and if one of the workspaces in the project contains exactly one script with a matching name, then this script will get executed. + + Whatever happens, the cwd of the spawned process will be the workspace that declares the script (which makes it possible to call commands cross-workspaces using the third syntax). + `,examples:[["Run the tests from the local workspace","$0 run test"],['Same thing, but without the "run" keyword',"$0 test"],["Inspect Webpack while running","$0 run --inspect-brk webpack"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a,locator:n}=await kt.find(r,this.context.cwd);await o.restoreInstallState();let u=this.topLevel?o.topLevelWorkspace.anchoredLocator:n;if(!this.binariesOnly&&await An.hasPackageScript(u,this.scriptName,{project:o}))return await An.executePackageScript(u,this.scriptName,this.args,{project:o,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});let A=await An.getPackageAccessibleBinaries(u,{project:o});if(A.get(this.scriptName)){let h=[];return this.inspect&&(typeof this.inspect=="string"?h.push(`--inspect=${this.inspect}`):h.push("--inspect")),this.inspectBrk&&(typeof this.inspectBrk=="string"?h.push(`--inspect-brk=${this.inspectBrk}`):h.push("--inspect-brk")),this.require&&h.push(`--require=${this.require}`),await An.executePackageAccessibleBinary(u,this.scriptName,this.args,{cwd:this.context.cwd,project:o,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,nodeArgs:h,packageAccessibleBinaries:A})}if(!this.topLevel&&!this.binariesOnly&&a&&this.scriptName.includes(":")){let E=(await Promise.all(o.workspaces.map(async I=>I.manifest.scripts.has(this.scriptName)?I:null))).filter(I=>I!==null);if(E.length===1)return await An.executeWorkspaceScript(E[0],this.scriptName,this.args,{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}if(this.topLevel)throw this.scriptName==="node-gyp"?new st(`Couldn't find a script name "${this.scriptName}" in the top-level (used by ${G.prettyLocator(r,n)}). This typically happens because some package depends on "node-gyp" to build itself, but didn't list it in their dependencies. To fix that, please run "yarn add node-gyp" into your top-level workspace. You also can open an issue on the repository of the specified package to suggest them to use an optional peer dependency.`):new st(`Couldn't find a script name "${this.scriptName}" in the top-level (used by ${G.prettyLocator(r,n)}).`);{if(this.scriptName==="global")throw new st("The 'yarn global' commands have been removed in 2.x - consider using 'yarn dlx' or a third-party plugin instead");let h=[this.scriptName].concat(this.args);for(let[E,I]of Uy)for(let v of I)if(h.length>=v.length&&JSON.stringify(h.slice(0,v.length))===JSON.stringify(v))throw new st(`Couldn't find a script named "${this.scriptName}", but a matching command can be found in the ${E} plugin. You can install it with "yarn plugin import ${E}".`);throw new st(`Couldn't find a script named "${this.scriptName}".`)}}};Ge();Ge();qt();var IE=class extends ut{constructor(){super(...arguments);this.descriptor=ge.String();this.resolution=ge.String()}static{this.paths=[["set","resolution"]]}static{this.usage=it.Usage({description:"enforce a package resolution",details:'\n This command updates the resolution table so that `descriptor` is resolved by `resolution`.\n\n Note that by default this command only affect the current resolution table - meaning that this "manual override" will disappear if you remove the lockfile, or if the package disappear from the table. If you wish to make the enforced resolution persist whatever happens, edit the `resolutions` field in your top-level manifest.\n\n Note that no attempt is made at validating that `resolution` is a valid resolution entry for `descriptor`.\n ',examples:[["Force all instances of lodash@npm:^1.2.3 to resolve to 1.5.0","$0 set resolution lodash@npm:^1.2.3 1.5.0"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(await o.restoreInstallState({restoreResolutions:!1}),!a)throw new sr(o.cwd,this.context.cwd);let u=G.parseDescriptor(this.descriptor,!0),A=G.makeDescriptor(u,this.resolution);return o.storedDescriptors.set(u.descriptorHash,u),o.storedDescriptors.set(A.descriptorHash,A),o.resolutionAliases.set(u.descriptorHash,A.descriptorHash),await o.installWithNewReport({stdout:this.context.stdout},{cache:n})}};Ge();Pt();qt();var ude=Ze($o()),BE=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("-A,--all",!1,{description:"Unlink all workspaces belonging to the target project from the current one"});this.leadingArguments=ge.Rest()}static{this.paths=[["unlink"]]}static{this.usage=it.Usage({description:"disconnect the local project from another one",details:` + This command will remove any resolutions in the project-level manifest that would have been added via a yarn link with similar arguments. + `,examples:[["Unregister a remote workspace in the current project","$0 unlink ~/ts-loader"],["Unregister all workspaces from a remote project in the current project","$0 unlink ~/jest --all"],["Unregister all previously linked workspaces","$0 unlink --all"],["Unregister all workspaces matching a glob","$0 unlink '@babel/*' 'pkg-{a,b}'"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);let u=o.topLevelWorkspace,A=new Set;if(this.leadingArguments.length===0&&this.all)for(let{pattern:p,reference:h}of u.manifest.resolutions)h.startsWith("portal:")&&A.add(p.descriptor.fullName);if(this.leadingArguments.length>0)for(let p of this.leadingArguments){let h=K.resolve(this.context.cwd,ue.toPortablePath(p));if(He.isPathLike(p)){let E=await Ke.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:I,workspace:v}=await kt.find(E,h);if(!v)throw new sr(I.cwd,h);if(this.all){for(let x of I.workspaces)x.manifest.name&&A.add(G.stringifyIdent(x.anchoredLocator));if(A.size===0)throw new st("No workspace found to be unlinked in the target project")}else{if(!v.manifest.name)throw new st("The target workspace doesn't have a name and thus cannot be unlinked");A.add(G.stringifyIdent(v.anchoredLocator))}}else{let E=[...u.manifest.resolutions.map(({pattern:I})=>I.descriptor.fullName)];for(let I of(0,ude.default)(E,p))A.add(I)}}return u.manifest.resolutions=u.manifest.resolutions.filter(({pattern:p})=>!A.has(p.descriptor.fullName)),await o.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};Ge();Ge();Ge();qt();var Ade=Ze(J1()),L8=Ze($o());el();var vE=class extends ut{constructor(){super(...arguments);this.interactive=ge.Boolean("-i,--interactive",{description:"Offer various choices, depending on the detected upgrade paths"});this.fixed=ge.Boolean("-F,--fixed",!1,{description:"Store dependency tags as-is instead of resolving them"});this.exact=ge.Boolean("-E,--exact",!1,{description:"Don't use any semver modifier on the resolved range"});this.tilde=ge.Boolean("-T,--tilde",!1,{description:"Use the `~` semver modifier on the resolved range"});this.caret=ge.Boolean("-C,--caret",!1,{description:"Use the `^` semver modifier on the resolved range"});this.recursive=ge.Boolean("-R,--recursive",!1,{description:"Resolve again ALL resolutions for those packages"});this.mode=ge.String("--mode",{description:"Change what artifacts installs generate",validator:Js(hl)});this.patterns=ge.Rest()}static{this.paths=[["up"]]}static{this.usage=it.Usage({description:"upgrade dependencies across the project",details:"\n This command upgrades the packages matching the list of specified patterns to their latest available version across the whole project (regardless of whether they're part of `dependencies` or `devDependencies` - `peerDependencies` won't be affected). This is a project-wide command: all workspaces will be upgraded in the process.\n\n If `-R,--recursive` is set the command will change behavior and no other switch will be allowed. When operating under this mode `yarn up` will force all ranges matching the selected packages to be resolved again (often to the highest available versions) before being stored in the lockfile. It however won't touch your manifests anymore, so depending on your needs you might want to run both `yarn up` and `yarn up -R` to cover all bases.\n\n If `-i,--interactive` is set (or if the `preferInteractive` settings is toggled on) the command will offer various choices, depending on the detected upgrade paths. Some upgrades require this flag in order to resolve ambiguities.\n\n The, `-C,--caret`, `-E,--exact` and `-T,--tilde` options have the same meaning as in the `add` command (they change the modifier used when the range is missing or a tag, and are ignored when the range is explicitly set).\n\n If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n Generally you can see `yarn up` as a counterpart to what was `yarn upgrade --latest` in Yarn 1 (ie it ignores the ranges previously listed in your manifests), but unlike `yarn upgrade` which only upgraded dependencies in the current workspace, `yarn up` will upgrade all workspaces at the same time.\n\n This command accepts glob patterns as arguments (if valid Descriptors and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n **Note:** The ranges have to be static, only the package scopes and names can contain glob patterns.\n ",examples:[["Upgrade all instances of lodash to the latest release","$0 up lodash"],["Upgrade all instances of lodash to the latest release, but ask confirmation for each","$0 up lodash -i"],["Upgrade all instances of lodash to 1.2.3","$0 up lodash@1.2.3"],["Upgrade all instances of packages with the `@babel` scope to the latest release","$0 up '@babel/*'"],["Upgrade all instances of packages containing the word `jest` to the latest release","$0 up '*jest*'"],["Upgrade all instances of packages with the `@babel` scope to 7.0.0","$0 up '@babel/*@7.0.0'"]]})}static{this.schema=[Yw("recursive",Yu.Forbids,["interactive","exact","tilde","caret"],{ignore:[void 0,!1]})]}async execute(){return this.recursive?await this.executeUpRecursive():await this.executeUpClassic()}async executeUpRecursive(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=[...o.storedDescriptors.values()],A=u.map(E=>G.stringifyIdent(E)),p=new Set;for(let E of this.patterns){if(G.parseDescriptor(E).range!=="unknown")throw new st("Ranges aren't allowed when using --recursive");for(let I of(0,L8.default)(A,E)){let v=G.parseIdent(I);p.add(v.identHash)}}let h=u.filter(E=>p.has(E.identHash));for(let E of h)o.storedDescriptors.delete(E.descriptorHash),o.storedResolutions.delete(E.descriptorHash);return await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}async executeUpClassic(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.fixed,A=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=Z1(this,o),h=A?["keep","reuse","project","latest"]:["project","latest"],E=[],I=[];for(let L of this.patterns){let U=!1,z=G.parseDescriptor(L),te=G.stringifyIdent(z);for(let ae of o.workspaces)for(let le of["dependencies","devDependencies"]){let Ce=[...ae.manifest.getForScope(le).values()].map(Be=>G.stringifyIdent(Be)),de=te==="*"?Ce:(0,L8.default)(Ce,te);for(let Be of de){let Ee=G.parseIdent(Be),g=ae.manifest[le].get(Ee.identHash);if(typeof g>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let me=G.makeDescriptor(Ee,z.range);E.push(Promise.resolve().then(async()=>[ae,le,g,await $1(me,{project:o,workspace:ae,cache:n,target:le,fixed:u,modifier:p,strategies:h})])),U=!0}}U||I.push(L)}if(I.length>1)throw new st(`Patterns ${pe.prettyList(r,I,pe.Type.CODE)} don't match any packages referenced by any workspace`);if(I.length>0)throw new st(`Pattern ${pe.prettyList(r,I,pe.Type.CODE)} doesn't match any packages referenced by any workspace`);let v=await Promise.all(E),x=await AA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async L=>{for(let[,,U,{suggestions:z,rejections:te}]of v){let ae=z.filter(le=>le.descriptor!==null);if(ae.length===0){let[le]=te;if(typeof le>"u")throw new Error("Assertion failed: Expected an error to have been set");let ce=this.cli.error(le);o.configuration.get("enableNetwork")?L.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range + +${ce}`):L.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range (note: network resolution has been disabled) + +${ce}`)}else ae.length>1&&!A&&L.reportError(27,`${G.prettyDescriptor(r,U)} has multiple possible upgrade strategies; use -i to disambiguate manually`)}});if(x.hasErrors())return x.exitCode();let C=!1,R=[];for(let[L,U,,{suggestions:z}]of v){let te,ae=z.filter(de=>de.descriptor!==null),le=ae[0].descriptor,ce=ae.every(de=>G.areDescriptorsEqual(de.descriptor,le));ae.length===1||ce?te=le:(C=!0,{answer:te}=await(0,Ade.prompt)({type:"select",name:"answer",message:`Which range do you want to use in ${G.prettyWorkspace(r,L)} \u276F ${U}?`,choices:z.map(({descriptor:de,name:Be,reason:Ee})=>de?{name:Be,hint:Ee,descriptor:de}:{name:Be,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(de){return this.find(de,"descriptor")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ce=L.manifest[U].get(te.identHash);if(typeof Ce>"u")throw new Error("Assertion failed: This descriptor should have a matching entry");if(Ce.descriptorHash!==te.descriptorHash)L.manifest[U].set(te.identHash,te),R.push([L,U,Ce,te]);else{let de=r.makeResolver(),Be={project:o,resolver:de},Ee=r.normalizeDependency(Ce),g=de.bindDescriptor(Ee,L.anchoredLocator,Be);o.forgetResolution(g)}}return await r.triggerMultipleHooks(L=>L.afterWorkspaceDependencyReplacement,R),C&&this.context.stdout.write(` +`),await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}};Ge();Ge();Ge();qt();var DE=class extends ut{constructor(){super(...arguments);this.recursive=ge.Boolean("-R,--recursive",!1,{description:"List, for each workspace, what are all the paths that lead to the dependency"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.peers=ge.Boolean("--peers",!1,{description:"Also print the peer dependencies that match the specified name"});this.package=ge.String()}static{this.paths=[["why"]]}static{this.usage=it.Usage({description:"display the reason why a package is needed",details:` + This command prints the exact reasons why a package appears in the dependency tree. + + If \`-R,--recursive\` is set, the listing will go in depth and will list, for each workspaces, what are all the paths that lead to the dependency. Note that the display is somewhat optimized in that it will not print the package listing twice for a single package, so if you see a leaf named "Foo" when looking for "Bar", it means that "Foo" already got printed higher in the tree. + `,examples:[["Explain why lodash is used in your project","$0 why lodash"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState();let n=G.parseIdent(this.package).identHash,u=this.recursive?cgt(o,n,{configuration:r,peers:this.peers}):lgt(o,n,{configuration:r,peers:this.peers});fs.emitTree(u,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1})}};function lgt(t,e,{configuration:r,peers:o}){let a=He.sortMap(t.storedPackages.values(),A=>G.stringifyLocator(A)),n={},u={children:n};for(let A of a){let p={};for(let E of A.dependencies.values()){if(!o&&A.peerDependencies.has(E.identHash))continue;let I=t.storedResolutions.get(E.descriptorHash);if(!I)throw new Error("Assertion failed: The resolution should have been registered");let v=t.storedPackages.get(I);if(!v)throw new Error("Assertion failed: The package should have been registered");if(v.identHash!==e)continue;{let C=G.stringifyLocator(A);n[C]={value:[A,pe.Type.LOCATOR],children:p}}let x=G.stringifyLocator(v);p[x]={value:[{descriptor:E,locator:v},pe.Type.DEPENDENT]}}}return u}function cgt(t,e,{configuration:r,peers:o}){let a=He.sortMap(t.workspaces,v=>G.stringifyLocator(v.anchoredLocator)),n=new Set,u=new Set,A=v=>{if(n.has(v.locatorHash))return u.has(v.locatorHash);if(n.add(v.locatorHash),v.identHash===e)return u.add(v.locatorHash),!0;let x=!1;v.identHash===e&&(x=!0);for(let C of v.dependencies.values()){if(!o&&v.peerDependencies.has(C.identHash))continue;let R=t.storedResolutions.get(C.descriptorHash);if(!R)throw new Error("Assertion failed: The resolution should have been registered");let L=t.storedPackages.get(R);if(!L)throw new Error("Assertion failed: The package should have been registered");A(L)&&(x=!0)}return x&&u.add(v.locatorHash),x};for(let v of a)A(v.anchoredPackage);let p=new Set,h={},E={children:h},I=(v,x,C)=>{if(!u.has(v.locatorHash))return;let R=C!==null?pe.tuple(pe.Type.DEPENDENT,{locator:v,descriptor:C}):pe.tuple(pe.Type.LOCATOR,v),L={},U={value:R,children:L},z=G.stringifyLocator(v);if(x[z]=U,!(C!==null&&t.tryWorkspaceByLocator(v))&&!p.has(v.locatorHash)){p.add(v.locatorHash);for(let te of v.dependencies.values()){if(!o&&v.peerDependencies.has(te.identHash))continue;let ae=t.storedResolutions.get(te.descriptorHash);if(!ae)throw new Error("Assertion failed: The resolution should have been registered");let le=t.storedPackages.get(ae);if(!le)throw new Error("Assertion failed: The package should have been registered");I(le,L,te)}}};for(let v of a)I(v.anchoredPackage,h,null);return E}Ge();var W8={};Vt(W8,{GitFetcher:()=>s2,GitResolver:()=>o2,default:()=>kgt,gitUtils:()=>ia});Ge();Pt();var ia={};Vt(ia,{TreeishProtocols:()=>i2,clone:()=>Y8,fetchBase:()=>Rde,fetchChangedFiles:()=>Tde,fetchChangedWorkspaces:()=>bgt,fetchRoot:()=>Fde,isGitUrl:()=>bE,lsRemote:()=>Qde,normalizeLocator:()=>Sgt,normalizeRepoUrl:()=>PE,resolveUrl:()=>G8,splitRepoUrl:()=>bh,validateRepoUrl:()=>j8});Ge();Pt();qt();var bde=Ze(Dde()),xde=Ze(uU()),SE=Ze(ve("querystring")),H8=Ze(Jn());function _8(t,e,r){let o=t.indexOf(r);return t.lastIndexOf(e,o>-1?o:1/0)}function Pde(t){try{return new URL(t)}catch{return}}function Dgt(t){let e=_8(t,"@","#"),r=_8(t,":","#");return r>e&&(t=`${t.slice(0,r)}/${t.slice(r+1)}`),_8(t,":","#")===-1&&t.indexOf("//")===-1&&(t=`ssh://${t}`),t}function Sde(t){return Pde(t)||Pde(Dgt(t))}function PE(t,{git:e=!1}={}){if(t=t.replace(/^git\+https:/,"https:"),t=t.replace(/^(?:github:|https:\/\/github\.com\/|git:\/\/github\.com\/)?(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)(?:\.git)?(#.*)?$/,"https://github.com/$1/$2.git$3"),t=t.replace(/^https:\/\/github\.com\/(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\/tarball\/(.+)?$/,"https://github.com/$1/$2.git#$3"),e){let r=Sde(t);r&&(t=r.href),t=t.replace(/^git\+([^:]+):/,"$1:")}return t}function kde(){return{...process.env,GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||`${process.env.GIT_SSH||"ssh"} -o BatchMode=yes`}}var Pgt=[/^ssh:/,/^git(?:\+[^:]+)?:/,/^(?:git\+)?https?:[^#]+\/[^#]+(?:\.git)(?:#.*)?$/,/^git@[^#]+\/[^#]+\.git(?:#.*)?$/,/^(?:github:|https:\/\/github\.com\/)?(?!\.{1,2}\/)([a-zA-Z._0-9-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z._0-9-]+?)(?:\.git)?(?:#.*)?$/,/^https:\/\/github\.com\/(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\/tarball\/(.+)?$/],i2=(a=>(a.Commit="commit",a.Head="head",a.Tag="tag",a.Semver="semver",a))(i2||{});function bE(t){return t?Pgt.some(e=>!!t.match(e)):!1}function bh(t){t=PE(t);let e=t.indexOf("#");if(e===-1)return{repo:t,treeish:{protocol:"head",request:"HEAD"},extra:{}};let r=t.slice(0,e),o=t.slice(e+1);if(o.match(/^[a-z]+=/)){let a=SE.default.parse(o);for(let[p,h]of Object.entries(a))if(typeof h!="string")throw new Error(`Assertion failed: The ${p} parameter must be a literal string`);let n=Object.values(i2).find(p=>Object.hasOwn(a,p)),[u,A]=typeof n<"u"?[n,a[n]]:["head","HEAD"];for(let p of Object.values(i2))delete a[p];return{repo:r,treeish:{protocol:u,request:A},extra:a}}else{let a=o.indexOf(":"),[n,u]=a===-1?[null,o]:[o.slice(0,a),o.slice(a+1)];return{repo:r,treeish:{protocol:n,request:u},extra:{}}}}function Sgt(t){return G.makeLocator(t,PE(t.reference))}function j8(t,{configuration:e}){let r=PE(t,{git:!0});if(!sn.getNetworkSettings(`https://${(0,bde.default)(r).resource}`,{configuration:e}).enableNetwork)throw new Jt(80,`Request to '${r}' has been blocked because of your configuration settings`);return r}async function Qde(t,e){let r=j8(t,{configuration:e}),o=await q8("listing refs",["ls-remote",r],{cwd:e.startingCwd,env:kde()},{configuration:e,normalizedRepoUrl:r}),a=new Map,n=/^([a-f0-9]{40})\t([^\n]+)/gm,u;for(;(u=n.exec(o.stdout))!==null;)a.set(u[2],u[1]);return a}async function G8(t,e){let{repo:r,treeish:{protocol:o,request:a},extra:n}=bh(t),u=await Qde(r,e),A=(h,E)=>{switch(h){case"commit":{if(!E.match(/^[a-f0-9]{40}$/))throw new Error("Invalid commit hash");return SE.default.stringify({...n,commit:E})}case"head":{let I=u.get(E==="HEAD"?E:`refs/heads/${E}`);if(typeof I>"u")throw new Error(`Unknown head ("${E}")`);return SE.default.stringify({...n,commit:I})}case"tag":{let I=u.get(`refs/tags/${E}`);if(typeof I>"u")throw new Error(`Unknown tag ("${E}")`);return SE.default.stringify({...n,commit:I})}case"semver":{let I=Lr.validRange(E);if(!I)throw new Error(`Invalid range ("${E}")`);let v=new Map([...u.entries()].filter(([C])=>C.startsWith("refs/tags/")).map(([C,R])=>[H8.default.parse(C.slice(10)),R]).filter(C=>C[0]!==null)),x=H8.default.maxSatisfying([...v.keys()],I);if(x===null)throw new Error(`No matching range ("${E}")`);return SE.default.stringify({...n,commit:v.get(x)})}case null:{let I;if((I=p("commit",E))!==null||(I=p("tag",E))!==null||(I=p("head",E))!==null)return I;throw E.match(/^[a-f0-9]+$/)?new Error(`Couldn't resolve "${E}" as either a commit, a tag, or a head - if a commit, use the 40-characters commit hash`):new Error(`Couldn't resolve "${E}" as either a commit, a tag, or a head`)}default:throw new Error(`Invalid Git resolution protocol ("${h}")`)}},p=(h,E)=>{try{return A(h,E)}catch{return null}};return PE(`${r}#${A(o,a)}`)}async function Y8(t,e){return await e.getLimit("cloneConcurrency")(async()=>{let{repo:r,treeish:{protocol:o,request:a}}=bh(t);if(o!=="commit")throw new Error("Invalid treeish protocol when cloning");let n=j8(r,{configuration:e}),u=await oe.mktempPromise(),A={cwd:u,env:kde()};return await q8("cloning the repository",["clone","-c core.autocrlf=false",n,ue.fromPortablePath(u)],A,{configuration:e,normalizedRepoUrl:n}),await q8("switching branch",["checkout",`${a}`],A,{configuration:e,normalizedRepoUrl:n}),u})}async function Fde(t){let e,r=t;do{if(e=r,await oe.existsPromise(K.join(e,".git")))return e;r=K.dirname(e)}while(r!==e);return null}async function Rde(t,{baseRefs:e}){if(e.length===0)throw new st("Can't run this command with zero base refs specified.");let r=[];for(let A of e){let{code:p}=await Ur.execvp("git",["merge-base",A,"HEAD"],{cwd:t});p===0&&r.push(A)}if(r.length===0)throw new st(`No ancestor could be found between any of HEAD and ${e.join(", ")}`);let{stdout:o}=await Ur.execvp("git",["merge-base","HEAD",...r],{cwd:t,strict:!0}),a=o.trim(),{stdout:n}=await Ur.execvp("git",["show","--quiet","--pretty=format:%s",a],{cwd:t,strict:!0}),u=n.trim();return{hash:a,title:u}}async function Tde(t,{base:e,project:r}){let o=He.buildIgnorePattern(r.configuration.get("changesetIgnorePatterns")),{stdout:a}=await Ur.execvp("git",["diff","--name-only",`${e}`],{cwd:t,strict:!0}),n=a.split(/\r\n|\r|\n/).filter(h=>h.length>0).map(h=>K.resolve(t,ue.toPortablePath(h))),{stdout:u}=await Ur.execvp("git",["ls-files","--others","--exclude-standard"],{cwd:t,strict:!0}),A=u.split(/\r\n|\r|\n/).filter(h=>h.length>0).map(h=>K.resolve(t,ue.toPortablePath(h))),p=[...new Set([...n,...A].sort())];return o?p.filter(h=>!K.relative(r.cwd,h).match(o)):p}async function bgt({ref:t,project:e}){if(e.configuration.projectCwd===null)throw new st("This command can only be run from within a Yarn project");let r=[K.resolve(e.cwd,dr.lockfile),K.resolve(e.cwd,e.configuration.get("cacheFolder")),K.resolve(e.cwd,e.configuration.get("installStatePath")),K.resolve(e.cwd,e.configuration.get("virtualFolder"))];await e.configuration.triggerHook(u=>u.populateYarnPaths,e,u=>{u!=null&&r.push(u)});let o=await Fde(e.configuration.projectCwd);if(o==null)throw new st("This command can only be run on Git repositories");let a=await Rde(o,{baseRefs:typeof t=="string"?[t]:e.configuration.get("changesetBaseRefs")}),n=await Tde(o,{base:a.hash,project:e});return new Set(He.mapAndFilter(n,u=>{let A=e.tryWorkspaceByFilePath(u);return A===null?He.mapAndFilter.skip:r.some(p=>u.startsWith(p))?He.mapAndFilter.skip:A}))}async function q8(t,e,r,{configuration:o,normalizedRepoUrl:a}){try{return await Ur.execvp("git",e,{...r,strict:!0})}catch(n){if(!(n instanceof Ur.ExecError))throw n;let u=n.reportExtra,A=n.stderr.toString();throw new Jt(1,`Failed ${t}`,p=>{p.reportError(1,` ${pe.prettyField(o,{label:"Repository URL",value:pe.tuple(pe.Type.URL,a)})}`);for(let h of A.matchAll(/^(.+?): (.*)$/gm)){let[,E,I]=h;E=E.toLowerCase();let v=E==="error"?"Error":`${(0,xde.default)(E)} Error`;p.reportError(1,` ${pe.prettyField(o,{label:v,value:pe.tuple(pe.Type.NO_HINT,I)})}`)}u?.(p)})}}var s2=class{supports(e,r){return bE(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,a=new Map(r.checksums);a.set(e.locatorHash,o);let n={...r,checksums:a},u=await this.downloadHosted(e,n);if(u!==null)return u;let[A,p,h]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote repository`),loader:()=>this.cloneFromRemote(e,n),...r.cacheOptions});return{packageFs:A,releaseFs:p,prefixPath:G.getIdentVendorPath(e),checksum:h}}async downloadHosted(e,r){return r.project.configuration.reduceHook(o=>o.fetchHostedRepository,null,e,r)}async cloneFromRemote(e,r){let o=bh(e.reference),a=await Y8(e.reference,r.project.configuration),n=K.resolve(a,o.extra.cwd??It.dot),u=K.join(n,"package.tgz");await An.prepareExternalProject(n,u,{configuration:r.project.configuration,report:r.report,workspace:o.extra.workspace,locator:e});let A=await oe.readFilePromise(u);return await He.releaseAfterUseAsync(async()=>await $i.convertToZip(A,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1}))}};Ge();Ge();var o2=class{supportsDescriptor(e,r){return bE(e.range)}supportsLocator(e,r){return bE(e.reference)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=await G8(e.range,o.project.configuration);return[G.makeLocator(e,a)]}async getSatisfying(e,r,o,a){let n=bh(e.range);return{locators:o.filter(A=>{if(A.identHash!==e.identHash)return!1;let p=bh(A.reference);return!(n.repo!==p.repo||n.treeish.protocol==="commit"&&n.treeish.request!==p.treeish.request)}),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await He.releaseAfterUseAsync(async()=>await Ut.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var xgt={configuration:{changesetBaseRefs:{description:"The base git refs that the current HEAD is compared against when detecting changes. Supports git branches, tags, and commits.",type:"STRING",isArray:!0,isNullable:!1,default:["master","origin/master","upstream/master","main","origin/main","upstream/main"]},changesetIgnorePatterns:{description:"Array of glob patterns; files matching them will be ignored when fetching the changed files",type:"STRING",default:[],isArray:!0},cloneConcurrency:{description:"Maximal number of concurrent clones",type:"NUMBER",default:2}},fetchers:[s2],resolvers:[o2]};var kgt=xgt;qt();var xE=class extends ut{constructor(){super(...arguments);this.since=ge.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.recursive=ge.Boolean("-R,--recursive",!1,{description:"Find packages via dependencies/devDependencies instead of using the workspaces field"});this.noPrivate=ge.Boolean("--no-private",{description:"Exclude workspaces that have the private field set to true"});this.verbose=ge.Boolean("-v,--verbose",!1,{description:"Also return the cross-dependencies between workspaces"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["workspaces","list"]]}static{this.usage=it.Usage({category:"Workspace-related commands",description:"list all available workspaces",details:"\n This command will print the list of all workspaces in the project.\n\n - If `--since` is set, Yarn will only list workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `--no-private` is set, Yarn will not list any workspaces that have the `private` field set to `true`.\n\n - If both the `-v,--verbose` and `--json` options are set, Yarn will also return the cross-dependencies between each workspaces (useful when you wish to automatically generate Buck / Bazel rules).\n "})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd);return(await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{let u=this.since?await ia.fetchChangedWorkspaces({ref:this.since,project:o}):o.workspaces,A=new Set(u);if(this.recursive)for(let p of[...u].map(h=>h.getRecursiveWorkspaceDependents()))for(let h of p)A.add(h);for(let p of A){let{manifest:h}=p;if(h.private&&this.noPrivate)continue;let E;if(this.verbose){let I=new Set,v=new Set;for(let x of Ut.hardDependencies)for(let[C,R]of h.getForScope(x)){let L=o.tryWorkspaceByDescriptor(R);L===null?o.workspacesByIdent.has(C)&&v.add(R):I.add(L)}E={workspaceDependencies:Array.from(I).map(x=>x.relativeCwd),mismatchedWorkspaceDependencies:Array.from(v).map(x=>G.stringifyDescriptor(x))}}n.reportInfo(null,`${p.relativeCwd}`),n.reportJson({location:p.relativeCwd,name:h.name?G.stringifyIdent(h.name):null,...E})}})).exitCode()}};Ge();Ge();qt();var kE=class extends ut{constructor(){super(...arguments);this.workspaceName=ge.String();this.commandName=ge.String();this.args=ge.Proxy()}static{this.paths=[["workspace"]]}static{this.usage=it.Usage({category:"Workspace-related commands",description:"run a command within the specified workspace",details:` + This command will run a given sub-command on a single workspace. + `,examples:[["Add a package to a single workspace","yarn workspace components add -D react"],["Run build script on a single workspace","yarn workspace components run build"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);let n=o.workspaces,u=new Map(n.map(p=>[G.stringifyIdent(p.anchoredLocator),p])),A=u.get(this.workspaceName);if(A===void 0){let p=Array.from(u.keys()).sort();throw new st(`Workspace '${this.workspaceName}' not found. Did you mean any of the following: + - ${p.join(` + - `)}?`)}return this.cli.run([this.commandName,...this.args],{cwd:A.cwd})}};var Qgt={configuration:{enableImmutableInstalls:{description:"If true (the default on CI), prevents the install command from modifying the lockfile",type:"BOOLEAN",default:Nde.isCI},defaultSemverRangePrefix:{description:"The default save prefix: '^', '~' or ''",type:"STRING",values:["^","~",""],default:"^"},preferReuse:{description:"If true, `yarn add` will attempt to reuse the most common dependency range in other workspaces.",type:"BOOLEAN",default:!1}},commands:[Ky,Vy,zy,Jy,IE,pE,sE,xE,$y,eE,tE,rE,Yy,Wy,Xy,Zy,nE,iE,oE,aE,lE,cE,BE,uE,AE,gE,hE,dE,fE,mE,yE,EE,CE,wE,vE,DE,kE]},Fgt=Qgt;var Z8={};Vt(Z8,{default:()=>Tgt});Ge();var xt={optional:!0},V8=[["@tailwindcss/aspect-ratio@<0.2.1",{peerDependencies:{tailwindcss:"^2.0.2"}}],["@tailwindcss/line-clamp@<0.2.1",{peerDependencies:{tailwindcss:"^2.0.2"}}],["@fullhuman/postcss-purgecss@3.1.3 || 3.1.3-alpha.0",{peerDependencies:{postcss:"^8.0.0"}}],["@samverschueren/stream-to-observable@<0.3.1",{peerDependenciesMeta:{rxjs:xt,zenObservable:xt}}],["any-observable@<0.5.1",{peerDependenciesMeta:{rxjs:xt,zenObservable:xt}}],["@pm2/agent@<1.0.4",{dependencies:{debug:"*"}}],["debug@<4.2.0",{peerDependenciesMeta:{"supports-color":xt}}],["got@<11",{dependencies:{"@types/responselike":"^1.0.0","@types/keyv":"^3.1.1"}}],["cacheable-lookup@<4.1.2",{dependencies:{"@types/keyv":"^3.1.1"}}],["http-link-dataloader@*",{peerDependencies:{graphql:"^0.13.1 || ^14.0.0"}}],["typescript-language-server@*",{dependencies:{"vscode-jsonrpc":"^5.0.1","vscode-languageserver-protocol":"^3.15.0"}}],["postcss-syntax@*",{peerDependenciesMeta:{"postcss-html":xt,"postcss-jsx":xt,"postcss-less":xt,"postcss-markdown":xt,"postcss-scss":xt}}],["jss-plugin-rule-value-function@<=10.1.1",{dependencies:{"tiny-warning":"^1.0.2"}}],["ink-select-input@<4.1.0",{peerDependencies:{react:"^16.8.2"}}],["license-webpack-plugin@<2.3.18",{peerDependenciesMeta:{webpack:xt}}],["snowpack@>=3.3.0",{dependencies:{"node-gyp":"^7.1.0"}}],["promise-inflight@*",{peerDependenciesMeta:{bluebird:xt}}],["reactcss@*",{peerDependencies:{react:"*"}}],["react-color@<=2.19.0",{peerDependencies:{react:"*"}}],["gatsby-plugin-i18n@*",{dependencies:{ramda:"^0.24.1"}}],["useragent@^2.0.0",{dependencies:{request:"^2.88.0",yamlparser:"0.0.x",semver:"5.5.x"}}],["@apollographql/apollo-tools@<=0.5.2",{peerDependencies:{graphql:"^14.2.1 || ^15.0.0"}}],["material-table@^2.0.0",{dependencies:{"@babel/runtime":"^7.11.2"}}],["@babel/parser@*",{dependencies:{"@babel/types":"^7.8.3"}}],["fork-ts-checker-webpack-plugin@<=6.3.4",{peerDependencies:{eslint:">= 6",typescript:">= 2.7",webpack:">= 4","vue-template-compiler":"*"},peerDependenciesMeta:{eslint:xt,"vue-template-compiler":xt}}],["rc-animate@<=3.1.1",{peerDependencies:{react:">=16.9.0","react-dom":">=16.9.0"}}],["react-bootstrap-table2-paginator@*",{dependencies:{classnames:"^2.2.6"}}],["react-draggable@<=4.4.3",{peerDependencies:{react:">= 16.3.0","react-dom":">= 16.3.0"}}],["apollo-upload-client@<14",{peerDependencies:{graphql:"14 - 15"}}],["react-instantsearch-core@<=6.7.0",{peerDependencies:{algoliasearch:">= 3.1 < 5"}}],["react-instantsearch-dom@<=6.7.0",{dependencies:{"react-fast-compare":"^3.0.0"}}],["ws@<7.2.1",{peerDependencies:{bufferutil:"^4.0.1","utf-8-validate":"^5.0.2"},peerDependenciesMeta:{bufferutil:xt,"utf-8-validate":xt}}],["react-portal@<4.2.2",{peerDependencies:{"react-dom":"^15.0.0-0 || ^16.0.0-0 || ^17.0.0-0"}}],["react-scripts@<=4.0.1",{peerDependencies:{react:"*"}}],["testcafe@<=1.10.1",{dependencies:{"@babel/plugin-transform-for-of":"^7.12.1","@babel/runtime":"^7.12.5"}}],["testcafe-legacy-api@<=4.2.0",{dependencies:{"testcafe-hammerhead":"^17.0.1","read-file-relative":"^1.2.0"}}],["@google-cloud/firestore@<=4.9.3",{dependencies:{protobufjs:"^6.8.6"}}],["gatsby-source-apiserver@*",{dependencies:{"babel-polyfill":"^6.26.0"}}],["@webpack-cli/package-utils@<=1.0.1-alpha.4",{dependencies:{"cross-spawn":"^7.0.3"}}],["gatsby-remark-prismjs@<3.3.28",{dependencies:{lodash:"^4"}}],["gatsby-plugin-favicon@*",{peerDependencies:{webpack:"*"}}],["gatsby-plugin-sharp@<=4.6.0-next.3",{dependencies:{debug:"^4.3.1"}}],["gatsby-react-router-scroll@<=5.6.0-next.0",{dependencies:{"prop-types":"^15.7.2"}}],["@rebass/forms@*",{dependencies:{"@styled-system/should-forward-prop":"^5.0.0"},peerDependencies:{react:"^16.8.6"}}],["rebass@*",{peerDependencies:{react:"^16.8.6"}}],["@ant-design/react-slick@<=0.28.3",{peerDependencies:{react:">=16.0.0"}}],["mqtt@<4.2.7",{dependencies:{duplexify:"^4.1.1"}}],["vue-cli-plugin-vuetify@<=2.0.3",{dependencies:{semver:"^6.3.0"},peerDependenciesMeta:{"sass-loader":xt,"vuetify-loader":xt}}],["vue-cli-plugin-vuetify@<=2.0.4",{dependencies:{"null-loader":"^3.0.0"}}],["vue-cli-plugin-vuetify@>=2.4.3",{peerDependencies:{vue:"*"}}],["@vuetify/cli-plugin-utils@<=0.0.4",{dependencies:{semver:"^6.3.0"},peerDependenciesMeta:{"sass-loader":xt}}],["@vue/cli-plugin-typescript@<=5.0.0-alpha.0",{dependencies:{"babel-loader":"^8.1.0"}}],["@vue/cli-plugin-typescript@<=5.0.0-beta.0",{dependencies:{"@babel/core":"^7.12.16"},peerDependencies:{"vue-template-compiler":"^2.0.0"},peerDependenciesMeta:{"vue-template-compiler":xt}}],["cordova-ios@<=6.3.0",{dependencies:{underscore:"^1.9.2"}}],["cordova-lib@<=10.0.1",{dependencies:{underscore:"^1.9.2"}}],["git-node-fs@*",{peerDependencies:{"js-git":"^0.7.8"},peerDependenciesMeta:{"js-git":xt}}],["consolidate@<0.16.0",{peerDependencies:{mustache:"^3.0.0"},peerDependenciesMeta:{mustache:xt}}],["consolidate@<=0.16.0",{peerDependencies:{velocityjs:"^2.0.1",tinyliquid:"^0.2.34","liquid-node":"^3.0.1",jade:"^1.11.0","then-jade":"*",dust:"^0.3.0","dustjs-helpers":"^1.7.4","dustjs-linkedin":"^2.7.5",swig:"^1.4.2","swig-templates":"^2.0.3","razor-tmpl":"^1.3.1",atpl:">=0.7.6",liquor:"^0.0.5",twig:"^1.15.2",ejs:"^3.1.5",eco:"^1.1.0-rc-3",jazz:"^0.0.18",jqtpl:"~1.1.0",hamljs:"^0.6.2",hamlet:"^0.3.3",whiskers:"^0.4.0","haml-coffee":"^1.14.1","hogan.js":"^3.0.2",templayed:">=0.2.3",handlebars:"^4.7.6",underscore:"^1.11.0",lodash:"^4.17.20",pug:"^3.0.0","then-pug":"*",qejs:"^3.0.5",walrus:"^0.10.1",mustache:"^4.0.1",just:"^0.1.8",ect:"^0.5.9",mote:"^0.2.0",toffee:"^0.3.6",dot:"^1.1.3","bracket-template":"^1.1.5",ractive:"^1.3.12",nunjucks:"^3.2.2",htmling:"^0.0.8","babel-core":"^6.26.3",plates:"~0.4.11","react-dom":"^16.13.1",react:"^16.13.1","arc-templates":"^0.5.3",vash:"^0.13.0",slm:"^2.0.0",marko:"^3.14.4",teacup:"^2.0.0","coffee-script":"^1.12.7",squirrelly:"^5.1.0",twing:"^5.0.2"},peerDependenciesMeta:{velocityjs:xt,tinyliquid:xt,"liquid-node":xt,jade:xt,"then-jade":xt,dust:xt,"dustjs-helpers":xt,"dustjs-linkedin":xt,swig:xt,"swig-templates":xt,"razor-tmpl":xt,atpl:xt,liquor:xt,twig:xt,ejs:xt,eco:xt,jazz:xt,jqtpl:xt,hamljs:xt,hamlet:xt,whiskers:xt,"haml-coffee":xt,"hogan.js":xt,templayed:xt,handlebars:xt,underscore:xt,lodash:xt,pug:xt,"then-pug":xt,qejs:xt,walrus:xt,mustache:xt,just:xt,ect:xt,mote:xt,toffee:xt,dot:xt,"bracket-template":xt,ractive:xt,nunjucks:xt,htmling:xt,"babel-core":xt,plates:xt,"react-dom":xt,react:xt,"arc-templates":xt,vash:xt,slm:xt,marko:xt,teacup:xt,"coffee-script":xt,squirrelly:xt,twing:xt}}],["vue-loader@<=16.3.3",{peerDependencies:{"@vue/compiler-sfc":"^3.0.8",webpack:"^4.1.0 || ^5.0.0-0"},peerDependenciesMeta:{"@vue/compiler-sfc":xt}}],["vue-loader@^16.7.0",{peerDependencies:{"@vue/compiler-sfc":"^3.0.8",vue:"^3.2.13"},peerDependenciesMeta:{"@vue/compiler-sfc":xt,vue:xt}}],["scss-parser@<=1.0.5",{dependencies:{lodash:"^4.17.21"}}],["query-ast@<1.0.5",{dependencies:{lodash:"^4.17.21"}}],["redux-thunk@<=2.3.0",{peerDependencies:{redux:"^4.0.0"}}],["skypack@<=0.3.2",{dependencies:{tar:"^6.1.0"}}],["@npmcli/metavuln-calculator@<2.0.0",{dependencies:{"json-parse-even-better-errors":"^2.3.1"}}],["bin-links@<2.3.0",{dependencies:{"mkdirp-infer-owner":"^1.0.2"}}],["rollup-plugin-polyfill-node@<=0.8.0",{peerDependencies:{rollup:"^1.20.0 || ^2.0.0"}}],["snowpack@<3.8.6",{dependencies:{"magic-string":"^0.25.7"}}],["elm-webpack-loader@*",{dependencies:{temp:"^0.9.4"}}],["winston-transport@<=4.4.0",{dependencies:{logform:"^2.2.0"}}],["jest-vue-preprocessor@*",{dependencies:{"@babel/core":"7.8.7","@babel/template":"7.8.6"},peerDependencies:{pug:"^2.0.4"},peerDependenciesMeta:{pug:xt}}],["redux-persist@*",{peerDependencies:{react:">=16"},peerDependenciesMeta:{react:xt}}],["sodium@>=3",{dependencies:{"node-gyp":"^3.8.0"}}],["babel-plugin-graphql-tag@<=3.1.0",{peerDependencies:{graphql:"^14.0.0 || ^15.0.0"}}],["@playwright/test@<=1.14.1",{dependencies:{"jest-matcher-utils":"^26.4.2"}}],...["babel-plugin-remove-graphql-queries@<3.14.0-next.1","babel-preset-gatsby-package@<1.14.0-next.1","create-gatsby@<1.14.0-next.1","gatsby-admin@<0.24.0-next.1","gatsby-cli@<3.14.0-next.1","gatsby-core-utils@<2.14.0-next.1","gatsby-design-tokens@<3.14.0-next.1","gatsby-legacy-polyfills@<1.14.0-next.1","gatsby-plugin-benchmark-reporting@<1.14.0-next.1","gatsby-plugin-graphql-config@<0.23.0-next.1","gatsby-plugin-image@<1.14.0-next.1","gatsby-plugin-mdx@<2.14.0-next.1","gatsby-plugin-netlify-cms@<5.14.0-next.1","gatsby-plugin-no-sourcemaps@<3.14.0-next.1","gatsby-plugin-page-creator@<3.14.0-next.1","gatsby-plugin-preact@<5.14.0-next.1","gatsby-plugin-preload-fonts@<2.14.0-next.1","gatsby-plugin-schema-snapshot@<2.14.0-next.1","gatsby-plugin-styletron@<6.14.0-next.1","gatsby-plugin-subfont@<3.14.0-next.1","gatsby-plugin-utils@<1.14.0-next.1","gatsby-recipes@<0.25.0-next.1","gatsby-source-shopify@<5.6.0-next.1","gatsby-source-wikipedia@<3.14.0-next.1","gatsby-transformer-screenshot@<3.14.0-next.1","gatsby-worker@<0.5.0-next.1"].map(t=>[t,{dependencies:{"@babel/runtime":"^7.14.8"}}]),["gatsby-core-utils@<2.14.0-next.1",{dependencies:{got:"8.3.2"}}],["gatsby-plugin-gatsby-cloud@<=3.1.0-next.0",{dependencies:{"gatsby-core-utils":"^2.13.0-next.0"}}],["gatsby-plugin-gatsby-cloud@<=3.2.0-next.1",{peerDependencies:{webpack:"*"}}],["babel-plugin-remove-graphql-queries@<=3.14.0-next.1",{dependencies:{"gatsby-core-utils":"^2.8.0-next.1"}}],["gatsby-plugin-netlify@3.13.0-next.1",{dependencies:{"gatsby-core-utils":"^2.13.0-next.0"}}],["clipanion-v3-codemod@<=0.2.0",{peerDependencies:{jscodeshift:"^0.11.0"}}],["react-live@*",{peerDependencies:{"react-dom":"*",react:"*"}}],["webpack@<4.44.1",{peerDependenciesMeta:{"webpack-cli":xt,"webpack-command":xt}}],["webpack@<5.0.0-beta.23",{peerDependenciesMeta:{"webpack-cli":xt}}],["webpack-dev-server@<3.10.2",{peerDependenciesMeta:{"webpack-cli":xt}}],["@docusaurus/responsive-loader@<1.5.0",{peerDependenciesMeta:{sharp:xt,jimp:xt}}],["eslint-module-utils@*",{peerDependenciesMeta:{"eslint-import-resolver-node":xt,"eslint-import-resolver-typescript":xt,"eslint-import-resolver-webpack":xt,"@typescript-eslint/parser":xt}}],["eslint-plugin-import@*",{peerDependenciesMeta:{"@typescript-eslint/parser":xt}}],["critters-webpack-plugin@<3.0.2",{peerDependenciesMeta:{"html-webpack-plugin":xt}}],["terser@<=5.10.0",{dependencies:{acorn:"^8.5.0"}}],["babel-preset-react-app@10.0.x <10.0.2",{dependencies:{"@babel/plugin-proposal-private-property-in-object":"^7.16.7"}}],["eslint-config-react-app@*",{peerDependenciesMeta:{typescript:xt}}],["@vue/eslint-config-typescript@<11.0.0",{peerDependenciesMeta:{typescript:xt}}],["unplugin-vue2-script-setup@<0.9.1",{peerDependencies:{"@vue/composition-api":"^1.4.3","@vue/runtime-dom":"^3.2.26"}}],["@cypress/snapshot@*",{dependencies:{debug:"^3.2.7"}}],["auto-relay@<=0.14.0",{peerDependencies:{"reflect-metadata":"^0.1.13"}}],["vue-template-babel-compiler@<1.2.0",{peerDependencies:{"vue-template-compiler":"^2.6.0"}}],["@parcel/transformer-image@<2.5.0",{peerDependencies:{"@parcel/core":"*"}}],["@parcel/transformer-js@<2.5.0",{peerDependencies:{"@parcel/core":"*"}}],["parcel@*",{peerDependenciesMeta:{"@parcel/core":xt}}],["react-scripts@*",{peerDependencies:{eslint:"*"}}],["focus-trap-react@^8.0.0",{dependencies:{tabbable:"^5.3.2"}}],["react-rnd@<10.3.7",{peerDependencies:{react:">=16.3.0","react-dom":">=16.3.0"}}],["connect-mongo@<5.0.0",{peerDependencies:{"express-session":"^1.17.1"}}],["vue-i18n@<9",{peerDependencies:{vue:"^2"}}],["vue-router@<4",{peerDependencies:{vue:"^2"}}],["unified@<10",{dependencies:{"@types/unist":"^2.0.0"}}],["react-github-btn@<=1.3.0",{peerDependencies:{react:">=16.3.0"}}],["react-dev-utils@*",{peerDependencies:{typescript:">=2.7",webpack:">=4"},peerDependenciesMeta:{typescript:xt}}],["@asyncapi/react-component@<=1.0.0-next.39",{peerDependencies:{react:">=16.8.0","react-dom":">=16.8.0"}}],["xo@*",{peerDependencies:{webpack:">=1.11.0"},peerDependenciesMeta:{webpack:xt}}],["babel-plugin-remove-graphql-queries@<=4.20.0-next.0",{dependencies:{"@babel/types":"^7.15.4"}}],["gatsby-plugin-page-creator@<=4.20.0-next.1",{dependencies:{"fs-extra":"^10.1.0"}}],["gatsby-plugin-utils@<=3.14.0-next.1",{dependencies:{fastq:"^1.13.0"},peerDependencies:{graphql:"^15.0.0"}}],["gatsby-plugin-mdx@<3.1.0-next.1",{dependencies:{mkdirp:"^1.0.4"}}],["gatsby-plugin-mdx@^2",{peerDependencies:{gatsby:"^3.0.0-next"}}],["fdir@<=5.2.0",{peerDependencies:{picomatch:"2.x"},peerDependenciesMeta:{picomatch:xt}}],["babel-plugin-transform-typescript-metadata@<=0.3.2",{peerDependencies:{"@babel/core":"^7","@babel/traverse":"^7"},peerDependenciesMeta:{"@babel/traverse":xt}}],["graphql-compose@>=9.0.10",{peerDependencies:{graphql:"^14.2.0 || ^15.0.0 || ^16.0.0"}}],["vite-plugin-vuetify@<=1.0.2",{peerDependencies:{vue:"^3.0.0"}}],["webpack-plugin-vuetify@<=2.0.1",{peerDependencies:{vue:"^3.2.6"}}],["eslint-import-resolver-vite@<2.0.1",{dependencies:{debug:"^4.3.4",resolve:"^1.22.8"}}]];var z8;function Lde(){return typeof z8>"u"&&(z8=ve("zlib").brotliDecompressSync(Buffer.from("G7weAByFTVk3Vs7UfHhq4yykgEM7pbW7TI43SG2S5tvGrwHBAzdz+s/npQ6tgEvobvxisrPIadkXeUAJotBn5bDZ5kAhcRqsIHe3F75Walet5hNalwgFDtxb0BiDUjiUQkjG0yW2hto9HPgiCkm316d6bC0kST72YN7D7rfkhCE9x4J0XwB0yavalxpUu2t9xszHrmtwalOxT7VslsxWcB1qpqZwERUra4psWhTV8BgwWeizurec82Caf1ABL11YMfbf8FJ9JBceZOkgmvrQPbC9DUldX/yMbmX06UQluCEjSwUoyO+EZPIjofr+/oAZUck2enraRD+oWLlnlYnj8xB+gwSo9lmmks4fXv574qSqcWA6z21uYkzMu3EWj+K23RxeQlLqiE35/rC8GcS4CGkKHKKq+zAIQwD9iRDNfiAqueLLpicFFrNsAI4zeTD/eO9MHcnRa5m8UT+M2+V+AkFST4BlKneiAQRSdST8KEAIyFlULt6wa9EBd0Ds28VmpaxquJdVt+nwdEs5xUskI13OVtFyY0UrQIRAlCuvvWivvlSKQfTO+2Q8OyUR1W5RvetaPz4jD27hdtwHFFA1Ptx6Ee/t2cY2rg2G46M1pNDRf2pWhvpy8pqMnuI3++4OF3+7OFIWXGjh+o7Nr2jNvbiYcQdQS1h903/jVFgOpA0yJ78z+x759bFA0rq+6aY5qPB4FzS3oYoLupDUhD9nDz6F6H7hpnlMf18KNKDu4IKjTWwrAnY6MFQw1W6ymOALHlFyCZmQhldg1MQHaMVVQTVgDC60TfaBqG++Y8PEoFhN/PBTZT175KNP/BlHDYGOOBmnBdzqJKplZ/ljiVG0ZBzfqeBRrrUkn6rA54462SgiliKoYVnbeptMdXNfAuaupIEi0bApF10TlgHfmEJAPUVidRVFyDupSem5po5vErPqWKhKbUIp0LozpYsIKK57dM/HKr+nguF+7924IIWMICkQ8JUigs9D+W+c4LnNoRtPPKNRUiCYmP+Jfo2lfKCKw8qpraEeWU3uiNRO6zcyKQoXPR5htmzzLznke7b4YbXW3I1lIRzmgG02Udb58U+7TpwyN7XymCgH+wuPDthZVQvRZuEP+SnLtMicz9m5zASWOBiAcLmkuFlTKuHspSIhCBD0yUPKcxu81A+4YD78rA2vtwsUEday9WNyrShyrl60rWmA+SmbYZkQOwFJWArxRYYc5jGhA5ikxYw1rx3ei4NmeX/lKiwpZ9Ln1tV2Ae7sArvxuVLbJjqJRjW1vFXAyHpvLG+8MJ6T2Ubx5M2KDa2SN6vuIGxJ9WQM9Mk3Q7aCNiZONXllhqq24DmoLbQfW2rYWsOgHWjtOmIQMyMKdiHZDjoyIq5+U700nZ6odJAoYXPQBvFNiQ78d5jaXliBqLTJEqUCwi+LiH2mx92EmNKDsJL74Z613+3lf20pxkV1+erOrjj8pW00vsPaahKUM+05ssd5uwM7K482KWEf3TCwlg/o3e5ngto7qSMz7YteIgCsF1UOcsLk7F7MxWbvrPMY473ew0G+noVL8EPbkmEMftMSeL6HFub/zy+2JQ==","base64")).toString()),z8}var J8;function Mde(){return typeof J8>"u"&&(J8=ve("zlib").brotliDecompressSync(Buffer.from("G8MSIIzURnVBnObTcvb3XE6v2S9Qgc2K801Oa5otNKEtK8BINZNcaQHy+9/vf/WXBimwutXC33P2DPc64pps5rz7NGGWaOKNSPL4Y2KRE8twut2lFOIN+OXPtRmPMRhMTILib2bEQx43az2I5d3YS8Roa5UZpF/ujHb3Djd3GDvYUfvFYSUQ39vb2cmifp/rgB4J/65JK3wRBTvMBoNBmn3mbXC63/gbBkW/2IRPri0O8bcsRBsmarF328pAln04nyJFkwUAvNu934supAqLtyerZZpJ8I8suJHhf/ocMV+scKwa8NOiDKIPXw6Ex/EEZD6TEGaW8N5zvNHYF10l6Lfooj7D5W2k3dgvQSbp2Wv8TGOayS978gxlOLVjTGXs66ozewbrjwElLtyrYNnWTfzzdEutgROUFPVMhnMoy8EjJLLlWwIEoySxliim9kYW30JUHiPVyjt0iAw/ZpPmCbUCltYPnq6ZNblIKhTNhqS/oqC9iya5sGKZTOVsTEg34n92uZTf2iPpcZih8rPW8CzA+adIGmyCPcKdLMsBLShd+zuEbTrqpwuh+DLmracZcjPC5Sdf5odDAhKpFuOsQS67RT+1VgWWygSv3YwxDnylc04/PYuaMeIzhBkLrvs7e/OUzRTF56MmfY6rI63QtEjEQzq637zQqJ39nNhu3NmoRRhW/086bHGBUtx0PE0j3aEGvkdh9WJC8y8j8mqqke9/dQ5la+Q3ba4RlhvTbnfQhPDDab3tUifkjKuOsp13mXEmO00Mu88F/M67R7LXfoFDFLNtgCSWjWX+3Jn1371pJTK9xPBiMJafvDjtFyAzu8rxeQ0TKMQXNPs5xxiBOd+BRJP8KP88XPtJIbZKh/cdW8KvBUkpqKpGoiIaA32c3/JnQr4efXt85mXvidOvn/eU3Pase1typLYBalJ14mCso9h79nuMOuCa/kZAOkJHmTjP5RM2WNoPasZUAnT1TAE/NH25hUxcQv6hQWR/m1PKk4ooXMcM4SR1iYU3fUohvqk4RY2hbmTVVIXv6TvqO+0doOjgeVFAcom+RlwJQmOVH7pr1Q9LoJT6n1DeQEB+NHygsATbIwTcOKZlJsY8G4+suX1uQLjUWwLjjs0mvSvZcLTpIGAekeR7GCgl8eo3ndAqEe2XCav4huliHjdbIPBsGJuPX7lrO9HX1UbXRH5opOe1x6JsOSgHZR+EaxuXVhpLLxm6jk1LJtZfHSc6BKPun3CpYYVMJGwEUyk8MTGG0XL5MfEwaXpnc9TKnBmlGn6nHiGREc3ysn47XIBDzA+YvFdjZzVIEDcKGpS6PbUJehFRjEne8D0lVU1XuRtlgszq6pTNlQ/3MzNOEgCWPyTct22V2mEi2krizn5VDo9B19/X2DB3hCGRMM7ONbtnAcIx/OWB1u5uPbW1gsH8irXxT/IzG0PoXWYjhbMsH3KTuoOl5o17PulcgvsfTSnKFM354GWI8luqZnrswWjiXy3G+Vbyo1KMopFmmvBwNELgaS8z8dNZchx/Cl/xjddxhMcyqtzFyONb2Zdu90NkI8pAeufe7YlXrp53v8Dj/l8vWeVspRKBGXScBBPI/HinSTGmLDOGGOCIyH0JFdOZx0gWsacNlQLJMIrBhqRxXxHF/5pseWwejlAAvZ3klZSDSYY8mkToaWejXhgNomeGtx1DTLEUFMRkgF5yFB22WYdJnaWN14r1YJj81hGi45+jrADS5nYRhCiSlCJJ1nL8pYX+HDSMhdTEWyRcgHVp/IsUIZYMfT+YYncUQPgcxNGCHfZ88vDdrcUuaGIl6zhAsiaq7R5dfqrqXH/JcBhfjT8D0azayIyEz75Nxp6YkcyDxlJq3EXnJUpqDohJJOysL1t1uNiHESlvsxPb5cpbW0+ICZqJmUZus1BMW0F5IVBODLIo2zHHjA0=","base64")).toString()),J8}var X8;function Ode(){return typeof X8>"u"&&(X8=ve("zlib").brotliDecompressSync(Buffer.from("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","base64")).toString()),X8}var Ude=new Map([[G.makeIdent(null,"fsevents").identHash,Lde],[G.makeIdent(null,"resolve").identHash,Mde],[G.makeIdent(null,"typescript").identHash,Ode]]),Rgt={hooks:{registerPackageExtensions:async(t,e)=>{for(let[r,o]of V8)e(G.parseDescriptor(r,!0),o)},getBuiltinPatch:async(t,e)=>{let r="compat/";if(!e.startsWith(r))return;let o=G.parseIdent(e.slice(r.length)),a=Ude.get(o.identHash)?.();return typeof a<"u"?a:null},reduceDependency:async(t,e,r,o)=>typeof Ude.get(t.identHash)>"u"?t:G.makeDescriptor(t,G.makeRange({protocol:"patch:",source:G.stringifyDescriptor(t),selector:`optional!builtin<compat/${G.stringifyIdent(t)}>`,params:null}))}},Tgt=Rgt;var dH={};Vt(dH,{ConstraintsCheckCommand:()=>OE,ConstraintsQueryCommand:()=>LE,ConstraintsSourceCommand:()=>ME,default:()=>adt});Ge();Ge();l2();var FE=class{constructor(e){this.project=e}createEnvironment(){let e=new QE(["cwd","ident"]),r=new QE(["workspace","type","ident"]),o=new QE(["ident"]),a={manifestUpdates:new Map,reportedErrors:new Map},n=new Map,u=new Map;for(let A of this.project.storedPackages.values()){let p=Array.from(A.peerDependencies.values(),h=>[G.stringifyIdent(h),h.range]);n.set(A.locatorHash,{workspace:null,ident:G.stringifyIdent(A),version:A.version,dependencies:new Map,peerDependencies:new Map(p.filter(([h])=>A.peerDependenciesMeta.get(h)?.optional!==!0)),optionalPeerDependencies:new Map(p.filter(([h])=>A.peerDependenciesMeta.get(h)?.optional===!0))})}for(let A of this.project.storedPackages.values()){let p=n.get(A.locatorHash);p.dependencies=new Map(Array.from(A.dependencies.values(),h=>{let E=this.project.storedResolutions.get(h.descriptorHash);if(typeof E>"u")throw new Error("Assertion failed: The resolution should have been registered");let I=n.get(E);if(typeof I>"u")throw new Error("Assertion failed: The package should have been registered");return[G.stringifyIdent(h),I]})),p.dependencies.delete(p.ident)}for(let A of this.project.workspaces){let p=G.stringifyIdent(A.anchoredLocator),h=A.manifest.exportTo({}),E=n.get(A.anchoredLocator.locatorHash);if(typeof E>"u")throw new Error("Assertion failed: The package should have been registered");let I=(R,L,{caller:U=Xi.getCaller()}={})=>{let z=a2(R),te=He.getMapWithDefault(a.manifestUpdates,A.cwd),ae=He.getMapWithDefault(te,z),le=He.getSetWithDefault(ae,L);U!==null&&le.add(U)},v=R=>I(R,void 0,{caller:Xi.getCaller()}),x=R=>{He.getArrayWithDefault(a.reportedErrors,A.cwd).push(R)},C=e.insert({cwd:A.relativeCwd,ident:p,manifest:h,pkg:E,set:I,unset:v,error:x});u.set(A,C);for(let R of Ut.allDependencies)for(let L of A.manifest[R].values()){let U=G.stringifyIdent(L),z=()=>{I([R,U],void 0,{caller:Xi.getCaller()})},te=le=>{I([R,U],le,{caller:Xi.getCaller()})},ae=null;if(R!=="peerDependencies"&&(R!=="dependencies"||!A.manifest.devDependencies.has(L.identHash))){let le=A.anchoredPackage.dependencies.get(L.identHash);if(le){if(typeof le>"u")throw new Error("Assertion failed: The dependency should have been registered");let ce=this.project.storedResolutions.get(le.descriptorHash);if(typeof ce>"u")throw new Error("Assertion failed: The resolution should have been registered");let Ce=n.get(ce);if(typeof Ce>"u")throw new Error("Assertion failed: The package should have been registered");ae=Ce}}r.insert({workspace:C,ident:U,range:L.range,type:R,resolution:ae,update:te,delete:z,error:x})}}for(let A of this.project.storedPackages.values()){let p=this.project.tryWorkspaceByLocator(A);if(!p)continue;let h=u.get(p);if(typeof h>"u")throw new Error("Assertion failed: The workspace should have been registered");let E=n.get(A.locatorHash);if(typeof E>"u")throw new Error("Assertion failed: The package should have been registered");E.workspace=h}return{workspaces:e,dependencies:r,packages:o,result:a}}async process(){let e=this.createEnvironment(),r={Yarn:{workspace:a=>e.workspaces.find(a)[0]??null,workspaces:a=>e.workspaces.find(a),dependency:a=>e.dependencies.find(a)[0]??null,dependencies:a=>e.dependencies.find(a),package:a=>e.packages.find(a)[0]??null,packages:a=>e.packages.find(a)}},o=await this.project.loadUserConfig();return o?.constraints?(await o.constraints(r),e.result):null}};Ge();Ge();qt();var LE=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.query=ge.String()}static{this.paths=[["constraints","query"]]}static{this.usage=it.Usage({category:"Constraints-related commands",description:"query the constraints fact database",details:` + This command will output all matches to the given prolog query. + `,examples:[["List all dependencies throughout the workspace","yarn constraints query 'workspace_has_dependency(_, DependencyName, _, _).'"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(f2(),A2)),o=await Ke.find(this.context.cwd,this.context.plugins),{project:a}=await kt.find(o,this.context.cwd),n=await r.find(a),u=this.query;return u.endsWith(".")||(u=`${u}.`),(await Rt.start({configuration:o,json:this.json,stdout:this.context.stdout},async p=>{for await(let h of n.query(u)){let E=Array.from(Object.entries(h)),I=E.length,v=E.reduce((x,[C])=>Math.max(x,C.length),0);for(let x=0;x<I;x++){let[C,R]=E[x];p.reportInfo(null,`${sdt(x,I)}${C.padEnd(v," ")} = ${idt(R)}`)}p.reportJson(h)}})).exitCode()}};function idt(t){return typeof t!="string"?`${t}`:t.match(/^[a-zA-Z][a-zA-Z0-9_]+$/)?t:`'${t}'`}function sdt(t,e){let r=t===0,o=t===e-1;return r&&o?"":r?"\u250C ":o?"\u2514 ":"\u2502 "}Ge();qt();var ME=class extends ut{constructor(){super(...arguments);this.verbose=ge.Boolean("-v,--verbose",!1,{description:"Also print the fact database automatically compiled from the workspace manifests"})}static{this.paths=[["constraints","source"]]}static{this.usage=it.Usage({category:"Constraints-related commands",description:"print the source code for the constraints",details:"\n This command will print the Prolog source code used by the constraints engine. Adding the `-v,--verbose` flag will print the *full* source code, including the fact database automatically compiled from the workspace manifests.\n ",examples:[["Prints the source code","yarn constraints source"],["Print the source code and the fact database","yarn constraints source -v"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(f2(),A2)),o=await Ke.find(this.context.cwd,this.context.plugins),{project:a}=await kt.find(o,this.context.cwd),n=await r.find(a);this.context.stdout.write(this.verbose?n.fullSource:n.source)}};Ge();Ge();qt();l2();var OE=class extends ut{constructor(){super(...arguments);this.fix=ge.Boolean("--fix",!1,{description:"Attempt to automatically fix unambiguous issues, following a multi-pass process"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["constraints"]]}static{this.usage=it.Usage({category:"Constraints-related commands",description:"check that the project constraints are met",details:` + This command will run constraints on your project and emit errors for each one that is found but isn't met. If any error is emitted the process will exit with a non-zero exit code. + + If the \`--fix\` flag is used, Yarn will attempt to automatically fix the issues the best it can, following a multi-pass process (with a maximum of 10 iterations). Some ambiguous patterns cannot be autofixed, in which case you'll have to manually specify the right resolution. + + For more information as to how to write constraints, please consult our dedicated page on our website: https://yarnpkg.com/features/constraints. + `,examples:[["Check that all constraints are satisfied","yarn constraints"],["Autofix all unmet constraints","yarn constraints --fix"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd);await o.restoreInstallState();let a=await o.loadUserConfig(),n;if(a?.constraints)n=new FE(o);else{let{Constraints:h}=await Promise.resolve().then(()=>(f2(),A2));n=await h.find(o)}let u,A=!1,p=!1;for(let h=this.fix?10:1;h>0;--h){let E=await n.process();if(!E)break;let{changedWorkspaces:I,remainingErrors:v}=ik(o,E,{fix:this.fix}),x=[];for(let[C,R]of I){let L=C.manifest.indent;C.manifest=new Ut,C.manifest.indent=L,C.manifest.load(R),x.push(C.persistManifest())}if(await Promise.all(x),!(I.size>0&&h>1)){u=Wde(v,{configuration:r}),A=!1,p=!0;for(let[,C]of v)for(let R of C)R.fixable?A=!0:p=!1}}if(u.children.length===0)return 0;if(A){let h=p?`Those errors can all be fixed by running ${pe.pretty(r,"yarn constraints --fix",pe.Type.CODE)}`:`Errors prefixed by '\u2699' can be fixed by running ${pe.pretty(r,"yarn constraints --fix",pe.Type.CODE)}`;await Rt.start({configuration:r,stdout:this.context.stdout,includeNames:!1,includeFooter:!1},async E=>{E.reportInfo(0,h),E.reportSeparator()})}return u.children=He.sortMap(u.children,h=>h.value[1]),fs.emitTree(u,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1}),1}};l2();var odt={configuration:{enableConstraintsChecks:{description:"If true, constraints will run during installs",type:"BOOLEAN",default:!1},constraintsPath:{description:"The path of the constraints file.",type:"ABSOLUTE_PATH",default:"./constraints.pro"}},commands:[LE,ME,OE],hooks:{async validateProjectAfterInstall(t,{reportError:e}){if(!t.configuration.get("enableConstraintsChecks"))return;let r=await t.loadUserConfig(),o;if(r?.constraints)o=new FE(t);else{let{Constraints:u}=await Promise.resolve().then(()=>(f2(),A2));o=await u.find(t)}let a=await o.process();if(!a)return;let{remainingErrors:n}=ik(t,a);if(n.size!==0)if(t.configuration.isCI)for(let[u,A]of n)for(let p of A)e(84,`${pe.pretty(t.configuration,u.anchoredLocator,pe.Type.IDENT)}: ${p.text}`);else e(84,`Constraint check failed; run ${pe.pretty(t.configuration,"yarn constraints",pe.Type.CODE)} for more details`)}}},adt=odt;var mH={};Vt(mH,{CreateCommand:()=>UE,DlxCommand:()=>_E,default:()=>cdt});Ge();qt();var UE=class extends ut{constructor(){super(...arguments);this.pkg=ge.String("-p,--package",{description:"The package to run the provided command from"});this.quiet=ge.Boolean("-q,--quiet",!1,{description:"Only report critical errors instead of printing the full install logs"});this.command=ge.String();this.args=ge.Proxy()}static{this.paths=[["create"]]}async execute(){let r=[];this.pkg&&r.push("--package",this.pkg),this.quiet&&r.push("--quiet");let o=this.command.replace(/^(@[^@/]+)(@|$)/,"$1/create$2"),a=G.parseDescriptor(o),n=a.name.match(/^create(-|$)/)?a:a.scope?G.makeIdent(a.scope,`create-${a.name}`):G.makeIdent(null,`create-${a.name}`),u=G.stringifyIdent(n);return a.range!=="unknown"&&(u+=`@${a.range}`),this.cli.run(["dlx",...r,u,...this.args])}};Ge();Ge();Pt();qt();var _E=class extends ut{constructor(){super(...arguments);this.packages=ge.Array("-p,--package",{description:"The package(s) to install before running the command"});this.quiet=ge.Boolean("-q,--quiet",!1,{description:"Only report critical errors instead of printing the full install logs"});this.command=ge.String();this.args=ge.Proxy()}static{this.paths=[["dlx"]]}static{this.usage=it.Usage({description:"run a package in a temporary environment",details:"\n This command will install a package within a temporary environment, and run its binary script if it contains any. The binary will run within the current cwd.\n\n By default Yarn will download the package named `command`, but this can be changed through the use of the `-p,--package` flag which will instruct Yarn to still run the same command but from a different package.\n\n Using `yarn dlx` as a replacement of `yarn add` isn't recommended, as it makes your project non-deterministic (Yarn doesn't keep track of the packages installed through `dlx` - neither their name, nor their version).\n ",examples:[["Use create-react-app to create a new React app","yarn dlx create-react-app ./my-app"],["Install multiple packages for a single command",`yarn dlx -p typescript -p ts-node ts-node --transpile-only -e "console.log('hello!')"`]]})}async execute(){return Ke.telemetry=null,await oe.mktempPromise(async r=>{let o=K.join(r,`dlx-${process.pid}`);await oe.mkdirPromise(o),await oe.writeFilePromise(K.join(o,"package.json"),`{} +`),await oe.writeFilePromise(K.join(o,"yarn.lock"),"");let a=K.join(o,".yarnrc.yml"),n=await Ke.findProjectCwd(this.context.cwd),A={enableGlobalCache:!(await Ke.find(this.context.cwd,null,{strict:!1})).get("enableGlobalCache"),enableTelemetry:!1,logFilters:[{code:Ku(68),level:pe.LogLevel.Discard}]},p=n!==null?K.join(n,".yarnrc.yml"):null;p!==null&&oe.existsSync(p)?(await oe.copyFilePromise(p,a),await Ke.updateConfiguration(o,L=>{let U=He.toMerged(L,A);return Array.isArray(L.plugins)&&(U.plugins=L.plugins.map(z=>{let te=typeof z=="string"?z:z.path,ae=ue.isAbsolute(te)?te:ue.resolve(ue.fromPortablePath(n),te);return typeof z=="string"?ae:{path:ae,spec:z.spec}})),U})):await oe.writeJsonPromise(a,A);let h=this.packages??[this.command],E=G.parseDescriptor(this.command).name,I=await this.cli.run(["add","--fixed","--",...h],{cwd:o,quiet:this.quiet});if(I!==0)return I;this.quiet||this.context.stdout.write(` +`);let v=await Ke.find(o,this.context.plugins),{project:x,workspace:C}=await kt.find(v,o);if(C===null)throw new sr(x.cwd,o);await x.restoreInstallState();let R=await An.getWorkspaceAccessibleBinaries(C);return R.has(E)===!1&&R.size===1&&typeof this.packages>"u"&&(E=Array.from(R)[0][0]),await An.executeWorkspaceAccessibleBinary(C,E,this.args,{packageAccessibleBinaries:R,cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})})}};var ldt={commands:[UE,_E]},cdt=ldt;var CH={};Vt(CH,{ExecFetcher:()=>h2,ExecResolver:()=>g2,default:()=>fdt,execUtils:()=>lk});Ge();Ge();Pt();var fA="exec:";var lk={};Vt(lk,{loadGeneratorFile:()=>p2,makeLocator:()=>EH,makeSpec:()=>yme,parseSpec:()=>yH});Ge();Pt();function yH(t){let{params:e,selector:r}=G.parseRange(t),o=ue.toPortablePath(r);return{parentLocator:e&&typeof e.locator=="string"?G.parseLocator(e.locator):null,path:o}}function yme({parentLocator:t,path:e,generatorHash:r,protocol:o}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<"u"?{hash:r}:{};return G.makeRange({protocol:o,source:e,selector:e,params:{...n,...a}})}function EH(t,{parentLocator:e,path:r,generatorHash:o,protocol:a}){return G.makeLocator(t,yme({parentLocator:e,path:r,generatorHash:o,protocol:a}))}async function p2(t,e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(t,{protocol:e}),n=K.isAbsolute(a)?{packageFs:new gn(It.root),prefixPath:It.dot,localPath:It.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new gn(It.root),prefixPath:K.relative(It.root,n.localPath)}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.join(u.prefixPath,a);return await A.readFilePromise(p,"utf8")}var h2=class{supports(e,r){return!!e.reference.startsWith(fA)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:fA});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async fetchFromDisk(e,r){let o=await p2(e.reference,fA,r);return oe.mktempPromise(async a=>{let n=K.join(a,"generator.js");return await oe.writeFilePromise(n,o),oe.mktempPromise(async u=>{if(await this.generatePackage(u,e,n,r),!oe.existsSync(K.join(u,"build")))throw new Error("The script should have generated a build directory");return await $i.makeArchiveFromDirectory(K.join(u,"build"),{prefixPath:G.getIdentVendorPath(e),compressionLevel:r.project.configuration.get("compressionLevel")})})})}async generatePackage(e,r,o,a){return await oe.mktempPromise(async n=>{let u=await An.makeScriptEnv({project:a.project,binFolder:n}),A=K.join(e,"runtime.js");return await oe.mktempPromise(async p=>{let h=K.join(p,"buildfile.log"),E=K.join(e,"generator"),I=K.join(e,"build");await oe.mkdirPromise(E),await oe.mkdirPromise(I);let v={tempDir:ue.fromPortablePath(E),buildDir:ue.fromPortablePath(I),locator:G.stringifyLocator(r)};await oe.writeFilePromise(A,` + // Expose 'Module' as a global variable + Object.defineProperty(global, 'Module', { + get: () => require('module'), + configurable: true, + enumerable: false, + }); + + // Expose non-hidden built-in modules as global variables + for (const name of Module.builtinModules.filter((name) => name !== 'module' && !name.startsWith('_'))) { + Object.defineProperty(global, name, { + get: () => require(name), + configurable: true, + enumerable: false, + }); + } + + // Expose the 'execEnv' global variable + Object.defineProperty(global, 'execEnv', { + value: { + ...${JSON.stringify(v)}, + }, + enumerable: true, + }); + `);let x=u.NODE_OPTIONS||"",C=/\s*--require\s+\S*\.pnp\.c?js\s*/g;x=x.replace(C," ").trim(),u.NODE_OPTIONS=x;let{stdout:R,stderr:L}=a.project.configuration.getSubprocessStreams(h,{header:`# This file contains the result of Yarn generating a package (${G.stringifyLocator(r)}) +`,prefix:G.prettyLocator(a.project.configuration,r),report:a.report}),{code:U}=await Ur.pipevp(process.execPath,["--require",ue.fromPortablePath(A),ue.fromPortablePath(o),G.stringifyIdent(r)],{cwd:e,env:u,stdin:null,stdout:R,stderr:L});if(U!==0)throw oe.detachTemp(p),new Error(`Package generation failed (exit code ${U}, logs can be found here: ${pe.pretty(a.project.configuration,h,pe.Type.PATH)})`)})})}};Ge();Ge();var udt=2,g2=class{supportsDescriptor(e,r){return!!e.range.startsWith(fA)}supportsLocator(e,r){return!!e.reference.startsWith(fA)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=yH(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let u=await p2(G.makeRange({protocol:fA,source:a,selector:a,params:{locator:G.stringifyLocator(n)}}),fA,o.fetchOptions),A=wn.makeHash(`${udt}`,u).slice(0,6);return[EH(e,{parentLocator:n,path:a,generatorHash:A,protocol:fA})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await He.releaseAfterUseAsync(async()=>await Ut.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var Adt={fetchers:[h2],resolvers:[g2]},fdt=Adt;var IH={};Vt(IH,{FileFetcher:()=>E2,FileResolver:()=>C2,TarballFileFetcher:()=>w2,TarballFileResolver:()=>I2,default:()=>gdt,fileUtils:()=>Yg});Ge();Pt();var HE=/^(?:[a-zA-Z]:[\\/]|\.{0,2}\/)/,d2=/^[^?]*\.(?:tar\.gz|tgz)(?:::.*)?$/,Ui="file:";var Yg={};Vt(Yg,{fetchArchiveFromLocator:()=>y2,makeArchiveFromLocator:()=>ck,makeBufferFromLocator:()=>wH,makeLocator:()=>qE,makeSpec:()=>Eme,parseSpec:()=>m2});Ge();Pt();function m2(t){let{params:e,selector:r}=G.parseRange(t),o=ue.toPortablePath(r);return{parentLocator:e&&typeof e.locator=="string"?G.parseLocator(e.locator):null,path:o}}function Eme({parentLocator:t,path:e,hash:r,protocol:o}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<"u"?{hash:r}:{};return G.makeRange({protocol:o,source:e,selector:e,params:{...n,...a}})}function qE(t,{parentLocator:e,path:r,hash:o,protocol:a}){return G.makeLocator(t,Eme({parentLocator:e,path:r,hash:o,protocol:a}))}async function y2(t,e){let{parentLocator:r,path:o}=G.parseFileStyleRange(t.reference,{protocol:Ui}),a=K.isAbsolute(o)?{packageFs:new gn(It.root),prefixPath:It.dot,localPath:It.root}:await e.fetcher.fetch(r,e),n=a.localPath?{packageFs:new gn(It.root),prefixPath:K.relative(It.root,a.localPath)}:a;a!==n&&a.releaseFs&&a.releaseFs();let u=n.packageFs,A=K.join(n.prefixPath,o);return await He.releaseAfterUseAsync(async()=>await u.readFilePromise(A),n.releaseFs)}async function ck(t,{protocol:e,fetchOptions:r,inMemory:o=!1}){let{parentLocator:a,path:n}=G.parseFileStyleRange(t.reference,{protocol:e}),u=K.isAbsolute(n)?{packageFs:new gn(It.root),prefixPath:It.dot,localPath:It.root}:await r.fetcher.fetch(a,r),A=u.localPath?{packageFs:new gn(It.root),prefixPath:K.relative(It.root,u.localPath)}:u;u!==A&&u.releaseFs&&u.releaseFs();let p=A.packageFs,h=K.join(A.prefixPath,n);return await He.releaseAfterUseAsync(async()=>await $i.makeArchiveFromDirectory(h,{baseFs:p,prefixPath:G.getIdentVendorPath(t),compressionLevel:r.project.configuration.get("compressionLevel"),inMemory:o}),A.releaseFs)}async function wH(t,{protocol:e,fetchOptions:r}){return(await ck(t,{protocol:e,fetchOptions:r,inMemory:!0})).getBufferAndClose()}var E2=class{supports(e,r){return!!e.reference.startsWith(Ui)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Ui});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async fetchFromDisk(e,r){return ck(e,{protocol:Ui,fetchOptions:r})}};Ge();Ge();var pdt=2,C2=class{supportsDescriptor(e,r){return e.range.match(HE)?!0:!!e.range.startsWith(Ui)}supportsLocator(e,r){return!!e.reference.startsWith(Ui)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return HE.test(e.range)&&(e=G.makeDescriptor(e,`${Ui}${e.range}`)),G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=m2(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let u=await wH(G.makeLocator(e,G.makeRange({protocol:Ui,source:a,selector:a,params:{locator:G.stringifyLocator(n)}})),{protocol:Ui,fetchOptions:o.fetchOptions}),A=wn.makeHash(`${pdt}`,u).slice(0,6);return[qE(e,{parentLocator:n,path:a,hash:A,protocol:Ui})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await He.releaseAfterUseAsync(async()=>await Ut.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};Ge();var w2=class{supports(e,r){return d2.test(e.reference)?!!e.reference.startsWith(Ui):!1}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromDisk(e,r){let o=await y2(e,r);return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ge();Ge();Ge();var I2=class{supportsDescriptor(e,r){return d2.test(e.range)?!!(e.range.startsWith(Ui)||HE.test(e.range)):!1}supportsLocator(e,r){return d2.test(e.reference)?!!e.reference.startsWith(Ui):!1}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return HE.test(e.range)&&(e=G.makeDescriptor(e,`${Ui}${e.range}`)),G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=m2(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let u=qE(e,{parentLocator:n,path:a,hash:"",protocol:Ui}),A=await y2(u,o.fetchOptions),p=wn.makeHash(A).slice(0,6);return[qE(e,{parentLocator:n,path:a,hash:p,protocol:Ui})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await He.releaseAfterUseAsync(async()=>await Ut.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var hdt={fetchers:[w2,E2],resolvers:[I2,C2]},gdt=hdt;var DH={};Vt(DH,{GithubFetcher:()=>B2,default:()=>mdt,githubUtils:()=>uk});Ge();Pt();var uk={};Vt(uk,{invalidGithubUrlMessage:()=>Ime,isGithubUrl:()=>BH,parseGithubUrl:()=>vH});var Cme=Ze(ve("querystring")),wme=[/^https?:\/\/(?:([^/]+?)@)?github.com\/([^/#]+)\/([^/#]+)\/tarball\/([^/#]+)(?:#(.*))?$/,/^https?:\/\/(?:([^/]+?)@)?github.com\/([^/#]+)\/([^/#]+?)(?:\.git)?(?:#(.*))?$/];function BH(t){return t?wme.some(e=>!!t.match(e)):!1}function vH(t){let e;for(let A of wme)if(e=t.match(A),e)break;if(!e)throw new Error(Ime(t));let[,r,o,a,n="master"]=e,{commit:u}=Cme.default.parse(n);return n=u||n.replace(/[^:]*:/,""),{auth:r,username:o,reponame:a,treeish:n}}function Ime(t){return`Input cannot be parsed as a valid GitHub URL ('${t}').`}var B2=class{supports(e,r){return!!BH(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from GitHub`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o=await sn.get(this.getLocatorUrl(e,r),{configuration:r.project.configuration});return await oe.mktempPromise(async a=>{let n=new gn(a);await $i.extractArchiveTo(o,n,{stripComponents:1});let u=ia.splitRepoUrl(e.reference),A=K.join(a,"package.tgz");await An.prepareExternalProject(a,A,{configuration:r.project.configuration,report:r.report,workspace:u.extra.workspace,locator:e});let p=await oe.readFilePromise(A);return await $i.convertToZip(p,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})})}getLocatorUrl(e,r){let{auth:o,username:a,reponame:n,treeish:u}=vH(e.reference);return`https://${o?`${o}@`:""}github.com/${a}/${n}/archive/${u}.tar.gz`}};var ddt={hooks:{async fetchHostedRepository(t,e,r){if(t!==null)return t;let o=new B2;if(!o.supports(e,r))return null;try{return await o.fetch(e,r)}catch{return null}}}},mdt=ddt;var PH={};Vt(PH,{TarballHttpFetcher:()=>D2,TarballHttpResolver:()=>P2,default:()=>Edt});Ge();function v2(t){let e;try{e=new URL(t)}catch{return!1}return!(e.protocol!=="http:"&&e.protocol!=="https:"||!e.pathname.match(/(\.tar\.gz|\.tgz|\/[^.]+)$/))}var D2=class{supports(e,r){return v2(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o=await sn.get(e.reference,{configuration:r.project.configuration});return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ge();Ge();var P2=class{supportsDescriptor(e,r){return v2(e.range)}supportsLocator(e,r){return v2(e.reference)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){return[G.convertDescriptorToLocator(e)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await He.releaseAfterUseAsync(async()=>await Ut.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var ydt={fetchers:[D2],resolvers:[P2]},Edt=ydt;var SH={};Vt(SH,{InitCommand:()=>jE,default:()=>wdt});Ge();Ge();Pt();qt();var jE=class extends ut{constructor(){super(...arguments);this.private=ge.Boolean("-p,--private",!1,{description:"Initialize a private package"});this.workspace=ge.Boolean("-w,--workspace",!1,{description:"Initialize a workspace root with a `packages/` directory"});this.install=ge.String("-i,--install",!1,{tolerateBoolean:!0,description:"Initialize a package with a specific bundle that will be locked in the project"});this.name=ge.String("-n,--name",{description:"Initialize a package with the given name"});this.usev2=ge.Boolean("-2",!1,{hidden:!0});this.yes=ge.Boolean("-y,--yes",{hidden:!0})}static{this.paths=[["init"]]}static{this.usage=it.Usage({description:"create a new package",details:"\n This command will setup a new package in your local directory.\n\n If the `-p,--private` or `-w,--workspace` options are set, the package will be private by default.\n\n If the `-w,--workspace` option is set, the package will be configured to accept a set of workspaces in the `packages/` directory.\n\n If the `-i,--install` option is given a value, Yarn will first download it using `yarn set version` and only then forward the init call to the newly downloaded bundle. Without arguments, the downloaded bundle will be `latest`.\n\n The initial settings of the manifest can be changed by using the `initScope` and `initFields` configuration values. Additionally, Yarn will generate an EditorConfig file whose rules can be altered via `initEditorConfig`, and will initialize a Git repository in the current directory.\n ",examples:[["Create a new package in the local directory","yarn init"],["Create a new private package in the local directory","yarn init -p"],["Create a new package and store the Yarn release inside","yarn init -i=latest"],["Create a new private package and defines it as a workspace root","yarn init -w"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=typeof this.install=="string"?this.install:this.usev2||this.install===!0?"latest":null;return o!==null?await this.executeProxy(r,o):await this.executeRegular(r)}async executeProxy(r,o){if(r.projectCwd!==null&&r.projectCwd!==this.context.cwd)throw new st("Cannot use the --install flag from within a project subdirectory");oe.existsSync(this.context.cwd)||await oe.mkdirPromise(this.context.cwd,{recursive:!0});let a=K.join(this.context.cwd,dr.lockfile);oe.existsSync(a)||await oe.writeFilePromise(a,"");let n=await this.cli.run(["set","version",o],{quiet:!0});if(n!==0)return n;let u=[];return this.private&&u.push("-p"),this.workspace&&u.push("-w"),this.name&&u.push(`-n=${this.name}`),this.yes&&u.push("-y"),await oe.mktempPromise(async A=>{let{code:p}=await Ur.pipevp("yarn",["init",...u],{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,env:await An.makeScriptEnv({binFolder:A})});return p})}async executeRegular(r){let o=null;try{o=(await kt.find(r,this.context.cwd)).project}catch{o=null}oe.existsSync(this.context.cwd)||await oe.mkdirPromise(this.context.cwd,{recursive:!0});let a=await Ut.tryFind(this.context.cwd),n=a??new Ut,u=Object.fromEntries(r.get("initFields").entries());n.load(u),n.name=n.name??G.makeIdent(r.get("initScope"),this.name??K.basename(this.context.cwd)),n.packageManager=nn&&He.isTaggedYarnVersion(nn)?`yarn@${nn}`:null,(!a&&this.workspace||this.private)&&(n.private=!0),this.workspace&&n.workspaceDefinitions.length===0&&(await oe.mkdirPromise(K.join(this.context.cwd,"packages"),{recursive:!0}),n.workspaceDefinitions=[{pattern:"packages/*"}]);let A={};n.exportTo(A);let p=K.join(this.context.cwd,Ut.fileName);await oe.changeFilePromise(p,`${JSON.stringify(A,null,2)} +`,{automaticNewlines:!0});let h=[p],E=K.join(this.context.cwd,"README.md");if(oe.existsSync(E)||(await oe.writeFilePromise(E,`# ${G.stringifyIdent(n.name)} +`),h.push(E)),!o||o.cwd===this.context.cwd){let I=K.join(this.context.cwd,dr.lockfile);oe.existsSync(I)||(await oe.writeFilePromise(I,""),h.push(I));let x=[".yarn/*","!.yarn/patches","!.yarn/plugins","!.yarn/releases","!.yarn/sdks","!.yarn/versions","","# Swap the comments on the following lines if you wish to use zero-installs","# In that case, don't forget to run `yarn config set enableGlobalCache false`!","# Documentation here: https://yarnpkg.com/features/caching#zero-installs","","#!.yarn/cache",".pnp.*"].map(le=>`${le} +`).join(""),C=K.join(this.context.cwd,".gitignore");oe.existsSync(C)||(await oe.writeFilePromise(C,x),h.push(C));let L=["/.yarn/** linguist-vendored","/.yarn/releases/* binary","/.yarn/plugins/**/* binary","/.pnp.* binary linguist-generated"].map(le=>`${le} +`).join(""),U=K.join(this.context.cwd,".gitattributes");oe.existsSync(U)||(await oe.writeFilePromise(U,L),h.push(U));let z={"*":{endOfLine:"lf",insertFinalNewline:!0},"*.{js,json,yml}":{charset:"utf-8",indentStyle:"space",indentSize:2}};He.mergeIntoTarget(z,r.get("initEditorConfig"));let te=`root = true +`;for(let[le,ce]of Object.entries(z)){te+=` +[${le}] +`;for(let[Ce,de]of Object.entries(ce)){let Be=Ce.replace(/[A-Z]/g,Ee=>`_${Ee.toLowerCase()}`);te+=`${Be} = ${de} +`}}let ae=K.join(this.context.cwd,".editorconfig");oe.existsSync(ae)||(await oe.writeFilePromise(ae,te),h.push(ae)),await this.cli.run(["install"],{quiet:!0}),oe.existsSync(K.join(this.context.cwd,".git"))||(await Ur.execvp("git",["init"],{cwd:this.context.cwd}),await Ur.execvp("git",["add","--",...h],{cwd:this.context.cwd}),await Ur.execvp("git",["commit","--allow-empty","-m","First commit"],{cwd:this.context.cwd}))}}};var Cdt={configuration:{initScope:{description:"Scope used when creating packages via the init command",type:"STRING",default:null},initFields:{description:"Additional fields to set when creating packages via the init command",type:"MAP",valueDefinition:{description:"",type:"ANY"}},initEditorConfig:{description:"Extra rules to define in the generator editorconfig",type:"MAP",valueDefinition:{description:"",type:"ANY"}}},commands:[jE]},wdt=Cdt;var kq={};Vt(kq,{SearchCommand:()=>oC,UpgradeInteractiveCommand:()=>aC,default:()=>cIt});Ge();var vme=Ze(ve("os"));function GE({stdout:t}){if(vme.default.endianness()==="BE")throw new Error("Interactive commands cannot be used on big-endian systems because ink depends on yoga-layout-prebuilt which only supports little-endian architectures");if(!t.isTTY)throw new Error("Interactive commands can only be used inside a TTY environment")}qt();var Lye=Ze(YH()),WH={appId:"OFCNCOG2CU",apiKey:"6fe4476ee5a1832882e326b506d14126",indexName:"npm-search"},yyt=(0,Lye.default)(WH.appId,WH.apiKey).initIndex(WH.indexName),KH=async(t,e=0)=>await yyt.search(t,{analyticsTags:["yarn-plugin-interactive-tools"],attributesToRetrieve:["name","version","owner","repository","humanDownloadsLast30Days"],page:e,hitsPerPage:10});var vB=["regular","dev","peer"],oC=class extends ut{static{this.paths=[["search"]]}static{this.usage=it.Usage({category:"Interactive commands",description:"open the search interface",details:` + This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry. + `,examples:[["Open the search window","yarn search"]]})}async execute(){GE(this.context);let{Gem:e}=await Promise.resolve().then(()=>(Zk(),Eq)),{ScrollableItems:r}=await Promise.resolve().then(()=>(rQ(),tQ)),{useKeypress:o}=await Promise.resolve().then(()=>(wB(),Xwe)),{useMinistore:a}=await Promise.resolve().then(()=>(Dq(),vq)),{renderForm:n}=await Promise.resolve().then(()=>(oQ(),sQ)),{default:u}=await Promise.resolve().then(()=>Ze(aIe())),{Box:A,Text:p}=await Promise.resolve().then(()=>Ze(ic())),{default:h,useEffect:E,useState:I}=await Promise.resolve().then(()=>Ze(an())),v=await Ke.find(this.context.cwd,this.context.plugins),x=()=>h.createElement(A,{flexDirection:"row"},h.createElement(A,{flexDirection:"column",width:48},h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<up>"),"/",h.createElement(p,{bold:!0,color:"cyanBright"},"<down>")," to move between packages.")),h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<space>")," to select a package.")),h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<space>")," again to change the target."))),h.createElement(A,{flexDirection:"column"},h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<enter>")," to install the selected packages.")),h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<ctrl+c>")," to abort.")))),C=()=>h.createElement(h.Fragment,null,h.createElement(A,{width:15},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Owner")),h.createElement(A,{width:11},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Version")),h.createElement(A,{width:10},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Downloads"))),R=()=>h.createElement(A,{width:17},h.createElement(p,{bold:!0,underline:!0,color:"gray"},"Target")),L=({hit:de,active:Be})=>{let[Ee,g]=a(de.name,null);o({active:Be},(Ae,ne)=>{if(ne.name!=="space")return;if(!Ee){g(vB[0]);return}let Z=vB.indexOf(Ee)+1;Z===vB.length?g(null):g(vB[Z])},[Ee,g]);let me=G.parseIdent(de.name),we=G.prettyIdent(v,me);return h.createElement(A,null,h.createElement(A,{width:45},h.createElement(p,{bold:!0,wrap:"wrap"},we)),h.createElement(A,{width:14,marginLeft:1},h.createElement(p,{bold:!0,wrap:"truncate"},de.owner.name)),h.createElement(A,{width:10,marginLeft:1},h.createElement(p,{italic:!0,wrap:"truncate"},de.version)),h.createElement(A,{width:16,marginLeft:1},h.createElement(p,null,de.humanDownloadsLast30Days)))},U=({name:de,active:Be})=>{let[Ee]=a(de,null),g=G.parseIdent(de);return h.createElement(A,null,h.createElement(A,{width:47},h.createElement(p,{bold:!0}," - ",G.prettyIdent(v,g))),vB.map(me=>h.createElement(A,{key:me,width:14,marginLeft:1},h.createElement(p,null," ",h.createElement(e,{active:Ee===me})," ",h.createElement(p,{bold:!0},me)))))},z=()=>h.createElement(A,{marginTop:1},h.createElement(p,null,"Powered by Algolia.")),ae=await n(({useSubmit:de})=>{let Be=a();de(Be);let Ee=Array.from(Be.keys()).filter(H=>Be.get(H)!==null),[g,me]=I(""),[we,Ae]=I(0),[ne,Z]=I([]),xe=H=>{H.match(/\t| /)||me(H)},Ne=async()=>{Ae(0);let H=await KH(g);H.query===g&&Z(H.hits)},ht=async()=>{let H=await KH(g,we+1);H.query===g&&H.page-1===we&&(Ae(H.page),Z([...ne,...H.hits]))};return E(()=>{g?Ne():Z([])},[g]),h.createElement(A,{flexDirection:"column"},h.createElement(x,null),h.createElement(A,{flexDirection:"row",marginTop:1},h.createElement(p,{bold:!0},"Search: "),h.createElement(A,{width:41},h.createElement(u,{value:g,onChange:xe,placeholder:"i.e. babel, webpack, react...",showCursor:!1})),h.createElement(C,null)),ne.length?h.createElement(r,{radius:2,loop:!1,children:ne.map(H=>h.createElement(L,{key:H.name,hit:H,active:!1})),willReachEnd:ht}):h.createElement(p,{color:"gray"},"Start typing..."),h.createElement(A,{flexDirection:"row",marginTop:1},h.createElement(A,{width:49},h.createElement(p,{bold:!0},"Selected:")),h.createElement(R,null)),Ee.length?Ee.map(H=>h.createElement(U,{key:H,name:H,active:!1})):h.createElement(p,{color:"gray"},"No selected packages..."),h.createElement(z,null))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof ae>"u")return 1;let le=Array.from(ae.keys()).filter(de=>ae.get(de)==="regular"),ce=Array.from(ae.keys()).filter(de=>ae.get(de)==="dev"),Ce=Array.from(ae.keys()).filter(de=>ae.get(de)==="peer");return le.length&&await this.cli.run(["add",...le]),ce.length&&await this.cli.run(["add","--dev",...ce]),Ce&&await this.cli.run(["add","--peer",...Ce]),0}};Ge();qt();f_();var hIe=Ze(Jn()),pIe=/^((?:[\^~]|>=?)?)([0-9]+)(\.[0-9]+)(\.[0-9]+)((?:-\S+)?)$/,gIe=(t,e)=>t.length>0?[t.slice(0,e)].concat(gIe(t.slice(e),e)):[],aC=class extends ut{static{this.paths=[["upgrade-interactive"]]}static{this.usage=it.Usage({category:"Interactive commands",description:"open the upgrade interface",details:` + This command opens a fullscreen terminal interface where you can see any out of date packages used by your application, their status compared to the latest versions available on the remote registry, and select packages to upgrade. + `,examples:[["Open the upgrade window","yarn upgrade-interactive"]]})}async execute(){GE(this.context);let{ItemOptions:e}=await Promise.resolve().then(()=>(fIe(),AIe)),{Pad:r}=await Promise.resolve().then(()=>(xq(),uIe)),{ScrollableItems:o}=await Promise.resolve().then(()=>(rQ(),tQ)),{useMinistore:a}=await Promise.resolve().then(()=>(Dq(),vq)),{renderForm:n}=await Promise.resolve().then(()=>(oQ(),sQ)),{Box:u,Text:A}=await Promise.resolve().then(()=>Ze(ic())),{default:p,useEffect:h,useRef:E,useState:I}=await Promise.resolve().then(()=>Ze(an())),v=await Ke.find(this.context.cwd,this.context.plugins),{project:x,workspace:C}=await kt.find(v,this.context.cwd),R=await Gr.find(v);if(!C)throw new sr(x.cwd,this.context.cwd);await x.restoreInstallState({restoreResolutions:!1});let L=this.context.stdout.rows-7,U=(me,we)=>{let Ae=gpe(me,we),ne="";for(let Z of Ae)Z.added?ne+=pe.pretty(v,Z.value,"green"):Z.removed||(ne+=Z.value);return ne},z=(me,we)=>{if(me===we)return we;let Ae=G.parseRange(me),ne=G.parseRange(we),Z=Ae.selector.match(pIe),xe=ne.selector.match(pIe);if(!Z||!xe)return U(me,we);let Ne=["gray","red","yellow","green","magenta"],ht=null,H="";for(let rt=1;rt<Ne.length;++rt)ht!==null||Z[rt]!==xe[rt]?(ht===null&&(ht=Ne[rt-1]),H+=pe.pretty(v,xe[rt],ht)):H+=xe[rt];return H},te=async(me,we,Ae)=>{let ne=await Zc.fetchDescriptorFrom(me,Ae,{project:x,cache:R,preserveModifier:we,workspace:C});return ne!==null?ne.range:me.range},ae=async me=>{let we=hIe.default.valid(me.range)?`^${me.range}`:me.range,[Ae,ne]=await Promise.all([te(me,me.range,we).catch(()=>null),te(me,me.range,"latest").catch(()=>null)]),Z=[{value:null,label:me.range}];return Ae&&Ae!==me.range?Z.push({value:Ae,label:z(me.range,Ae)}):Z.push({value:null,label:""}),ne&&ne!==Ae&&ne!==me.range?Z.push({value:ne,label:z(me.range,ne)}):Z.push({value:null,label:""}),Z},le=()=>p.createElement(u,{flexDirection:"row"},p.createElement(u,{flexDirection:"column",width:49},p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},"<up>"),"/",p.createElement(A,{bold:!0,color:"cyanBright"},"<down>")," to select packages.")),p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},"<left>"),"/",p.createElement(A,{bold:!0,color:"cyanBright"},"<right>")," to select versions."))),p.createElement(u,{flexDirection:"column"},p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},"<enter>")," to install.")),p.createElement(u,{marginLeft:1},p.createElement(A,null,"Press ",p.createElement(A,{bold:!0,color:"cyanBright"},"<ctrl+c>")," to abort.")))),ce=()=>p.createElement(u,{flexDirection:"row",paddingTop:1,paddingBottom:1},p.createElement(u,{width:50},p.createElement(A,{bold:!0},p.createElement(A,{color:"greenBright"},"?")," Pick the packages you want to upgrade.")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:"gray"},"Current")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:"gray"},"Range")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:"gray"},"Latest"))),Ce=({active:me,descriptor:we,suggestions:Ae})=>{let[ne,Z]=a(we.descriptorHash,null),xe=G.stringifyIdent(we),Ne=Math.max(0,45-xe.length);return p.createElement(p.Fragment,null,p.createElement(u,null,p.createElement(u,{width:45},p.createElement(A,{bold:!0},G.prettyIdent(v,we)),p.createElement(r,{active:me,length:Ne})),p.createElement(e,{active:me,options:Ae,value:ne,skewer:!0,onChange:Z,sizes:[17,17,17]})))},de=({dependencies:me})=>{let[we,Ae]=I(me.map(()=>null)),ne=E(!0),Z=async xe=>{let Ne=await ae(xe);return Ne.filter(ht=>ht.label!=="").length<=1?null:{descriptor:xe,suggestions:Ne}};return h(()=>()=>{ne.current=!1},[]),h(()=>{let xe=Math.trunc(L*1.75),Ne=me.slice(0,xe),ht=me.slice(xe),H=gIe(ht,L),rt=Ne.map(Z).reduce(async(Te,Fe)=>{await Te;let ke=await Fe;ke!==null&&ne.current&&Ae(Ye=>{let Se=Ye.findIndex(Ue=>Ue===null),et=[...Ye];return et[Se]=ke,et})},Promise.resolve());H.reduce((Te,Fe)=>Promise.all(Fe.map(ke=>Promise.resolve().then(()=>Z(ke)))).then(async ke=>{ke=ke.filter(Ye=>Ye!==null),await Te,ne.current&&Ae(Ye=>{let Se=Ye.findIndex(et=>et===null);return Ye.slice(0,Se).concat(ke).concat(Ye.slice(Se+ke.length))})}),rt).then(()=>{ne.current&&Ae(Te=>Te.filter(Fe=>Fe!==null))})},[]),we.length?p.createElement(o,{radius:L>>1,children:we.map((xe,Ne)=>xe!==null?p.createElement(Ce,{key:Ne,active:!1,descriptor:xe.descriptor,suggestions:xe.suggestions}):p.createElement(A,{key:Ne},"Loading..."))}):p.createElement(A,null,"No upgrades found")},Ee=await n(({useSubmit:me})=>{me(a());let we=new Map;for(let ne of x.workspaces)for(let Z of["dependencies","devDependencies"])for(let xe of ne.manifest[Z].values())x.tryWorkspaceByDescriptor(xe)===null&&(xe.range.startsWith("link:")||we.set(xe.descriptorHash,xe));let Ae=He.sortMap(we.values(),ne=>G.stringifyDescriptor(ne));return p.createElement(u,{flexDirection:"column"},p.createElement(le,null),p.createElement(ce,null),p.createElement(de,{dependencies:Ae}))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof Ee>"u")return 1;let g=!1;for(let me of x.workspaces)for(let we of["dependencies","devDependencies"]){let Ae=me.manifest[we];for(let ne of Ae.values()){let Z=Ee.get(ne.descriptorHash);typeof Z<"u"&&Z!==null&&(Ae.set(ne.identHash,G.makeDescriptor(ne,Z)),g=!0)}}return g?await x.installWithNewReport({quiet:this.context.quiet,stdout:this.context.stdout},{cache:R}):0}};var lIt={commands:[oC,aC]},cIt=lIt;var Qq={};Vt(Qq,{LinkFetcher:()=>PB,LinkResolver:()=>SB,PortalFetcher:()=>bB,PortalResolver:()=>xB,default:()=>AIt});Ge();Pt();var Xf="portal:",Zf="link:";var PB=class{supports(e,r){return!!e.reference.startsWith(Zf)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Zf});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Zf}),n=K.isAbsolute(a)?{packageFs:new gn(It.root),prefixPath:It.dot,localPath:It.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new gn(It.root),prefixPath:K.relative(It.root,n.localPath),localPath:It.root}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.resolve(u.localPath??u.packageFs.getRealPath(),u.prefixPath,a);return n.localPath?{packageFs:new gn(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:It.dot,discardFromLookup:!0,localPath:p}:{packageFs:new qu(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:It.dot,discardFromLookup:!0}}};Ge();Pt();var SB=class{supportsDescriptor(e,r){return!!e.range.startsWith(Zf)}supportsLocator(e,r){return!!e.reference.startsWith(Zf)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Zf.length);return[G.makeLocator(e,`${Zf}${ue.toPortablePath(a)}`)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){return{...e,version:"0.0.0",languageName:r.project.configuration.get("defaultLanguageName"),linkType:"SOFT",conditions:null,dependencies:new Map,peerDependencies:new Map,dependenciesMeta:new Map,peerDependenciesMeta:new Map,bin:new Map}}};Ge();Pt();var bB=class{supports(e,r){return!!e.reference.startsWith(Xf)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Xf});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Xf}),n=K.isAbsolute(a)?{packageFs:new gn(It.root),prefixPath:It.dot,localPath:It.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new gn(It.root),prefixPath:K.relative(It.root,n.localPath),localPath:It.root}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.resolve(u.localPath??u.packageFs.getRealPath(),u.prefixPath,a);return n.localPath?{packageFs:new gn(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:It.dot,localPath:p}:{packageFs:new qu(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:It.dot}}};Ge();Ge();Pt();var xB=class{supportsDescriptor(e,r){return!!e.range.startsWith(Xf)}supportsLocator(e,r){return!!e.reference.startsWith(Xf)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Xf.length);return[G.makeLocator(e,`${Xf}${ue.toPortablePath(a)}`)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await He.releaseAfterUseAsync(async()=>await Ut.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"SOFT",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var uIt={fetchers:[PB,bB],resolvers:[SB,xB]},AIt=uIt;var hj={};Vt(hj,{NodeModulesLinker:()=>GB,NodeModulesMode:()=>uj,PnpLooseLinker:()=>YB,default:()=>S1t});Pt();Ge();Pt();Pt();var Rq=(t,e)=>`${t}@${e}`,dIe=(t,e)=>{let r=e.indexOf("#"),o=r>=0?e.substring(r+1):e;return Rq(t,o)};var yIe=(t,e={})=>{let r=e.debugLevel||Number(process.env.NM_DEBUG_LEVEL||-1),o=e.check||r>=9,a=e.hoistingLimits||new Map,n={check:o,debugLevel:r,hoistingLimits:a,fastLookupPossible:!0},u;n.debugLevel>=0&&(u=Date.now());let A=yIt(t,n),p=!1,h=0;do p=Tq(A,[A],new Set([A.locator]),new Map,n).anotherRoundNeeded,n.fastLookupPossible=!1,h++;while(p);if(n.debugLevel>=0&&console.log(`hoist time: ${Date.now()-u}ms, rounds: ${h}`),n.debugLevel>=1){let E=kB(A);if(Tq(A,[A],new Set([A.locator]),new Map,n).isGraphChanged)throw new Error(`The hoisting result is not terminal, prev tree: +${E}, next tree: +${kB(A)}`);let v=EIe(A);if(v)throw new Error(`${v}, after hoisting finished: +${kB(A)}`)}return n.debugLevel>=2&&console.log(kB(A)),EIt(A)},fIt=t=>{let e=t[t.length-1],r=new Map,o=new Set,a=n=>{if(!o.has(n)){o.add(n);for(let u of n.hoistedDependencies.values())r.set(u.name,u);for(let u of n.dependencies.values())n.peerNames.has(u.name)||a(u)}};return a(e),r},pIt=t=>{let e=t[t.length-1],r=new Map,o=new Set,a=new Set,n=(u,A)=>{if(o.has(u))return;o.add(u);for(let h of u.hoistedDependencies.values())if(!A.has(h.name)){let E;for(let I of t)E=I.dependencies.get(h.name),E&&r.set(E.name,E)}let p=new Set;for(let h of u.dependencies.values())p.add(h.name);for(let h of u.dependencies.values())u.peerNames.has(h.name)||n(h,p)};return n(e,a),r},mIe=(t,e)=>{if(e.decoupled)return e;let{name:r,references:o,ident:a,locator:n,dependencies:u,originalDependencies:A,hoistedDependencies:p,peerNames:h,reasons:E,isHoistBorder:I,hoistPriority:v,dependencyKind:x,hoistedFrom:C,hoistedTo:R}=e,L={name:r,references:new Set(o),ident:a,locator:n,dependencies:new Map(u),originalDependencies:new Map(A),hoistedDependencies:new Map(p),peerNames:new Set(h),reasons:new Map(E),decoupled:!0,isHoistBorder:I,hoistPriority:v,dependencyKind:x,hoistedFrom:new Map(C),hoistedTo:new Map(R)},U=L.dependencies.get(r);return U&&U.ident==L.ident&&L.dependencies.set(r,L),t.dependencies.set(L.name,L),L},hIt=(t,e)=>{let r=new Map([[t.name,[t.ident]]]);for(let a of t.dependencies.values())t.peerNames.has(a.name)||r.set(a.name,[a.ident]);let o=Array.from(e.keys());o.sort((a,n)=>{let u=e.get(a),A=e.get(n);return A.hoistPriority!==u.hoistPriority?A.hoistPriority-u.hoistPriority:A.peerDependents.size!==u.peerDependents.size?A.peerDependents.size-u.peerDependents.size:A.dependents.size-u.dependents.size});for(let a of o){let n=a.substring(0,a.indexOf("@",1)),u=a.substring(n.length+1);if(!t.peerNames.has(n)){let A=r.get(n);A||(A=[],r.set(n,A)),A.indexOf(u)<0&&A.push(u)}}return r},Fq=t=>{let e=new Set,r=(o,a=new Set)=>{if(!a.has(o)){a.add(o);for(let n of o.peerNames)if(!t.peerNames.has(n)){let u=t.dependencies.get(n);u&&!e.has(u)&&r(u,a)}e.add(o)}};for(let o of t.dependencies.values())t.peerNames.has(o.name)||r(o);return e},Tq=(t,e,r,o,a,n=new Set)=>{let u=e[e.length-1];if(n.has(u))return{anotherRoundNeeded:!1,isGraphChanged:!1};n.add(u);let A=CIt(u),p=hIt(u,A),h=t==u?new Map:a.fastLookupPossible?fIt(e):pIt(e),E,I=!1,v=!1,x=new Map(Array.from(p.entries()).map(([R,L])=>[R,L[0]])),C=new Map;do{let R=mIt(t,e,r,h,x,p,o,C,a);R.isGraphChanged&&(v=!0),R.anotherRoundNeeded&&(I=!0),E=!1;for(let[L,U]of p)U.length>1&&!u.dependencies.has(L)&&(x.delete(L),U.shift(),x.set(L,U[0]),E=!0)}while(E);for(let R of u.dependencies.values())if(!u.peerNames.has(R.name)&&!r.has(R.locator)){r.add(R.locator);let L=Tq(t,[...e,R],r,C,a);L.isGraphChanged&&(v=!0),L.anotherRoundNeeded&&(I=!0),r.delete(R.locator)}return{anotherRoundNeeded:I,isGraphChanged:v}},gIt=t=>{for(let[e,r]of t.dependencies)if(!t.peerNames.has(e)&&r.ident!==t.ident)return!0;return!1},dIt=(t,e,r,o,a,n,u,A,{outputReason:p,fastLookupPossible:h})=>{let E,I=null,v=new Set;p&&(E=`${Array.from(e).map(L=>no(L)).join("\u2192")}`);let x=r[r.length-1],R=!(o.ident===x.ident);if(p&&!R&&(I="- self-reference"),R&&(R=o.dependencyKind!==1,p&&!R&&(I="- workspace")),R&&o.dependencyKind===2&&(R=!gIt(o),p&&!R&&(I="- external soft link with unhoisted dependencies")),R&&(R=x.dependencyKind!==1||x.hoistedFrom.has(o.name)||e.size===1,p&&!R&&(I=x.reasons.get(o.name))),R&&(R=!t.peerNames.has(o.name),p&&!R&&(I=`- cannot shadow peer: ${no(t.originalDependencies.get(o.name).locator)} at ${E}`)),R){let L=!1,U=a.get(o.name);if(L=!U||U.ident===o.ident,p&&!L&&(I=`- filled by: ${no(U.locator)} at ${E}`),L)for(let z=r.length-1;z>=1;z--){let ae=r[z].dependencies.get(o.name);if(ae&&ae.ident!==o.ident){L=!1;let le=A.get(x);le||(le=new Set,A.set(x,le)),le.add(o.name),p&&(I=`- filled by ${no(ae.locator)} at ${r.slice(0,z).map(ce=>no(ce.locator)).join("\u2192")}`);break}}R=L}if(R&&(R=n.get(o.name)===o.ident,p&&!R&&(I=`- filled by: ${no(u.get(o.name)[0])} at ${E}`)),R){let L=!0,U=new Set(o.peerNames);for(let z=r.length-1;z>=1;z--){let te=r[z];for(let ae of U){if(te.peerNames.has(ae)&&te.originalDependencies.has(ae))continue;let le=te.dependencies.get(ae);le&&t.dependencies.get(ae)!==le&&(z===r.length-1?v.add(le):(v=null,L=!1,p&&(I=`- peer dependency ${no(le.locator)} from parent ${no(te.locator)} was not hoisted to ${E}`))),U.delete(ae)}if(!L)break}R=L}if(R&&!h)for(let L of o.hoistedDependencies.values()){let U=a.get(L.name)||t.dependencies.get(L.name);if(!U||L.ident!==U.ident){R=!1,p&&(I=`- previously hoisted dependency mismatch, needed: ${no(L.locator)}, available: ${no(U?.locator)}`);break}}return v!==null&&v.size>0?{isHoistable:2,dependsOn:v,reason:I}:{isHoistable:R?0:1,reason:I}},aQ=t=>`${t.name}@${t.locator}`,mIt=(t,e,r,o,a,n,u,A,p)=>{let h=e[e.length-1],E=new Set,I=!1,v=!1,x=(U,z,te,ae,le)=>{if(E.has(ae))return;let ce=[...z,aQ(ae)],Ce=[...te,aQ(ae)],de=new Map,Be=new Map;for(let Ae of Fq(ae)){let ne=dIt(h,r,[h,...U,ae],Ae,o,a,n,A,{outputReason:p.debugLevel>=2,fastLookupPossible:p.fastLookupPossible});if(Be.set(Ae,ne),ne.isHoistable===2)for(let Z of ne.dependsOn){let xe=de.get(Z.name)||new Set;xe.add(Ae.name),de.set(Z.name,xe)}}let Ee=new Set,g=(Ae,ne,Z)=>{if(!Ee.has(Ae)){Ee.add(Ae),Be.set(Ae,{isHoistable:1,reason:Z});for(let xe of de.get(Ae.name)||[])g(ae.dependencies.get(xe),ne,p.debugLevel>=2?`- peer dependency ${no(Ae.locator)} from parent ${no(ae.locator)} was not hoisted`:"")}};for(let[Ae,ne]of Be)ne.isHoistable===1&&g(Ae,ne,ne.reason);let me=!1;for(let Ae of Be.keys())if(!Ee.has(Ae)){v=!0;let ne=u.get(ae);ne&&ne.has(Ae.name)&&(I=!0),me=!0,ae.dependencies.delete(Ae.name),ae.hoistedDependencies.set(Ae.name,Ae),ae.reasons.delete(Ae.name);let Z=h.dependencies.get(Ae.name);if(p.debugLevel>=2){let xe=Array.from(z).concat([ae.locator]).map(ht=>no(ht)).join("\u2192"),Ne=h.hoistedFrom.get(Ae.name);Ne||(Ne=[],h.hoistedFrom.set(Ae.name,Ne)),Ne.push(xe),ae.hoistedTo.set(Ae.name,Array.from(e).map(ht=>no(ht.locator)).join("\u2192"))}if(!Z)h.ident!==Ae.ident&&(h.dependencies.set(Ae.name,Ae),le.add(Ae));else for(let xe of Ae.references)Z.references.add(xe)}if(ae.dependencyKind===2&&me&&(I=!0),p.check){let Ae=EIe(t);if(Ae)throw new Error(`${Ae}, after hoisting dependencies of ${[h,...U,ae].map(ne=>no(ne.locator)).join("\u2192")}: +${kB(t)}`)}let we=Fq(ae);for(let Ae of we)if(Ee.has(Ae)){let ne=Be.get(Ae);if((a.get(Ae.name)===Ae.ident||!ae.reasons.has(Ae.name))&&ne.isHoistable!==0&&ae.reasons.set(Ae.name,ne.reason),!Ae.isHoistBorder&&Ce.indexOf(aQ(Ae))<0){E.add(ae);let xe=mIe(ae,Ae);x([...U,ae],ce,Ce,xe,R),E.delete(ae)}}},C,R=new Set(Fq(h)),L=Array.from(e).map(U=>aQ(U));do{C=R,R=new Set;for(let U of C){if(U.locator===h.locator||U.isHoistBorder)continue;let z=mIe(h,U);x([],Array.from(r),L,z,R)}}while(R.size>0);return{anotherRoundNeeded:I,isGraphChanged:v}},EIe=t=>{let e=[],r=new Set,o=new Set,a=(n,u,A)=>{if(r.has(n)||(r.add(n),o.has(n)))return;let p=new Map(u);for(let h of n.dependencies.values())n.peerNames.has(h.name)||p.set(h.name,h);for(let h of n.originalDependencies.values()){let E=p.get(h.name),I=()=>`${Array.from(o).concat([n]).map(v=>no(v.locator)).join("\u2192")}`;if(n.peerNames.has(h.name)){let v=u.get(h.name);(v!==E||!v||v.ident!==h.ident)&&e.push(`${I()} - broken peer promise: expected ${h.ident} but found ${v&&v.ident}`)}else{let v=A.hoistedFrom.get(n.name),x=n.hoistedTo.get(h.name),C=`${v?` hoisted from ${v.join(", ")}`:""}`,R=`${x?` hoisted to ${x}`:""}`,L=`${I()}${C}`;E?E.ident!==h.ident&&e.push(`${L} - broken require promise for ${h.name}${R}: expected ${h.ident}, but found: ${E.ident}`):e.push(`${L} - broken require promise: no required dependency ${h.name}${R} found`)}}o.add(n);for(let h of n.dependencies.values())n.peerNames.has(h.name)||a(h,p,n);o.delete(n)};return a(t,t.dependencies,t),e.join(` +`)},yIt=(t,e)=>{let{identName:r,name:o,reference:a,peerNames:n}=t,u={name:o,references:new Set([a]),locator:Rq(r,a),ident:dIe(r,a),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(n),reasons:new Map,decoupled:!0,isHoistBorder:!0,hoistPriority:0,dependencyKind:1,hoistedFrom:new Map,hoistedTo:new Map},A=new Map([[t,u]]),p=(h,E)=>{let I=A.get(h),v=!!I;if(!I){let{name:x,identName:C,reference:R,peerNames:L,hoistPriority:U,dependencyKind:z}=h,te=e.hoistingLimits.get(E.locator);I={name:x,references:new Set([R]),locator:Rq(C,R),ident:dIe(C,R),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(L),reasons:new Map,decoupled:!0,isHoistBorder:te?te.has(x):!1,hoistPriority:U||0,dependencyKind:z||0,hoistedFrom:new Map,hoistedTo:new Map},A.set(h,I)}if(E.dependencies.set(h.name,I),E.originalDependencies.set(h.name,I),v){let x=new Set,C=R=>{if(!x.has(R)){x.add(R),R.decoupled=!1;for(let L of R.dependencies.values())R.peerNames.has(L.name)||C(L)}};C(I)}else for(let x of h.dependencies)p(x,I)};for(let h of t.dependencies)p(h,u);return u},Nq=t=>t.substring(0,t.indexOf("@",1)),EIt=t=>{let e={name:t.name,identName:Nq(t.locator),references:new Set(t.references),dependencies:new Set},r=new Set([t]),o=(a,n,u)=>{let A=r.has(a),p;if(n===a)p=u;else{let{name:h,references:E,locator:I}=a;p={name:h,identName:Nq(I),references:E,dependencies:new Set}}if(u.dependencies.add(p),!A){r.add(a);for(let h of a.dependencies.values())a.peerNames.has(h.name)||o(h,a,p);r.delete(a)}};for(let a of t.dependencies.values())o(a,t,e);return e},CIt=t=>{let e=new Map,r=new Set([t]),o=u=>`${u.name}@${u.ident}`,a=u=>{let A=o(u),p=e.get(A);return p||(p={dependents:new Set,peerDependents:new Set,hoistPriority:0},e.set(A,p)),p},n=(u,A)=>{let p=!!r.has(A);if(a(A).dependents.add(u.ident),!p){r.add(A);for(let E of A.dependencies.values()){let I=a(E);I.hoistPriority=Math.max(I.hoistPriority,E.hoistPriority),A.peerNames.has(E.name)?I.peerDependents.add(A.ident):n(A,E)}}};for(let u of t.dependencies.values())t.peerNames.has(u.name)||n(t,u);return e},no=t=>{if(!t)return"none";let e=t.indexOf("@",1),r=t.substring(0,e);r.endsWith("$wsroot$")&&(r=`wh:${r.replace("$wsroot$","")}`);let o=t.substring(e+1);if(o==="workspace:.")return".";if(o){let a=(o.indexOf("#")>0?o.split("#")[1]:o).replace("npm:","");return o.startsWith("virtual")&&(r=`v:${r}`),a.startsWith("workspace")&&(r=`w:${r}`,a=""),`${r}${a?`@${a}`:""}`}else return`${r}`};var kB=t=>{let e=0,r=(a,n,u="")=>{if(e>5e4||n.has(a))return"";e++;let A=Array.from(a.dependencies.values()).sort((h,E)=>h.name===E.name?0:h.name>E.name?1:-1),p="";n.add(a);for(let h=0;h<A.length;h++){let E=A[h];if(!a.peerNames.has(E.name)&&E!==a){let I=a.reasons.get(E.name),v=Nq(E.locator);p+=`${u}${h<A.length-1?"\u251C\u2500":"\u2514\u2500"}${(n.has(E)?">":"")+(v!==E.name?`a:${E.name}:`:"")+no(E.locator)+(I?` ${I}`:"")} +`,p+=r(E,n,`${u}${h<A.length-1?"\u2502 ":" "}`)}}return n.delete(a),p};return r(t,new Set)+(e>5e4?` +Tree is too large, part of the tree has been dunped +`:"")};var QB=(o=>(o.WORKSPACES="workspaces",o.DEPENDENCIES="dependencies",o.NONE="none",o))(QB||{}),CIe="node_modules",Oh="$wsroot$";var FB=(t,e)=>{let{packageTree:r,hoistingLimits:o,errors:a,preserveSymlinksRequired:n}=IIt(t,e),u=null;if(a.length===0){let A=yIe(r,{hoistingLimits:o});u=vIt(t,A,e)}return{tree:u,errors:a,preserveSymlinksRequired:n}},gA=t=>`${t.name}@${t.reference}`,Mq=t=>{let e=new Map;for(let[r,o]of t.entries())if(!o.dirList){let a=e.get(o.locator);a||(a={target:o.target,linkType:o.linkType,locations:[],aliases:o.aliases},e.set(o.locator,a)),a.locations.push(r)}for(let r of e.values())r.locations=r.locations.sort((o,a)=>{let n=o.split(K.delimiter).length,u=a.split(K.delimiter).length;return a===o?0:n!==u?u-n:a>o?1:-1});return e},wIe=(t,e)=>{let r=G.isVirtualLocator(t)?G.devirtualizeLocator(t):t,o=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e;return G.areLocatorsEqual(r,o)},Lq=(t,e,r,o)=>{if(t.linkType!=="SOFT")return!1;let a=ue.toPortablePath(r.resolveVirtual&&e.reference&&e.reference.startsWith("virtual:")?r.resolveVirtual(t.packageLocation):t.packageLocation);return K.contains(o,a)===null},wIt=t=>{let e=t.getPackageInformation(t.topLevel);if(e===null)throw new Error("Assertion failed: Expected the top-level package to have been registered");if(t.findPackageLocator(e.packageLocation)===null)throw new Error("Assertion failed: Expected the top-level package to have a physical locator");let o=ue.toPortablePath(e.packageLocation.slice(0,-1)),a=new Map,n={children:new Map},u=t.getDependencyTreeRoots(),A=new Map,p=new Set,h=(v,x)=>{let C=gA(v);if(p.has(C))return;p.add(C);let R=t.getPackageInformation(v);if(R){let L=x?gA(x):"";if(gA(v)!==L&&R.linkType==="SOFT"&&!v.reference.startsWith("link:")&&!Lq(R,v,t,o)){let U=IIe(R,v,t);(!A.get(U)||v.reference.startsWith("workspace:"))&&A.set(U,v)}for(let[U,z]of R.packageDependencies)z!==null&&(R.packagePeers.has(U)||h(t.getLocator(U,z),v))}};for(let v of u)h(v,null);let E=o.split(K.sep);for(let v of A.values()){let x=t.getPackageInformation(v),R=ue.toPortablePath(x.packageLocation.slice(0,-1)).split(K.sep).slice(E.length),L=n;for(let U of R){let z=L.children.get(U);z||(z={children:new Map},L.children.set(U,z)),L=z}L.workspaceLocator=v}let I=(v,x)=>{if(v.workspaceLocator){let C=gA(x),R=a.get(C);R||(R=new Set,a.set(C,R)),R.add(v.workspaceLocator)}for(let C of v.children.values())I(C,v.workspaceLocator||x)};for(let v of n.children.values())I(v,n.workspaceLocator);return a},IIt=(t,e)=>{let r=[],o=!1,a=new Map,n=wIt(t),u=t.getPackageInformation(t.topLevel);if(u===null)throw new Error("Assertion failed: Expected the top-level package to have been registered");let A=t.findPackageLocator(u.packageLocation);if(A===null)throw new Error("Assertion failed: Expected the top-level package to have a physical locator");let p=ue.toPortablePath(u.packageLocation.slice(0,-1)),h={name:A.name,identName:A.name,reference:A.reference,peerNames:u.packagePeers,dependencies:new Set,dependencyKind:1},E=new Map,I=(x,C)=>`${gA(C)}:${x}`,v=(x,C,R,L,U,z,te,ae)=>{let le=I(x,R),ce=E.get(le),Ce=!!ce;!Ce&&R.name===A.name&&R.reference===A.reference&&(ce=h,E.set(le,h));let de=Lq(C,R,t,p);if(!ce){let Ae=0;de?Ae=2:C.linkType==="SOFT"&&R.name.endsWith(Oh)&&(Ae=1),ce={name:x,identName:R.name,reference:R.reference,dependencies:new Set,peerNames:Ae===1?new Set:C.packagePeers,dependencyKind:Ae},E.set(le,ce)}let Be;if(de?Be=2:U.linkType==="SOFT"?Be=1:Be=0,ce.hoistPriority=Math.max(ce.hoistPriority||0,Be),ae&&!de){let Ae=gA({name:L.identName,reference:L.reference}),ne=a.get(Ae)||new Set;a.set(Ae,ne),ne.add(ce.name)}let Ee=new Map(C.packageDependencies);if(e.project){let Ae=e.project.workspacesByCwd.get(ue.toPortablePath(C.packageLocation.slice(0,-1)));if(Ae){let ne=new Set([...Array.from(Ae.manifest.peerDependencies.values(),Z=>G.stringifyIdent(Z)),...Array.from(Ae.manifest.peerDependenciesMeta.keys())]);for(let Z of ne)Ee.has(Z)||(Ee.set(Z,z.get(Z)||null),ce.peerNames.add(Z))}}let g=gA({name:R.name.replace(Oh,""),reference:R.reference}),me=n.get(g);if(me)for(let Ae of me)Ee.set(`${Ae.name}${Oh}`,Ae.reference);(C!==U||C.linkType!=="SOFT"||!de&&(!e.selfReferencesByCwd||e.selfReferencesByCwd.get(te)))&&L.dependencies.add(ce);let we=R!==A&&C.linkType==="SOFT"&&!R.name.endsWith(Oh)&&!de;if(!Ce&&!we){let Ae=new Map;for(let[ne,Z]of Ee)if(Z!==null){let xe=t.getLocator(ne,Z),Ne=t.getLocator(ne.replace(Oh,""),Z),ht=t.getPackageInformation(Ne);if(ht===null)throw new Error("Assertion failed: Expected the package to have been registered");let H=Lq(ht,xe,t,p);if(e.validateExternalSoftLinks&&e.project&&H){ht.packageDependencies.size>0&&(o=!0);for(let[Ye,Se]of ht.packageDependencies)if(Se!==null){let et=G.parseLocator(Array.isArray(Se)?`${Se[0]}@${Se[1]}`:`${Ye}@${Se}`);if(gA(et)!==gA(xe)){let Ue=Ee.get(Ye);if(Ue){let b=G.parseLocator(Array.isArray(Ue)?`${Ue[0]}@${Ue[1]}`:`${Ye}@${Ue}`);wIe(b,et)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(xe.name))} into ${G.prettyLocator(e.project.configuration,G.parseLocator(`${R.name}@${R.reference}`))} dependency ${G.prettyLocator(e.project.configuration,et)} conflicts with parent dependency ${G.prettyLocator(e.project.configuration,b)}`})}else{let b=Ae.get(Ye);if(b){let w=b.target,S=G.parseLocator(Array.isArray(w)?`${w[0]}@${w[1]}`:`${Ye}@${w}`);wIe(S,et)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(xe.name))} into ${G.prettyLocator(e.project.configuration,G.parseLocator(`${R.name}@${R.reference}`))} dependency ${G.prettyLocator(e.project.configuration,et)} conflicts with dependency ${G.prettyLocator(e.project.configuration,S)} from sibling portal ${G.prettyIdent(e.project.configuration,G.parseIdent(b.portal.name))}`})}else Ae.set(Ye,{target:et.reference,portal:xe})}}}}let rt=e.hoistingLimitsByCwd?.get(te),Te=H?te:K.relative(p,ue.toPortablePath(ht.packageLocation))||It.dot,Fe=e.hoistingLimitsByCwd?.get(Te);v(ne,ht,xe,ce,C,Ee,Te,rt==="dependencies"||Fe==="dependencies"||Fe==="workspaces")}}};return v(A.name,u,A,h,u,u.packageDependencies,It.dot,!1),{packageTree:h,hoistingLimits:a,errors:r,preserveSymlinksRequired:o}};function IIe(t,e,r){let o=r.resolveVirtual&&e.reference&&e.reference.startsWith("virtual:")?r.resolveVirtual(t.packageLocation):t.packageLocation;return ue.toPortablePath(o||t.packageLocation)}function BIt(t,e,r){let o=e.getLocator(t.name.replace(Oh,""),t.reference),a=e.getPackageInformation(o);if(a===null)throw new Error("Assertion failed: Expected the package to be registered");return r.pnpifyFs?{linkType:"SOFT",target:ue.toPortablePath(a.packageLocation)}:{linkType:a.linkType,target:IIe(a,t,e)}}var vIt=(t,e,r)=>{let o=new Map,a=(E,I,v)=>{let{linkType:x,target:C}=BIt(E,t,r);return{locator:gA(E),nodePath:I,target:C,linkType:x,aliases:v}},n=E=>{let[I,v]=E.split("/");return v?{scope:I,name:v}:{scope:null,name:I}},u=new Set,A=(E,I,v)=>{if(u.has(E))return;u.add(E);let x=Array.from(E.references).sort().join("#");for(let C of E.dependencies){let R=Array.from(C.references).sort().join("#");if(C.identName===E.identName.replace(Oh,"")&&R===x)continue;let L=Array.from(C.references).sort(),U={name:C.identName,reference:L[0]},{name:z,scope:te}=n(C.name),ae=te?[te,z]:[z],le=K.join(I,CIe),ce=K.join(le,...ae),Ce=`${v}/${U.name}`,de=a(U,v,L.slice(1)),Be=!1;if(de.linkType==="SOFT"&&r.project){let Ee=r.project.workspacesByCwd.get(de.target.slice(0,-1));Be=!!(Ee&&!Ee.manifest.name)}if(!C.name.endsWith(Oh)&&!Be){let Ee=o.get(ce);if(Ee){if(Ee.dirList)throw new Error(`Assertion failed: ${ce} cannot merge dir node with leaf node`);{let we=G.parseLocator(Ee.locator),Ae=G.parseLocator(de.locator);if(Ee.linkType!==de.linkType)throw new Error(`Assertion failed: ${ce} cannot merge nodes with different link types ${Ee.nodePath}/${G.stringifyLocator(we)} and ${v}/${G.stringifyLocator(Ae)}`);if(we.identHash!==Ae.identHash)throw new Error(`Assertion failed: ${ce} cannot merge nodes with different idents ${Ee.nodePath}/${G.stringifyLocator(we)} and ${v}/s${G.stringifyLocator(Ae)}`);de.aliases=[...de.aliases,...Ee.aliases,G.parseLocator(Ee.locator).reference]}}o.set(ce,de);let g=ce.split("/"),me=g.indexOf(CIe);for(let we=g.length-1;me>=0&&we>me;we--){let Ae=ue.toPortablePath(g.slice(0,we).join(K.sep)),ne=g[we],Z=o.get(Ae);if(!Z)o.set(Ae,{dirList:new Set([ne])});else if(Z.dirList){if(Z.dirList.has(ne))break;Z.dirList.add(ne)}}}A(C,de.linkType==="SOFT"?de.target:ce,Ce)}},p=a({name:e.name,reference:Array.from(e.references)[0]},"",[]),h=p.target;return o.set(h,p),A(e,h,""),o};Ge();Ge();Pt();Pt();nA();Nl();var rj={};Vt(rj,{PnpInstaller:()=>sd,PnpLinker:()=>Hh,UnplugCommand:()=>cC,default:()=>e1t,getPnpPath:()=>qh,jsInstallUtils:()=>mA,pnpUtils:()=>jB,quotePathIfNeeded:()=>o1e});Pt();var s1e=ve("url");Ge();Ge();Pt();Pt();var BIe={DEFAULT:{collapsed:!1,next:{"*":"DEFAULT"}},TOP_LEVEL:{collapsed:!1,next:{fallbackExclusionList:"FALLBACK_EXCLUSION_LIST",packageRegistryData:"PACKAGE_REGISTRY_DATA","*":"DEFAULT"}},FALLBACK_EXCLUSION_LIST:{collapsed:!1,next:{"*":"FALLBACK_EXCLUSION_ENTRIES"}},FALLBACK_EXCLUSION_ENTRIES:{collapsed:!0,next:{"*":"FALLBACK_EXCLUSION_DATA"}},FALLBACK_EXCLUSION_DATA:{collapsed:!0,next:{"*":"DEFAULT"}},PACKAGE_REGISTRY_DATA:{collapsed:!1,next:{"*":"PACKAGE_REGISTRY_ENTRIES"}},PACKAGE_REGISTRY_ENTRIES:{collapsed:!0,next:{"*":"PACKAGE_STORE_DATA"}},PACKAGE_STORE_DATA:{collapsed:!1,next:{"*":"PACKAGE_STORE_ENTRIES"}},PACKAGE_STORE_ENTRIES:{collapsed:!0,next:{"*":"PACKAGE_INFORMATION_DATA"}},PACKAGE_INFORMATION_DATA:{collapsed:!1,next:{packageDependencies:"PACKAGE_DEPENDENCIES","*":"DEFAULT"}},PACKAGE_DEPENDENCIES:{collapsed:!1,next:{"*":"PACKAGE_DEPENDENCY"}},PACKAGE_DEPENDENCY:{collapsed:!0,next:{"*":"DEFAULT"}}};function DIt(t,e,r){let o="";o+="[";for(let a=0,n=t.length;a<n;++a)o+=lQ(String(a),t[a],e,r).replace(/^ +/g,""),a+1<n&&(o+=", ");return o+="]",o}function PIt(t,e,r){let o=`${r} `,a="";a+=r,a+=`[ +`;for(let n=0,u=t.length;n<u;++n)a+=o+lQ(String(n),t[n],e,o).replace(/^ +/,""),n+1<u&&(a+=","),a+=` +`;return a+=r,a+="]",a}function SIt(t,e,r){let o=Object.keys(t),a="";a+="{";for(let n=0,u=o.length,A=0;n<u;++n){let p=o[n],h=t[p];typeof h>"u"||(A!==0&&(a+=", "),a+=JSON.stringify(p),a+=": ",a+=lQ(p,h,e,r).replace(/^ +/g,""),A+=1)}return a+="}",a}function bIt(t,e,r){let o=Object.keys(t),a=`${r} `,n="";n+=r,n+=`{ +`;let u=0;for(let A=0,p=o.length;A<p;++A){let h=o[A],E=t[h];typeof E>"u"||(u!==0&&(n+=",",n+=` +`),n+=a,n+=JSON.stringify(h),n+=": ",n+=lQ(h,E,e,a).replace(/^ +/g,""),u+=1)}return u!==0&&(n+=` +`),n+=r,n+="}",n}function lQ(t,e,r,o){let{next:a}=BIe[r],n=a[t]||a["*"];return vIe(e,n,o)}function vIe(t,e,r){let{collapsed:o}=BIe[e];return Array.isArray(t)?o?DIt(t,e,r):PIt(t,e,r):typeof t=="object"&&t!==null?o?SIt(t,e,r):bIt(t,e,r):JSON.stringify(t)}function DIe(t){return vIe(t,"TOP_LEVEL","")}function RB(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let o=[];for(let n of e)o.push(r.map(u=>n(u)));let a=r.map((n,u)=>u);return a.sort((n,u)=>{for(let A of o){let p=A[n]<A[u]?-1:A[n]>A[u]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function xIt(t){let e=new Map,r=RB(t.fallbackExclusionList||[],[({name:o,reference:a})=>o,({name:o,reference:a})=>a]);for(let{name:o,reference:a}of r){let n=e.get(o);typeof n>"u"&&e.set(o,n=new Set),n.add(a)}return Array.from(e).map(([o,a])=>[o,Array.from(a)])}function kIt(t){return RB(t.fallbackPool||[],([e])=>e)}function QIt(t){let e=[];for(let[r,o]of RB(t.packageRegistry,([a])=>a===null?"0":`1${a}`)){let a=[];e.push([r,a]);for(let[n,{packageLocation:u,packageDependencies:A,packagePeers:p,linkType:h,discardFromLookup:E}]of RB(o,([I])=>I===null?"0":`1${I}`)){let I=[];r!==null&&n!==null&&!A.has(r)&&I.push([r,n]);for(let[C,R]of RB(A.entries(),([L])=>L))I.push([C,R]);let v=p&&p.size>0?Array.from(p):void 0,x=E||void 0;a.push([n,{packageLocation:u,packageDependencies:I,packagePeers:v,linkType:h,discardFromLookup:x}])}}return e}function TB(t){return{__info:["This file is automatically generated. Do not touch it, or risk","your modifications being lost."],dependencyTreeRoots:t.dependencyTreeRoots,enableTopLevelFallback:t.enableTopLevelFallback||!1,ignorePatternData:t.ignorePattern||null,fallbackExclusionList:xIt(t),fallbackPool:kIt(t),packageRegistryData:QIt(t)}}var bIe=Ze(SIe());function xIe(t,e){return[t?`${t} +`:"",`/* eslint-disable */ +`,`// @ts-nocheck +`,`"use strict"; +`,` +`,e,` +`,(0,bIe.default)()].join("")}function FIt(t){return JSON.stringify(t,null,2)}function RIt(t){return`'${t.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,`\\ +`)}'`}function TIt(t){return[`const RAW_RUNTIME_STATE = +`,`${RIt(DIe(t))}; + +`,`function $$SETUP_STATE(hydrateRuntimeState, basePath) { +`,` return hydrateRuntimeState(JSON.parse(RAW_RUNTIME_STATE), {basePath: basePath || __dirname}); +`,`} +`].join("")}function NIt(){return[`function $$SETUP_STATE(hydrateRuntimeState, basePath) { +`,` const fs = require('fs'); +`,` const path = require('path'); +`,` const pnpDataFilepath = path.resolve(__dirname, ${JSON.stringify(dr.pnpData)}); +`,` return hydrateRuntimeState(JSON.parse(fs.readFileSync(pnpDataFilepath, 'utf8')), {basePath: basePath || __dirname}); +`,`} +`].join("")}function kIe(t){let e=TB(t),r=TIt(e);return xIe(t.shebang,r)}function QIe(t){let e=TB(t),r=NIt(),o=xIe(t.shebang,r);return{dataFile:FIt(e),loaderFile:o}}Pt();function Uq(t,{basePath:e}){let r=ue.toPortablePath(e),o=K.resolve(r),a=t.ignorePatternData!==null?new RegExp(t.ignorePatternData):null,n=new Map,u=new Map(t.packageRegistryData.map(([I,v])=>[I,new Map(v.map(([x,C])=>{if(I===null!=(x===null))throw new Error("Assertion failed: The name and reference should be null, or neither should");let R=C.discardFromLookup??!1,L={name:I,reference:x},U=n.get(C.packageLocation);U?(U.discardFromLookup=U.discardFromLookup&&R,R||(U.locator=L)):n.set(C.packageLocation,{locator:L,discardFromLookup:R});let z=null;return[x,{packageDependencies:new Map(C.packageDependencies),packagePeers:new Set(C.packagePeers),linkType:C.linkType,discardFromLookup:R,get packageLocation(){return z||(z=K.join(o,C.packageLocation))}}]}))])),A=new Map(t.fallbackExclusionList.map(([I,v])=>[I,new Set(v)])),p=new Map(t.fallbackPool),h=t.dependencyTreeRoots,E=t.enableTopLevelFallback;return{basePath:r,dependencyTreeRoots:h,enableTopLevelFallback:E,fallbackExclusionList:A,fallbackPool:p,ignorePattern:a,packageLocatorsByLocations:n,packageRegistry:u}}Pt();Pt();var ep=ve("module"),id=ve("url"),zq=ve("util");var Oo=ve("url");var NIe=Ze(ve("assert"));var _q=Array.isArray,NB=JSON.stringify,LB=Object.getOwnPropertyNames,nd=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),Hq=(t,e)=>RegExp.prototype.exec.call(t,e),qq=(t,...e)=>RegExp.prototype[Symbol.replace].apply(t,e),Uh=(t,...e)=>String.prototype.endsWith.apply(t,e),jq=(t,...e)=>String.prototype.includes.apply(t,e),Gq=(t,...e)=>String.prototype.lastIndexOf.apply(t,e),MB=(t,...e)=>String.prototype.indexOf.apply(t,e),FIe=(t,...e)=>String.prototype.replace.apply(t,e),_h=(t,...e)=>String.prototype.slice.apply(t,e),dA=(t,...e)=>String.prototype.startsWith.apply(t,e),RIe=Map,TIe=JSON.parse;function OB(t,e,r){return class extends r{constructor(...o){super(e(...o)),this.code=t,this.name=`${r.name} [${t}]`}}}var LIe=OB("ERR_PACKAGE_IMPORT_NOT_DEFINED",(t,e,r)=>`Package import specifier "${t}" is not defined${e?` in package ${e}package.json`:""} imported from ${r}`,TypeError),Yq=OB("ERR_INVALID_MODULE_SPECIFIER",(t,e,r=void 0)=>`Invalid module "${t}" ${e}${r?` imported from ${r}`:""}`,TypeError),MIe=OB("ERR_INVALID_PACKAGE_TARGET",(t,e,r,o=!1,a=void 0)=>{let n=typeof r=="string"&&!o&&r.length&&!dA(r,"./");return e==="."?((0,NIe.default)(o===!1),`Invalid "exports" main target ${NB(r)} defined in the package config ${t}package.json${a?` imported from ${a}`:""}${n?'; targets must start with "./"':""}`):`Invalid "${o?"imports":"exports"}" target ${NB(r)} defined for '${e}' in the package config ${t}package.json${a?` imported from ${a}`:""}${n?'; targets must start with "./"':""}`},Error),UB=OB("ERR_INVALID_PACKAGE_CONFIG",(t,e,r)=>`Invalid package config ${t}${e?` while importing ${e}`:""}${r?`. ${r}`:""}`,Error),OIe=OB("ERR_PACKAGE_PATH_NOT_EXPORTED",(t,e,r=void 0)=>e==="."?`No "exports" main defined in ${t}package.json${r?` imported from ${r}`:""}`:`Package subpath '${e}' is not defined by "exports" in ${t}package.json${r?` imported from ${r}`:""}`,Error);var uQ=ve("url");function UIe(t,e){let r=Object.create(null);for(let o=0;o<e.length;o++){let a=e[o];nd(t,a)&&(r[a]=t[a])}return r}var cQ=new RIe;function LIt(t,e,r,o){let a=cQ.get(t);if(a!==void 0)return a;let n=o(t);if(n===void 0){let x={pjsonPath:t,exists:!1,main:void 0,name:void 0,type:"none",exports:void 0,imports:void 0};return cQ.set(t,x),x}let u;try{u=TIe(n)}catch(x){throw new UB(t,(r?`"${e}" from `:"")+(0,uQ.fileURLToPath)(r||e),x.message)}let{imports:A,main:p,name:h,type:E}=UIe(u,["imports","main","name","type"]),I=nd(u,"exports")?u.exports:void 0;(typeof A!="object"||A===null)&&(A=void 0),typeof p!="string"&&(p=void 0),typeof h!="string"&&(h=void 0),E!=="module"&&E!=="commonjs"&&(E="none");let v={pjsonPath:t,exists:!0,main:p,name:h,type:E,exports:I,imports:A};return cQ.set(t,v),v}function _Ie(t,e){let r=new URL("./package.json",t);for(;;){let n=r.pathname;if(Uh(n,"node_modules/package.json"))break;let u=LIt((0,uQ.fileURLToPath)(r),t,void 0,e);if(u.exists)return u;let A=r;if(r=new URL("../package.json",r),r.pathname===A.pathname)break}let o=(0,uQ.fileURLToPath)(r),a={pjsonPath:o,exists:!1,main:void 0,name:void 0,type:"none",exports:void 0,imports:void 0};return cQ.set(o,a),a}function MIt(t,e,r){throw new LIe(t,e&&(0,Oo.fileURLToPath)(new URL(".",e)),(0,Oo.fileURLToPath)(r))}function OIt(t,e,r,o){let a=`request is not a valid subpath for the "${r?"imports":"exports"}" resolution of ${(0,Oo.fileURLToPath)(e)}`;throw new Yq(t,a,o&&(0,Oo.fileURLToPath)(o))}function _B(t,e,r,o,a){throw typeof e=="object"&&e!==null?e=NB(e,null,""):e=`${e}`,new MIe((0,Oo.fileURLToPath)(new URL(".",r)),t,e,o,a&&(0,Oo.fileURLToPath)(a))}var HIe=/(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i,qIe=/\*/g;function UIt(t,e,r,o,a,n,u,A){if(e!==""&&!n&&t[t.length-1]!=="/"&&_B(r,t,o,u,a),!dA(t,"./")){if(u&&!dA(t,"../")&&!dA(t,"/")){let I=!1;try{new URL(t),I=!0}catch{}if(!I)return n?qq(qIe,t,()=>e):t+e}_B(r,t,o,u,a)}Hq(HIe,_h(t,2))!==null&&_B(r,t,o,u,a);let p=new URL(t,o),h=p.pathname,E=new URL(".",o).pathname;if(dA(h,E)||_B(r,t,o,u,a),e==="")return p;if(Hq(HIe,e)!==null){let I=n?FIe(r,"*",()=>e):r+e;OIt(I,o,u,a)}return n?new URL(qq(qIe,p.href,()=>e)):new URL(e,p)}function _It(t){let e=+t;return`${e}`!==t?!1:e>=0&&e<4294967295}function lC(t,e,r,o,a,n,u,A){if(typeof e=="string")return UIt(e,r,o,t,a,n,u,A);if(_q(e)){if(e.length===0)return null;let p;for(let h=0;h<e.length;h++){let E=e[h],I;try{I=lC(t,E,r,o,a,n,u,A)}catch(v){if(p=v,v.code==="ERR_INVALID_PACKAGE_TARGET")continue;throw v}if(I!==void 0){if(I===null){p=null;continue}return I}}if(p==null)return p;throw p}else if(typeof e=="object"&&e!==null){let p=LB(e);for(let h=0;h<p.length;h++){let E=p[h];if(_It(E))throw new UB((0,Oo.fileURLToPath)(t),a,'"exports" cannot contain numeric property keys.')}for(let h=0;h<p.length;h++){let E=p[h];if(E==="default"||A.has(E)){let I=e[E],v=lC(t,I,r,o,a,n,u,A);if(v===void 0)continue;return v}}return}else if(e===null)return null;_B(o,e,t,u,a)}function GIe(t,e){let r=MB(t,"*"),o=MB(e,"*"),a=r===-1?t.length:r+1,n=o===-1?e.length:o+1;return a>n?-1:n>a||r===-1?1:o===-1||t.length>e.length?-1:e.length>t.length?1:0}function HIt(t,e,r){if(typeof t=="string"||_q(t))return!0;if(typeof t!="object"||t===null)return!1;let o=LB(t),a=!1,n=0;for(let u=0;u<o.length;u++){let A=o[u],p=A===""||A[0]!==".";if(n++===0)a=p;else if(a!==p)throw new UB((0,Oo.fileURLToPath)(e),r,`"exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.`)}return a}function Wq(t,e,r){throw new OIe((0,Oo.fileURLToPath)(new URL(".",e)),t,r&&(0,Oo.fileURLToPath)(r))}var jIe=new Set;function qIt(t,e,r){let o=(0,Oo.fileURLToPath)(e);jIe.has(o+"|"+t)||(jIe.add(o+"|"+t),process.emitWarning(`Use of deprecated trailing slash pattern mapping "${t}" in the "exports" field module resolution of the package at ${o}${r?` imported from ${(0,Oo.fileURLToPath)(r)}`:""}. Mapping specifiers ending in "/" is no longer supported.`,"DeprecationWarning","DEP0155"))}function YIe({packageJSONUrl:t,packageSubpath:e,exports:r,base:o,conditions:a}){if(HIt(r,t,o)&&(r={".":r}),nd(r,e)&&!jq(e,"*")&&!Uh(e,"/")){let p=r[e],h=lC(t,p,"",e,o,!1,!1,a);return h==null&&Wq(e,t,o),h}let n="",u,A=LB(r);for(let p=0;p<A.length;p++){let h=A[p],E=MB(h,"*");if(E!==-1&&dA(e,_h(h,0,E))){Uh(e,"/")&&qIt(e,t,o);let I=_h(h,E+1);e.length>=h.length&&Uh(e,I)&&GIe(n,h)===1&&Gq(h,"*")===E&&(n=h,u=_h(e,E,e.length-I.length))}}if(n){let p=r[n],h=lC(t,p,u,n,o,!0,!1,a);return h==null&&Wq(e,t,o),h}Wq(e,t,o)}function WIe({name:t,base:e,conditions:r,readFileSyncFn:o}){if(t==="#"||dA(t,"#/")||Uh(t,"/")){let u="is not a valid internal imports specifier name";throw new Yq(t,u,(0,Oo.fileURLToPath)(e))}let a,n=_Ie(e,o);if(n.exists){a=(0,Oo.pathToFileURL)(n.pjsonPath);let u=n.imports;if(u)if(nd(u,t)&&!jq(t,"*")){let A=lC(a,u[t],"",t,e,!1,!0,r);if(A!=null)return A}else{let A="",p,h=LB(u);for(let E=0;E<h.length;E++){let I=h[E],v=MB(I,"*");if(v!==-1&&dA(t,_h(I,0,v))){let x=_h(I,v+1);t.length>=I.length&&Uh(t,x)&&GIe(A,I)===1&&Gq(I,"*")===v&&(A=I,p=_h(t,v,t.length-x.length))}}if(A){let E=u[A],I=lC(a,E,p,A,e,!0,!0,r);if(I!=null)return I}}}MIt(t,a,e)}Pt();var jIt=new Set(["BUILTIN_NODE_RESOLUTION_FAILED","MISSING_DEPENDENCY","MISSING_PEER_DEPENDENCY","QUALIFIED_PATH_RESOLUTION_FAILED","UNDECLARED_DEPENDENCY"]);function ts(t,e,r={},o){o??=jIt.has(t)?"MODULE_NOT_FOUND":t;let a={configurable:!0,writable:!0,enumerable:!1};return Object.defineProperties(new Error(e),{code:{...a,value:o},pnpCode:{...a,value:t},data:{...a,value:r}})}function cu(t){return ue.normalize(ue.fromPortablePath(t))}var JIe=Ze(VIe());function XIe(t){return GIt(),Vq[t]}var Vq;function GIt(){Vq||(Vq={"--conditions":[],...zIe(YIt()),...zIe(process.execArgv)})}function zIe(t){return(0,JIe.default)({"--conditions":[String],"-C":"--conditions"},{argv:t,permissive:!0})}function YIt(){let t=[],e=WIt(process.env.NODE_OPTIONS||"",t);return t.length,e}function WIt(t,e){let r=[],o=!1,a=!0;for(let n=0;n<t.length;++n){let u=t[n];if(u==="\\"&&o){if(n+1===t.length)return e.push(`invalid value for NODE_OPTIONS (invalid escape) +`),r;u=t[++n]}else if(u===" "&&!o){a=!0;continue}else if(u==='"'){o=!o;continue}a?(r.push(u),a=!1):r[r.length-1]+=u}return o&&e.push(`invalid value for NODE_OPTIONS (unterminated string) +`),r}Pt();var[Ua,$f]=process.versions.node.split(".").map(t=>parseInt(t,10)),ZIe=Ua>19||Ua===19&&$f>=2||Ua===18&&$f>=13,xJt=Ua===20&&$f<6||Ua===19&&$f>=3,kJt=Ua>19||Ua===19&&$f>=6,QJt=Ua>=21||Ua===20&&$f>=10||Ua===18&&$f>=19,FJt=Ua>=21||Ua===20&&$f>=10||Ua===18&&$f>=20,RJt=Ua>=22;function $Ie(t){if(process.env.WATCH_REPORT_DEPENDENCIES&&process.send)if(t=t.map(e=>ue.fromPortablePath(zs.resolveVirtual(ue.toPortablePath(e)))),ZIe)process.send({"watch:require":t});else for(let e of t)process.send({"watch:require":e})}function Jq(t,e){let r=Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK)>0,o=Number(process.env.PNP_DEBUG_LEVEL),a=/^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:node:)?(?:@[^/]+\/)?[^/]+)\/*(.*|)$/,n=/^(\/|\.{1,2}(\/|$))/,u=/\/$/,A=/^\.{0,2}\//,p={name:null,reference:null},h=[],E=new Set;if(t.enableTopLevelFallback===!0&&h.push(p),e.compatibilityMode!==!1)for(let Te of["react-scripts","gatsby"]){let Fe=t.packageRegistry.get(Te);if(Fe)for(let ke of Fe.keys()){if(ke===null)throw new Error("Assertion failed: This reference shouldn't be null");h.push({name:Te,reference:ke})}}let{ignorePattern:I,packageRegistry:v,packageLocatorsByLocations:x}=t;function C(Te,Fe){return{fn:Te,args:Fe,error:null,result:null}}function R(Te){let Fe=process.stderr?.hasColors?.()??process.stdout.isTTY,ke=(et,Ue)=>`\x1B[${et}m${Ue}\x1B[0m`,Ye=Te.error;console.error(Ye?ke("31;1",`\u2716 ${Te.error?.message.replace(/\n.*/s,"")}`):ke("33;1","\u203C Resolution")),Te.args.length>0&&console.error();for(let et of Te.args)console.error(` ${ke("37;1","In \u2190")} ${(0,zq.inspect)(et,{colors:Fe,compact:!0})}`);Te.result&&(console.error(),console.error(` ${ke("37;1","Out \u2192")} ${(0,zq.inspect)(Te.result,{colors:Fe,compact:!0})}`));let Se=new Error().stack.match(/(?<=^ +)at.*/gm)?.slice(2)??[];if(Se.length>0){console.error();for(let et of Se)console.error(` ${ke("38;5;244",et)}`)}console.error()}function L(Te,Fe){if(e.allowDebug===!1)return Fe;if(Number.isFinite(o)){if(o>=2)return(...ke)=>{let Ye=C(Te,ke);try{return Ye.result=Fe(...ke)}catch(Se){throw Ye.error=Se}finally{R(Ye)}};if(o>=1)return(...ke)=>{try{return Fe(...ke)}catch(Ye){let Se=C(Te,ke);throw Se.error=Ye,R(Se),Ye}}}return Fe}function U(Te){let Fe=g(Te);if(!Fe)throw ts("INTERNAL","Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)");return Fe}function z(Te){if(Te.name===null)return!0;for(let Fe of t.dependencyTreeRoots)if(Fe.name===Te.name&&Fe.reference===Te.reference)return!0;return!1}let te=new Set(["node","require",...XIe("--conditions")]);function ae(Te,Fe=te,ke){let Ye=Ae(K.join(Te,"internal.js"),{resolveIgnored:!0,includeDiscardFromLookup:!0});if(Ye===null)throw ts("INTERNAL",`The locator that owns the "${Te}" path can't be found inside the dependency tree (this is probably an internal error)`);let{packageLocation:Se}=U(Ye),et=K.join(Se,dr.manifest);if(!e.fakeFs.existsSync(et))return null;let Ue=JSON.parse(e.fakeFs.readFileSync(et,"utf8"));if(Ue.exports==null)return null;let b=K.contains(Se,Te);if(b===null)throw ts("INTERNAL","unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)");b!=="."&&!A.test(b)&&(b=`./${b}`);try{let w=YIe({packageJSONUrl:(0,id.pathToFileURL)(ue.fromPortablePath(et)),packageSubpath:b,exports:Ue.exports,base:ke?(0,id.pathToFileURL)(ue.fromPortablePath(ke)):null,conditions:Fe});return ue.toPortablePath((0,id.fileURLToPath)(w))}catch(w){throw ts("EXPORTS_RESOLUTION_FAILED",w.message,{unqualifiedPath:cu(Te),locator:Ye,pkgJson:Ue,subpath:cu(b),conditions:Fe},w.code)}}function le(Te,Fe,{extensions:ke}){let Ye;try{Fe.push(Te),Ye=e.fakeFs.statSync(Te)}catch{}if(Ye&&!Ye.isDirectory())return e.fakeFs.realpathSync(Te);if(Ye&&Ye.isDirectory()){let Se;try{Se=JSON.parse(e.fakeFs.readFileSync(K.join(Te,dr.manifest),"utf8"))}catch{}let et;if(Se&&Se.main&&(et=K.resolve(Te,Se.main)),et&&et!==Te){let Ue=le(et,Fe,{extensions:ke});if(Ue!==null)return Ue}}for(let Se=0,et=ke.length;Se<et;Se++){let Ue=`${Te}${ke[Se]}`;if(Fe.push(Ue),e.fakeFs.existsSync(Ue))return Ue}if(Ye&&Ye.isDirectory())for(let Se=0,et=ke.length;Se<et;Se++){let Ue=K.format({dir:Te,name:"index",ext:ke[Se]});if(Fe.push(Ue),e.fakeFs.existsSync(Ue))return Ue}return null}function ce(Te){let Fe=new ep.Module(Te,null);return Fe.filename=Te,Fe.paths=ep.Module._nodeModulePaths(Te),Fe}function Ce(Te,Fe){return Fe.endsWith("/")&&(Fe=K.join(Fe,"internal.js")),ep.Module._resolveFilename(ue.fromPortablePath(Te),ce(ue.fromPortablePath(Fe)),!1,{plugnplay:!1})}function de(Te){if(I===null)return!1;let Fe=K.contains(t.basePath,Te);return Fe===null?!1:!!I.test(Fe.replace(/\/$/,""))}let Be={std:3,resolveVirtual:1,getAllLocators:1},Ee=p;function g({name:Te,reference:Fe}){let ke=v.get(Te);if(!ke)return null;let Ye=ke.get(Fe);return Ye||null}function me({name:Te,reference:Fe}){let ke=[];for(let[Ye,Se]of v)if(Ye!==null)for(let[et,Ue]of Se)et===null||Ue.packageDependencies.get(Te)!==Fe||Ye===Te&&et===Fe||ke.push({name:Ye,reference:et});return ke}function we(Te,Fe){let ke=new Map,Ye=new Set,Se=Ue=>{let b=JSON.stringify(Ue.name);if(Ye.has(b))return;Ye.add(b);let w=me(Ue);for(let S of w)if(U(S).packagePeers.has(Te))Se(S);else{let F=ke.get(S.name);typeof F>"u"&&ke.set(S.name,F=new Set),F.add(S.reference)}};Se(Fe);let et=[];for(let Ue of[...ke.keys()].sort())for(let b of[...ke.get(Ue)].sort())et.push({name:Ue,reference:b});return et}function Ae(Te,{resolveIgnored:Fe=!1,includeDiscardFromLookup:ke=!1}={}){if(de(Te)&&!Fe)return null;let Ye=K.relative(t.basePath,Te);Ye.match(n)||(Ye=`./${Ye}`),Ye.endsWith("/")||(Ye=`${Ye}/`);do{let Se=x.get(Ye);if(typeof Se>"u"||Se.discardFromLookup&&!ke){Ye=Ye.substring(0,Ye.lastIndexOf("/",Ye.length-2)+1);continue}return Se.locator}while(Ye!=="");return null}function ne(Te){try{return e.fakeFs.readFileSync(ue.toPortablePath(Te),"utf8")}catch(Fe){if(Fe.code==="ENOENT")return;throw Fe}}function Z(Te,Fe,{considerBuiltins:ke=!0}={}){if(Te.startsWith("#"))throw new Error("resolveToUnqualified can not handle private import mappings");if(Te==="pnpapi")return ue.toPortablePath(e.pnpapiResolution);if(ke&&(0,ep.isBuiltin)(Te))return null;let Ye=cu(Te),Se=Fe&&cu(Fe);if(Fe&&de(Fe)&&(!K.isAbsolute(Te)||Ae(Te)===null)){let b=Ce(Te,Fe);if(b===!1)throw ts("BUILTIN_NODE_RESOLUTION_FAILED",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp) + +Require request: "${Ye}" +Required by: ${Se} +`,{request:Ye,issuer:Se});return ue.toPortablePath(b)}let et,Ue=Te.match(a);if(Ue){if(!Fe)throw ts("API_ERROR","The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute",{request:Ye,issuer:Se});let[,b,w]=Ue,S=Ae(Fe);if(!S){let Re=Ce(Te,Fe);if(Re===!1)throw ts("BUILTIN_NODE_RESOLUTION_FAILED",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree). + +Require path: "${Ye}" +Required by: ${Se} +`,{request:Ye,issuer:Se});return ue.toPortablePath(Re)}let F=U(S).packageDependencies.get(b),J=null;if(F==null&&S.name!==null){let Re=t.fallbackExclusionList.get(S.name);if(!Re||!Re.has(S.reference)){for(let dt=0,jt=h.length;dt<jt;++dt){let St=U(h[dt]).packageDependencies.get(b);if(St!=null){r?J=St:F=St;break}}if(t.enableTopLevelFallback&&F==null&&J===null){let dt=t.fallbackPool.get(b);dt!=null&&(J=dt)}}}let X=null;if(F===null)if(z(S))X=ts("MISSING_PEER_DEPENDENCY",`Your application tried to access ${b} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${Se} +`,{request:Ye,issuer:Se,dependencyName:b});else{let Re=we(b,S);Re.every(at=>z(at))?X=ts("MISSING_PEER_DEPENDENCY",`${S.name} tried to access ${b} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) +${Re.map(at=>`Ancestor breaking the chain: ${at.name}@${at.reference} +`).join("")} +`,{request:Ye,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b,brokenAncestors:Re}):X=ts("MISSING_PEER_DEPENDENCY",`${S.name} tried to access ${b} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) + +${Re.map(at=>`Ancestor breaking the chain: ${at.name}@${at.reference} +`).join("")} +`,{request:Ye,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b,brokenAncestors:Re})}else F===void 0&&(!ke&&(0,ep.isBuiltin)(Te)?z(S)?X=ts("UNDECLARED_DEPENDENCY",`Your application tried to access ${b}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${b} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${Se} +`,{request:Ye,issuer:Se,dependencyName:b}):X=ts("UNDECLARED_DEPENDENCY",`${S.name} tried to access ${b}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${b} isn't otherwise declared in ${S.name}'s dependencies, this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${Se} +`,{request:Ye,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b}):z(S)?X=ts("UNDECLARED_DEPENDENCY",`Your application tried to access ${b}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${Se} +`,{request:Ye,issuer:Se,dependencyName:b}):X=ts("UNDECLARED_DEPENDENCY",`${S.name} tried to access ${b}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound. + +Required package: ${b}${b!==Ye?` (via "${Ye}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) +`,{request:Ye,issuer:Se,issuerLocator:Object.assign({},S),dependencyName:b}));if(F==null){if(J===null||X===null)throw X||new Error("Assertion failed: Expected an error to have been set");F=J;let Re=X.message.replace(/\n.*/g,"");X.message=Re,!E.has(Re)&&o!==0&&(E.add(Re),process.emitWarning(X))}let $=Array.isArray(F)?{name:F[0],reference:F[1]}:{name:b,reference:F},ie=U($);if(!ie.packageLocation)throw ts("MISSING_DEPENDENCY",`A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod. + +Required package: ${$.name}@${$.reference}${$.name!==Ye?` (via "${Ye}")`:""} +Required by: ${S.name}@${S.reference} (via ${Se}) +`,{request:Ye,issuer:Se,dependencyLocator:Object.assign({},$)});let be=ie.packageLocation;w?et=K.join(be,w):et=be}else if(K.isAbsolute(Te))et=K.normalize(Te);else{if(!Fe)throw ts("API_ERROR","The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute",{request:Ye,issuer:Se});let b=K.resolve(Fe);Fe.match(u)?et=K.normalize(K.join(b,Te)):et=K.normalize(K.join(K.dirname(b),Te))}return K.normalize(et)}function xe(Te,Fe,ke=te,Ye){if(n.test(Te))return Fe;let Se=ae(Fe,ke,Ye);return Se?K.normalize(Se):Fe}function Ne(Te,{extensions:Fe=Object.keys(ep.Module._extensions)}={}){let ke=[],Ye=le(Te,ke,{extensions:Fe});if(Ye)return K.normalize(Ye);{$Ie(ke.map(Ue=>ue.fromPortablePath(Ue)));let Se=cu(Te),et=Ae(Te);if(et){let{packageLocation:Ue}=U(et),b=!0;try{e.fakeFs.accessSync(Ue)}catch(w){if(w?.code==="ENOENT")b=!1;else{let S=(w?.message??w??"empty exception thrown").replace(/^[A-Z]/,y=>y.toLowerCase());throw ts("QUALIFIED_PATH_RESOLUTION_FAILED",`Required package exists but could not be accessed (${S}). + +Missing package: ${et.name}@${et.reference} +Expected package location: ${cu(Ue)} +`,{unqualifiedPath:Se,extensions:Fe})}}if(!b){let w=Ue.includes("/unplugged/")?"Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).":"Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.";throw ts("QUALIFIED_PATH_RESOLUTION_FAILED",`${w} + +Missing package: ${et.name}@${et.reference} +Expected package location: ${cu(Ue)} +`,{unqualifiedPath:Se,extensions:Fe})}}throw ts("QUALIFIED_PATH_RESOLUTION_FAILED",`Qualified path resolution failed: we looked for the following paths, but none could be accessed. + +Source path: ${Se} +${ke.map(Ue=>`Not found: ${cu(Ue)} +`).join("")}`,{unqualifiedPath:Se,extensions:Fe})}}function ht(Te,Fe,ke){if(!Fe)throw new Error("Assertion failed: An issuer is required to resolve private import mappings");let Ye=WIe({name:Te,base:(0,id.pathToFileURL)(ue.fromPortablePath(Fe)),conditions:ke.conditions??te,readFileSyncFn:ne});if(Ye instanceof URL)return Ne(ue.toPortablePath((0,id.fileURLToPath)(Ye)),{extensions:ke.extensions});if(Ye.startsWith("#"))throw new Error("Mapping from one private import to another isn't allowed");return H(Ye,Fe,ke)}function H(Te,Fe,ke={}){try{if(Te.startsWith("#"))return ht(Te,Fe,ke);let{considerBuiltins:Ye,extensions:Se,conditions:et}=ke,Ue=Z(Te,Fe,{considerBuiltins:Ye});if(Te==="pnpapi")return Ue;if(Ue===null)return null;let b=()=>Fe!==null?de(Fe):!1,w=(!Ye||!(0,ep.isBuiltin)(Te))&&!b()?xe(Te,Ue,et,Fe):Ue;return Ne(w,{extensions:Se})}catch(Ye){throw Object.hasOwn(Ye,"pnpCode")&&Object.assign(Ye.data,{request:cu(Te),issuer:Fe&&cu(Fe)}),Ye}}function rt(Te){let Fe=K.normalize(Te),ke=zs.resolveVirtual(Fe);return ke!==Fe?ke:null}return{VERSIONS:Be,topLevel:Ee,getLocator:(Te,Fe)=>Array.isArray(Fe)?{name:Fe[0],reference:Fe[1]}:{name:Te,reference:Fe},getDependencyTreeRoots:()=>[...t.dependencyTreeRoots],getAllLocators(){let Te=[];for(let[Fe,ke]of v)for(let Ye of ke.keys())Fe!==null&&Ye!==null&&Te.push({name:Fe,reference:Ye});return Te},getPackageInformation:Te=>{let Fe=g(Te);if(Fe===null)return null;let ke=ue.fromPortablePath(Fe.packageLocation);return{...Fe,packageLocation:ke}},findPackageLocator:Te=>Ae(ue.toPortablePath(Te)),resolveToUnqualified:L("resolveToUnqualified",(Te,Fe,ke)=>{let Ye=Fe!==null?ue.toPortablePath(Fe):null,Se=Z(ue.toPortablePath(Te),Ye,ke);return Se===null?null:ue.fromPortablePath(Se)}),resolveUnqualified:L("resolveUnqualified",(Te,Fe)=>ue.fromPortablePath(Ne(ue.toPortablePath(Te),Fe))),resolveRequest:L("resolveRequest",(Te,Fe,ke)=>{let Ye=Fe!==null?ue.toPortablePath(Fe):null,Se=H(ue.toPortablePath(Te),Ye,ke);return Se===null?null:ue.fromPortablePath(Se)}),resolveVirtual:L("resolveVirtual",Te=>{let Fe=rt(ue.toPortablePath(Te));return Fe!==null?ue.fromPortablePath(Fe):null})}}Pt();var e1e=(t,e,r)=>{let o=TB(t),a=Uq(o,{basePath:e}),n=ue.join(e,dr.pnpCjs);return Jq(a,{fakeFs:r,pnpapiResolution:n})};var Zq=Ze(r1e());qt();var mA={};Vt(mA,{checkManifestCompatibility:()=>n1e,extractBuildRequest:()=>AQ,getExtractHint:()=>$q,hasBindingGyp:()=>ej});Ge();Pt();function n1e(t){return G.isPackageCompatible(t,Xi.getArchitectureSet())}function AQ(t,e,r,{configuration:o}){let a=[];for(let n of["preinstall","install","postinstall"])e.manifest.scripts.has(n)&&a.push({type:0,script:n});return!e.manifest.scripts.has("install")&&e.misc.hasBindingGyp&&a.push({type:1,script:"node-gyp rebuild"}),a.length===0?null:t.linkType!=="HARD"?{skipped:!0,explain:n=>n.reportWarningOnce(6,`${G.prettyLocator(o,t)} lists build scripts, but is referenced through a soft link. Soft links don't support build scripts, so they'll be ignored.`)}:r&&r.built===!1?{skipped:!0,explain:n=>n.reportInfoOnce(5,`${G.prettyLocator(o,t)} lists build scripts, but its build has been explicitly disabled through configuration.`)}:!o.get("enableScripts")&&!r.built?{skipped:!0,explain:n=>n.reportWarningOnce(4,`${G.prettyLocator(o,t)} lists build scripts, but all build scripts have been disabled.`)}:n1e(t)?{skipped:!1,directives:a}:{skipped:!0,explain:n=>n.reportWarningOnce(76,`${G.prettyLocator(o,t)} The ${Xi.getArchitectureName()} architecture is incompatible with this package, build skipped.`)}}var VIt=new Set([".exe",".bin",".h",".hh",".hpp",".c",".cc",".cpp",".java",".jar",".node"]);function $q(t){return t.packageFs.getExtractHint({relevantExtensions:VIt})}function ej(t){let e=K.join(t.prefixPath,"binding.gyp");return t.packageFs.existsSync(e)}var jB={};Vt(jB,{getUnpluggedPath:()=>qB});Ge();Pt();function qB(t,{configuration:e}){return K.resolve(e.get("pnpUnpluggedFolder"),G.slugifyLocator(t))}var zIt=new Set([G.makeIdent(null,"open").identHash,G.makeIdent(null,"opn").identHash]),Hh=class{constructor(){this.mode="strict";this.pnpCache=new Map}getCustomDataKey(){return JSON.stringify({name:"PnpLinker",version:2})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the PnP linker to be enabled");let o=qh(r.project).cjs;if(!oe.existsSync(o))throw new st(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let a=He.getFactoryWithDefault(this.pnpCache,o,()=>He.dynamicRequire(o,{cachingStrategy:He.CachingStrategy.FsTime})),n={name:G.stringifyIdent(e),reference:e.reference},u=a.getPackageInformation(n);if(!u)throw new st(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed PnP map - running an install might help`);return ue.toPortablePath(u.packageLocation)}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=qh(r.project).cjs;if(!oe.existsSync(o))return null;let n=He.getFactoryWithDefault(this.pnpCache,o,()=>He.dynamicRequire(o,{cachingStrategy:He.CachingStrategy.FsTime})).findPackageLocator(ue.fromPortablePath(e));return n?G.makeLocator(G.parseIdent(n.name),n.reference):null}makeInstaller(e){return new sd(e)}isEnabled(e){return!(e.project.configuration.get("nodeLinker")!=="pnp"||e.project.configuration.get("pnpMode")!==this.mode)}},sd=class{constructor(e){this.opts=e;this.mode="strict";this.asyncActions=new He.AsyncActions(10);this.packageRegistry=new Map;this.virtualTemplates=new Map;this.isESMLoaderRequired=!1;this.customData={store:new Map};this.unpluggedPaths=new Set;this.opts=e}attachCustomData(e){this.customData=e}async installPackage(e,r,o){let a=G.stringifyIdent(e),n=e.reference,u=!!this.opts.project.tryWorkspaceByLocator(e),A=G.isVirtualLocator(e),p=e.peerDependencies.size>0&&!A,h=!p&&!u,E=!p&&e.linkType!=="SOFT",I,v;if(h||E){let te=A?G.devirtualizeLocator(e):e;I=this.customData.store.get(te.locatorHash),typeof I>"u"&&(I=await JIt(r),e.linkType==="HARD"&&this.customData.store.set(te.locatorHash,I)),I.manifest.type==="module"&&(this.isESMLoaderRequired=!0),v=this.opts.project.getDependencyMeta(te,e.version)}let x=h?AQ(e,I,v,{configuration:this.opts.project.configuration}):null,C=E?await this.unplugPackageIfNeeded(e,I,r,v,o):r.packageFs;if(K.isAbsolute(r.prefixPath))throw new Error(`Assertion failed: Expected the prefix path (${r.prefixPath}) to be relative to the parent`);let R=K.resolve(C.getRealPath(),r.prefixPath),L=tj(this.opts.project.cwd,R),U=new Map,z=new Set;if(A){for(let te of e.peerDependencies.values())U.set(G.stringifyIdent(te),null),z.add(G.stringifyIdent(te));if(!u){let te=G.devirtualizeLocator(e);this.virtualTemplates.set(te.locatorHash,{location:tj(this.opts.project.cwd,zs.resolveVirtual(R)),locator:te})}}return He.getMapWithDefault(this.packageRegistry,a).set(n,{packageLocation:L,packageDependencies:U,packagePeers:z,linkType:e.linkType,discardFromLookup:r.discardFromLookup||!1}),{packageLocation:R,buildRequest:x}}async attachInternalDependencies(e,r){let o=this.getPackageInformation(e);for(let[a,n]of r){let u=G.areIdentsEqual(a,n)?n.reference:[G.stringifyIdent(n),n.reference];o.packageDependencies.set(G.stringifyIdent(a),u)}}async attachExternalDependents(e,r){for(let o of r)this.getDiskInformation(o).packageDependencies.set(G.stringifyIdent(e),e.reference)}async finalizeInstall(){if(this.opts.project.configuration.get("pnpMode")!==this.mode)return;let e=qh(this.opts.project);if(this.isEsmEnabled()||await oe.removePromise(e.esmLoader),this.opts.project.configuration.get("nodeLinker")!=="pnp"){await oe.removePromise(e.cjs),await oe.removePromise(e.data),await oe.removePromise(e.esmLoader),await oe.removePromise(this.opts.project.configuration.get("pnpUnpluggedFolder"));return}for(let{locator:E,location:I}of this.virtualTemplates.values())He.getMapWithDefault(this.packageRegistry,G.stringifyIdent(E)).set(E.reference,{packageLocation:I,packageDependencies:new Map,packagePeers:new Set,linkType:"SOFT",discardFromLookup:!1});this.packageRegistry.set(null,new Map([[null,this.getPackageInformation(this.opts.project.topLevelWorkspace.anchoredLocator)]]));let r=this.opts.project.configuration.get("pnpFallbackMode"),o=this.opts.project.workspaces.map(({anchoredLocator:E})=>({name:G.stringifyIdent(E),reference:E.reference})),a=r!=="none",n=[],u=new Map,A=He.buildIgnorePattern([".yarn/sdks/**",...this.opts.project.configuration.get("pnpIgnorePatterns")]),p=this.packageRegistry,h=this.opts.project.configuration.get("pnpShebang");if(r==="dependencies-only")for(let E of this.opts.project.storedPackages.values())this.opts.project.tryWorkspaceByLocator(E)&&n.push({name:G.stringifyIdent(E),reference:E.reference});return await this.asyncActions.wait(),await this.finalizeInstallWithPnp({dependencyTreeRoots:o,enableTopLevelFallback:a,fallbackExclusionList:n,fallbackPool:u,ignorePattern:A,packageRegistry:p,shebang:h}),{customData:this.customData}}async transformPnpSettings(e){}isEsmEnabled(){if(this.opts.project.configuration.sources.has("pnpEnableEsmLoader"))return this.opts.project.configuration.get("pnpEnableEsmLoader");if(this.isESMLoaderRequired)return!0;for(let e of this.opts.project.workspaces)if(e.manifest.type==="module")return!0;return!1}async finalizeInstallWithPnp(e){let r=qh(this.opts.project),o=await this.locateNodeModules(e.ignorePattern);if(o.length>0){this.opts.report.reportWarning(31,"One or more node_modules have been detected and will be removed. This operation may take some time.");for(let n of o)await oe.removePromise(n)}if(await this.transformPnpSettings(e),this.opts.project.configuration.get("pnpEnableInlining")){let n=kIe(e);await oe.changeFilePromise(r.cjs,n,{automaticNewlines:!0,mode:493}),await oe.removePromise(r.data)}else{let{dataFile:n,loaderFile:u}=QIe(e);await oe.changeFilePromise(r.cjs,u,{automaticNewlines:!0,mode:493}),await oe.changeFilePromise(r.data,n,{automaticNewlines:!0,mode:420})}this.isEsmEnabled()&&(this.opts.report.reportWarning(0,"ESM support for PnP uses the experimental loader API and is therefore experimental"),await oe.changeFilePromise(r.esmLoader,(0,Zq.default)(),{automaticNewlines:!0,mode:420}));let a=this.opts.project.configuration.get("pnpUnpluggedFolder");if(this.unpluggedPaths.size===0)await oe.removePromise(a);else for(let n of await oe.readdirPromise(a)){let u=K.resolve(a,n);this.unpluggedPaths.has(u)||await oe.removePromise(u)}}async locateNodeModules(e){let r=[],o=e?new RegExp(e):null;for(let a of this.opts.project.workspaces){let n=K.join(a.cwd,"node_modules");if(o&&o.test(K.relative(this.opts.project.cwd,a.cwd))||!oe.existsSync(n))continue;let u=await oe.readdirPromise(n,{withFileTypes:!0}),A=u.filter(p=>!p.isDirectory()||p.name===".bin"||!p.name.startsWith("."));if(A.length===u.length)r.push(n);else for(let p of A)r.push(K.join(n,p.name))}return r}async unplugPackageIfNeeded(e,r,o,a,n){return this.shouldBeUnplugged(e,r,a)?this.unplugPackage(e,o,n):o.packageFs}shouldBeUnplugged(e,r,o){return typeof o.unplugged<"u"?o.unplugged:zIt.has(e.identHash)||e.conditions!=null?!0:r.manifest.preferUnplugged!==null?r.manifest.preferUnplugged:!!(AQ(e,r,o,{configuration:this.opts.project.configuration})?.skipped===!1||r.misc.extractHint)}async unplugPackage(e,r,o){let a=qB(e,{configuration:this.opts.project.configuration});return this.opts.project.disabledLocators.has(e.locatorHash)?new Hu(a,{baseFs:r.packageFs,pathUtils:K}):(this.unpluggedPaths.add(a),o.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{let n=K.join(a,r.prefixPath,".ready");await oe.existsPromise(n)||(this.opts.project.storedBuildState.delete(e.locatorHash),await oe.mkdirPromise(a,{recursive:!0}),await oe.copyPromise(a,It.dot,{baseFs:r.packageFs,overwrite:!1}),await oe.writeFilePromise(n,""))})),new gn(a))}getPackageInformation(e){let r=G.stringifyIdent(e),o=e.reference,a=this.packageRegistry.get(r);if(!a)throw new Error(`Assertion failed: The package information store should have been available (for ${G.prettyIdent(this.opts.project.configuration,e)})`);let n=a.get(o);if(!n)throw new Error(`Assertion failed: The package information should have been available (for ${G.prettyLocator(this.opts.project.configuration,e)})`);return n}getDiskInformation(e){let r=He.getMapWithDefault(this.packageRegistry,"@@disk"),o=tj(this.opts.project.cwd,e);return He.getFactoryWithDefault(r,o,()=>({packageLocation:o,packageDependencies:new Map,packagePeers:new Set,linkType:"SOFT",discardFromLookup:!1}))}};function tj(t,e){let r=K.relative(t,e);return r.match(/^\.{0,2}\//)||(r=`./${r}`),r.replace(/\/?$/,"/")}async function JIt(t){let e=await Ut.tryFind(t.prefixPath,{baseFs:t.packageFs})??new Ut,r=new Set(["preinstall","install","postinstall"]);for(let o of e.scripts.keys())r.has(o)||e.scripts.delete(o);return{manifest:{scripts:e.scripts,preferUnplugged:e.preferUnplugged,type:e.type},misc:{extractHint:$q(t),hasBindingGyp:ej(t)}}}Ge();Ge();qt();var i1e=Ze($o());var cC=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("-A,--all",!1,{description:"Unplug direct dependencies from the entire project"});this.recursive=ge.Boolean("-R,--recursive",!1,{description:"Unplug both direct and transitive dependencies"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.patterns=ge.Rest()}static{this.paths=[["unplug"]]}static{this.usage=it.Usage({description:"force the unpacking of a list of packages",details:"\n This command will add the selectors matching the specified patterns to the list of packages that must be unplugged when installed.\n\n A package being unplugged means that instead of being referenced directly through its archive, it will be unpacked at install time in the directory configured via `pnpUnpluggedFolder`. Note that unpacking packages this way is generally not recommended because it'll make it harder to store your packages within the repository. However, it's a good approach to quickly and safely debug some packages, and can even sometimes be required depending on the context (for example when the package contains shellscripts).\n\n Running the command will set a persistent flag inside your top-level `package.json`, in the `dependenciesMeta` field. As such, to undo its effects, you'll need to revert the changes made to the manifest and run `yarn install` to apply the modification.\n\n By default, only direct dependencies from the current workspace are affected. If `-A,--all` is set, direct dependencies from the entire project are affected. Using the `-R,--recursive` flag will affect transitive dependencies as well as direct ones.\n\n This command accepts glob patterns inside the scope and name components (not the range). Make sure to escape the patterns to prevent your own shell from trying to expand them.\n ",examples:[["Unplug the lodash dependency from the active workspace","yarn unplug lodash"],["Unplug all instances of lodash referenced by any workspace","yarn unplug lodash -A"],["Unplug all instances of lodash referenced by the active workspace and its dependencies","yarn unplug lodash -R"],["Unplug all instances of lodash, anywhere","yarn unplug lodash -AR"],["Unplug one specific version of lodash","yarn unplug lodash@1.2.3"],["Unplug all packages with the `@babel` scope","yarn unplug '@babel/*'"],["Unplug all packages (only for testing, not recommended)","yarn unplug -R '*'"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);if(r.get("nodeLinker")!=="pnp")throw new st("This command can only be used if the `nodeLinker` option is set to `pnp`");await o.restoreInstallState();let u=new Set(this.patterns),A=this.patterns.map(x=>{let C=G.parseDescriptor(x),R=C.range!=="unknown"?C:G.makeDescriptor(C,"*");if(!Lr.validRange(R.range))throw new st(`The range of the descriptor patterns must be a valid semver range (${G.prettyDescriptor(r,R)})`);return L=>{let U=G.stringifyIdent(L);return!i1e.default.isMatch(U,G.stringifyIdent(R))||L.version&&!Lr.satisfiesWithPrereleases(L.version,R.range)?!1:(u.delete(x),!0)}}),p=()=>{let x=[];for(let C of o.storedPackages.values())!o.tryWorkspaceByLocator(C)&&!G.isVirtualLocator(C)&&A.some(R=>R(C))&&x.push(C);return x},h=x=>{let C=new Set,R=[],L=(U,z)=>{if(C.has(U.locatorHash))return;let te=!!o.tryWorkspaceByLocator(U);if(!(z>0&&!this.recursive&&te)&&(C.add(U.locatorHash),!o.tryWorkspaceByLocator(U)&&A.some(ae=>ae(U))&&R.push(U),!(z>0&&!this.recursive)))for(let ae of U.dependencies.values()){let le=o.storedResolutions.get(ae.descriptorHash);if(!le)throw new Error("Assertion failed: The resolution should have been registered");let ce=o.storedPackages.get(le);if(!ce)throw new Error("Assertion failed: The package should have been registered");L(ce,z+1)}};for(let U of x)L(U.anchoredPackage,0);return R},E,I;if(this.all&&this.recursive?(E=p(),I="the project"):this.all?(E=h(o.workspaces),I="any workspace"):(E=h([a]),I="this workspace"),u.size>1)throw new st(`Patterns ${pe.prettyList(r,u,pe.Type.CODE)} don't match any packages referenced by ${I}`);if(u.size>0)throw new st(`Pattern ${pe.prettyList(r,u,pe.Type.CODE)} doesn't match any packages referenced by ${I}`);E=He.sortMap(E,x=>G.stringifyLocator(x));let v=await Rt.start({configuration:r,stdout:this.context.stdout,json:this.json},async x=>{for(let C of E){let R=C.version??"unknown",L=o.topLevelWorkspace.manifest.ensureDependencyMeta(G.makeDescriptor(C,R));L.unplugged=!0,x.reportInfo(0,`Will unpack ${G.prettyLocator(r,C)} to ${pe.pretty(r,qB(C,{configuration:r}),pe.Type.PATH)}`),x.reportJson({locator:G.stringifyLocator(C),version:R})}await o.topLevelWorkspace.persistManifest(),this.json||x.reportSeparator()});return v.hasErrors()?v.exitCode():await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};var qh=t=>({cjs:K.join(t.cwd,dr.pnpCjs),data:K.join(t.cwd,dr.pnpData),esmLoader:K.join(t.cwd,dr.pnpEsmLoader)}),o1e=t=>/\s/.test(t)?JSON.stringify(t):t;async function XIt(t,e,r){let o=/\s*--require\s+\S*\.pnp\.c?js\s*/g,a=/\s*--experimental-loader\s+\S*\.pnp\.loader\.mjs\s*/,n=(e.NODE_OPTIONS??"").replace(o," ").replace(a," ").trim();if(t.configuration.get("nodeLinker")!=="pnp"){e.NODE_OPTIONS=n||void 0;return}let u=qh(t),A=`--require ${o1e(ue.fromPortablePath(u.cjs))}`;oe.existsSync(u.esmLoader)&&(A=`${A} --experimental-loader ${(0,s1e.pathToFileURL)(ue.fromPortablePath(u.esmLoader)).href}`),oe.existsSync(u.cjs)&&(e.NODE_OPTIONS=n?`${A} ${n}`:A)}async function ZIt(t,e){let r=qh(t);e(r.cjs),e(r.data),e(r.esmLoader),e(t.configuration.get("pnpUnpluggedFolder"))}var $It={hooks:{populateYarnPaths:ZIt,setupScriptEnvironment:XIt},configuration:{nodeLinker:{description:'The linker used for installing Node packages, one of: "pnp", "pnpm", or "node-modules"',type:"STRING",default:"pnp"},winLinkType:{description:"Whether Yarn should use Windows Junctions or symlinks when creating links on Windows.",type:"STRING",values:["junctions","symlinks"],default:"junctions"},pnpMode:{description:"If 'strict', generates standard PnP maps. If 'loose', merges them with the n_m resolution.",type:"STRING",default:"strict"},pnpShebang:{description:"String to prepend to the generated PnP script",type:"STRING",default:"#!/usr/bin/env node"},pnpIgnorePatterns:{description:"Array of glob patterns; files matching them will use the classic resolution",type:"STRING",default:[],isArray:!0},pnpEnableEsmLoader:{description:"If true, Yarn will generate an ESM loader (`.pnp.loader.mjs`). If this is not explicitly set Yarn tries to automatically detect whether ESM support is required.",type:"BOOLEAN",default:!1},pnpEnableInlining:{description:"If true, the PnP data will be inlined along with the generated loader",type:"BOOLEAN",default:!0},pnpFallbackMode:{description:"If true, the generated PnP loader will follow the top-level fallback rule",type:"STRING",default:"dependencies-only"},pnpUnpluggedFolder:{description:"Folder where the unplugged packages must be stored",type:"ABSOLUTE_PATH",default:"./.yarn/unplugged"}},linkers:[Hh],commands:[cC]},e1t=$It;var h1e=Ze(A1e());qt();var cj=Ze(ve("crypto")),g1e=Ze(ve("fs")),d1e=1,Di="node_modules",fQ=".bin",m1e=".yarn-state.yml",m1t=1e3,uj=(o=>(o.CLASSIC="classic",o.HARDLINKS_LOCAL="hardlinks-local",o.HARDLINKS_GLOBAL="hardlinks-global",o))(uj||{}),GB=class{constructor(){this.installStateCache=new Map}getCustomDataKey(){return JSON.stringify({name:"NodeModulesLinker",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the node-modules linker to be enabled");let o=r.project.tryWorkspaceByLocator(e);if(o)return o.cwd;let a=await He.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await lj(r.project,{unrollAliases:!0}));if(a===null)throw new st("Couldn't find the node_modules state file - running an install might help (findPackageLocation)");let n=a.locatorMap.get(G.stringifyLocator(e));if(!n){let p=new st(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed node_modules map - running an install might help`);throw p.code="LOCATOR_NOT_INSTALLED",p}let u=n.locations.sort((p,h)=>p.split(K.sep).length-h.split(K.sep).length),A=K.join(r.project.configuration.startingCwd,Di);return u.find(p=>K.contains(A,p))||n.locations[0]}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=await He.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await lj(r.project,{unrollAliases:!0}));if(o===null)return null;let{locationRoot:a,segments:n}=pQ(K.resolve(e),{skipPrefix:r.project.cwd}),u=o.locationTree.get(a);if(!u)return null;let A=u.locator;for(let p of n){if(u=u.children.get(p),!u)break;A=u.locator||A}return G.parseLocator(A)}makeInstaller(e){return new aj(e)}isEnabled(e){return e.project.configuration.get("nodeLinker")==="node-modules"}},aj=class{constructor(e){this.opts=e;this.localStore=new Map;this.realLocatorChecksums=new Map;this.customData={store:new Map}}attachCustomData(e){this.customData=e}async installPackage(e,r){let o=K.resolve(r.packageFs.getRealPath(),r.prefixPath),a=this.customData.store.get(e.locatorHash);if(typeof a>"u"&&(a=await y1t(e,r),e.linkType==="HARD"&&this.customData.store.set(e.locatorHash,a)),!G.isPackageCompatible(e,this.opts.project.configuration.getSupportedArchitectures()))return{packageLocation:null,buildRequest:null};let n=new Map,u=new Set;n.has(G.stringifyIdent(e))||n.set(G.stringifyIdent(e),e.reference);let A=e;if(G.isVirtualLocator(e)){A=G.devirtualizeLocator(e);for(let E of e.peerDependencies.values())n.set(G.stringifyIdent(E),null),u.add(G.stringifyIdent(E))}let p={packageLocation:`${ue.fromPortablePath(o)}/`,packageDependencies:n,packagePeers:u,linkType:e.linkType,discardFromLookup:r.discardFromLookup??!1};this.localStore.set(e.locatorHash,{pkg:e,customPackageData:a,dependencyMeta:this.opts.project.getDependencyMeta(e,e.version),pnpNode:p});let h=r.checksum?r.checksum.substring(r.checksum.indexOf("/")+1):null;return this.realLocatorChecksums.set(A.locatorHash,h),{packageLocation:o,buildRequest:null}}async attachInternalDependencies(e,r){let o=this.localStore.get(e.locatorHash);if(typeof o>"u")throw new Error("Assertion failed: Expected information object to have been registered");for(let[a,n]of r){let u=G.areIdentsEqual(a,n)?n.reference:[G.stringifyIdent(n),n.reference];o.pnpNode.packageDependencies.set(G.stringifyIdent(a),u)}}async attachExternalDependents(e,r){throw new Error("External dependencies haven't been implemented for the node-modules linker")}async finalizeInstall(){if(this.opts.project.configuration.get("nodeLinker")!=="node-modules")return;let e=new zs({baseFs:new rA({maxOpenFiles:80,readOnlyArchives:!0})}),r=await lj(this.opts.project),o=this.opts.project.configuration.get("nmMode");(r===null||o!==r.nmMode)&&(this.opts.project.storedBuildState.clear(),r={locatorMap:new Map,binSymlinks:new Map,locationTree:new Map,nmMode:o,mtimeMs:0});let a=new Map(this.opts.project.workspaces.map(v=>{let x=this.opts.project.configuration.get("nmHoistingLimits");try{x=He.validateEnum(QB,v.manifest.installConfig?.hoistingLimits??x)}catch{let R=G.prettyWorkspace(this.opts.project.configuration,v);this.opts.report.reportWarning(57,`${R}: Invalid 'installConfig.hoistingLimits' value. Expected one of ${Object.values(QB).join(", ")}, using default: "${x}"`)}return[v.relativeCwd,x]})),n=new Map(this.opts.project.workspaces.map(v=>{let x=this.opts.project.configuration.get("nmSelfReferences");return x=v.manifest.installConfig?.selfReferences??x,[v.relativeCwd,x]})),u={VERSIONS:{std:1},topLevel:{name:null,reference:null},getLocator:(v,x)=>Array.isArray(x)?{name:x[0],reference:x[1]}:{name:v,reference:x},getDependencyTreeRoots:()=>this.opts.project.workspaces.map(v=>{let x=v.anchoredLocator;return{name:G.stringifyIdent(x),reference:x.reference}}),getPackageInformation:v=>{let x=v.reference===null?this.opts.project.topLevelWorkspace.anchoredLocator:G.makeLocator(G.parseIdent(v.name),v.reference),C=this.localStore.get(x.locatorHash);if(typeof C>"u")throw new Error("Assertion failed: Expected the package reference to have been registered");return C.pnpNode},findPackageLocator:v=>{let x=this.opts.project.tryWorkspaceByCwd(ue.toPortablePath(v));if(x!==null){let C=x.anchoredLocator;return{name:G.stringifyIdent(C),reference:C.reference}}throw new Error("Assertion failed: Unimplemented")},resolveToUnqualified:()=>{throw new Error("Assertion failed: Unimplemented")},resolveUnqualified:()=>{throw new Error("Assertion failed: Unimplemented")},resolveRequest:()=>{throw new Error("Assertion failed: Unimplemented")},resolveVirtual:v=>ue.fromPortablePath(zs.resolveVirtual(ue.toPortablePath(v)))},{tree:A,errors:p,preserveSymlinksRequired:h}=FB(u,{pnpifyFs:!1,validateExternalSoftLinks:!0,hoistingLimitsByCwd:a,project:this.opts.project,selfReferencesByCwd:n});if(!A){for(let{messageName:v,text:x}of p)this.opts.report.reportError(v,x);return}let E=Mq(A);await v1t(r,E,{baseFs:e,project:this.opts.project,report:this.opts.report,realLocatorChecksums:this.realLocatorChecksums,loadManifest:async v=>{let x=G.parseLocator(v),C=this.localStore.get(x.locatorHash);if(typeof C>"u")throw new Error("Assertion failed: Expected the slot to exist");return C.customPackageData.manifest}});let I=[];for(let[v,x]of E.entries()){if(C1e(v))continue;let C=G.parseLocator(v),R=this.localStore.get(C.locatorHash);if(typeof R>"u")throw new Error("Assertion failed: Expected the slot to exist");if(this.opts.project.tryWorkspaceByLocator(R.pkg))continue;let L=mA.extractBuildRequest(R.pkg,R.customPackageData,R.dependencyMeta,{configuration:this.opts.project.configuration});L&&I.push({buildLocations:x.locations,locator:C,buildRequest:L})}return h&&this.opts.report.reportWarning(72,`The application uses portals and that's why ${pe.pretty(this.opts.project.configuration,"--preserve-symlinks",pe.Type.CODE)} Node option is required for launching it`),{customData:this.customData,records:I}}};async function y1t(t,e){let r=await Ut.tryFind(e.prefixPath,{baseFs:e.packageFs})??new Ut,o=new Set(["preinstall","install","postinstall"]);for(let a of r.scripts.keys())o.has(a)||r.scripts.delete(a);return{manifest:{bin:r.bin,scripts:r.scripts},misc:{hasBindingGyp:mA.hasBindingGyp(e)}}}async function E1t(t,e,r,o,{installChangedByUser:a}){let n="";n+=`# Warning: This file is automatically generated. Removing it is fine, but will +`,n+=`# cause your node_modules installation to become invalidated. +`,n+=` +`,n+=`__metadata: +`,n+=` version: ${d1e} +`,n+=` nmMode: ${o.value} +`;let u=Array.from(e.keys()).sort(),A=G.stringifyLocator(t.topLevelWorkspace.anchoredLocator);for(let E of u){let I=e.get(E);n+=` +`,n+=`${JSON.stringify(E)}: +`,n+=` locations: +`;for(let v of I.locations){let x=K.contains(t.cwd,v);if(x===null)throw new Error(`Assertion failed: Expected the path to be within the project (${v})`);n+=` - ${JSON.stringify(x)} +`}if(I.aliases.length>0){n+=` aliases: +`;for(let v of I.aliases)n+=` - ${JSON.stringify(v)} +`}if(E===A&&r.size>0){n+=` bin: +`;for(let[v,x]of r){let C=K.contains(t.cwd,v);if(C===null)throw new Error(`Assertion failed: Expected the path to be within the project (${v})`);n+=` ${JSON.stringify(C)}: +`;for(let[R,L]of x){let U=K.relative(K.join(v,Di),L);n+=` ${JSON.stringify(R)}: ${JSON.stringify(U)} +`}}}}let p=t.cwd,h=K.join(p,Di,m1e);a&&await oe.removePromise(h),await oe.changeFilePromise(h,n,{automaticNewlines:!0})}async function lj(t,{unrollAliases:e=!1}={}){let r=t.cwd,o=K.join(r,Di,m1e),a;try{a=await oe.statPromise(o)}catch{}if(!a)return null;let n=Ki(await oe.readFilePromise(o,"utf8"));if(n.__metadata.version>d1e)return null;let u=n.__metadata.nmMode||"classic",A=new Map,p=new Map;delete n.__metadata;for(let[h,E]of Object.entries(n)){let I=E.locations.map(x=>K.join(r,x)),v=E.bin;if(v)for(let[x,C]of Object.entries(v)){let R=K.join(r,ue.toPortablePath(x)),L=He.getMapWithDefault(p,R);for(let[U,z]of Object.entries(C))L.set(U,ue.toPortablePath([R,Di,z].join(K.sep)))}if(A.set(h,{target:It.dot,linkType:"HARD",locations:I,aliases:E.aliases||[]}),e&&E.aliases)for(let x of E.aliases){let{scope:C,name:R}=G.parseLocator(h),L=G.makeLocator(G.makeIdent(C,R),x),U=G.stringifyLocator(L);A.set(U,{target:It.dot,linkType:"HARD",locations:I,aliases:[]})}}return{locatorMap:A,binSymlinks:p,locationTree:y1e(A,{skipPrefix:t.cwd}),nmMode:u,mtimeMs:a.mtimeMs}}var AC=async(t,e)=>{if(t.split(K.sep).indexOf(Di)<0)throw new Error(`Assertion failed: trying to remove dir that doesn't contain node_modules: ${t}`);try{if(!e.innerLoop){let o=e.allowSymlink?await oe.statPromise(t):await oe.lstatPromise(t);if(e.allowSymlink&&!o.isDirectory()||!e.allowSymlink&&o.isSymbolicLink()){await oe.unlinkPromise(t);return}}let r=await oe.readdirPromise(t,{withFileTypes:!0});for(let o of r){let a=K.join(t,o.name);o.isDirectory()?(o.name!==Di||e&&e.innerLoop)&&await AC(a,{innerLoop:!0,contentsOnly:!1}):await oe.unlinkPromise(a)}e.contentsOnly||await oe.rmdirPromise(t)}catch(r){if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw r}},f1e=4,pQ=(t,{skipPrefix:e})=>{let r=K.contains(e,t);if(r===null)throw new Error(`Assertion failed: Writing attempt prevented to ${t} which is outside project root: ${e}`);let o=r.split(K.sep).filter(p=>p!==""),a=o.indexOf(Di),n=o.slice(0,a).join(K.sep),u=K.join(e,n),A=o.slice(a);return{locationRoot:u,segments:A}},y1e=(t,{skipPrefix:e})=>{let r=new Map;if(t===null)return r;let o=()=>({children:new Map,linkType:"HARD"});for(let[a,n]of t.entries()){if(n.linkType==="SOFT"&&K.contains(e,n.target)!==null){let A=He.getFactoryWithDefault(r,n.target,o);A.locator=a,A.linkType=n.linkType}for(let u of n.locations){let{locationRoot:A,segments:p}=pQ(u,{skipPrefix:e}),h=He.getFactoryWithDefault(r,A,o);for(let E=0;E<p.length;++E){let I=p[E];if(I!=="."){let v=He.getFactoryWithDefault(h.children,I,o);h.children.set(I,v),h=v}E===p.length-1&&(h.locator=a,h.linkType=n.linkType)}}}return r},Aj=async(t,e,r)=>{if(process.platform==="win32"&&r==="junctions"){let o;try{o=await oe.lstatPromise(t)}catch{}if(!o||o.isDirectory()){await oe.symlinkPromise(t,e,"junction");return}}await oe.symlinkPromise(K.relative(K.dirname(e),t),e)};async function E1e(t,e,r){let o=K.join(t,`${cj.default.randomBytes(16).toString("hex")}.tmp`);try{await oe.writeFilePromise(o,r);try{await oe.linkPromise(o,e)}catch{}}finally{await oe.unlinkPromise(o)}}async function C1t({srcPath:t,dstPath:e,entry:r,globalHardlinksStore:o,baseFs:a,nmMode:n}){if(r.kind==="file"){if(n.value==="hardlinks-global"&&o&&r.digest){let A=K.join(o,r.digest.substring(0,2),`${r.digest.substring(2)}.dat`),p;try{let h=await oe.statPromise(A);if(h&&(!r.mtimeMs||h.mtimeMs>r.mtimeMs||h.mtimeMs<r.mtimeMs-m1t))if(await wn.checksumFile(A,{baseFs:oe,algorithm:"sha1"})!==r.digest){let I=K.join(o,`${cj.default.randomBytes(16).toString("hex")}.tmp`);await oe.renamePromise(A,I);let v=await a.readFilePromise(t);await oe.writeFilePromise(I,v);try{await oe.linkPromise(I,A),r.mtimeMs=new Date().getTime(),await oe.unlinkPromise(I)}catch{}}else r.mtimeMs||(r.mtimeMs=Math.ceil(h.mtimeMs));await oe.linkPromise(A,e),p=!0}catch{p=!1}if(!p){let h=await a.readFilePromise(t);await E1e(o,A,h),r.mtimeMs=new Date().getTime();try{await oe.linkPromise(A,e)}catch(E){E&&E.code&&E.code=="EXDEV"&&(n.value="hardlinks-local",await a.copyFilePromise(t,e))}}}else await a.copyFilePromise(t,e);let u=r.mode&511;u!==420&&await oe.chmodPromise(e,u)}}var w1t=async(t,e,{baseFs:r,globalHardlinksStore:o,nmMode:a,windowsLinkType:n,packageChecksum:u})=>{await oe.mkdirPromise(t,{recursive:!0});let A=async(E=It.dot)=>{let I=K.join(e,E),v=await r.readdirPromise(I,{withFileTypes:!0}),x=new Map;for(let C of v){let R=K.join(E,C.name),L,U=K.join(I,C.name);if(C.isFile()){if(L={kind:"file",mode:(await r.lstatPromise(U)).mode},a.value==="hardlinks-global"){let z=await wn.checksumFile(U,{baseFs:r,algorithm:"sha1"});L.digest=z}}else if(C.isDirectory())L={kind:"directory"};else if(C.isSymbolicLink())L={kind:"symlink",symlinkTo:await r.readlinkPromise(U)};else throw new Error(`Unsupported file type (file: ${U}, mode: 0o${await r.statSync(U).mode.toString(8).padStart(6,"0")})`);if(x.set(R,L),C.isDirectory()&&R!==Di){let z=await A(R);for(let[te,ae]of z)x.set(te,ae)}}return x},p;if(a.value==="hardlinks-global"&&o&&u){let E=K.join(o,u.substring(0,2),`${u.substring(2)}.json`);try{p=new Map(Object.entries(JSON.parse(await oe.readFilePromise(E,"utf8"))))}catch{p=await A()}}else p=await A();let h=!1;for(let[E,I]of p){let v=K.join(e,E),x=K.join(t,E);if(I.kind==="directory")await oe.mkdirPromise(x,{recursive:!0});else if(I.kind==="file"){let C=I.mtimeMs;await C1t({srcPath:v,dstPath:x,entry:I,nmMode:a,baseFs:r,globalHardlinksStore:o}),I.mtimeMs!==C&&(h=!0)}else I.kind==="symlink"&&await Aj(K.resolve(K.dirname(x),I.symlinkTo),x,n)}if(a.value==="hardlinks-global"&&o&&h&&u){let E=K.join(o,u.substring(0,2),`${u.substring(2)}.json`);await oe.removePromise(E),await E1e(o,E,Buffer.from(JSON.stringify(Object.fromEntries(p))))}};function I1t(t,e,r,o){let a=new Map,n=new Map,u=new Map,A=!1,p=(h,E,I,v,x)=>{let C=!0,R=K.join(h,E),L=new Set;if(E===Di||E.startsWith("@")){let z;try{z=oe.statSync(R)}catch{}C=!!z,z?z.mtimeMs>r?(A=!0,L=new Set(oe.readdirSync(R))):L=new Set(I.children.get(E).children.keys()):A=!0;let te=e.get(h);if(te){let ae=K.join(h,Di,fQ),le;try{le=oe.statSync(ae)}catch{}if(!le)A=!0;else if(le.mtimeMs>r){A=!0;let ce=new Set(oe.readdirSync(ae)),Ce=new Map;n.set(h,Ce);for(let[de,Be]of te)ce.has(de)&&Ce.set(de,Be)}else n.set(h,te)}}else C=x.has(E);let U=I.children.get(E);if(C){let{linkType:z,locator:te}=U,ae={children:new Map,linkType:z,locator:te};if(v.children.set(E,ae),te){let le=He.getSetWithDefault(u,te);le.add(R),u.set(te,le)}for(let le of U.children.keys())p(R,le,U,ae,L)}else U.locator&&o.storedBuildState.delete(G.parseLocator(U.locator).locatorHash)};for(let[h,E]of t){let{linkType:I,locator:v}=E,x={children:new Map,linkType:I,locator:v};if(a.set(h,x),v){let C=He.getSetWithDefault(u,E.locator);C.add(h),u.set(E.locator,C)}E.children.has(Di)&&p(h,Di,E,x,new Set)}return{locationTree:a,binSymlinks:n,locatorLocations:u,installChangedByUser:A}}function C1e(t){let e=G.parseDescriptor(t);return G.isVirtualDescriptor(e)&&(e=G.devirtualizeDescriptor(e)),e.range.startsWith("link:")}async function B1t(t,e,r,{loadManifest:o}){let a=new Map;for(let[A,{locations:p}]of t){let h=C1e(A)?null:await o(A,p[0]),E=new Map;if(h)for(let[I,v]of h.bin){let x=K.join(p[0],v);v!==""&&oe.existsSync(x)&&E.set(I,v)}a.set(A,E)}let n=new Map,u=(A,p,h)=>{let E=new Map,I=K.contains(r,A);if(h.locator&&I!==null){let v=a.get(h.locator);for(let[x,C]of v){let R=K.join(A,ue.toPortablePath(C));E.set(x,R)}for(let[x,C]of h.children){let R=K.join(A,x),L=u(R,R,C);L.size>0&&n.set(A,new Map([...n.get(A)||new Map,...L]))}}else for(let[v,x]of h.children){let C=u(K.join(A,v),p,x);for(let[R,L]of C)E.set(R,L)}return E};for(let[A,p]of e){let h=u(A,A,p);h.size>0&&n.set(A,new Map([...n.get(A)||new Map,...h]))}return n}var p1e=(t,e)=>{if(!t||!e)return t===e;let r=G.parseLocator(t);G.isVirtualLocator(r)&&(r=G.devirtualizeLocator(r));let o=G.parseLocator(e);return G.isVirtualLocator(o)&&(o=G.devirtualizeLocator(o)),G.areLocatorsEqual(r,o)};function fj(t){return K.join(t.get("globalFolder"),"store")}async function v1t(t,e,{baseFs:r,project:o,report:a,loadManifest:n,realLocatorChecksums:u}){let A=K.join(o.cwd,Di),{locationTree:p,binSymlinks:h,locatorLocations:E,installChangedByUser:I}=I1t(t.locationTree,t.binSymlinks,t.mtimeMs,o),v=y1e(e,{skipPrefix:o.cwd}),x=[],C=async({srcDir:Be,dstDir:Ee,linkType:g,globalHardlinksStore:me,nmMode:we,windowsLinkType:Ae,packageChecksum:ne})=>{let Z=(async()=>{try{g==="SOFT"?(await oe.mkdirPromise(K.dirname(Ee),{recursive:!0}),await Aj(K.resolve(Be),Ee,Ae)):await w1t(Ee,Be,{baseFs:r,globalHardlinksStore:me,nmMode:we,windowsLinkType:Ae,packageChecksum:ne})}catch(xe){throw xe.message=`While persisting ${Be} -> ${Ee} ${xe.message}`,xe}finally{ae.tick()}})().then(()=>x.splice(x.indexOf(Z),1));x.push(Z),x.length>f1e&&await Promise.race(x)},R=async(Be,Ee,g)=>{let me=(async()=>{let we=async(Ae,ne,Z)=>{try{Z.innerLoop||await oe.mkdirPromise(ne,{recursive:!0});let xe=await oe.readdirPromise(Ae,{withFileTypes:!0});for(let Ne of xe){if(!Z.innerLoop&&Ne.name===fQ)continue;let ht=K.join(Ae,Ne.name),H=K.join(ne,Ne.name);Ne.isDirectory()?(Ne.name!==Di||Z&&Z.innerLoop)&&(await oe.mkdirPromise(H,{recursive:!0}),await we(ht,H,{...Z,innerLoop:!0})):Ce.value==="hardlinks-local"||Ce.value==="hardlinks-global"?await oe.linkPromise(ht,H):await oe.copyFilePromise(ht,H,g1e.default.constants.COPYFILE_FICLONE)}}catch(xe){throw Z.innerLoop||(xe.message=`While cloning ${Ae} -> ${ne} ${xe.message}`),xe}finally{Z.innerLoop||ae.tick()}};await we(Be,Ee,g)})().then(()=>x.splice(x.indexOf(me),1));x.push(me),x.length>f1e&&await Promise.race(x)},L=async(Be,Ee,g)=>{if(g)for(let[me,we]of Ee.children){let Ae=g.children.get(me);await L(K.join(Be,me),we,Ae)}else{Ee.children.has(Di)&&await AC(K.join(Be,Di),{contentsOnly:!1});let me=K.basename(Be)===Di&&v.has(K.join(K.dirname(Be),K.sep));await AC(Be,{contentsOnly:Be===A,allowSymlink:me})}};for(let[Be,Ee]of p){let g=v.get(Be);for(let[me,we]of Ee.children){if(me===".")continue;let Ae=g&&g.children.get(me),ne=K.join(Be,me);await L(ne,we,Ae)}}let U=async(Be,Ee,g)=>{if(g){p1e(Ee.locator,g.locator)||await AC(Be,{contentsOnly:Ee.linkType==="HARD"});for(let[me,we]of Ee.children){let Ae=g.children.get(me);await U(K.join(Be,me),we,Ae)}}else{Ee.children.has(Di)&&await AC(K.join(Be,Di),{contentsOnly:!0});let me=K.basename(Be)===Di&&v.has(K.join(K.dirname(Be),K.sep));await AC(Be,{contentsOnly:Ee.linkType==="HARD",allowSymlink:me})}};for(let[Be,Ee]of v){let g=p.get(Be);for(let[me,we]of Ee.children){if(me===".")continue;let Ae=g&&g.children.get(me);await U(K.join(Be,me),we,Ae)}}let z=new Map,te=[];for(let[Be,Ee]of E)for(let g of Ee){let{locationRoot:me,segments:we}=pQ(g,{skipPrefix:o.cwd}),Ae=v.get(me),ne=me;if(Ae){for(let Z of we)if(ne=K.join(ne,Z),Ae=Ae.children.get(Z),!Ae)break;if(Ae){let Z=p1e(Ae.locator,Be),xe=e.get(Ae.locator),Ne=xe.target,ht=ne,H=xe.linkType;if(Z)z.has(Ne)||z.set(Ne,ht);else if(Ne!==ht){let rt=G.parseLocator(Ae.locator);G.isVirtualLocator(rt)&&(rt=G.devirtualizeLocator(rt)),te.push({srcDir:Ne,dstDir:ht,linkType:H,realLocatorHash:rt.locatorHash})}}}}for(let[Be,{locations:Ee}]of e.entries())for(let g of Ee){let{locationRoot:me,segments:we}=pQ(g,{skipPrefix:o.cwd}),Ae=p.get(me),ne=v.get(me),Z=me,xe=e.get(Be),Ne=G.parseLocator(Be);G.isVirtualLocator(Ne)&&(Ne=G.devirtualizeLocator(Ne));let ht=Ne.locatorHash,H=xe.target,rt=g;if(H===rt)continue;let Te=xe.linkType;for(let Fe of we)ne=ne.children.get(Fe);if(!Ae)te.push({srcDir:H,dstDir:rt,linkType:Te,realLocatorHash:ht});else for(let Fe of we)if(Z=K.join(Z,Fe),Ae=Ae.children.get(Fe),!Ae){te.push({srcDir:H,dstDir:rt,linkType:Te,realLocatorHash:ht});break}}let ae=Zs.progressViaCounter(te.length),le=a.reportProgress(ae),ce=o.configuration.get("nmMode"),Ce={value:ce},de=o.configuration.get("winLinkType");try{let Be=Ce.value==="hardlinks-global"?`${fj(o.configuration)}/v1`:null;if(Be&&!await oe.existsPromise(Be)){await oe.mkdirpPromise(Be);for(let g=0;g<256;g++)await oe.mkdirPromise(K.join(Be,g.toString(16).padStart(2,"0")))}for(let g of te)(g.linkType==="SOFT"||!z.has(g.srcDir))&&(z.set(g.srcDir,g.dstDir),await C({...g,globalHardlinksStore:Be,nmMode:Ce,windowsLinkType:de,packageChecksum:u.get(g.realLocatorHash)||null}));await Promise.all(x),x.length=0;for(let g of te){let me=z.get(g.srcDir);g.linkType!=="SOFT"&&g.dstDir!==me&&await R(me,g.dstDir,{nmMode:Ce})}await Promise.all(x),await oe.mkdirPromise(A,{recursive:!0});let Ee=await B1t(e,v,o.cwd,{loadManifest:n});await D1t(h,Ee,o.cwd,de),await E1t(o,e,Ee,Ce,{installChangedByUser:I}),ce=="hardlinks-global"&&Ce.value=="hardlinks-local"&&a.reportWarningOnce(74,"'nmMode' has been downgraded to 'hardlinks-local' due to global cache and install folder being on different devices")}finally{le.stop()}}async function D1t(t,e,r,o){for(let a of t.keys()){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);if(!e.has(a)){let n=K.join(a,Di,fQ);await oe.removePromise(n)}}for(let[a,n]of e){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);let u=K.join(a,Di,fQ),A=t.get(a)||new Map;await oe.mkdirPromise(u,{recursive:!0});for(let p of A.keys())n.has(p)||(await oe.removePromise(K.join(u,p)),process.platform==="win32"&&await oe.removePromise(K.join(u,`${p}.cmd`)));for(let[p,h]of n){let E=A.get(p),I=K.join(u,p);E!==h&&(process.platform==="win32"?await(0,h1e.default)(ue.fromPortablePath(h),ue.fromPortablePath(I),{createPwshFile:!1}):(await oe.removePromise(I),await Aj(h,I,o),K.contains(r,await oe.realpathPromise(h))!==null&&await oe.chmodPromise(h,493)))}}}Ge();Pt();nA();var YB=class extends Hh{constructor(){super(...arguments);this.mode="loose"}makeInstaller(r){return new pj(r)}},pj=class extends sd{constructor(){super(...arguments);this.mode="loose"}async transformPnpSettings(r){let o=new zs({baseFs:new rA({maxOpenFiles:80,readOnlyArchives:!0})}),a=e1e(r,this.opts.project.cwd,o),{tree:n,errors:u}=FB(a,{pnpifyFs:!1,project:this.opts.project});if(!n){for(let{messageName:I,text:v}of u)this.opts.report.reportError(I,v);return}let A=new Map;r.fallbackPool=A;let p=(I,v)=>{let x=G.parseLocator(v.locator),C=G.stringifyIdent(x);C===I?A.set(I,x.reference):A.set(I,[C,x.reference])},h=K.join(this.opts.project.cwd,dr.nodeModules),E=n.get(h);if(!(typeof E>"u")){if("target"in E)throw new Error("Assertion failed: Expected the root junction point to be a directory");for(let I of E.dirList){let v=K.join(h,I),x=n.get(v);if(typeof x>"u")throw new Error("Assertion failed: Expected the child to have been registered");if("target"in x)p(I,x);else for(let C of x.dirList){let R=K.join(v,C),L=n.get(R);if(typeof L>"u")throw new Error("Assertion failed: Expected the subchild to have been registered");if("target"in L)p(`${I}/${C}`,L);else throw new Error("Assertion failed: Expected the leaf junction to be a package")}}}}};var P1t={hooks:{cleanGlobalArtifacts:async t=>{let e=fj(t);await oe.removePromise(e)}},configuration:{nmHoistingLimits:{description:"Prevents packages to be hoisted past specific levels",type:"STRING",values:["workspaces","dependencies","none"],default:"none"},nmMode:{description:"Defines in which measure Yarn must use hardlinks and symlinks when generated `node_modules` directories.",type:"STRING",values:["classic","hardlinks-local","hardlinks-global"],default:"classic"},nmSelfReferences:{description:"Defines whether the linker should generate self-referencing symlinks for workspaces.",type:"BOOLEAN",default:!0}},linkers:[GB,YB]},S1t=P1t;var f5={};Vt(f5,{NpmHttpFetcher:()=>VB,NpmRemapResolver:()=>zB,NpmSemverFetcher:()=>tp,NpmSemverResolver:()=>JB,NpmTagResolver:()=>XB,default:()=>qvt,npmConfigUtils:()=>Zn,npmHttpUtils:()=>Zr,npmPublishUtils:()=>PC});Ge();var b1e=Ze(Jn());var Wn="npm:";var Zr={};Vt(Zr,{AuthType:()=>D1e,customPackageError:()=>od,del:()=>U1t,get:()=>ad,getIdentUrl:()=>hQ,getPackageMetadata:()=>hC,handleInvalidAuthenticationError:()=>jh,post:()=>M1t,put:()=>O1t});Ge();Ge();Pt();var mj=Ze(J1()),B1e=Ze(y_()),v1e=Ze(Jn());var Zn={};Vt(Zn,{RegistryType:()=>w1e,getAuditRegistry:()=>b1t,getAuthConfiguration:()=>dj,getDefaultRegistry:()=>WB,getPublishRegistry:()=>x1t,getRegistryConfiguration:()=>I1e,getScopeConfiguration:()=>gj,getScopeRegistry:()=>fC,normalizeRegistry:()=>ac});var w1e=(o=>(o.AUDIT_REGISTRY="npmAuditRegistry",o.FETCH_REGISTRY="npmRegistryServer",o.PUBLISH_REGISTRY="npmPublishRegistry",o))(w1e||{});function ac(t){return t.replace(/\/$/,"")}function b1t({configuration:t}){return WB({configuration:t,type:"npmAuditRegistry"})}function x1t(t,{configuration:e}){return t.publishConfig?.registry?ac(t.publishConfig.registry):t.name?fC(t.name.scope,{configuration:e,type:"npmPublishRegistry"}):WB({configuration:e,type:"npmPublishRegistry"})}function fC(t,{configuration:e,type:r="npmRegistryServer"}){let o=gj(t,{configuration:e});if(o===null)return WB({configuration:e,type:r});let a=o.get(r);return a===null?WB({configuration:e,type:r}):ac(a)}function WB({configuration:t,type:e="npmRegistryServer"}){let r=t.get(e);return ac(r!==null?r:t.get("npmRegistryServer"))}function I1e(t,{configuration:e}){let r=e.get("npmRegistries"),o=ac(t),a=r.get(o);if(typeof a<"u")return a;let n=r.get(o.replace(/^[a-z]+:/,""));return typeof n<"u"?n:null}function gj(t,{configuration:e}){if(t===null)return null;let o=e.get("npmScopes").get(t);return o||null}function dj(t,{configuration:e,ident:r}){let o=r&&gj(r.scope,{configuration:e});return o?.get("npmAuthIdent")||o?.get("npmAuthToken")?o:I1e(t,{configuration:e})||e}var D1e=(a=>(a[a.NO_AUTH=0]="NO_AUTH",a[a.BEST_EFFORT=1]="BEST_EFFORT",a[a.CONFIGURATION=2]="CONFIGURATION",a[a.ALWAYS_AUTH=3]="ALWAYS_AUTH",a))(D1e||{});async function jh(t,{attemptedAs:e,registry:r,headers:o,configuration:a}){if(dQ(t))throw new Jt(41,"Invalid OTP token");if(t.originalError?.name==="HTTPError"&&t.originalError?.response.statusCode===401)throw new Jt(41,`Invalid authentication (${typeof e!="string"?`as ${await H1t(r,o,{configuration:a})}`:`attempted as ${e}`})`)}function od(t,e){let r=t.response?.statusCode;return r?r===404?"Package not found":r>=500&&r<600?`The registry appears to be down (using a ${pe.applyHyperlink(e,"local cache","https://yarnpkg.com/advanced/lexicon#local-cache")} might have protected you against such outages)`:null:null}function hQ(t){return t.scope?`/@${t.scope}%2f${t.name}`:`/${t.name}`}var P1e=new Map,k1t=new Map;async function Q1t(t){return await He.getFactoryWithDefault(P1e,t,async()=>{let e=null;try{e=await oe.readJsonPromise(t)}catch{}return e})}async function F1t(t,e,{configuration:r,cached:o,registry:a,headers:n,version:u,...A}){return await He.getFactoryWithDefault(k1t,t,async()=>await ad(hQ(e),{...A,customErrorMessage:od,configuration:r,registry:a,ident:e,headers:{...n,"If-None-Match":o?.etag,"If-Modified-Since":o?.lastModified},wrapNetworkRequest:async p=>async()=>{let h=await p();if(h.statusCode===304){if(o===null)throw new Error("Assertion failed: cachedMetadata should not be null");return{...h,body:o.metadata}}let E=R1t(JSON.parse(h.body.toString())),I={metadata:E,etag:h.headers.etag,lastModified:h.headers["last-modified"]};return P1e.set(t,Promise.resolve(I)),Promise.resolve().then(async()=>{let v=`${t}-${process.pid}.tmp`;await oe.mkdirPromise(K.dirname(v),{recursive:!0}),await oe.writeJsonPromise(v,I,{compact:!0}),await oe.renamePromise(v,t)}).catch(()=>{}),{...h,body:E}}}))}async function hC(t,{cache:e,project:r,registry:o,headers:a,version:n,...u}){let{configuration:A}=r;o=KB(A,{ident:t,registry:o});let p=N1t(A,o),h=K.join(p,`${G.slugifyIdent(t)}.json`),E=null;if(!r.lockfileNeedsRefresh&&(E=await Q1t(h),E)){if(typeof n<"u"&&typeof E.metadata.versions[n]<"u")return E.metadata;if(A.get("enableOfflineMode")){let I=structuredClone(E.metadata),v=new Set;if(e){for(let C of Object.keys(I.versions)){let R=G.makeLocator(t,`npm:${C}`),L=e.getLocatorMirrorPath(R);(!L||!oe.existsSync(L))&&(delete I.versions[C],v.add(C))}let x=I["dist-tags"].latest;if(v.has(x)){let C=Object.keys(E.metadata.versions).sort(v1e.default.compare),R=C.indexOf(x);for(;v.has(C[R])&&R>=0;)R-=1;R>=0?I["dist-tags"].latest=C[R]:delete I["dist-tags"].latest}}return I}}return await F1t(h,t,{...u,configuration:A,cached:E,registry:o,headers:a,version:n})}var S1e=["name","dist.tarball","bin","scripts","os","cpu","libc","dependencies","dependenciesMeta","optionalDependencies","peerDependencies","peerDependenciesMeta","deprecated"];function R1t(t){return{"dist-tags":t["dist-tags"],versions:Object.fromEntries(Object.entries(t.versions).map(([e,r])=>[e,(0,B1e.default)(r,S1e)]))}}var T1t=wn.makeHash(...S1e).slice(0,6);function N1t(t,e){let r=L1t(t),o=new URL(e);return K.join(r,T1t,o.hostname)}function L1t(t){return K.join(t.get("globalFolder"),"metadata/npm")}async function ad(t,{configuration:e,headers:r,ident:o,authType:a,registry:n,...u}){n=KB(e,{ident:o,registry:n}),o&&o.scope&&typeof a>"u"&&(a=1);let A=await gQ(n,{authType:a,configuration:e,ident:o});A&&(r={...r,authorization:A});try{return await sn.get(t.charAt(0)==="/"?`${n}${t}`:t,{configuration:e,headers:r,...u})}catch(p){throw await jh(p,{registry:n,configuration:e,headers:r}),p}}async function M1t(t,e,{attemptedAs:r,configuration:o,headers:a,ident:n,authType:u=3,registry:A,otp:p,...h}){A=KB(o,{ident:n,registry:A});let E=await gQ(A,{authType:u,configuration:o,ident:n});E&&(a={...a,authorization:E}),p&&(a={...a,...pC(p)});try{return await sn.post(A+t,e,{configuration:o,headers:a,...h})}catch(I){if(!dQ(I)||p)throw await jh(I,{attemptedAs:r,registry:A,configuration:o,headers:a}),I;p=await yj(I,{configuration:o});let v={...a,...pC(p)};try{return await sn.post(`${A}${t}`,e,{configuration:o,headers:v,...h})}catch(x){throw await jh(x,{attemptedAs:r,registry:A,configuration:o,headers:a}),x}}}async function O1t(t,e,{attemptedAs:r,configuration:o,headers:a,ident:n,authType:u=3,registry:A,otp:p,...h}){A=KB(o,{ident:n,registry:A});let E=await gQ(A,{authType:u,configuration:o,ident:n});E&&(a={...a,authorization:E}),p&&(a={...a,...pC(p)});try{return await sn.put(A+t,e,{configuration:o,headers:a,...h})}catch(I){if(!dQ(I))throw await jh(I,{attemptedAs:r,registry:A,configuration:o,headers:a}),I;p=await yj(I,{configuration:o});let v={...a,...pC(p)};try{return await sn.put(`${A}${t}`,e,{configuration:o,headers:v,...h})}catch(x){throw await jh(x,{attemptedAs:r,registry:A,configuration:o,headers:a}),x}}}async function U1t(t,{attemptedAs:e,configuration:r,headers:o,ident:a,authType:n=3,registry:u,otp:A,...p}){u=KB(r,{ident:a,registry:u});let h=await gQ(u,{authType:n,configuration:r,ident:a});h&&(o={...o,authorization:h}),A&&(o={...o,...pC(A)});try{return await sn.del(u+t,{configuration:r,headers:o,...p})}catch(E){if(!dQ(E)||A)throw await jh(E,{attemptedAs:e,registry:u,configuration:r,headers:o}),E;A=await yj(E,{configuration:r});let I={...o,...pC(A)};try{return await sn.del(`${u}${t}`,{configuration:r,headers:I,...p})}catch(v){throw await jh(v,{attemptedAs:e,registry:u,configuration:r,headers:o}),v}}}function KB(t,{ident:e,registry:r}){if(typeof r>"u"&&e)return fC(e.scope,{configuration:t});if(typeof r!="string")throw new Error("Assertion failed: The registry should be a string");return ac(r)}async function gQ(t,{authType:e=2,configuration:r,ident:o}){let a=dj(t,{configuration:r,ident:o}),n=_1t(a,e);if(!n)return null;let u=await r.reduceHook(A=>A.getNpmAuthenticationHeader,void 0,t,{configuration:r,ident:o});if(u)return u;if(a.get("npmAuthToken"))return`Bearer ${a.get("npmAuthToken")}`;if(a.get("npmAuthIdent")){let A=a.get("npmAuthIdent");return A.includes(":")?`Basic ${Buffer.from(A).toString("base64")}`:`Basic ${A}`}if(n&&e!==1)throw new Jt(33,"No authentication configured for request");return null}function _1t(t,e){switch(e){case 2:return t.get("npmAlwaysAuth");case 1:case 3:return!0;case 0:return!1;default:throw new Error("Unreachable")}}async function H1t(t,e,{configuration:r}){if(typeof e>"u"||typeof e.authorization>"u")return"an anonymous user";try{return(await sn.get(new URL(`${t}/-/whoami`).href,{configuration:r,headers:e,jsonResponse:!0})).username??"an unknown user"}catch{return"an unknown user"}}async function yj(t,{configuration:e}){let r=t.originalError?.response.headers["npm-notice"];if(r&&(await Rt.start({configuration:e,stdout:process.stdout,includeFooter:!1},async a=>{if(a.reportInfo(0,r.replace(/(https?:\/\/\S+)/g,pe.pretty(e,"$1",pe.Type.URL))),!process.env.YARN_IS_TEST_ENV){let n=r.match(/open (https?:\/\/\S+)/i);if(n&&Xi.openUrl){let{openNow:u}=await(0,mj.prompt)({type:"confirm",name:"openNow",message:"Do you want to try to open this url now?",required:!0,initial:!0,onCancel:()=>process.exit(130)});u&&(await Xi.openUrl(n[1])||(a.reportSeparator(),a.reportWarning(0,"We failed to automatically open the url; you'll have to open it yourself in your browser of choice.")))}}}),process.stdout.write(` +`)),process.env.YARN_IS_TEST_ENV)return process.env.YARN_INJECT_NPM_2FA_TOKEN||"";let{otp:o}=await(0,mj.prompt)({type:"password",name:"otp",message:"One-time password:",required:!0,onCancel:()=>process.exit(130)});return process.stdout.write(` +`),o}function dQ(t){if(t.originalError?.name!=="HTTPError")return!1;try{return(t.originalError?.response.headers["www-authenticate"].split(/,\s*/).map(r=>r.toLowerCase())).includes("otp")}catch{return!1}}function pC(t){return{"npm-otp":t}}var VB=class{supports(e,r){if(!e.reference.startsWith(Wn))return!1;let{selector:o,params:a}=G.parseRange(e.reference);return!(!b1e.default.valid(o)||a===null||typeof a.__archiveUrl!="string")}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let{params:o}=G.parseRange(e.reference);if(o===null||typeof o.__archiveUrl!="string")throw new Error("Assertion failed: The archiveUrl querystring parameter should have been available");let a=await ad(o.__archiveUrl,{customErrorMessage:od,configuration:r.project.configuration,ident:e});return await $i.convertToZip(a,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ge();var zB=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Wn)||!G.tryParseDescriptor(e.range.slice(Wn.length),!0))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Unreachable")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){let o=r.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Wn.length),!0));return r.resolver.getResolutionDependencies(o,r)}async getCandidates(e,r,o){let a=o.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Wn.length),!0));return await o.resolver.getCandidates(a,r,o)}async getSatisfying(e,r,o,a){let n=a.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Wn.length),!0));return a.resolver.getSatisfying(n,r,o,a)}resolve(e,r){throw new Error("Unreachable")}};Ge();Ge();var x1e=Ze(Jn());var tp=class t{supports(e,r){if(!e.reference.startsWith(Wn))return!1;let o=new URL(e.reference);return!(!x1e.default.valid(o.pathname)||o.searchParams.has("__archiveUrl"))}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote registry`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o;try{o=await ad(t.getLocatorUrl(e),{customErrorMessage:od,configuration:r.project.configuration,ident:e})}catch{o=await ad(t.getLocatorUrl(e).replace(/%2f/g,"/"),{customErrorMessage:od,configuration:r.project.configuration,ident:e})}return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}static isConventionalTarballUrl(e,r,{configuration:o}){let a=fC(e.scope,{configuration:o}),n=t.getLocatorUrl(e);return r=r.replace(/^https?:(\/\/(?:[^/]+\.)?npmjs.org(?:$|\/))/,"https:$1"),a=a.replace(/^https:\/\/registry\.npmjs\.org($|\/)/,"https://registry.yarnpkg.com$1"),r=r.replace(/^https:\/\/registry\.npmjs\.org($|\/)/,"https://registry.yarnpkg.com$1"),r===a+n||r===a+n.replace(/%2f/g,"/")}static getLocatorUrl(e){let r=Lr.clean(e.reference.slice(Wn.length));if(r===null)throw new Jt(10,"The npm semver resolver got selected, but the version isn't semver");return`${hQ(e)}/-/${e.name}-${r}.tgz`}};Ge();Ge();Ge();var Ej=Ze(Jn());var mQ=G.makeIdent(null,"node-gyp"),q1t=/\b(node-gyp|prebuild-install)\b/,JB=class{supportsDescriptor(e,r){return e.range.startsWith(Wn)?!!Lr.validRange(e.range.slice(Wn.length)):!1}supportsLocator(e,r){if(!e.reference.startsWith(Wn))return!1;let{selector:o}=G.parseRange(e.reference);return!!Ej.default.valid(o)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=Lr.validRange(e.range.slice(Wn.length));if(a===null)throw new Error(`Expected a valid range, got ${e.range.slice(Wn.length)}`);let n=await hC(e,{cache:o.fetchOptions?.cache,project:o.project,version:Ej.default.valid(a.raw)?a.raw:void 0}),u=He.mapAndFilter(Object.keys(n.versions),h=>{try{let E=new Lr.SemVer(h);if(a.test(E))return E}catch{}return He.mapAndFilter.skip}),A=u.filter(h=>!n.versions[h.raw].deprecated),p=A.length>0?A:u;return p.sort((h,E)=>-h.compare(E)),p.map(h=>{let E=G.makeLocator(e,`${Wn}${h.raw}`),I=n.versions[h.raw].dist.tarball;return tp.isConventionalTarballUrl(E,I,{configuration:o.project.configuration})?E:G.bindLocator(E,{__archiveUrl:I})})}async getSatisfying(e,r,o,a){let n=Lr.validRange(e.range.slice(Wn.length));if(n===null)throw new Error(`Expected a valid range, got ${e.range.slice(Wn.length)}`);return{locators:He.mapAndFilter(o,p=>{if(p.identHash!==e.identHash)return He.mapAndFilter.skip;let h=G.tryParseRange(p.reference,{requireProtocol:Wn});if(!h)return He.mapAndFilter.skip;let E=new Lr.SemVer(h.selector);return n.test(E)?{locator:p,version:E}:He.mapAndFilter.skip}).sort((p,h)=>-p.version.compare(h.version)).map(({locator:p})=>p),sorted:!0}}async resolve(e,r){let{selector:o}=G.parseRange(e.reference),a=Lr.clean(o);if(a===null)throw new Jt(10,"The npm semver resolver got selected, but the version isn't semver");let n=await hC(e,{cache:r.fetchOptions?.cache,project:r.project,version:a});if(!Object.hasOwn(n,"versions"))throw new Jt(15,'Registry returned invalid data for - missing "versions" field');if(!Object.hasOwn(n.versions,a))throw new Jt(16,`Registry failed to return reference "${a}"`);let u=new Ut;if(u.load(n.versions[a]),!u.dependencies.has(mQ.identHash)&&!u.peerDependencies.has(mQ.identHash)){for(let A of u.scripts.values())if(A.match(q1t)){u.dependencies.set(mQ.identHash,G.makeDescriptor(mQ,"latest"));break}}return{...e,version:a,languageName:"node",linkType:"HARD",conditions:u.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(u.dependencies),peerDependencies:u.peerDependencies,dependenciesMeta:u.dependenciesMeta,peerDependenciesMeta:u.peerDependenciesMeta,bin:u.bin}}};Ge();Ge();var k1e=Ze(Jn());var XB=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Wn)||!ly.test(e.range.slice(Wn.length)))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Unreachable")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Wn.length),n=await hC(e,{cache:o.fetchOptions?.cache,project:o.project});if(!Object.hasOwn(n,"dist-tags"))throw new Jt(15,'Registry returned invalid data - missing "dist-tags" field');let u=n["dist-tags"];if(!Object.hasOwn(u,a))throw new Jt(16,`Registry failed to return tag "${a}"`);let A=u[a],p=G.makeLocator(e,`${Wn}${A}`),h=n.versions[A].dist.tarball;return tp.isConventionalTarballUrl(p,h,{configuration:o.project.configuration})?[p]:[G.bindLocator(p,{__archiveUrl:h})]}async getSatisfying(e,r,o,a){let n=[];for(let u of o){if(u.identHash!==e.identHash)continue;let A=G.tryParseRange(u.reference,{requireProtocol:Wn});if(!(!A||!k1e.default.valid(A.selector))){if(A.params?.__archiveUrl){let p=G.makeRange({protocol:Wn,selector:A.selector,source:null,params:null}),[h]=await a.resolver.getCandidates(G.makeDescriptor(e,p),r,a);if(u.reference!==h.reference)continue}n.push(u)}}return{locators:n,sorted:!1}}async resolve(e,r){throw new Error("Unreachable")}};var PC={};Vt(PC,{getGitHead:()=>_vt,getPublishAccess:()=>EBe,getReadmeContent:()=>CBe,makePublishBody:()=>Uvt});Ge();Ge();Pt();var a5={};Vt(a5,{PackCommand:()=>DC,default:()=>wvt,packUtils:()=>CA});Ge();Ge();Ge();Pt();qt();var CA={};Vt(CA,{genPackList:()=>_Q,genPackStream:()=>o5,genPackageManifest:()=>aBe,hasPackScripts:()=>i5,prepareForPack:()=>s5});Ge();Pt();var n5=Ze($o()),sBe=Ze(tBe()),oBe=ve("zlib"),uvt=["/package.json","/readme","/readme.*","/license","/license.*","/licence","/licence.*","/changelog","/changelog.*"],Avt=["/package.tgz",".github",".git",".hg","node_modules",".npmignore",".gitignore",".#*",".DS_Store"];async function i5(t){return!!(An.hasWorkspaceScript(t,"prepack")||An.hasWorkspaceScript(t,"postpack"))}async function s5(t,{report:e},r){await An.maybeExecuteWorkspaceLifecycleScript(t,"prepack",{report:e});try{let o=K.join(t.cwd,Ut.fileName);await oe.existsPromise(o)&&await t.manifest.loadFile(o,{baseFs:oe}),await r()}finally{await An.maybeExecuteWorkspaceLifecycleScript(t,"postpack",{report:e})}}async function o5(t,e){typeof e>"u"&&(e=await _Q(t));let r=new Set;for(let n of t.manifest.publishConfig?.executableFiles??new Set)r.add(K.normalize(n));for(let n of t.manifest.bin.values())r.add(K.normalize(n));let o=sBe.default.pack();process.nextTick(async()=>{for(let n of e){let u=K.normalize(n),A=K.resolve(t.cwd,u),p=K.join("package",u),h=await oe.lstatPromise(A),E={name:p,mtime:new Date(Bi.SAFE_TIME*1e3)},I=r.has(u)?493:420,v,x,C=new Promise((L,U)=>{v=L,x=U}),R=L=>{L?x(L):v()};if(h.isFile()){let L;u==="package.json"?L=Buffer.from(JSON.stringify(await aBe(t),null,2)):L=await oe.readFilePromise(A),o.entry({...E,mode:I,type:"file"},L,R)}else h.isSymbolicLink()?o.entry({...E,mode:I,type:"symlink",linkname:await oe.readlinkPromise(A)},R):R(new Error(`Unsupported file type ${h.mode} for ${ue.fromPortablePath(u)}`));await C}o.finalize()});let a=(0,oBe.createGzip)();return o.pipe(a),a}async function aBe(t){let e=JSON.parse(JSON.stringify(t.manifest.raw));return await t.project.configuration.triggerHook(r=>r.beforeWorkspacePacking,t,e),e}async function _Q(t){let e=t.project,r=e.configuration,o={accept:[],reject:[]};for(let I of Avt)o.reject.push(I);for(let I of uvt)o.accept.push(I);o.reject.push(r.get("rcFilename"));let a=I=>{if(I===null||!I.startsWith(`${t.cwd}/`))return;let v=K.relative(t.cwd,I),x=K.resolve(It.root,v);o.reject.push(x)};a(K.resolve(e.cwd,dr.lockfile)),a(r.get("cacheFolder")),a(r.get("globalFolder")),a(r.get("installStatePath")),a(r.get("virtualFolder")),a(r.get("yarnPath")),await r.triggerHook(I=>I.populateYarnPaths,e,I=>{a(I)});for(let I of e.workspaces){let v=K.relative(t.cwd,I.cwd);v!==""&&!v.match(/^(\.\.)?\//)&&o.reject.push(`/${v}`)}let n={accept:[],reject:[]},u=t.manifest.publishConfig?.main??t.manifest.main,A=t.manifest.publishConfig?.module??t.manifest.module,p=t.manifest.publishConfig?.browser??t.manifest.browser,h=t.manifest.publishConfig?.bin??t.manifest.bin;u!=null&&n.accept.push(K.resolve(It.root,u)),A!=null&&n.accept.push(K.resolve(It.root,A)),typeof p=="string"&&n.accept.push(K.resolve(It.root,p));for(let I of h.values())n.accept.push(K.resolve(It.root,I));if(p instanceof Map)for(let[I,v]of p.entries())n.accept.push(K.resolve(It.root,I)),typeof v=="string"&&n.accept.push(K.resolve(It.root,v));let E=t.manifest.files!==null;if(E){n.reject.push("/*");for(let I of t.manifest.files)lBe(n.accept,I,{cwd:It.root})}return await fvt(t.cwd,{hasExplicitFileList:E,globalList:o,ignoreList:n})}async function fvt(t,{hasExplicitFileList:e,globalList:r,ignoreList:o}){let a=[],n=new qu(t),u=[[It.root,[o]]];for(;u.length>0;){let[A,p]=u.pop(),h=await n.lstatPromise(A);if(!nBe(A,{globalList:r,ignoreLists:h.isDirectory()?null:p}))if(h.isDirectory()){let E=await n.readdirPromise(A),I=!1,v=!1;if(!e||A!==It.root)for(let R of E)I=I||R===".gitignore",v=v||R===".npmignore";let x=v?await rBe(n,A,".npmignore"):I?await rBe(n,A,".gitignore"):null,C=x!==null?[x].concat(p):p;nBe(A,{globalList:r,ignoreLists:p})&&(C=[...p,{accept:[],reject:["**/*"]}]);for(let R of E)u.push([K.resolve(A,R),C])}else(h.isFile()||h.isSymbolicLink())&&a.push(K.relative(It.root,A))}return a.sort()}async function rBe(t,e,r){let o={accept:[],reject:[]},a=await t.readFilePromise(K.join(e,r),"utf8");for(let n of a.split(/\n/g))lBe(o.reject,n,{cwd:e});return o}function pvt(t,{cwd:e}){let r=t[0]==="!";return r&&(t=t.slice(1)),t.match(/\.{0,1}\//)&&(t=K.resolve(e,t)),r&&(t=`!${t}`),t}function lBe(t,e,{cwd:r}){let o=e.trim();o===""||o[0]==="#"||t.push(pvt(o,{cwd:r}))}function nBe(t,{globalList:e,ignoreLists:r}){let o=UQ(t,e.accept);if(o!==0)return o===2;let a=UQ(t,e.reject);if(a!==0)return a===1;if(r!==null)for(let n of r){let u=UQ(t,n.accept);if(u!==0)return u===2;let A=UQ(t,n.reject);if(A!==0)return A===1}return!1}function UQ(t,e){let r=e,o=[];for(let a=0;a<e.length;++a)e[a][0]!=="!"?r!==e&&r.push(e[a]):(r===e&&(r=e.slice(0,a)),o.push(e[a].slice(1)));return iBe(t,o)?2:iBe(t,r)?1:0}function iBe(t,e){let r=e,o=[];for(let a=0;a<e.length;++a)e[a].includes("/")?r!==e&&r.push(e[a]):(r===e&&(r=e.slice(0,a)),o.push(e[a]));return!!(n5.default.isMatch(t,r,{dot:!0,nocase:!0})||n5.default.isMatch(t,o,{dot:!0,basename:!0,nocase:!0}))}var DC=class extends ut{constructor(){super(...arguments);this.installIfNeeded=ge.Boolean("--install-if-needed",!1,{description:"Run a preliminary `yarn install` if the package contains build scripts"});this.dryRun=ge.Boolean("-n,--dry-run",!1,{description:"Print the file paths without actually generating the package archive"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.out=ge.String("-o,--out",{description:"Create the archive at the specified path"});this.filename=ge.String("--filename",{hidden:!0})}static{this.paths=[["pack"]]}static{this.usage=it.Usage({description:"generate a tarball from the active workspace",details:"\n This command will turn the active workspace into a compressed archive suitable for publishing. The archive will by default be stored at the root of the workspace (`package.tgz`).\n\n If the `-o,---out` is set the archive will be created at the specified path. The `%s` and `%v` variables can be used within the path and will be respectively replaced by the package name and version.\n ",examples:[["Create an archive from the active workspace","yarn pack"],["List the files that would be made part of the workspace's archive","yarn pack --dry-run"],["Name and output the archive in a dedicated folder","yarn pack --out /artifacts/%s-%v.tgz"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);await i5(a)&&(this.installIfNeeded?await o.install({cache:await Gr.find(r),report:new ki}):await o.restoreInstallState());let n=this.out??this.filename,u=typeof n<"u"?K.resolve(this.context.cwd,hvt(n,{workspace:a})):K.resolve(a.cwd,"package.tgz");return(await Rt.start({configuration:r,stdout:this.context.stdout,json:this.json},async p=>{await s5(a,{report:p},async()=>{p.reportJson({base:ue.fromPortablePath(a.cwd)});let h=await _Q(a);for(let E of h)p.reportInfo(null,ue.fromPortablePath(E)),p.reportJson({location:ue.fromPortablePath(E)});if(!this.dryRun){let E=await o5(a,h),I=oe.createWriteStream(u);E.pipe(I),await new Promise(v=>{I.on("finish",v)})}}),this.dryRun||(p.reportInfo(0,`Package archive generated in ${pe.pretty(r,u,pe.Type.PATH)}`),p.reportJson({output:ue.fromPortablePath(u)}))})).exitCode()}};function hvt(t,{workspace:e}){let r=t.replace("%s",gvt(e)).replace("%v",dvt(e));return ue.toPortablePath(r)}function gvt(t){return t.manifest.name!==null?G.slugifyIdent(t.manifest.name):"package"}function dvt(t){return t.manifest.version!==null?t.manifest.version:"unknown"}var mvt=["dependencies","devDependencies","peerDependencies"],yvt="workspace:",Evt=(t,e)=>{e.publishConfig&&(e.publishConfig.type&&(e.type=e.publishConfig.type),e.publishConfig.main&&(e.main=e.publishConfig.main),e.publishConfig.browser&&(e.browser=e.publishConfig.browser),e.publishConfig.module&&(e.module=e.publishConfig.module),e.publishConfig.exports&&(e.exports=e.publishConfig.exports),e.publishConfig.imports&&(e.imports=e.publishConfig.imports),e.publishConfig.bin&&(e.bin=e.publishConfig.bin));let r=t.project;for(let o of mvt)for(let a of t.manifest.getForScope(o).values()){let n=r.tryWorkspaceByDescriptor(a),u=G.parseRange(a.range);if(u.protocol===yvt)if(n===null){if(r.tryWorkspaceByIdent(a)===null)throw new Jt(21,`${G.prettyDescriptor(r.configuration,a)}: No local workspace found for this range`)}else{let A;G.areDescriptorsEqual(a,n.anchoredDescriptor)||u.selector==="*"?A=n.manifest.version??"0.0.0":u.selector==="~"||u.selector==="^"?A=`${u.selector}${n.manifest.version??"0.0.0"}`:A=u.selector;let p=o==="dependencies"?G.makeDescriptor(a,"unknown"):null,h=p!==null&&t.manifest.ensureDependencyMeta(p).optional?"optionalDependencies":o;e[h][G.stringifyIdent(a)]=A}}},Cvt={hooks:{beforeWorkspacePacking:Evt},commands:[DC]},wvt=Cvt;var mBe=ve("crypto"),yBe=Ze(dBe());async function Uvt(t,e,{access:r,tag:o,registry:a,gitHead:n}){let u=t.manifest.name,A=t.manifest.version,p=G.stringifyIdent(u),h=(0,mBe.createHash)("sha1").update(e).digest("hex"),E=yBe.default.fromData(e).toString(),I=r??EBe(t,u),v=await CBe(t),x=await CA.genPackageManifest(t),C=`${p}-${A}.tgz`,R=new URL(`${ac(a)}/${p}/-/${C}`);return{_id:p,_attachments:{[C]:{content_type:"application/octet-stream",data:e.toString("base64"),length:e.length}},name:p,access:I,"dist-tags":{[o]:A},versions:{[A]:{...x,_id:`${p}@${A}`,name:p,version:A,gitHead:n,dist:{shasum:h,integrity:E,tarball:R.toString()}}},readme:v}}async function _vt(t){try{let{stdout:e}=await Ur.execvp("git",["rev-parse","--revs-only","HEAD"],{cwd:t});return e.trim()===""?void 0:e.trim()}catch{return}}function EBe(t,e){let r=t.project.configuration;return t.manifest.publishConfig&&typeof t.manifest.publishConfig.access=="string"?t.manifest.publishConfig.access:r.get("npmPublishAccess")!==null?r.get("npmPublishAccess"):e.scope?"restricted":"public"}async function CBe(t){let e=ue.toPortablePath(`${t.cwd}/README.md`),r=t.manifest.name,a=`# ${G.stringifyIdent(r)} +`;try{a=await oe.readFilePromise(e,"utf8")}catch(n){if(n.code==="ENOENT")return a;throw n}return a}var A5={npmAlwaysAuth:{description:"URL of the selected npm registry (note: npm enterprise isn't supported)",type:"BOOLEAN",default:!1},npmAuthIdent:{description:"Authentication identity for the npm registry (_auth in npm and yarn v1)",type:"SECRET",default:null},npmAuthToken:{description:"Authentication token for the npm registry (_authToken in npm and yarn v1)",type:"SECRET",default:null}},wBe={npmAuditRegistry:{description:"Registry to query for audit reports",type:"STRING",default:null},npmPublishRegistry:{description:"Registry to push packages to",type:"STRING",default:null},npmRegistryServer:{description:"URL of the selected npm registry (note: npm enterprise isn't supported)",type:"STRING",default:"https://registry.yarnpkg.com"}},Hvt={configuration:{...A5,...wBe,npmScopes:{description:"Settings per package scope",type:"MAP",valueDefinition:{description:"",type:"SHAPE",properties:{...A5,...wBe}}},npmRegistries:{description:"Settings per registry",type:"MAP",normalizeKeys:ac,valueDefinition:{description:"",type:"SHAPE",properties:{...A5}}}},fetchers:[VB,tp],resolvers:[zB,JB,XB]},qvt=Hvt;var w5={};Vt(w5,{NpmAuditCommand:()=>bC,NpmInfoCommand:()=>xC,NpmLoginCommand:()=>kC,NpmLogoutCommand:()=>FC,NpmPublishCommand:()=>RC,NpmTagAddCommand:()=>NC,NpmTagListCommand:()=>TC,NpmTagRemoveCommand:()=>LC,NpmWhoamiCommand:()=>MC,default:()=>zvt,npmAuditTypes:()=>dv,npmAuditUtils:()=>HQ});Ge();Ge();qt();var m5=Ze($o());el();var dv={};Vt(dv,{Environment:()=>hv,Severity:()=>gv});var hv=(o=>(o.All="all",o.Production="production",o.Development="development",o))(hv||{}),gv=(n=>(n.Info="info",n.Low="low",n.Moderate="moderate",n.High="high",n.Critical="critical",n))(gv||{});var HQ={};Vt(HQ,{allSeverities:()=>SC,getPackages:()=>d5,getReportTree:()=>h5,getSeverityInclusions:()=>p5,getTopLevelDependencies:()=>g5});Ge();var IBe=Ze(Jn());var SC=["info","low","moderate","high","critical"];function p5(t){if(typeof t>"u")return new Set(SC);let e=SC.indexOf(t),r=SC.slice(e);return new Set(r)}function h5(t){let e={},r={children:e};for(let[o,a]of He.sortMap(Object.entries(t),n=>n[0]))for(let n of He.sortMap(a,u=>`${u.id}`))e[`${o}/${n.id}`]={value:pe.tuple(pe.Type.IDENT,G.parseIdent(o)),children:{ID:typeof n.id<"u"&&{label:"ID",value:pe.tuple(pe.Type.ID,n.id)},Issue:{label:"Issue",value:pe.tuple(pe.Type.NO_HINT,n.title)},URL:typeof n.url<"u"&&{label:"URL",value:pe.tuple(pe.Type.URL,n.url)},Severity:{label:"Severity",value:pe.tuple(pe.Type.NO_HINT,n.severity)},"Vulnerable Versions":{label:"Vulnerable Versions",value:pe.tuple(pe.Type.RANGE,n.vulnerable_versions)},"Tree Versions":{label:"Tree Versions",children:[...n.versions].sort(IBe.default.compare).map(u=>({value:pe.tuple(pe.Type.REFERENCE,u)}))},Dependents:{label:"Dependents",children:He.sortMap(n.dependents,u=>G.stringifyLocator(u)).map(u=>({value:pe.tuple(pe.Type.LOCATOR,u)}))}}};return r}function g5(t,e,{all:r,environment:o}){let a=[],n=r?t.workspaces:[e],u=["all","production"].includes(o),A=["all","development"].includes(o);for(let p of n)for(let h of p.anchoredPackage.dependencies.values())(p.manifest.devDependencies.has(h.identHash)?!A:!u)||a.push({workspace:p,dependency:h});return a}function d5(t,e,{recursive:r}){let o=new Map,a=new Set,n=[],u=(A,p)=>{let h=t.storedResolutions.get(p.descriptorHash);if(typeof h>"u")throw new Error("Assertion failed: The resolution should have been registered");if(!a.has(h))a.add(h);else return;let E=t.storedPackages.get(h);if(typeof E>"u")throw new Error("Assertion failed: The package should have been registered");if(G.ensureDevirtualizedLocator(E).reference.startsWith("npm:")&&E.version!==null){let v=G.stringifyIdent(E),x=He.getMapWithDefault(o,v);He.getArrayWithDefault(x,E.version).push(A)}if(r)for(let v of E.dependencies.values())n.push([E,v])};for(let{workspace:A,dependency:p}of e)n.push([A.anchoredLocator,p]);for(;n.length>0;){let[A,p]=n.shift();u(A,p)}return o}var bC=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("-A,--all",!1,{description:"Audit dependencies from all workspaces"});this.recursive=ge.Boolean("-R,--recursive",!1,{description:"Audit transitive dependencies as well"});this.environment=ge.String("--environment","all",{description:"Which environments to cover",validator:Js(hv)});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.noDeprecations=ge.Boolean("--no-deprecations",!1,{description:"Don't warn about deprecated packages"});this.severity=ge.String("--severity","info",{description:"Minimal severity requested for packages to be displayed",validator:Js(gv)});this.excludes=ge.Array("--exclude",[],{description:"Array of glob patterns of packages to exclude from audit"});this.ignores=ge.Array("--ignore",[],{description:"Array of glob patterns of advisory ID's to ignore in the audit report"})}static{this.paths=[["npm","audit"]]}static{this.usage=it.Usage({description:"perform a vulnerability audit against the installed packages",details:` + This command checks for known security reports on the packages you use. The reports are by default extracted from the npm registry, and may or may not be relevant to your actual program (not all vulnerabilities affect all code paths). + + For consistency with our other commands the default is to only check the direct dependencies for the active workspace. To extend this search to all workspaces, use \`-A,--all\`. To extend this search to both direct and transitive dependencies, use \`-R,--recursive\`. + + Applying the \`--severity\` flag will limit the audit table to vulnerabilities of the corresponding severity and above. Valid values are ${SC.map(r=>`\`${r}\``).join(", ")}. + + If the \`--json\` flag is set, Yarn will print the output exactly as received from the registry. Regardless of this flag, the process will exit with a non-zero exit code if a report is found for the selected packages. + + If certain packages produce false positives for a particular environment, the \`--exclude\` flag can be used to exclude any number of packages from the audit. This can also be set in the configuration file with the \`npmAuditExcludePackages\` option. + + If particular advisories are needed to be ignored, the \`--ignore\` flag can be used with Advisory ID's to ignore any number of advisories in the audit report. This can also be set in the configuration file with the \`npmAuditIgnoreAdvisories\` option. + + To understand the dependency tree requiring vulnerable packages, check the raw report with the \`--json\` flag or use \`yarn why package\` to get more information as to who depends on them. + `,examples:[["Checks for known security issues with the installed packages. The output is a list of known issues.","yarn npm audit"],["Audit dependencies in all workspaces","yarn npm audit --all"],["Limit auditing to `dependencies` (excludes `devDependencies`)","yarn npm audit --environment production"],["Show audit report as valid JSON","yarn npm audit --json"],["Audit all direct and transitive dependencies","yarn npm audit --recursive"],["Output moderate (or more severe) vulnerabilities","yarn npm audit --severity moderate"],["Exclude certain packages","yarn npm audit --exclude package1 --exclude package2"],["Ignore specific advisories","yarn npm audit --ignore 1234567 --ignore 7654321"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState();let n=g5(o,a,{all:this.all,environment:this.environment}),u=d5(o,n,{recursive:this.recursive}),A=Array.from(new Set([...r.get("npmAuditExcludePackages"),...this.excludes])),p=Object.create(null);for(let[L,U]of u)A.some(z=>m5.default.isMatch(L,z))||(p[L]=[...U.keys()]);let h=Zn.getAuditRegistry({configuration:r}),E,I=await AA.start({configuration:r,stdout:this.context.stdout},async()=>{let L=Zr.post("/-/npm/v1/security/advisories/bulk",p,{authType:Zr.AuthType.BEST_EFFORT,configuration:r,jsonResponse:!0,registry:h}),U=this.noDeprecations?[]:await Promise.all(Array.from(Object.entries(p),async([te,ae])=>{let le=await Zr.getPackageMetadata(G.parseIdent(te),{project:o});return He.mapAndFilter(ae,ce=>{let{deprecated:Ce}=le.versions[ce];return Ce?[te,ce,Ce]:He.mapAndFilter.skip})})),z=await L;for(let[te,ae,le]of U.flat(1))Object.hasOwn(z,te)&&z[te].some(ce=>Lr.satisfiesWithPrereleases(ae,ce.vulnerable_versions))||(z[te]??=[],z[te].push({id:`${te} (deprecation)`,title:le.trim()||"This package has been deprecated.",severity:"moderate",vulnerable_versions:ae}));E=z});if(I.hasErrors())return I.exitCode();let v=p5(this.severity),x=Array.from(new Set([...r.get("npmAuditIgnoreAdvisories"),...this.ignores])),C=Object.create(null);for(let[L,U]of Object.entries(E)){let z=U.filter(te=>!m5.default.isMatch(`${te.id}`,x)&&v.has(te.severity));z.length>0&&(C[L]=z.map(te=>{let ae=u.get(L);if(typeof ae>"u")throw new Error("Assertion failed: Expected the registry to only return packages that were requested");let le=[...ae.keys()].filter(Ce=>Lr.satisfiesWithPrereleases(Ce,te.vulnerable_versions)),ce=new Map;for(let Ce of le)for(let de of ae.get(Ce))ce.set(de.locatorHash,de);return{...te,versions:le,dependents:[...ce.values()]}}))}let R=Object.keys(C).length>0;return R?(fs.emitTree(h5(C),{configuration:r,json:this.json,stdout:this.context.stdout,separators:2}),1):(await Rt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async L=>{L.reportInfo(1,"No audit suggestions")}),R?1:0)}};Ge();Ge();Pt();qt();var y5=Ze(Jn()),E5=ve("util"),xC=class extends ut{constructor(){super(...arguments);this.fields=ge.String("-f,--fields",{description:"A comma-separated list of manifest fields that should be displayed"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.packages=ge.Rest()}static{this.paths=[["npm","info"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"show information about a package",details:"\n This command fetches information about a package from the npm registry and prints it in a tree format.\n\n The package does not have to be installed locally, but needs to have been published (in particular, local changes will be ignored even for workspaces).\n\n Append `@<range>` to the package argument to provide information specific to the latest version that satisfies the range or to the corresponding tagged version. If the range is invalid or if there is no version satisfying the range, the command will print a warning and fall back to the latest version.\n\n If the `-f,--fields` option is set, it's a comma-separated list of fields which will be used to only display part of the package information.\n\n By default, this command won't return the `dist`, `readme`, and `users` fields, since they are often very long. To explicitly request those fields, explicitly list them with the `--fields` flag or request the output in JSON mode.\n ",examples:[["Show all available information about react (except the `dist`, `readme`, and `users` fields)","yarn npm info react"],["Show all available information about react as valid JSON (including the `dist`, `readme`, and `users` fields)","yarn npm info react --json"],["Show all available information about react@16.12.0","yarn npm info react@16.12.0"],["Show all available information about react@next","yarn npm info react@next"],["Show the description of react","yarn npm info react --fields description"],["Show all available versions of react","yarn npm info react --fields versions"],["Show the readme of react","yarn npm info react --fields readme"],["Show a few fields of react","yarn npm info react --fields homepage,repository"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd),a=typeof this.fields<"u"?new Set(["name",...this.fields.split(/\s*,\s*/)]):null,n=[],u=!1,A=await Rt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async p=>{for(let h of this.packages){let E;if(h==="."){let ae=o.topLevelWorkspace;if(!ae.manifest.name)throw new st(`Missing ${pe.pretty(r,"name",pe.Type.CODE)} field in ${ue.fromPortablePath(K.join(ae.cwd,dr.manifest))}`);E=G.makeDescriptor(ae.manifest.name,"unknown")}else E=G.parseDescriptor(h);let I=Zr.getIdentUrl(E),v=C5(await Zr.get(I,{configuration:r,ident:E,jsonResponse:!0,customErrorMessage:Zr.customPackageError})),x=Object.keys(v.versions).sort(y5.default.compareLoose),R=v["dist-tags"].latest||x[x.length-1],L=Lr.validRange(E.range);if(L){let ae=y5.default.maxSatisfying(x,L);ae!==null?R=ae:(p.reportWarning(0,`Unmet range ${G.prettyRange(r,E.range)}; falling back to the latest version`),u=!0)}else Object.hasOwn(v["dist-tags"],E.range)?R=v["dist-tags"][E.range]:E.range!=="unknown"&&(p.reportWarning(0,`Unknown tag ${G.prettyRange(r,E.range)}; falling back to the latest version`),u=!0);let U=v.versions[R],z={...v,...U,version:R,versions:x},te;if(a!==null){te={};for(let ae of a){let le=z[ae];if(typeof le<"u")te[ae]=le;else{p.reportWarning(1,`The ${pe.pretty(r,ae,pe.Type.CODE)} field doesn't exist inside ${G.prettyIdent(r,E)}'s information`),u=!0;continue}}}else this.json||(delete z.dist,delete z.readme,delete z.users),te=z;p.reportJson(te),this.json||n.push(te)}});E5.inspect.styles.name="cyan";for(let p of n)(p!==n[0]||u)&&this.context.stdout.write(` +`),this.context.stdout.write(`${(0,E5.inspect)(p,{depth:1/0,colors:!0,compact:!1})} +`);return A.exitCode()}};function C5(t){if(Array.isArray(t)){let e=[];for(let r of t)r=C5(r),r&&e.push(r);return e}else if(typeof t=="object"&&t!==null){let e={};for(let r of Object.keys(t)){if(r.startsWith("_"))continue;let o=C5(t[r]);o&&(e[r]=o)}return e}else return t||null}Ge();Ge();qt();var BBe=Ze(J1()),kC=class extends ut{constructor(){super(...arguments);this.scope=ge.String("-s,--scope",{description:"Login to the registry configured for a given scope"});this.publish=ge.Boolean("--publish",!1,{description:"Login to the publish registry"});this.alwaysAuth=ge.Boolean("--always-auth",{description:"Set the npmAlwaysAuth configuration"})}static{this.paths=[["npm","login"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"store new login info to access the npm registry",details:"\n This command will ask you for your username, password, and 2FA One-Time-Password (when it applies). It will then modify your local configuration (in your home folder, never in the project itself) to reference the new tokens thus generated.\n\n Adding the `-s,--scope` flag will cause the authentication to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\n\n Adding the `--publish` flag will cause the authentication to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\n ",examples:[["Login to the default registry","yarn npm login"],["Login to the registry linked to the @my-scope registry","yarn npm login --scope my-scope"],["Login to the publish registry for the current package","yarn npm login --publish"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=await qQ({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope});return(await Rt.start({configuration:r,stdout:this.context.stdout,includeFooter:!1},async n=>{let u=await Yvt({configuration:r,registry:o,report:n,stdin:this.context.stdin,stdout:this.context.stdout}),A=await jvt(o,u,r);return await Gvt(o,A,{alwaysAuth:this.alwaysAuth,scope:this.scope}),n.reportInfo(0,"Successfully logged in")})).exitCode()}};async function qQ({scope:t,publish:e,configuration:r,cwd:o}){return t&&e?Zn.getScopeRegistry(t,{configuration:r,type:Zn.RegistryType.PUBLISH_REGISTRY}):t?Zn.getScopeRegistry(t,{configuration:r}):e?Zn.getPublishRegistry((await _y(r,o)).manifest,{configuration:r}):Zn.getDefaultRegistry({configuration:r})}async function jvt(t,e,r){let o=`/-/user/org.couchdb.user:${encodeURIComponent(e.name)}`,a={_id:`org.couchdb.user:${e.name}`,name:e.name,password:e.password,type:"user",roles:[],date:new Date().toISOString()},n={attemptedAs:e.name,configuration:r,registry:t,jsonResponse:!0,authType:Zr.AuthType.NO_AUTH};try{return(await Zr.put(o,a,n)).token}catch(E){if(!(E.originalError?.name==="HTTPError"&&E.originalError?.response.statusCode===409))throw E}let u={...n,authType:Zr.AuthType.NO_AUTH,headers:{authorization:`Basic ${Buffer.from(`${e.name}:${e.password}`).toString("base64")}`}},A=await Zr.get(o,u);for(let[E,I]of Object.entries(A))(!a[E]||E==="roles")&&(a[E]=I);let p=`${o}/-rev/${a._rev}`;return(await Zr.put(p,a,u)).token}async function Gvt(t,e,{alwaysAuth:r,scope:o}){let a=u=>A=>{let p=He.isIndexableObject(A)?A:{},h=p[u],E=He.isIndexableObject(h)?h:{};return{...p,[u]:{...E,...r!==void 0?{npmAlwaysAuth:r}:{},npmAuthToken:e}}},n=o?{npmScopes:a(o)}:{npmRegistries:a(t)};return await Ke.updateHomeConfiguration(n)}async function Yvt({configuration:t,registry:e,report:r,stdin:o,stdout:a}){r.reportInfo(0,`Logging in to ${pe.pretty(t,e,pe.Type.URL)}`);let n=!1;if(e.match(/^https:\/\/npm\.pkg\.github\.com(\/|$)/)&&(r.reportInfo(0,"You seem to be using the GitHub Package Registry. Tokens must be generated with the 'repo', 'write:packages', and 'read:packages' permissions."),n=!0),r.reportSeparator(),t.env.YARN_IS_TEST_ENV)return{name:t.env.YARN_INJECT_NPM_USER||"",password:t.env.YARN_INJECT_NPM_PASSWORD||""};let u=await(0,BBe.prompt)([{type:"input",name:"name",message:"Username:",required:!0,onCancel:()=>process.exit(130),stdin:o,stdout:a},{type:"password",name:"password",message:n?"Token:":"Password:",required:!0,onCancel:()=>process.exit(130),stdin:o,stdout:a}]);return r.reportSeparator(),u}Ge();Ge();qt();var QC=new Set(["npmAuthIdent","npmAuthToken"]),FC=class extends ut{constructor(){super(...arguments);this.scope=ge.String("-s,--scope",{description:"Logout of the registry configured for a given scope"});this.publish=ge.Boolean("--publish",!1,{description:"Logout of the publish registry"});this.all=ge.Boolean("-A,--all",!1,{description:"Logout of all registries"})}static{this.paths=[["npm","logout"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"logout of the npm registry",details:"\n This command will log you out by modifying your local configuration (in your home folder, never in the project itself) to delete all credentials linked to a registry.\n\n Adding the `-s,--scope` flag will cause the deletion to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\n\n Adding the `--publish` flag will cause the deletion to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\n\n Adding the `-A,--all` flag will cause the deletion to be done against all registries and scopes.\n ",examples:[["Logout of the default registry","yarn npm logout"],["Logout of the @my-scope scope","yarn npm logout --scope my-scope"],["Logout of the publish registry for the current package","yarn npm logout --publish"],["Logout of all registries","yarn npm logout --all"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o=async()=>{let n=await qQ({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope}),u=await Ke.find(this.context.cwd,this.context.plugins),A=G.makeIdent(this.scope??null,"pkg");return!Zn.getAuthConfiguration(n,{configuration:u,ident:A}).get("npmAuthToken")};return(await Rt.start({configuration:r,stdout:this.context.stdout},async n=>{if(this.all&&(await Kvt(),n.reportInfo(0,"Successfully logged out from everything")),this.scope){await vBe("npmScopes",this.scope),await o()?n.reportInfo(0,`Successfully logged out from ${this.scope}`):n.reportWarning(0,"Scope authentication settings removed, but some other ones settings still apply to it");return}let u=await qQ({configuration:r,cwd:this.context.cwd,publish:this.publish});await vBe("npmRegistries",u),await o()?n.reportInfo(0,`Successfully logged out from ${u}`):n.reportWarning(0,"Registry authentication settings removed, but some other ones settings still apply to it")})).exitCode()}};function Wvt(t,e){let r=t[e];if(!He.isIndexableObject(r))return!1;let o=new Set(Object.keys(r));if([...QC].every(n=>!o.has(n)))return!1;for(let n of QC)o.delete(n);if(o.size===0)return t[e]=void 0,!0;let a={...r};for(let n of QC)delete a[n];return t[e]=a,!0}async function Kvt(){let t=e=>{let r=!1,o=He.isIndexableObject(e)?{...e}:{};o.npmAuthToken&&(delete o.npmAuthToken,r=!0);for(let a of Object.keys(o))Wvt(o,a)&&(r=!0);if(Object.keys(o).length!==0)return r?o:e};return await Ke.updateHomeConfiguration({npmRegistries:t,npmScopes:t})}async function vBe(t,e){return await Ke.updateHomeConfiguration({[t]:r=>{let o=He.isIndexableObject(r)?r:{};if(!Object.hasOwn(o,e))return r;let a=o[e],n=He.isIndexableObject(a)?a:{},u=new Set(Object.keys(n));if([...QC].every(p=>!u.has(p)))return r;for(let p of QC)u.delete(p);if(u.size===0)return Object.keys(o).length===1?void 0:{...o,[e]:void 0};let A={};for(let p of QC)A[p]=void 0;return{...o,[e]:{...n,...A}}}})}Ge();qt();var RC=class extends ut{constructor(){super(...arguments);this.access=ge.String("--access",{description:"The access for the published package (public or restricted)"});this.tag=ge.String("--tag","latest",{description:"The tag on the registry that the package should be attached to"});this.tolerateRepublish=ge.Boolean("--tolerate-republish",!1,{description:"Warn and exit when republishing an already existing version of a package"});this.otp=ge.String("--otp",{description:"The OTP token to use with the command"})}static{this.paths=[["npm","publish"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"publish the active workspace to the npm registry",details:'\n This command will pack the active workspace into a fresh archive and upload it to the npm registry.\n\n The package will by default be attached to the `latest` tag on the registry, but this behavior can be overridden by using the `--tag` option.\n\n Note that for legacy reasons scoped packages are by default published with an access set to `restricted` (aka "private packages"). This requires you to register for a paid npm plan. In case you simply wish to publish a public scoped package to the registry (for free), just add the `--access public` flag. This behavior can be enabled by default through the `npmPublishAccess` settings.\n ',examples:[["Publish the active workspace","yarn npm publish"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);if(a.manifest.private)throw new st("Private workspaces cannot be published");if(a.manifest.name===null||a.manifest.version===null)throw new st("Workspaces must have valid names and versions to be published on an external registry");await o.restoreInstallState();let n=a.manifest.name,u=a.manifest.version,A=Zn.getPublishRegistry(a.manifest,{configuration:r});return(await Rt.start({configuration:r,stdout:this.context.stdout},async h=>{if(this.tolerateRepublish)try{let E=await Zr.get(Zr.getIdentUrl(n),{configuration:r,registry:A,ident:n,jsonResponse:!0});if(!Object.hasOwn(E,"versions"))throw new Jt(15,'Registry returned invalid data for - missing "versions" field');if(Object.hasOwn(E.versions,u)){h.reportWarning(0,`Registry already knows about version ${u}; skipping.`);return}}catch(E){if(E.originalError?.response?.statusCode!==404)throw E}await An.maybeExecuteWorkspaceLifecycleScript(a,"prepublish",{report:h}),await CA.prepareForPack(a,{report:h},async()=>{let E=await CA.genPackList(a);for(let R of E)h.reportInfo(null,R);let I=await CA.genPackStream(a,E),v=await He.bufferStream(I),x=await PC.getGitHead(a.cwd),C=await PC.makePublishBody(a,v,{access:this.access,tag:this.tag,registry:A,gitHead:x});await Zr.put(Zr.getIdentUrl(n),C,{configuration:r,registry:A,ident:n,otp:this.otp,jsonResponse:!0})}),h.reportInfo(0,"Package archive published")})).exitCode()}};Ge();qt();var DBe=Ze(Jn());Ge();Pt();qt();var TC=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.package=ge.String({required:!1})}static{this.paths=[["npm","tag","list"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"list all dist-tags of a package",details:` + This command will list all tags of a package from the npm registry. + + If the package is not specified, Yarn will default to the current workspace. + `,examples:[["List all tags of package `my-pkg`","yarn npm tag list my-pkg"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n;if(typeof this.package<"u")n=G.parseIdent(this.package);else{if(!a)throw new sr(o.cwd,this.context.cwd);if(!a.manifest.name)throw new st(`Missing 'name' field in ${ue.fromPortablePath(K.join(a.cwd,dr.manifest))}`);n=a.manifest.name}let u=await mv(n,r),p={children:He.sortMap(Object.entries(u),([h])=>h).map(([h,E])=>({value:pe.tuple(pe.Type.RESOLUTION,{descriptor:G.makeDescriptor(n,h),locator:G.makeLocator(n,E)})}))};return fs.emitTree(p,{configuration:r,json:this.json,stdout:this.context.stdout})}};async function mv(t,e){let r=`/-/package${Zr.getIdentUrl(t)}/dist-tags`;return Zr.get(r,{configuration:e,ident:t,jsonResponse:!0,customErrorMessage:Zr.customPackageError})}var NC=class extends ut{constructor(){super(...arguments);this.package=ge.String();this.tag=ge.String()}static{this.paths=[["npm","tag","add"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"add a tag for a specific version of a package",details:` + This command will add a tag to the npm registry for a specific version of a package. If the tag already exists, it will be overwritten. + `,examples:[["Add a `beta` tag for version `2.3.4-beta.4` of package `my-pkg`","yarn npm tag add my-pkg@2.3.4-beta.4 beta"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);let n=G.parseDescriptor(this.package,!0),u=n.range;if(!DBe.default.valid(u))throw new st(`The range ${pe.pretty(r,n.range,pe.Type.RANGE)} must be a valid semver version`);let A=Zn.getPublishRegistry(a.manifest,{configuration:r}),p=pe.pretty(r,n,pe.Type.IDENT),h=pe.pretty(r,u,pe.Type.RANGE),E=pe.pretty(r,this.tag,pe.Type.CODE);return(await Rt.start({configuration:r,stdout:this.context.stdout},async v=>{let x=await mv(n,r);Object.hasOwn(x,this.tag)&&x[this.tag]===u&&v.reportWarning(0,`Tag ${E} is already set to version ${h}`);let C=`/-/package${Zr.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await Zr.put(C,u,{configuration:r,registry:A,ident:n,jsonRequest:!0,jsonResponse:!0}),v.reportInfo(0,`Tag ${E} added to version ${h} of package ${p}`)})).exitCode()}};Ge();qt();var LC=class extends ut{constructor(){super(...arguments);this.package=ge.String();this.tag=ge.String()}static{this.paths=[["npm","tag","remove"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"remove a tag from a package",details:` + This command will remove a tag from a package from the npm registry. + `,examples:[["Remove the `beta` tag from package `my-pkg`","yarn npm tag remove my-pkg beta"]]})}async execute(){if(this.tag==="latest")throw new st("The 'latest' tag cannot be removed.");let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);let n=G.parseIdent(this.package),u=Zn.getPublishRegistry(a.manifest,{configuration:r}),A=pe.pretty(r,this.tag,pe.Type.CODE),p=pe.pretty(r,n,pe.Type.IDENT),h=await mv(n,r);if(!Object.hasOwn(h,this.tag))throw new st(`${A} is not a tag of package ${p}`);return(await Rt.start({configuration:r,stdout:this.context.stdout},async I=>{let v=`/-/package${Zr.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await Zr.del(v,{configuration:r,registry:u,ident:n,jsonResponse:!0}),I.reportInfo(0,`Tag ${A} removed from package ${p}`)})).exitCode()}};Ge();Ge();qt();var MC=class extends ut{constructor(){super(...arguments);this.scope=ge.String("-s,--scope",{description:"Print username for the registry configured for a given scope"});this.publish=ge.Boolean("--publish",!1,{description:"Print username for the publish registry"})}static{this.paths=[["npm","whoami"]]}static{this.usage=it.Usage({category:"Npm-related commands",description:"display the name of the authenticated user",details:"\n Print the username associated with the current authentication settings to the standard output.\n\n When using `-s,--scope`, the username printed will be the one that matches the authentication settings of the registry associated with the given scope (those settings can be overriden using the `npmRegistries` map, and the registry associated with the scope is configured via the `npmScopes` map).\n\n When using `--publish`, the registry we'll select will by default be the one used when publishing packages (`publishConfig.registry` or `npmPublishRegistry` if available, otherwise we'll fallback to the regular `npmRegistryServer`).\n ",examples:[["Print username for the default registry","yarn npm whoami"],["Print username for the registry on a given scope","yarn npm whoami --scope company"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),o;return this.scope&&this.publish?o=Zn.getScopeRegistry(this.scope,{configuration:r,type:Zn.RegistryType.PUBLISH_REGISTRY}):this.scope?o=Zn.getScopeRegistry(this.scope,{configuration:r}):this.publish?o=Zn.getPublishRegistry((await _y(r,this.context.cwd)).manifest,{configuration:r}):o=Zn.getDefaultRegistry({configuration:r}),(await Rt.start({configuration:r,stdout:this.context.stdout},async n=>{let u;try{u=await Zr.get("/-/whoami",{configuration:r,registry:o,authType:Zr.AuthType.ALWAYS_AUTH,jsonResponse:!0,ident:this.scope?G.makeIdent(this.scope,""):void 0})}catch(A){if(A.response?.statusCode===401||A.response?.statusCode===403){n.reportError(41,"Authentication failed - your credentials may have expired");return}else throw A}n.reportInfo(0,u.username)})).exitCode()}};var Vvt={configuration:{npmPublishAccess:{description:"Default access of the published packages",type:"STRING",default:null},npmAuditExcludePackages:{description:"Array of glob patterns of packages to exclude from npm audit",type:"STRING",default:[],isArray:!0},npmAuditIgnoreAdvisories:{description:"Array of glob patterns of advisory IDs to exclude from npm audit",type:"STRING",default:[],isArray:!0}},commands:[bC,xC,kC,FC,RC,NC,TC,LC,MC]},zvt=Vvt;var b5={};Vt(b5,{PatchCommand:()=>jC,PatchCommitCommand:()=>qC,PatchFetcher:()=>Iv,PatchResolver:()=>Bv,default:()=>pDt,patchUtils:()=>pd});Ge();Ge();Pt();nA();var pd={};Vt(pd,{applyPatchFile:()=>GQ,diffFolders:()=>P5,ensureUnpatchedDescriptor:()=>I5,ensureUnpatchedLocator:()=>WQ,extractPackageToDisk:()=>D5,extractPatchFlags:()=>FBe,isParentRequired:()=>v5,isPatchDescriptor:()=>YQ,isPatchLocator:()=>$h,loadPatchFiles:()=>wv,makeDescriptor:()=>KQ,makeLocator:()=>B5,makePatchHash:()=>S5,parseDescriptor:()=>Ev,parseLocator:()=>Cv,parsePatchFile:()=>yv,unpatchDescriptor:()=>uDt,unpatchLocator:()=>ADt});Ge();Pt();Ge();Pt();var Jvt=/^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@.*/;function OC(t){return K.relative(It.root,K.resolve(It.root,ue.toPortablePath(t)))}function Xvt(t){let e=t.trim().match(Jvt);if(!e)throw new Error(`Bad header line: '${t}'`);return{original:{start:Math.max(Number(e[1]),1),length:Number(e[3]||1)},patched:{start:Math.max(Number(e[4]),1),length:Number(e[6]||1)}}}var Zvt=420,$vt=493;var PBe=()=>({semverExclusivity:null,diffLineFromPath:null,diffLineToPath:null,oldMode:null,newMode:null,deletedFileMode:null,newFileMode:null,renameFrom:null,renameTo:null,beforeHash:null,afterHash:null,fromPath:null,toPath:null,hunks:null}),eDt=t=>({header:Xvt(t),parts:[]}),tDt={"@":"header","-":"deletion","+":"insertion"," ":"context","\\":"pragma",undefined:"context"};function rDt(t){let e=[],r=PBe(),o="parsing header",a=null,n=null;function u(){a&&(n&&(a.parts.push(n),n=null),r.hunks.push(a),a=null)}function A(){u(),e.push(r),r=PBe()}for(let p=0;p<t.length;p++){let h=t[p];if(o==="parsing header")if(h.startsWith("@@"))o="parsing hunks",r.hunks=[],p-=1;else if(h.startsWith("diff --git ")){r&&r.diffLineFromPath&&A();let E=h.match(/^diff --git a\/(.*?) b\/(.*?)\s*$/);if(!E)throw new Error(`Bad diff line: ${h}`);r.diffLineFromPath=E[1],r.diffLineToPath=E[2]}else if(h.startsWith("old mode "))r.oldMode=h.slice(9).trim();else if(h.startsWith("new mode "))r.newMode=h.slice(9).trim();else if(h.startsWith("deleted file mode "))r.deletedFileMode=h.slice(18).trim();else if(h.startsWith("new file mode "))r.newFileMode=h.slice(14).trim();else if(h.startsWith("rename from "))r.renameFrom=h.slice(12).trim();else if(h.startsWith("rename to "))r.renameTo=h.slice(10).trim();else if(h.startsWith("index ")){let E=h.match(/(\w+)\.\.(\w+)/);if(!E)continue;r.beforeHash=E[1],r.afterHash=E[2]}else h.startsWith("semver exclusivity ")?r.semverExclusivity=h.slice(19).trim():h.startsWith("--- ")?r.fromPath=h.slice(6).trim():h.startsWith("+++ ")&&(r.toPath=h.slice(6).trim());else{let E=tDt[h[0]]||null;switch(E){case"header":u(),a=eDt(h);break;case null:o="parsing header",A(),p-=1;break;case"pragma":{if(!h.startsWith("\\ No newline at end of file"))throw new Error(`Unrecognized pragma in patch file: ${h}`);if(!n)throw new Error("Bad parser state: No newline at EOF pragma encountered without context");n.noNewlineAtEndOfFile=!0}break;case"context":case"deletion":case"insertion":{if(!a)throw new Error("Bad parser state: Hunk lines encountered before hunk header");n&&n.type!==E&&(a.parts.push(n),n=null),n||(n={type:E,lines:[],noNewlineAtEndOfFile:!1}),n.lines.push(h.slice(1))}break;default:He.assertNever(E);break}}}A();for(let{hunks:p}of e)if(p)for(let h of p)iDt(h);return e}function nDt(t){let e=[];for(let r of t){let{semverExclusivity:o,diffLineFromPath:a,diffLineToPath:n,oldMode:u,newMode:A,deletedFileMode:p,newFileMode:h,renameFrom:E,renameTo:I,beforeHash:v,afterHash:x,fromPath:C,toPath:R,hunks:L}=r,U=E?"rename":p?"file deletion":h?"file creation":L&&L.length>0?"patch":"mode change",z=null;switch(U){case"rename":{if(!E||!I)throw new Error("Bad parser state: rename from & to not given");e.push({type:"rename",semverExclusivity:o,fromPath:OC(E),toPath:OC(I)}),z=I}break;case"file deletion":{let te=a||C;if(!te)throw new Error("Bad parse state: no path given for file deletion");e.push({type:"file deletion",semverExclusivity:o,hunk:L&&L[0]||null,path:OC(te),mode:jQ(p),hash:v})}break;case"file creation":{let te=n||R;if(!te)throw new Error("Bad parse state: no path given for file creation");e.push({type:"file creation",semverExclusivity:o,hunk:L&&L[0]||null,path:OC(te),mode:jQ(h),hash:x})}break;case"patch":case"mode change":z=R||n;break;default:He.assertNever(U);break}z&&u&&A&&u!==A&&e.push({type:"mode change",semverExclusivity:o,path:OC(z),oldMode:jQ(u),newMode:jQ(A)}),z&&L&&L.length&&e.push({type:"patch",semverExclusivity:o,path:OC(z),hunks:L,beforeHash:v,afterHash:x})}if(e.length===0)throw new Error("Unable to parse patch file: No changes found. Make sure the patch is a valid UTF8 encoded string");return e}function jQ(t){let e=parseInt(t,8)&511;if(e!==Zvt&&e!==$vt)throw new Error(`Unexpected file mode string: ${t}`);return e}function yv(t){let e=t.split(/\n/g);return e[e.length-1]===""&&e.pop(),nDt(rDt(e))}function iDt(t){let e=0,r=0;for(let{type:o,lines:a}of t.parts)switch(o){case"context":r+=a.length,e+=a.length;break;case"deletion":e+=a.length;break;case"insertion":r+=a.length;break;default:He.assertNever(o);break}if(e!==t.header.original.length||r!==t.header.patched.length){let o=a=>a<0?a:`+${a}`;throw new Error(`hunk header integrity check failed (expected @@ ${o(t.header.original.length)} ${o(t.header.patched.length)} @@, got @@ ${o(e)} ${o(r)} @@)`)}}Ge();Pt();var UC=class extends Error{constructor(r,o){super(`Cannot apply hunk #${r+1}`);this.hunk=o}};async function _C(t,e,r){let o=await t.lstatPromise(e),a=await r();typeof a<"u"&&(e=a),await t.lutimesPromise(e,o.atime,o.mtime)}async function GQ(t,{baseFs:e=new Tn,dryRun:r=!1,version:o=null}={}){for(let a of t)if(!(a.semverExclusivity!==null&&o!==null&&!Lr.satisfiesWithPrereleases(o,a.semverExclusivity)))switch(a.type){case"file deletion":if(r){if(!e.existsSync(a.path))throw new Error(`Trying to delete a file that doesn't exist: ${a.path}`)}else await _C(e,K.dirname(a.path),async()=>{await e.unlinkPromise(a.path)});break;case"rename":if(r){if(!e.existsSync(a.fromPath))throw new Error(`Trying to move a file that doesn't exist: ${a.fromPath}`)}else await _C(e,K.dirname(a.fromPath),async()=>{await _C(e,K.dirname(a.toPath),async()=>{await _C(e,a.fromPath,async()=>(await e.movePromise(a.fromPath,a.toPath),a.toPath))})});break;case"file creation":if(r){if(e.existsSync(a.path))throw new Error(`Trying to create a file that already exists: ${a.path}`)}else{let n=a.hunk?a.hunk.parts[0].lines.join(` +`)+(a.hunk.parts[0].noNewlineAtEndOfFile?"":` +`):"";await e.mkdirpPromise(K.dirname(a.path),{chmod:493,utimes:[Bi.SAFE_TIME,Bi.SAFE_TIME]}),await e.writeFilePromise(a.path,n,{mode:a.mode}),await e.utimesPromise(a.path,Bi.SAFE_TIME,Bi.SAFE_TIME)}break;case"patch":await _C(e,a.path,async()=>{await aDt(a,{baseFs:e,dryRun:r})});break;case"mode change":{let u=(await e.statPromise(a.path)).mode;if(SBe(a.newMode)!==SBe(u))continue;await _C(e,a.path,async()=>{await e.chmodPromise(a.path,a.newMode)})}break;default:He.assertNever(a);break}}function SBe(t){return(t&64)>0}function bBe(t){return t.replace(/\s+$/,"")}function oDt(t,e){return bBe(t)===bBe(e)}async function aDt({hunks:t,path:e},{baseFs:r,dryRun:o=!1}){let a=await r.statSync(e).mode,u=(await r.readFileSync(e,"utf8")).split(/\n/),A=[],p=0,h=0;for(let I of t){let v=Math.max(h,I.header.patched.start+p),x=Math.max(0,v-h),C=Math.max(0,u.length-v-I.header.original.length),R=Math.max(x,C),L=0,U=0,z=null;for(;L<=R;){if(L<=x&&(U=v-L,z=xBe(I,u,U),z!==null)){L=-L;break}if(L<=C&&(U=v+L,z=xBe(I,u,U),z!==null))break;L+=1}if(z===null)throw new UC(t.indexOf(I),I);A.push(z),p+=L,h=U+I.header.original.length}if(o)return;let E=0;for(let I of A)for(let v of I)switch(v.type){case"splice":{let x=v.index+E;u.splice(x,v.numToDelete,...v.linesToInsert),E+=v.linesToInsert.length-v.numToDelete}break;case"pop":u.pop();break;case"push":u.push(v.line);break;default:He.assertNever(v);break}await r.writeFilePromise(e,u.join(` +`),{mode:a})}function xBe(t,e,r){let o=[];for(let a of t.parts)switch(a.type){case"context":case"deletion":{for(let n of a.lines){let u=e[r];if(u==null||!oDt(u,n))return null;r+=1}a.type==="deletion"&&(o.push({type:"splice",index:r-a.lines.length,numToDelete:a.lines.length,linesToInsert:[]}),a.noNewlineAtEndOfFile&&o.push({type:"push",line:""}))}break;case"insertion":o.push({type:"splice",index:r,numToDelete:0,linesToInsert:a.lines}),a.noNewlineAtEndOfFile&&o.push({type:"pop"});break;default:He.assertNever(a.type);break}return o}var cDt=/^builtin<([^>]+)>$/;function HC(t,e){let{protocol:r,source:o,selector:a,params:n}=G.parseRange(t);if(r!=="patch:")throw new Error("Invalid patch range");if(o===null)throw new Error("Patch locators must explicitly define their source");let u=a?a.split(/&/).map(E=>ue.toPortablePath(E)):[],A=n&&typeof n.locator=="string"?G.parseLocator(n.locator):null,p=n&&typeof n.version=="string"?n.version:null,h=e(o);return{parentLocator:A,sourceItem:h,patchPaths:u,sourceVersion:p}}function YQ(t){return t.range.startsWith("patch:")}function $h(t){return t.reference.startsWith("patch:")}function Ev(t){let{sourceItem:e,...r}=HC(t.range,G.parseDescriptor);return{...r,sourceDescriptor:e}}function Cv(t){let{sourceItem:e,...r}=HC(t.reference,G.parseLocator);return{...r,sourceLocator:e}}function uDt(t){let{sourceItem:e}=HC(t.range,G.parseDescriptor);return e}function ADt(t){let{sourceItem:e}=HC(t.reference,G.parseLocator);return e}function I5(t){if(!YQ(t))return t;let{sourceItem:e}=HC(t.range,G.parseDescriptor);return e}function WQ(t){if(!$h(t))return t;let{sourceItem:e}=HC(t.reference,G.parseLocator);return e}function kBe({parentLocator:t,sourceItem:e,patchPaths:r,sourceVersion:o,patchHash:a},n){let u=t!==null?{locator:G.stringifyLocator(t)}:{},A=typeof o<"u"?{version:o}:{},p=typeof a<"u"?{hash:a}:{};return G.makeRange({protocol:"patch:",source:n(e),selector:r.join("&"),params:{...A,...p,...u}})}function KQ(t,{parentLocator:e,sourceDescriptor:r,patchPaths:o}){return G.makeDescriptor(t,kBe({parentLocator:e,sourceItem:r,patchPaths:o},G.stringifyDescriptor))}function B5(t,{parentLocator:e,sourcePackage:r,patchPaths:o,patchHash:a}){return G.makeLocator(t,kBe({parentLocator:e,sourceItem:r,sourceVersion:r.version,patchPaths:o,patchHash:a},G.stringifyLocator))}function QBe({onAbsolute:t,onRelative:e,onProject:r,onBuiltin:o},a){let n=a.lastIndexOf("!");n!==-1&&(a=a.slice(n+1));let u=a.match(cDt);return u!==null?o(u[1]):a.startsWith("~/")?r(a.slice(2)):K.isAbsolute(a)?t(a):e(a)}function FBe(t){let e=t.lastIndexOf("!");return{optional:(e!==-1?new Set(t.slice(0,e).split(/!/)):new Set).has("optional")}}function v5(t){return QBe({onAbsolute:()=>!1,onRelative:()=>!0,onProject:()=>!1,onBuiltin:()=>!1},t)}async function wv(t,e,r){let o=t!==null?await r.fetcher.fetch(t,r):null,a=o&&o.localPath?{packageFs:new gn(It.root),prefixPath:K.relative(It.root,o.localPath)}:o;o&&o!==a&&o.releaseFs&&o.releaseFs();let n=await He.releaseAfterUseAsync(async()=>await Promise.all(e.map(async u=>{let A=FBe(u),p=await QBe({onAbsolute:async h=>await oe.readFilePromise(h,"utf8"),onRelative:async h=>{if(a===null)throw new Error("Assertion failed: The parent locator should have been fetched");return await a.packageFs.readFilePromise(K.join(a.prefixPath,h),"utf8")},onProject:async h=>await oe.readFilePromise(K.join(r.project.cwd,h),"utf8"),onBuiltin:async h=>await r.project.configuration.firstHook(E=>E.getBuiltinPatch,r.project,h)},u);return{...A,source:p}})));for(let u of n)typeof u.source=="string"&&(u.source=u.source.replace(/\r\n?/g,` +`));return n}async function D5(t,{cache:e,project:r}){let o=r.storedPackages.get(t.locatorHash);if(typeof o>"u")throw new Error("Assertion failed: Expected the package to be registered");let a=WQ(t),n=r.storedChecksums,u=new ki,A=await oe.mktempPromise(),p=K.join(A,"source"),h=K.join(A,"user"),E=K.join(A,".yarn-patch.json"),I=r.configuration.makeFetcher(),v=[];try{let x,C;if(t.locatorHash===a.locatorHash){let R=await I.fetch(t,{cache:e,project:r,fetcher:I,checksums:n,report:u});v.push(()=>R.releaseFs?.()),x=R,C=R}else x=await I.fetch(t,{cache:e,project:r,fetcher:I,checksums:n,report:u}),v.push(()=>x.releaseFs?.()),C=await I.fetch(t,{cache:e,project:r,fetcher:I,checksums:n,report:u}),v.push(()=>C.releaseFs?.());await Promise.all([oe.copyPromise(p,x.prefixPath,{baseFs:x.packageFs}),oe.copyPromise(h,C.prefixPath,{baseFs:C.packageFs}),oe.writeJsonPromise(E,{locator:G.stringifyLocator(t),version:o.version})])}finally{for(let x of v)x()}return oe.detachTemp(A),h}async function P5(t,e){let r=ue.fromPortablePath(t).replace(/\\/g,"/"),o=ue.fromPortablePath(e).replace(/\\/g,"/"),{stdout:a,stderr:n}=await Ur.execvp("git",["-c","core.safecrlf=false","diff","--src-prefix=a/","--dst-prefix=b/","--ignore-cr-at-eol","--full-index","--no-index","--no-renames","--text",r,o],{cwd:ue.toPortablePath(process.cwd()),env:{...process.env,GIT_CONFIG_NOSYSTEM:"1",HOME:"",XDG_CONFIG_HOME:"",USERPROFILE:""}});if(n.length>0)throw new Error(`Unable to diff directories. Make sure you have a recent version of 'git' available in PATH. +The following error was reported by 'git': +${n}`);let u=r.startsWith("/")?A=>A.slice(1):A=>A;return a.replace(new RegExp(`(a|b)(${He.escapeRegExp(`/${u(r)}/`)})`,"g"),"$1/").replace(new RegExp(`(a|b)${He.escapeRegExp(`/${u(o)}/`)}`,"g"),"$1/").replace(new RegExp(He.escapeRegExp(`${r}/`),"g"),"").replace(new RegExp(He.escapeRegExp(`${o}/`),"g"),"")}function S5(t,e){let r=[];for(let{source:o}of t){if(o===null)continue;let a=yv(o);for(let n of a){let{semverExclusivity:u,...A}=n;u!==null&&e!==null&&!Lr.satisfiesWithPrereleases(e,u)||r.push(JSON.stringify(A))}}return wn.makeHash(`${3}`,...r).slice(0,6)}Ge();function RBe(t,{configuration:e,report:r}){for(let o of t.parts)for(let a of o.lines)switch(o.type){case"context":r.reportInfo(null,` ${pe.pretty(e,a,"grey")}`);break;case"deletion":r.reportError(28,`- ${pe.pretty(e,a,pe.Type.REMOVED)}`);break;case"insertion":r.reportError(28,`+ ${pe.pretty(e,a,pe.Type.ADDED)}`);break;default:He.assertNever(o.type)}}var Iv=class{supports(e,r){return!!$h(e)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.patchPackage(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async patchPackage(e,r){let{parentLocator:o,sourceLocator:a,sourceVersion:n,patchPaths:u}=Cv(e),A=await wv(o,u,r),p=await oe.mktempPromise(),h=K.join(p,"current.zip"),E=await r.fetcher.fetch(a,r),I=G.getIdentVendorPath(e),v=new Zi(h,{create:!0,level:r.project.configuration.get("compressionLevel")});await He.releaseAfterUseAsync(async()=>{await v.copyPromise(I,E.prefixPath,{baseFs:E.packageFs,stableSort:!0})},E.releaseFs),v.saveAndClose();for(let{source:x,optional:C}of A){if(x===null)continue;let R=new Zi(h,{level:r.project.configuration.get("compressionLevel")}),L=new gn(K.resolve(It.root,I),{baseFs:R});try{await GQ(yv(x),{baseFs:L,version:n})}catch(U){if(!(U instanceof UC))throw U;let z=r.project.configuration.get("enableInlineHunks"),te=!z&&!C?" (set enableInlineHunks for details)":"",ae=`${G.prettyLocator(r.project.configuration,e)}: ${U.message}${te}`,le=ce=>{z&&RBe(U.hunk,{configuration:r.project.configuration,report:ce})};if(R.discardAndClose(),C){r.report.reportWarningOnce(66,ae,{reportExtra:le});continue}else throw new Jt(66,ae,le)}R.saveAndClose()}return new Zi(h,{level:r.project.configuration.get("compressionLevel")})}};Ge();var Bv=class{supportsDescriptor(e,r){return!!YQ(e)}supportsLocator(e,r){return!!$h(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){let{patchPaths:a}=Ev(e);return a.every(n=>!v5(n))?e:G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){let{sourceDescriptor:o}=Ev(e);return{sourceDescriptor:r.project.configuration.normalizeDependency(o)}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{parentLocator:a,patchPaths:n}=Ev(e),u=await wv(a,n,o.fetchOptions),A=r.sourceDescriptor;if(typeof A>"u")throw new Error("Assertion failed: The dependency should have been resolved");let p=S5(u,A.version);return[B5(e,{parentLocator:a,sourcePackage:A,patchPaths:n,patchHash:p})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let{sourceLocator:o}=Cv(e);return{...await r.resolver.resolve(o,r),...e}}};Ge();Pt();qt();var qC=class extends ut{constructor(){super(...arguments);this.save=ge.Boolean("-s,--save",!1,{description:"Add the patch to your resolution entries"});this.patchFolder=ge.String()}static{this.paths=[["patch-commit"]]}static{this.usage=it.Usage({description:"generate a patch out of a directory",details:"\n By default, this will print a patchfile on stdout based on the diff between the folder passed in and the original version of the package. Such file is suitable for consumption with the `patch:` protocol.\n\n With the `-s,--save` option set, the patchfile won't be printed on stdout anymore and will instead be stored within a local file (by default kept within `.yarn/patches`, but configurable via the `patchFolder` setting). A `resolutions` entry will also be added to your top-level manifest, referencing the patched package via the `patch:` protocol.\n\n Note that only folders generated by `yarn patch` are accepted as valid input for `yarn patch-commit`.\n "})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState();let n=K.resolve(this.context.cwd,ue.toPortablePath(this.patchFolder)),u=K.join(n,"../source"),A=K.join(n,"../.yarn-patch.json");if(!oe.existsSync(u))throw new st("The argument folder didn't get created by 'yarn patch'");let p=await P5(u,n),h=await oe.readJsonPromise(A),E=G.parseLocator(h.locator,!0);if(!o.storedPackages.has(E.locatorHash))throw new st("No package found in the project for the given locator");if(!this.save){this.context.stdout.write(p);return}let I=r.get("patchFolder"),v=K.join(I,`${G.slugifyLocator(E)}.patch`);await oe.mkdirPromise(I,{recursive:!0}),await oe.writeFilePromise(v,p);let x=[],C=new Map;for(let R of o.storedPackages.values()){if(G.isVirtualLocator(R))continue;let L=R.dependencies.get(E.identHash);if(!L)continue;let U=G.ensureDevirtualizedDescriptor(L),z=I5(U),te=o.storedResolutions.get(z.descriptorHash);if(!te)throw new Error("Assertion failed: Expected the resolution to have been registered");if(!o.storedPackages.get(te))throw new Error("Assertion failed: Expected the package to have been registered");let le=o.tryWorkspaceByLocator(R);if(le)x.push(le);else{let ce=o.originalPackages.get(R.locatorHash);if(!ce)throw new Error("Assertion failed: Expected the original package to have been registered");let Ce=ce.dependencies.get(L.identHash);if(!Ce)throw new Error("Assertion failed: Expected the original dependency to have been registered");C.set(Ce.descriptorHash,Ce)}}for(let R of x)for(let L of Ut.hardDependencies){let U=R.manifest[L].get(E.identHash);if(!U)continue;let z=KQ(U,{parentLocator:null,sourceDescriptor:G.convertLocatorToDescriptor(E),patchPaths:[K.join(dr.home,K.relative(o.cwd,v))]});R.manifest[L].set(U.identHash,z)}for(let R of C.values()){let L=KQ(R,{parentLocator:null,sourceDescriptor:G.convertLocatorToDescriptor(E),patchPaths:[K.join(dr.home,K.relative(o.cwd,v))]});o.topLevelWorkspace.manifest.resolutions.push({pattern:{descriptor:{fullName:G.stringifyIdent(L),description:R.range}},reference:L.range})}await o.persist()}};Ge();Pt();qt();var jC=class extends ut{constructor(){super(...arguments);this.update=ge.Boolean("-u,--update",!1,{description:"Reapply local patches that already apply to this packages"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.package=ge.String()}static{this.paths=[["patch"]]}static{this.usage=it.Usage({description:"prepare a package for patching",details:"\n This command will cause a package to be extracted in a temporary directory intended to be editable at will.\n\n Once you're done with your changes, run `yarn patch-commit -s path` (with `path` being the temporary directory you received) to generate a patchfile and register it into your top-level manifest via the `patch:` protocol. Run `yarn patch-commit -h` for more details.\n\n Calling the command when you already have a patch won't import it by default (in other words, the default behavior is to reset existing patches). However, adding the `-u,--update` flag will import any current patch.\n "})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState();let u=G.parseLocator(this.package);if(u.reference==="unknown"){let A=He.mapAndFilter([...o.storedPackages.values()],p=>p.identHash!==u.identHash?He.mapAndFilter.skip:G.isVirtualLocator(p)?He.mapAndFilter.skip:$h(p)!==this.update?He.mapAndFilter.skip:p);if(A.length===0)throw new st("No package found in the project for the given locator");if(A.length>1)throw new st(`Multiple candidate packages found; explicitly choose one of them (use \`yarn why <package>\` to get more information as to who depends on them): +${A.map(p=>` +- ${G.prettyLocator(r,p)}`).join("")}`);u=A[0]}if(!o.storedPackages.has(u.locatorHash))throw new st("No package found in the project for the given locator");await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async A=>{let p=WQ(u),h=await D5(u,{cache:n,project:o});A.reportJson({locator:G.stringifyLocator(p),path:ue.fromPortablePath(h)});let E=this.update?" along with its current modifications":"";A.reportInfo(0,`Package ${G.prettyLocator(r,p)} got extracted with success${E}!`),A.reportInfo(0,`You can now edit the following folder: ${pe.pretty(r,ue.fromPortablePath(h),"magenta")}`),A.reportInfo(0,`Once you are done run ${pe.pretty(r,`yarn patch-commit -s ${process.platform==="win32"?'"':""}${ue.fromPortablePath(h)}${process.platform==="win32"?'"':""}`,"cyan")} and Yarn will store a patchfile based on your changes.`)})}};var fDt={configuration:{enableInlineHunks:{description:"If true, the installs will print unmatched patch hunks",type:"BOOLEAN",default:!1},patchFolder:{description:"Folder where the patch files must be written",type:"ABSOLUTE_PATH",default:"./.yarn/patches"}},commands:[qC,jC],fetchers:[Iv],resolvers:[Bv]},pDt=fDt;var Q5={};Vt(Q5,{PnpmLinker:()=>vv,default:()=>yDt});Ge();Pt();qt();var vv=class{getCustomDataKey(){return JSON.stringify({name:"PnpmLinker",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the pnpm linker to be enabled");let o=this.getCustomDataKey(),a=r.project.linkersCustomData.get(o);if(!a)throw new st(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=a.pathsByLocator.get(e.locatorHash);if(typeof n>"u")throw new st(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed pnpm map - running an install might help`);return n.packageLocation}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=this.getCustomDataKey(),a=r.project.linkersCustomData.get(o);if(!a)throw new st(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=e.match(/(^.*\/node_modules\/(@[^/]*\/)?[^/]+)(\/.*$)/);if(n){let p=a.locatorByPath.get(n[1]);if(p)return p}let u=e,A=e;do{A=u,u=K.dirname(A);let p=a.locatorByPath.get(A);if(p)return p}while(u!==A);return null}makeInstaller(e){return new x5(e)}isEnabled(e){return e.project.configuration.get("nodeLinker")==="pnpm"}},x5=class{constructor(e){this.opts=e;this.asyncActions=new He.AsyncActions(10);this.customData={pathsByLocator:new Map,locatorByPath:new Map};this.indexFolderPromise=cD(oe,{indexPath:K.join(e.project.configuration.get("globalFolder"),"index")})}attachCustomData(e){}async installPackage(e,r,o){switch(e.linkType){case"SOFT":return this.installPackageSoft(e,r,o);case"HARD":return this.installPackageHard(e,r,o)}throw new Error("Assertion failed: Unsupported package link type")}async installPackageSoft(e,r,o){let a=K.resolve(r.packageFs.getRealPath(),r.prefixPath),n=this.opts.project.tryWorkspaceByLocator(e)?K.join(a,dr.nodeModules):null;return this.customData.pathsByLocator.set(e.locatorHash,{packageLocation:a,dependenciesLocation:n}),{packageLocation:a,buildRequest:null}}async installPackageHard(e,r,o){let a=hDt(e,{project:this.opts.project}),n=a.packageLocation;this.customData.locatorByPath.set(n,G.stringifyLocator(e)),this.customData.pathsByLocator.set(e.locatorHash,a),o.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{await oe.mkdirPromise(n,{recursive:!0}),await oe.copyPromise(n,r.prefixPath,{baseFs:r.packageFs,overwrite:!1,linkStrategy:{type:"HardlinkFromIndex",indexPath:await this.indexFolderPromise,autoRepair:!0}})}));let A=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e,p={manifest:await Ut.tryFind(r.prefixPath,{baseFs:r.packageFs})??new Ut,misc:{hasBindingGyp:mA.hasBindingGyp(r)}},h=this.opts.project.getDependencyMeta(A,e.version),E=mA.extractBuildRequest(e,p,h,{configuration:this.opts.project.configuration});return{packageLocation:n,buildRequest:E}}async attachInternalDependencies(e,r){if(this.opts.project.configuration.get("nodeLinker")!=="pnpm"||!TBe(e,{project:this.opts.project}))return;let o=this.customData.pathsByLocator.get(e.locatorHash);if(typeof o>"u")throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(e)})`);let{dependenciesLocation:a}=o;a&&this.asyncActions.reduce(e.locatorHash,async n=>{await oe.mkdirPromise(a,{recursive:!0});let u=await gDt(a),A=new Map(u),p=[n],h=(I,v)=>{let x=v;TBe(v,{project:this.opts.project})||(this.opts.report.reportWarningOnce(0,"The pnpm linker doesn't support providing different versions to workspaces' peer dependencies"),x=G.devirtualizeLocator(v));let C=this.customData.pathsByLocator.get(x.locatorHash);if(typeof C>"u")throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(v)})`);let R=G.stringifyIdent(I),L=K.join(a,R),U=K.relative(K.dirname(L),C.packageLocation),z=A.get(R);A.delete(R),p.push(Promise.resolve().then(async()=>{if(z){if(z.isSymbolicLink()&&await oe.readlinkPromise(L)===U)return;await oe.removePromise(L)}await oe.mkdirpPromise(K.dirname(L)),process.platform=="win32"&&this.opts.project.configuration.get("winLinkType")==="junctions"?await oe.symlinkPromise(C.packageLocation,L,"junction"):await oe.symlinkPromise(U,L)}))},E=!1;for(let[I,v]of r)I.identHash===e.identHash&&(E=!0),h(I,v);!E&&!this.opts.project.tryWorkspaceByLocator(e)&&h(G.convertLocatorToDescriptor(e),e),p.push(dDt(a,A)),await Promise.all(p)})}async attachExternalDependents(e,r){throw new Error("External dependencies haven't been implemented for the pnpm linker")}async finalizeInstall(){let e=LBe(this.opts.project);if(this.opts.project.configuration.get("nodeLinker")!=="pnpm")await oe.removePromise(e);else{let r;try{r=new Set(await oe.readdirPromise(e))}catch{r=new Set}for(let{dependenciesLocation:o}of this.customData.pathsByLocator.values()){if(!o)continue;let a=K.contains(e,o);if(a===null)continue;let[n]=a.split(K.sep);r.delete(n)}await Promise.all([...r].map(async o=>{await oe.removePromise(K.join(e,o))}))}return await this.asyncActions.wait(),await k5(e),this.opts.project.configuration.get("nodeLinker")!=="node-modules"&&await k5(NBe(this.opts.project)),{customData:this.customData}}};function NBe(t){return K.join(t.cwd,dr.nodeModules)}function LBe(t){return K.join(NBe(t),".store")}function hDt(t,{project:e}){let r=G.slugifyLocator(t),o=LBe(e),a=K.join(o,r,"package"),n=K.join(o,r,dr.nodeModules);return{packageLocation:a,dependenciesLocation:n}}function TBe(t,{project:e}){return!G.isVirtualLocator(t)||!e.tryWorkspaceByLocator(t)}async function gDt(t){let e=new Map,r=[];try{r=await oe.readdirPromise(t,{withFileTypes:!0})}catch(o){if(o.code!=="ENOENT")throw o}try{for(let o of r)if(!o.name.startsWith("."))if(o.name.startsWith("@")){let a=await oe.readdirPromise(K.join(t,o.name),{withFileTypes:!0});if(a.length===0)e.set(o.name,o);else for(let n of a)e.set(`${o.name}/${n.name}`,n)}else e.set(o.name,o)}catch(o){if(o.code!=="ENOENT")throw o}return e}async function dDt(t,e){let r=[],o=new Set;for(let a of e.keys()){r.push(oe.removePromise(K.join(t,a)));let n=G.tryParseIdent(a)?.scope;n&&o.add(`@${n}`)}return Promise.all(r).then(()=>Promise.all([...o].map(a=>k5(K.join(t,a)))))}async function k5(t){try{await oe.rmdirPromise(t)}catch(e){if(e.code!=="ENOENT"&&e.code!=="ENOTEMPTY")throw e}}var mDt={linkers:[vv]},yDt=mDt;var O5={};Vt(O5,{StageCommand:()=>GC,default:()=>xDt,stageUtils:()=>zQ});Ge();Pt();qt();Ge();Pt();var zQ={};Vt(zQ,{ActionType:()=>F5,checkConsensus:()=>VQ,expandDirectory:()=>N5,findConsensus:()=>L5,findVcsRoot:()=>R5,genCommitMessage:()=>M5,getCommitPrefix:()=>MBe,isYarnFile:()=>T5});Pt();var F5=(n=>(n[n.CREATE=0]="CREATE",n[n.DELETE=1]="DELETE",n[n.ADD=2]="ADD",n[n.REMOVE=3]="REMOVE",n[n.MODIFY=4]="MODIFY",n))(F5||{});async function R5(t,{marker:e}){do if(!oe.existsSync(K.join(t,e)))t=K.dirname(t);else return t;while(t!=="/");return null}function T5(t,{roots:e,names:r}){if(r.has(K.basename(t)))return!0;do if(!e.has(t))t=K.dirname(t);else return!0;while(t!=="/");return!1}function N5(t){let e=[],r=[t];for(;r.length>0;){let o=r.pop(),a=oe.readdirSync(o);for(let n of a){let u=K.resolve(o,n);oe.lstatSync(u).isDirectory()?r.push(u):e.push(u)}}return e}function VQ(t,e){let r=0,o=0;for(let a of t)a!=="wip"&&(e.test(a)?r+=1:o+=1);return r>=o}function L5(t){let e=VQ(t,/^(\w\(\w+\):\s*)?\w+s/),r=VQ(t,/^(\w\(\w+\):\s*)?[A-Z]/),o=VQ(t,/^\w\(\w+\):/);return{useThirdPerson:e,useUpperCase:r,useComponent:o}}function MBe(t){return t.useComponent?"chore(yarn): ":""}var EDt=new Map([[0,"create"],[1,"delete"],[2,"add"],[3,"remove"],[4,"update"]]);function M5(t,e){let r=MBe(t),o=[],a=e.slice().sort((n,u)=>n[0]-u[0]);for(;a.length>0;){let[n,u]=a.shift(),A=EDt.get(n);t.useUpperCase&&o.length===0&&(A=`${A[0].toUpperCase()}${A.slice(1)}`),t.useThirdPerson&&(A+="s");let p=[u];for(;a.length>0&&a[0][0]===n;){let[,E]=a.shift();p.push(E)}p.sort();let h=p.shift();p.length===1?h+=" (and one other)":p.length>1&&(h+=` (and ${p.length} others)`),o.push(`${A} ${h}`)}return`${r}${o.join(", ")}`}var CDt="Commit generated via `yarn stage`",wDt=11;async function OBe(t){let{code:e,stdout:r}=await Ur.execvp("git",["log","-1","--pretty=format:%H"],{cwd:t});return e===0?r.trim():null}async function IDt(t,e){let r=[],o=e.filter(h=>K.basename(h.path)==="package.json");for(let{action:h,path:E}of o){let I=K.relative(t,E);if(h===4){let v=await OBe(t),{stdout:x}=await Ur.execvp("git",["show",`${v}:${I}`],{cwd:t,strict:!0}),C=await Ut.fromText(x),R=await Ut.fromFile(E),L=new Map([...R.dependencies,...R.devDependencies]),U=new Map([...C.dependencies,...C.devDependencies]);for(let[z,te]of U){let ae=G.stringifyIdent(te),le=L.get(z);le?le.range!==te.range&&r.push([4,`${ae} to ${le.range}`]):r.push([3,ae])}for(let[z,te]of L)U.has(z)||r.push([2,G.stringifyIdent(te)])}else if(h===0){let v=await Ut.fromFile(E);v.name?r.push([0,G.stringifyIdent(v.name)]):r.push([0,"a package"])}else if(h===1){let v=await OBe(t),{stdout:x}=await Ur.execvp("git",["show",`${v}:${I}`],{cwd:t,strict:!0}),C=await Ut.fromText(x);C.name?r.push([1,G.stringifyIdent(C.name)]):r.push([1,"a package"])}else throw new Error("Assertion failed: Unsupported action type")}let{code:a,stdout:n}=await Ur.execvp("git",["log",`-${wDt}`,"--pretty=format:%s"],{cwd:t}),u=a===0?n.split(/\n/g).filter(h=>h!==""):[],A=L5(u);return M5(A,r)}var BDt={0:[" A ","?? "],4:[" M "],1:[" D "]},vDt={0:["A "],4:["M "],1:["D "]},UBe={async findRoot(t){return await R5(t,{marker:".git"})},async filterChanges(t,e,r,o){let{stdout:a}=await Ur.execvp("git",["status","-s"],{cwd:t,strict:!0}),n=a.toString().split(/\n/g),u=o?.staged?vDt:BDt;return[].concat(...n.map(p=>{if(p==="")return[];let h=p.slice(0,3),E=K.resolve(t,p.slice(3));if(!o?.staged&&h==="?? "&&p.endsWith("/"))return N5(E).map(I=>({action:0,path:I}));{let v=[0,4,1].find(x=>u[x].includes(h));return v!==void 0?[{action:v,path:E}]:[]}})).filter(p=>T5(p.path,{roots:e,names:r}))},async genCommitMessage(t,e){return await IDt(t,e)},async makeStage(t,e){let r=e.map(o=>ue.fromPortablePath(o.path));await Ur.execvp("git",["add","--",...r],{cwd:t,strict:!0})},async makeCommit(t,e,r){let o=e.map(a=>ue.fromPortablePath(a.path));await Ur.execvp("git",["add","-N","--",...o],{cwd:t,strict:!0}),await Ur.execvp("git",["commit","-m",`${r} + +${CDt} +`,"--",...o],{cwd:t,strict:!0})},async makeReset(t,e){let r=e.map(o=>ue.fromPortablePath(o.path));await Ur.execvp("git",["reset","HEAD","--",...r],{cwd:t,strict:!0})}};var DDt=[UBe],GC=class extends ut{constructor(){super(...arguments);this.commit=ge.Boolean("-c,--commit",!1,{description:"Commit the staged files"});this.reset=ge.Boolean("-r,--reset",!1,{description:"Remove all files from the staging area"});this.dryRun=ge.Boolean("-n,--dry-run",!1,{description:"Print the commit message and the list of modified files without staging / committing"});this.update=ge.Boolean("-u,--update",!1,{hidden:!0})}static{this.paths=[["stage"]]}static{this.usage=it.Usage({description:"add all yarn files to your vcs",details:"\n This command will add to your staging area the files belonging to Yarn (typically any modified `package.json` and `.yarnrc.yml` files, but also linker-generated files, cache data, etc). It will take your ignore list into account, so the cache files won't be added if the cache is ignored in a `.gitignore` file (assuming you use Git).\n\n Running `--reset` will instead remove them from the staging area (the changes will still be there, but won't be committed until you stage them back).\n\n Since the staging area is a non-existent concept in Mercurial, Yarn will always create a new commit when running this command on Mercurial repositories. You can get this behavior when using Git by using the `--commit` flag which will directly create a commit.\n ",examples:[["Adds all modified project files to the staging area","yarn stage"],["Creates a new commit containing all modified project files","yarn stage --commit"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o}=await kt.find(r,this.context.cwd),{driver:a,root:n}=await PDt(o.cwd),u=[r.get("cacheFolder"),r.get("globalFolder"),r.get("virtualFolder"),r.get("yarnPath")];await r.triggerHook(I=>I.populateYarnPaths,o,I=>{u.push(I)});let A=new Set;for(let I of u)for(let v of SDt(n,I))A.add(v);let p=new Set([r.get("rcFilename"),dr.lockfile,dr.manifest]),h=await a.filterChanges(n,A,p),E=await a.genCommitMessage(n,h);if(this.dryRun)if(this.commit)this.context.stdout.write(`${E} +`);else for(let I of h)this.context.stdout.write(`${ue.fromPortablePath(I.path)} +`);else if(this.reset){let I=await a.filterChanges(n,A,p,{staged:!0});I.length===0?this.context.stdout.write("No staged changes found!"):await a.makeReset(n,I)}else h.length===0?this.context.stdout.write("No changes found!"):this.commit?await a.makeCommit(n,h,E):(await a.makeStage(n,h),this.context.stdout.write(E))}};async function PDt(t){let e=null,r=null;for(let o of DDt)if((r=await o.findRoot(t))!==null){e=o;break}if(e===null||r===null)throw new st("No stage driver has been found for your current project");return{driver:e,root:r}}function SDt(t,e){let r=[];if(e===null)return r;for(;;){(e===t||e.startsWith(`${t}/`))&&r.push(e);let o;try{o=oe.statSync(e)}catch{break}if(o.isSymbolicLink())e=K.resolve(K.dirname(e),oe.readlinkSync(e));else break}return r}var bDt={commands:[GC]},xDt=bDt;var U5={};Vt(U5,{default:()=>MDt});Ge();Ge();Pt();var qBe=Ze(Jn());Ge();var _Be=Ze(YH()),kDt="e8e1bd300d860104bb8c58453ffa1eb4",QDt="OFCNCOG2CU",HBe=async(t,e)=>{let r=G.stringifyIdent(t),a=FDt(e).initIndex("npm-search");try{return(await a.getObject(r,{attributesToRetrieve:["types"]})).types?.ts==="definitely-typed"}catch{return!1}},FDt=t=>(0,_Be.default)(QDt,kDt,{requester:{async send(r){try{let o=await sn.request(r.url,r.data||null,{configuration:t,headers:r.headers});return{content:o.body,isTimedOut:!1,status:o.statusCode}}catch(o){return{content:o.response.body,isTimedOut:!1,status:o.response.statusCode}}}}});var jBe=t=>t.scope?`${t.scope}__${t.name}`:`${t.name}`,RDt=async(t,e,r,o)=>{if(r.scope==="types")return;let{project:a}=t,{configuration:n}=a;if(!(n.get("tsEnableAutoTypes")??(oe.existsSync(K.join(t.cwd,"tsconfig.json"))||oe.existsSync(K.join(a.cwd,"tsconfig.json")))))return;let A=n.makeResolver(),p={project:a,resolver:A,report:new ki};if(!await HBe(r,n))return;let E=jBe(r),I=G.parseRange(r.range).selector;if(!Lr.validRange(I)){let L=n.normalizeDependency(r),U=await A.getCandidates(L,{},p);I=G.parseRange(U[0].reference).selector}let v=qBe.default.coerce(I);if(v===null)return;let x=`${Zc.Modifier.CARET}${v.major}`,C=G.makeDescriptor(G.makeIdent("types",E),x),R=He.mapAndFind(a.workspaces,L=>{let U=L.manifest.dependencies.get(r.identHash)?.descriptorHash,z=L.manifest.devDependencies.get(r.identHash)?.descriptorHash;if(U!==r.descriptorHash&&z!==r.descriptorHash)return He.mapAndFind.skip;let te=[];for(let ae of Ut.allDependencies){let le=L.manifest[ae].get(C.identHash);typeof le>"u"||te.push([ae,le])}return te.length===0?He.mapAndFind.skip:te});if(typeof R<"u")for(let[L,U]of R)t.manifest[L].set(U.identHash,U);else{try{let L=n.normalizeDependency(C);if((await A.getCandidates(L,{},p)).length===0)return}catch{return}t.manifest[Zc.Target.DEVELOPMENT].set(C.identHash,C)}},TDt=async(t,e,r)=>{if(r.scope==="types")return;let{project:o}=t,{configuration:a}=o;if(!(a.get("tsEnableAutoTypes")??(oe.existsSync(K.join(t.cwd,"tsconfig.json"))||oe.existsSync(K.join(o.cwd,"tsconfig.json")))))return;let u=jBe(r),A=G.makeIdent("types",u);for(let p of Ut.allDependencies)typeof t.manifest[p].get(A.identHash)>"u"||t.manifest[p].delete(A.identHash)},NDt=(t,e)=>{e.publishConfig&&e.publishConfig.typings&&(e.typings=e.publishConfig.typings),e.publishConfig&&e.publishConfig.types&&(e.types=e.publishConfig.types)},LDt={configuration:{tsEnableAutoTypes:{description:"Whether Yarn should auto-install @types/ dependencies on 'yarn add'",type:"BOOLEAN",isNullable:!0,default:null}},hooks:{afterWorkspaceDependencyAddition:RDt,afterWorkspaceDependencyRemoval:TDt,beforeWorkspacePacking:NDt}},MDt=LDt;var G5={};Vt(G5,{VersionApplyCommand:()=>zC,VersionCheckCommand:()=>JC,VersionCommand:()=>XC,default:()=>rPt,versionUtils:()=>VC});Ge();Ge();qt();var VC={};Vt(VC,{Decision:()=>WC,applyPrerelease:()=>zBe,applyReleases:()=>j5,applyStrategy:()=>XQ,clearVersionFiles:()=>_5,getUndecidedDependentWorkspaces:()=>Pv,getUndecidedWorkspaces:()=>JQ,openVersionFile:()=>KC,requireMoreDecisions:()=>$Dt,resolveVersionFiles:()=>Dv,suggestStrategy:()=>q5,updateVersionFiles:()=>H5,validateReleaseDecision:()=>YC});Ge();Pt();Nl();qt();var VBe=Ze(KBe()),BA=Ze(Jn()),ZDt=/^(>=|[~^]|)(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/,WC=(u=>(u.UNDECIDED="undecided",u.DECLINE="decline",u.MAJOR="major",u.MINOR="minor",u.PATCH="patch",u.PRERELEASE="prerelease",u))(WC||{});function YC(t){let e=BA.default.valid(t);return e||He.validateEnum((0,VBe.default)(WC,"UNDECIDED"),t)}async function Dv(t,{prerelease:e=null}={}){let r=new Map,o=t.configuration.get("deferredVersionFolder");if(!oe.existsSync(o))return r;let a=await oe.readdirPromise(o);for(let n of a){if(!n.endsWith(".yml"))continue;let u=K.join(o,n),A=await oe.readFilePromise(u,"utf8"),p=Ki(A);for(let[h,E]of Object.entries(p.releases||{})){if(E==="decline")continue;let I=G.parseIdent(h),v=t.tryWorkspaceByIdent(I);if(v===null)throw new Error(`Assertion failed: Expected a release definition file to only reference existing workspaces (${K.basename(u)} references ${h})`);if(v.manifest.version===null)throw new Error(`Assertion failed: Expected the workspace to have a version (${G.prettyLocator(t.configuration,v.anchoredLocator)})`);let x=v.manifest.raw.stableVersion??v.manifest.version,C=r.get(v),R=XQ(x,YC(E));if(R===null)throw new Error(`Assertion failed: Expected ${x} to support being bumped via strategy ${E}`);let L=typeof C<"u"?BA.default.gt(R,C)?R:C:R;r.set(v,L)}}return e&&(r=new Map([...r].map(([n,u])=>[n,zBe(u,{current:n.manifest.version,prerelease:e})]))),r}async function _5(t){let e=t.configuration.get("deferredVersionFolder");oe.existsSync(e)&&await oe.removePromise(e)}async function H5(t,e){let r=new Set(e),o=t.configuration.get("deferredVersionFolder");if(!oe.existsSync(o))return;let a=await oe.readdirPromise(o);for(let n of a){if(!n.endsWith(".yml"))continue;let u=K.join(o,n),A=await oe.readFilePromise(u,"utf8"),p=Ki(A),h=p?.releases;if(h){for(let E of Object.keys(h)){let I=G.parseIdent(E),v=t.tryWorkspaceByIdent(I);(v===null||r.has(v))&&delete p.releases[E]}Object.keys(p.releases).length>0?await oe.changeFilePromise(u,Da(new Da.PreserveOrdering(p))):await oe.unlinkPromise(u)}}}async function KC(t,{allowEmpty:e=!1}={}){let r=t.configuration;if(r.projectCwd===null)throw new st("This command can only be run from within a Yarn project");let o=await ia.fetchRoot(r.projectCwd),a=o!==null?await ia.fetchBase(o,{baseRefs:r.get("changesetBaseRefs")}):null,n=o!==null?await ia.fetchChangedFiles(o,{base:a.hash,project:t}):[],u=r.get("deferredVersionFolder"),A=n.filter(x=>K.contains(u,x)!==null);if(A.length>1)throw new st(`Your current branch contains multiple versioning files; this isn't supported: +- ${A.map(x=>ue.fromPortablePath(x)).join(` +- `)}`);let p=new Set(He.mapAndFilter(n,x=>{let C=t.tryWorkspaceByFilePath(x);return C===null?He.mapAndFilter.skip:C}));if(A.length===0&&p.size===0&&!e)return null;let h=A.length===1?A[0]:K.join(u,`${wn.makeHash(Math.random().toString()).slice(0,8)}.yml`),E=oe.existsSync(h)?await oe.readFilePromise(h,"utf8"):"{}",I=Ki(E),v=new Map;for(let x of I.declined||[]){let C=G.parseIdent(x),R=t.getWorkspaceByIdent(C);v.set(R,"decline")}for(let[x,C]of Object.entries(I.releases||{})){let R=G.parseIdent(x),L=t.getWorkspaceByIdent(R);v.set(L,YC(C))}return{project:t,root:o,baseHash:a!==null?a.hash:null,baseTitle:a!==null?a.title:null,changedFiles:new Set(n),changedWorkspaces:p,releaseRoots:new Set([...p].filter(x=>x.manifest.version!==null)),releases:v,async saveAll(){let x={},C=[],R=[];for(let L of t.workspaces){if(L.manifest.version===null)continue;let U=G.stringifyIdent(L.anchoredLocator),z=v.get(L);z==="decline"?C.push(U):typeof z<"u"?x[U]=YC(z):p.has(L)&&R.push(U)}await oe.mkdirPromise(K.dirname(h),{recursive:!0}),await oe.changeFilePromise(h,Da(new Da.PreserveOrdering({releases:Object.keys(x).length>0?x:void 0,declined:C.length>0?C:void 0,undecided:R.length>0?R:void 0})))}}}function $Dt(t){return JQ(t).size>0||Pv(t).length>0}function JQ(t){let e=new Set;for(let r of t.changedWorkspaces)r.manifest.version!==null&&(t.releases.has(r)||e.add(r));return e}function Pv(t,{include:e=new Set}={}){let r=[],o=new Map(He.mapAndFilter([...t.releases],([n,u])=>u==="decline"?He.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n])),a=new Map(He.mapAndFilter([...t.releases],([n,u])=>u!=="decline"?He.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n]));for(let n of t.project.workspaces)if(!(!e.has(n)&&(a.has(n.anchoredLocator.locatorHash)||o.has(n.anchoredLocator.locatorHash)))&&n.manifest.version!==null)for(let u of Ut.hardDependencies)for(let A of n.manifest.getForScope(u).values()){let p=t.project.tryWorkspaceByDescriptor(A);p!==null&&o.has(p.anchoredLocator.locatorHash)&&r.push([n,p])}return r}function q5(t,e){let r=BA.default.clean(e);for(let o of Object.values(WC))if(o!=="undecided"&&o!=="decline"&&BA.default.inc(t,o)===r)return o;return null}function XQ(t,e){if(BA.default.valid(e))return e;if(t===null)throw new st(`Cannot apply the release strategy "${e}" unless the workspace already has a valid version`);if(!BA.default.valid(t))throw new st(`Cannot apply the release strategy "${e}" on a non-semver version (${t})`);let r=BA.default.inc(t,e);if(r===null)throw new st(`Cannot apply the release strategy "${e}" on the specified version (${t})`);return r}function j5(t,e,{report:r}){let o=new Map;for(let a of t.workspaces)for(let n of Ut.allDependencies)for(let u of a.manifest[n].values()){let A=t.tryWorkspaceByDescriptor(u);if(A===null||!e.has(A))continue;He.getArrayWithDefault(o,A).push([a,n,u.identHash])}for(let[a,n]of e){let u=a.manifest.version;a.manifest.version=n,BA.default.prerelease(n)===null?delete a.manifest.raw.stableVersion:a.manifest.raw.stableVersion||(a.manifest.raw.stableVersion=u);let A=a.manifest.name!==null?G.stringifyIdent(a.manifest.name):null;r.reportInfo(0,`${G.prettyLocator(t.configuration,a.anchoredLocator)}: Bumped to ${n}`),r.reportJson({cwd:ue.fromPortablePath(a.cwd),ident:A,oldVersion:u,newVersion:n});let p=o.get(a);if(!(typeof p>"u"))for(let[h,E,I]of p){let v=h.manifest[E].get(I);if(typeof v>"u")throw new Error("Assertion failed: The dependency should have existed");let x=v.range,C=!1;if(x.startsWith(ei.protocol)&&(x=x.slice(ei.protocol.length),C=!0,x===a.relativeCwd))continue;let R=x.match(ZDt);if(!R){r.reportWarning(0,`Couldn't auto-upgrade range ${x} (in ${G.prettyLocator(t.configuration,h.anchoredLocator)})`);continue}let L=`${R[1]}${n}`;C&&(L=`${ei.protocol}${L}`);let U=G.makeDescriptor(v,L);h.manifest[E].set(I,U)}}}var ePt=new Map([["%n",{extract:t=>t.length>=1?[t[0],t.slice(1)]:null,generate:(t=0)=>`${t+1}`}]]);function zBe(t,{current:e,prerelease:r}){let o=new BA.default.SemVer(e),a=o.prerelease.slice(),n=[];o.prerelease=[],o.format()!==t&&(a.length=0);let u=!0,A=r.split(/\./g);for(let p of A){let h=ePt.get(p);if(typeof h>"u")n.push(p),a[0]===p?a.shift():u=!1;else{let E=u?h.extract(a):null;E!==null&&typeof E[0]=="number"?(n.push(h.generate(E[0])),a=E[1]):(n.push(h.generate()),u=!1)}}return o.prerelease&&(o.prerelease=[]),`${t}-${n.join(".")}`}var zC=class extends ut{constructor(){super(...arguments);this.all=ge.Boolean("--all",!1,{description:"Apply the deferred version changes on all workspaces"});this.dryRun=ge.Boolean("--dry-run",!1,{description:"Print the versions without actually generating the package archive"});this.prerelease=ge.String("--prerelease",{description:"Add a prerelease identifier to new versions",tolerateBoolean:!0});this.recursive=ge.Boolean("-R,--recursive",{description:"Release the transitive workspaces as well"});this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["version","apply"]]}static{this.usage=it.Usage({category:"Release-related commands",description:"apply all the deferred version bumps at once",details:` + This command will apply the deferred version changes and remove their definitions from the repository. + + Note that if \`--prerelease\` is set, the given prerelease identifier (by default \`rc.%n\`) will be used on all new versions and the version definitions will be kept as-is. + + By default only the current workspace will be bumped, but you can configure this behavior by using one of: + + - \`--recursive\` to also apply the version bump on its dependencies + - \`--all\` to apply the version bump on all packages in the repository + + Note that this command will also update the \`workspace:\` references across all your local workspaces, thus ensuring that they keep referring to the same workspaces even after the version bump. + `,examples:[["Apply the version change to the local workspace","yarn version apply"],["Apply the version change to all the workspaces in the local workspace","yarn version apply --all"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);if(!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=await Rt.start({configuration:r,json:this.json,stdout:this.context.stdout},async A=>{let p=this.prerelease?typeof this.prerelease!="boolean"?this.prerelease:"rc.%n":null,h=await Dv(o,{prerelease:p}),E=new Map;if(this.all)E=h;else{let I=this.recursive?a.getRecursiveWorkspaceDependencies():[a];for(let v of I){let x=h.get(v);typeof x<"u"&&E.set(v,x)}}if(E.size===0){let I=h.size>0?" Did you want to add --all?":"";A.reportWarning(0,`The current workspace doesn't seem to require a version bump.${I}`);return}j5(o,E,{report:A}),this.dryRun||(p||(this.all?await _5(o):await H5(o,[...E.keys()])),A.reportSeparator())});return this.dryRun||u.hasErrors()?u.exitCode():await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};Ge();Pt();qt();var ZQ=Ze(Jn());var JC=class extends ut{constructor(){super(...arguments);this.interactive=ge.Boolean("-i,--interactive",{description:"Open an interactive interface used to set version bumps"})}static{this.paths=[["version","check"]]}static{this.usage=it.Usage({category:"Release-related commands",description:"check that all the relevant packages have been bumped",details:"\n **Warning:** This command currently requires Git.\n\n This command will check that all the packages covered by the files listed in argument have been properly bumped or declined to bump.\n\n In the case of a bump, the check will also cover transitive packages - meaning that should `Foo` be bumped, a package `Bar` depending on `Foo` will require a decision as to whether `Bar` will need to be bumped. This check doesn't cross packages that have declined to bump.\n\n In case no arguments are passed to the function, the list of modified files will be generated by comparing the HEAD against `master`.\n ",examples:[["Check whether the modified packages need a bump","yarn version check"]]})}async execute(){return this.interactive?await this.executeInteractive():await this.executeStandard()}async executeInteractive(){GE(this.context);let{Gem:r}=await Promise.resolve().then(()=>(Zk(),Eq)),{ScrollableItems:o}=await Promise.resolve().then(()=>(rQ(),tQ)),{FocusRequest:a}=await Promise.resolve().then(()=>(wq(),$we)),{useListInput:n}=await Promise.resolve().then(()=>(eQ(),eIe)),{renderForm:u}=await Promise.resolve().then(()=>(oQ(),sQ)),{Box:A,Text:p}=await Promise.resolve().then(()=>Ze(ic())),{default:h,useCallback:E,useState:I}=await Promise.resolve().then(()=>Ze(an())),v=await Ke.find(this.context.cwd,this.context.plugins),{project:x,workspace:C}=await kt.find(v,this.context.cwd);if(!C)throw new sr(x.cwd,this.context.cwd);await x.restoreInstallState();let R=await KC(x);if(R===null||R.releaseRoots.size===0)return 0;if(R.root===null)throw new st("This command can only be run on Git repositories");let L=()=>h.createElement(A,{flexDirection:"row",paddingBottom:1},h.createElement(A,{flexDirection:"column",width:60},h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<up>"),"/",h.createElement(p,{bold:!0,color:"cyanBright"},"<down>")," to select workspaces.")),h.createElement(A,null,h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<left>"),"/",h.createElement(p,{bold:!0,color:"cyanBright"},"<right>")," to select release strategies."))),h.createElement(A,{flexDirection:"column"},h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<enter>")," to save.")),h.createElement(A,{marginLeft:1},h.createElement(p,null,"Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<ctrl+c>")," to abort.")))),U=({workspace:Ce,active:de,decision:Be,setDecision:Ee})=>{let g=Ce.manifest.raw.stableVersion??Ce.manifest.version;if(g===null)throw new Error(`Assertion failed: The version should have been set (${G.prettyLocator(v,Ce.anchoredLocator)})`);if(ZQ.default.prerelease(g)!==null)throw new Error(`Assertion failed: Prerelease identifiers shouldn't be found (${g})`);let me=["undecided","decline","patch","minor","major"];n(Be,me,{active:de,minus:"left",plus:"right",set:Ee});let we=Be==="undecided"?h.createElement(p,{color:"yellow"},g):Be==="decline"?h.createElement(p,{color:"green"},g):h.createElement(p,null,h.createElement(p,{color:"magenta"},g)," \u2192 ",h.createElement(p,{color:"green"},ZQ.default.valid(Be)?Be:ZQ.default.inc(g,Be)));return h.createElement(A,{flexDirection:"column"},h.createElement(A,null,h.createElement(p,null,G.prettyLocator(v,Ce.anchoredLocator)," - ",we)),h.createElement(A,null,me.map(Ae=>h.createElement(A,{key:Ae,paddingLeft:2},h.createElement(p,null,h.createElement(r,{active:Ae===Be})," ",Ae)))))},z=Ce=>{let de=new Set(R.releaseRoots),Be=new Map([...Ce].filter(([Ee])=>de.has(Ee)));for(;;){let Ee=Pv({project:R.project,releases:Be}),g=!1;if(Ee.length>0){for(let[me]of Ee)if(!de.has(me)){de.add(me),g=!0;let we=Ce.get(me);typeof we<"u"&&Be.set(me,we)}}if(!g)break}return{relevantWorkspaces:de,relevantReleases:Be}},te=()=>{let[Ce,de]=I(()=>new Map(R.releases)),Be=E((Ee,g)=>{let me=new Map(Ce);g!=="undecided"?me.set(Ee,g):me.delete(Ee);let{relevantReleases:we}=z(me);de(we)},[Ce,de]);return[Ce,Be]},ae=({workspaces:Ce,releases:de})=>{let Be=[];Be.push(`${Ce.size} total`);let Ee=0,g=0;for(let me of Ce){let we=de.get(me);typeof we>"u"?g+=1:we!=="decline"&&(Ee+=1)}return Be.push(`${Ee} release${Ee===1?"":"s"}`),Be.push(`${g} remaining`),h.createElement(p,{color:"yellow"},Be.join(", "))},ce=await u(({useSubmit:Ce})=>{let[de,Be]=te();Ce(de);let{relevantWorkspaces:Ee}=z(de),g=new Set([...Ee].filter(ne=>!R.releaseRoots.has(ne))),[me,we]=I(0),Ae=E(ne=>{switch(ne){case a.BEFORE:we(me-1);break;case a.AFTER:we(me+1);break}},[me,we]);return h.createElement(A,{flexDirection:"column"},h.createElement(L,null),h.createElement(A,null,h.createElement(p,{wrap:"wrap"},"The following files have been modified in your local checkout.")),h.createElement(A,{flexDirection:"column",marginTop:1,paddingLeft:2},[...R.changedFiles].map(ne=>h.createElement(A,{key:ne},h.createElement(p,null,h.createElement(p,{color:"grey"},ue.fromPortablePath(R.root)),ue.sep,ue.relative(ue.fromPortablePath(R.root),ue.fromPortablePath(ne)))))),R.releaseRoots.size>0&&h.createElement(h.Fragment,null,h.createElement(A,{marginTop:1},h.createElement(p,{wrap:"wrap"},"Because of those files having been modified, the following workspaces may need to be released again (note that private workspaces are also shown here, because even though they won't be published, releasing them will allow us to flag their dependents for potential re-release):")),g.size>3?h.createElement(A,{marginTop:1},h.createElement(ae,{workspaces:R.releaseRoots,releases:de})):null,h.createElement(A,{marginTop:1,flexDirection:"column"},h.createElement(o,{active:me%2===0,radius:1,size:2,onFocusRequest:Ae},[...R.releaseRoots].map(ne=>h.createElement(U,{key:ne.cwd,workspace:ne,decision:de.get(ne)||"undecided",setDecision:Z=>Be(ne,Z)}))))),g.size>0?h.createElement(h.Fragment,null,h.createElement(A,{marginTop:1},h.createElement(p,{wrap:"wrap"},"The following workspaces depend on other workspaces that have been marked for release, and thus may need to be released as well:")),h.createElement(A,null,h.createElement(p,null,"(Press ",h.createElement(p,{bold:!0,color:"cyanBright"},"<tab>")," to move the focus between the workspace groups.)")),g.size>5?h.createElement(A,{marginTop:1},h.createElement(ae,{workspaces:g,releases:de})):null,h.createElement(A,{marginTop:1,flexDirection:"column"},h.createElement(o,{active:me%2===1,radius:2,size:2,onFocusRequest:Ae},[...g].map(ne=>h.createElement(U,{key:ne.cwd,workspace:ne,decision:de.get(ne)||"undecided",setDecision:Z=>Be(ne,Z)}))))):null)},{versionFile:R},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof ce>"u")return 1;R.releases.clear();for(let[Ce,de]of ce)R.releases.set(Ce,de);await R.saveAll()}async executeStandard(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);return await o.restoreInstallState(),(await Rt.start({configuration:r,stdout:this.context.stdout},async u=>{let A=await KC(o);if(A===null||A.releaseRoots.size===0)return;if(A.root===null)throw new st("This command can only be run on Git repositories");if(u.reportInfo(0,`Your PR was started right after ${pe.pretty(r,A.baseHash.slice(0,7),"yellow")} ${pe.pretty(r,A.baseTitle,"magenta")}`),A.changedFiles.size>0){u.reportInfo(0,"You have changed the following files since then:"),u.reportSeparator();for(let v of A.changedFiles)u.reportInfo(null,`${pe.pretty(r,ue.fromPortablePath(A.root),"gray")}${ue.sep}${ue.relative(ue.fromPortablePath(A.root),ue.fromPortablePath(v))}`)}let p=!1,h=!1,E=JQ(A);if(E.size>0){p||u.reportSeparator();for(let v of E)u.reportError(0,`${G.prettyLocator(r,v.anchoredLocator)} has been modified but doesn't have a release strategy attached`);p=!0}let I=Pv(A);for(let[v,x]of I)h||u.reportSeparator(),u.reportError(0,`${G.prettyLocator(r,v.anchoredLocator)} doesn't have a release strategy attached, but depends on ${G.prettyWorkspace(r,x)} which is planned for release.`),h=!0;(p||h)&&(u.reportSeparator(),u.reportInfo(0,"This command detected that at least some workspaces have received modifications without explicit instructions as to how they had to be released (if needed)."),u.reportInfo(0,"To correct these errors, run `yarn version check --interactive` then follow the instructions."))})).exitCode()}};Ge();qt();var $Q=Ze(Jn());var XC=class extends ut{constructor(){super(...arguments);this.deferred=ge.Boolean("-d,--deferred",{description:"Prepare the version to be bumped during the next release cycle"});this.immediate=ge.Boolean("-i,--immediate",{description:"Bump the version immediately"});this.strategy=ge.String()}static{this.paths=[["version"]]}static{this.usage=it.Usage({category:"Release-related commands",description:"apply a new version to the current package",details:"\n This command will bump the version number for the given package, following the specified strategy:\n\n - If `major`, the first number from the semver range will be increased (`X.0.0`).\n - If `minor`, the second number from the semver range will be increased (`0.X.0`).\n - If `patch`, the third number from the semver range will be increased (`0.0.X`).\n - If prefixed by `pre` (`premajor`, ...), a `-0` suffix will be set (`0.0.0-0`).\n - If `prerelease`, the suffix will be increased (`0.0.0-X`); the third number from the semver range will also be increased if there was no suffix in the previous version.\n - If `decline`, the nonce will be increased for `yarn version check` to pass without version bump.\n - If a valid semver range, it will be used as new version.\n - If unspecified, Yarn will ask you for guidance.\n\n For more information about the `--deferred` flag, consult our documentation (https://yarnpkg.com/features/release-workflow#deferred-versioning).\n ",examples:[["Immediately bump the version to the next major","yarn version major"],["Prepare the version to be bumped to the next major","yarn version major --deferred"]]})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!a)throw new sr(o.cwd,this.context.cwd);let n=r.get("preferDeferredVersions");this.deferred&&(n=!0),this.immediate&&(n=!1);let u=$Q.default.valid(this.strategy),A=this.strategy==="decline",p;if(u)if(a.manifest.version!==null){let E=q5(a.manifest.version,this.strategy);E!==null?p=E:p=this.strategy}else p=this.strategy;else{let E=a.manifest.version;if(!A){if(E===null)throw new st("Can't bump the version if there wasn't a version to begin with - use 0.0.0 as initial version then run the command again.");if(typeof E!="string"||!$Q.default.valid(E))throw new st(`Can't bump the version (${E}) if it's not valid semver`)}p=YC(this.strategy)}if(!n){let I=(await Dv(o)).get(a);if(typeof I<"u"&&p!=="decline"){let v=XQ(a.manifest.version,p);if($Q.default.lt(v,I))throw new st(`Can't bump the version to one that would be lower than the current deferred one (${I})`)}}let h=await KC(o,{allowEmpty:!0});return h.releases.set(a,p),await h.saveAll(),n?0:await this.cli.run(["version","apply"])}};var tPt={configuration:{deferredVersionFolder:{description:"Folder where are stored the versioning files",type:"ABSOLUTE_PATH",default:"./.yarn/versions"},preferDeferredVersions:{description:"If true, running `yarn version` will assume the `--deferred` flag unless `--immediate` is set",type:"BOOLEAN",default:!1}},commands:[zC,JC,XC]},rPt=tPt;var Y5={};Vt(Y5,{WorkspacesFocusCommand:()=>ZC,WorkspacesForeachCommand:()=>ew,default:()=>sPt});Ge();Ge();qt();var ZC=class extends ut{constructor(){super(...arguments);this.json=ge.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.production=ge.Boolean("--production",!1,{description:"Only install regular dependencies by omitting dev dependencies"});this.all=ge.Boolean("-A,--all",!1,{description:"Install the entire project"});this.workspaces=ge.Rest()}static{this.paths=[["workspaces","focus"]]}static{this.usage=it.Usage({category:"Workspace-related commands",description:"install a single workspace and its dependencies",details:"\n This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\n\n Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\n\n If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\n "})}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd),n=await Gr.find(r);await o.restoreInstallState({restoreResolutions:!1});let u;if(this.all)u=new Set(o.workspaces);else if(this.workspaces.length===0){if(!a)throw new sr(o.cwd,this.context.cwd);u=new Set([a])}else u=new Set(this.workspaces.map(A=>o.getWorkspaceByIdent(G.parseIdent(A))));for(let A of u)for(let p of this.production?["dependencies"]:Ut.hardDependencies)for(let h of A.manifest.getForScope(p).values()){let E=o.tryWorkspaceByDescriptor(h);E!==null&&u.add(E)}for(let A of o.workspaces)u.has(A)?this.production&&A.manifest.devDependencies.clear():(A.manifest.installConfig=A.manifest.installConfig||{},A.manifest.installConfig.selfReferences=!1,A.manifest.dependencies.clear(),A.manifest.devDependencies.clear(),A.manifest.peerDependencies.clear(),A.manifest.scripts.clear());return await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n,persistProject:!1})}};Ge();Ge();Ge();qt();var $C=Ze($o()),XBe=Ze(eg());el();var ew=class extends ut{constructor(){super(...arguments);this.from=ge.Array("--from",{description:"An array of glob pattern idents or paths from which to base any recursion"});this.all=ge.Boolean("-A,--all",{description:"Run the command on all workspaces of a project"});this.recursive=ge.Boolean("-R,--recursive",{description:"Run the command on the current workspace and all of its recursive dependencies"});this.worktree=ge.Boolean("-W,--worktree",{description:"Run the command on all workspaces of the current worktree"});this.verbose=ge.Counter("-v,--verbose",{description:"Increase level of logging verbosity up to 2 times"});this.parallel=ge.Boolean("-p,--parallel",!1,{description:"Run the commands in parallel"});this.interlaced=ge.Boolean("-i,--interlaced",!1,{description:"Print the output of commands in real-time instead of buffering it"});this.jobs=ge.String("-j,--jobs",{description:"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`",validator:IT([Js(["unlimited"]),jw(wT(),[vT(),BT(1)])])});this.topological=ge.Boolean("-t,--topological",!1,{description:"Run the command after all workspaces it depends on (regular) have finished"});this.topologicalDev=ge.Boolean("--topological-dev",!1,{description:"Run the command after all workspaces it depends on (regular + dev) have finished"});this.include=ge.Array("--include",[],{description:"An array of glob pattern idents or paths; only matching workspaces will be traversed"});this.exclude=ge.Array("--exclude",[],{description:"An array of glob pattern idents or paths; matching workspaces won't be traversed"});this.publicOnly=ge.Boolean("--no-private",{description:"Avoid running the command on private workspaces"});this.since=ge.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.dryRun=ge.Boolean("-n,--dry-run",{description:"Print the commands that would be run, without actually running them"});this.commandName=ge.String();this.args=ge.Proxy()}static{this.paths=[["workspaces","foreach"]]}static{this.usage=it.Usage({category:"Workspace-related commands",description:"run a command on all workspaces",details:"\n This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\n\n - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\n\n - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\n\n - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\n\n - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `-W,--worktree` is set, Yarn will find workspaces to run the command on by looking at the current worktree.\n\n - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\n\n - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - If `--dry-run` is set, Yarn will explain what it would do without actually doing anything.\n\n - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n The `-v,--verbose` flag can be passed up to twice: once to prefix output lines with the originating workspace's name, and again to include start/finish/timing log lines. Maximum verbosity is enabled by default in terminal environments.\n\n If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\n ",examples:[["Publish all packages","yarn workspaces foreach -A npm publish --tolerate-republish"],["Run the build script on all descendant packages","yarn workspaces foreach -A run build"],["Run the build script on current and all descendant packages in parallel, building package dependencies first","yarn workspaces foreach -Apt run build"],["Run the build script on several packages and all their dependencies, building dependencies first","yarn workspaces foreach -Rpt --from '{workspace-a,workspace-b}' run build"]]})}static{this.schema=[Yw("all",Yu.Forbids,["from","recursive","since","worktree"],{missingIf:"undefined"}),DT(["all","recursive","since","worktree"],{missingIf:"undefined"})]}async execute(){let r=await Ke.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await kt.find(r,this.context.cwd);if(!this.all&&!a)throw new sr(o.cwd,this.context.cwd);await o.restoreInstallState();let n=this.cli.process([this.commandName,...this.args]),u=n.path.length===1&&n.path[0]==="run"&&typeof n.scriptName<"u"?n.scriptName:null;if(n.path.length===0)throw new st("Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script");let A=Ee=>{this.dryRun&&this.context.stdout.write(`${Ee} +`)},p=()=>{let Ee=this.from.map(g=>$C.default.matcher(g));return o.workspaces.filter(g=>{let me=G.stringifyIdent(g.anchoredLocator),we=g.relativeCwd;return Ee.some(Ae=>Ae(me)||Ae(we))})},h=[];if(this.since?(A("Option --since is set; selecting the changed workspaces as root for workspace selection"),h=Array.from(await ia.fetchChangedWorkspaces({ref:this.since,project:o}))):this.from?(A("Option --from is set; selecting the specified workspaces"),h=[...p()]):this.worktree?(A("Option --worktree is set; selecting the current workspace"),h=[a]):this.recursive?(A("Option --recursive is set; selecting the current workspace"),h=[a]):this.all&&(A("Option --all is set; selecting all workspaces"),h=[...o.workspaces]),this.dryRun&&!this.all){for(let Ee of h)A(` +- ${Ee.relativeCwd} + ${G.prettyLocator(r,Ee.anchoredLocator)}`);h.length>0&&A("")}let E;if(this.recursive?this.since?(A("Option --recursive --since is set; recursively selecting all dependent workspaces"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependents()]).flat())):(A("Option --recursive is set; recursively selecting all transitive dependencies"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependencies()]).flat())):this.worktree?(A("Option --worktree is set; recursively selecting all nested workspaces"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceChildren()]).flat())):E=null,E!==null&&(h=[...new Set([...h,...E])],this.dryRun))for(let Ee of E)A(` +- ${Ee.relativeCwd} + ${G.prettyLocator(r,Ee.anchoredLocator)}`);let I=[],v=!1;if(u?.includes(":")){for(let Ee of o.workspaces)if(Ee.manifest.scripts.has(u)&&(v=!v,v===!1))break}for(let Ee of h){if(u&&!Ee.manifest.scripts.has(u)&&!v&&!(await An.getWorkspaceAccessibleBinaries(Ee)).has(u)){A(`Excluding ${Ee.relativeCwd} because it doesn't have a "${u}" script`);continue}if(!(u===r.env.npm_lifecycle_event&&Ee.cwd===a.cwd)){if(this.include.length>0&&!$C.default.isMatch(G.stringifyIdent(Ee.anchoredLocator),this.include)&&!$C.default.isMatch(Ee.relativeCwd,this.include)){A(`Excluding ${Ee.relativeCwd} because it doesn't match the --include filter`);continue}if(this.exclude.length>0&&($C.default.isMatch(G.stringifyIdent(Ee.anchoredLocator),this.exclude)||$C.default.isMatch(Ee.relativeCwd,this.exclude))){A(`Excluding ${Ee.relativeCwd} because it matches the --include filter`);continue}if(this.publicOnly&&Ee.manifest.private===!0){A(`Excluding ${Ee.relativeCwd} because it's a private workspace and --no-private was set`);continue}I.push(Ee)}}if(this.dryRun)return 0;let x=this.verbose??(this.context.stdout.isTTY?1/0:0),C=x>0,R=x>1,L=this.parallel?this.jobs==="unlimited"?1/0:Number(this.jobs)||Math.ceil(Xi.availableParallelism()/2):1,U=L===1?!1:this.parallel,z=U?this.interlaced:!0,te=(0,XBe.default)(L),ae=new Map,le=new Set,ce=0,Ce=null,de=!1,Be=await Rt.start({configuration:r,stdout:this.context.stdout,includePrefix:!1},async Ee=>{let g=async(me,{commandIndex:we})=>{if(de)return-1;!U&&R&&we>1&&Ee.reportSeparator();let Ae=nPt(me,{configuration:r,label:C,commandIndex:we}),[ne,Z]=JBe(Ee,{prefix:Ae,interlaced:z}),[xe,Ne]=JBe(Ee,{prefix:Ae,interlaced:z});try{R&&Ee.reportInfo(null,`${Ae?`${Ae} `:""}Process started`);let ht=Date.now(),H=await this.cli.run([this.commandName,...this.args],{cwd:me.cwd,stdout:ne,stderr:xe})||0;ne.end(),xe.end(),await Z,await Ne;let rt=Date.now();if(R){let Te=r.get("enableTimers")?`, completed in ${pe.pretty(r,rt-ht,pe.Type.DURATION)}`:"";Ee.reportInfo(null,`${Ae?`${Ae} `:""}Process exited (exit code ${H})${Te}`)}return H===130&&(de=!0,Ce=H),H}catch(ht){throw ne.end(),xe.end(),await Z,await Ne,ht}};for(let me of I)ae.set(me.anchoredLocator.locatorHash,me);for(;ae.size>0&&!Ee.hasErrors();){let me=[];for(let[ne,Z]of ae){if(le.has(Z.anchoredDescriptor.descriptorHash))continue;let xe=!0;if(this.topological||this.topologicalDev){let Ne=this.topologicalDev?new Map([...Z.manifest.dependencies,...Z.manifest.devDependencies]):Z.manifest.dependencies;for(let ht of Ne.values()){let H=o.tryWorkspaceByDescriptor(ht);if(xe=H===null||!ae.has(H.anchoredLocator.locatorHash),!xe)break}}if(xe&&(le.add(Z.anchoredDescriptor.descriptorHash),me.push(te(async()=>{let Ne=await g(Z,{commandIndex:++ce});return ae.delete(ne),le.delete(Z.anchoredDescriptor.descriptorHash),Ne})),!U))break}if(me.length===0){let ne=Array.from(ae.values()).map(Z=>G.prettyLocator(r,Z.anchoredLocator)).join(", ");Ee.reportError(3,`Dependency cycle detected (${ne})`);return}let Ae=(await Promise.all(me)).find(ne=>ne!==0);Ce===null&&(Ce=typeof Ae<"u"?1:Ce),(this.topological||this.topologicalDev)&&typeof Ae<"u"&&Ee.reportError(0,"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph")}});return Ce!==null?Ce:Be.exitCode()}};function JBe(t,{prefix:e,interlaced:r}){let o=t.createStreamReporter(e),a=new He.DefaultStream;a.pipe(o,{end:!1}),a.on("finish",()=>{o.end()});let n=new Promise(A=>{o.on("finish",()=>{A(a.active)})});if(r)return[a,n];let u=new He.BufferStream;return u.pipe(a,{end:!1}),u.on("finish",()=>{a.end()}),[u,n]}function nPt(t,{configuration:e,commandIndex:r,label:o}){if(!o)return null;let n=`[${G.stringifyIdent(t.anchoredLocator)}]:`,u=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],A=u[r%u.length];return pe.pretty(e,n,A)}var iPt={commands:[ZC,ew]},sPt=iPt;var Hy=()=>({modules:new Map([["@yarnpkg/cli",W1],["@yarnpkg/core",Y1],["@yarnpkg/fslib",kw],["@yarnpkg/libzip",p1],["@yarnpkg/parsers",Ow],["@yarnpkg/shell",E1],["clipanion",Jw],["semver",oPt],["typanion",Vo],["@yarnpkg/plugin-essentials",K8],["@yarnpkg/plugin-compat",Z8],["@yarnpkg/plugin-constraints",dH],["@yarnpkg/plugin-dlx",mH],["@yarnpkg/plugin-exec",CH],["@yarnpkg/plugin-file",IH],["@yarnpkg/plugin-git",W8],["@yarnpkg/plugin-github",DH],["@yarnpkg/plugin-http",PH],["@yarnpkg/plugin-init",SH],["@yarnpkg/plugin-interactive-tools",kq],["@yarnpkg/plugin-link",Qq],["@yarnpkg/plugin-nm",hj],["@yarnpkg/plugin-npm",f5],["@yarnpkg/plugin-npm-cli",w5],["@yarnpkg/plugin-pack",a5],["@yarnpkg/plugin-patch",b5],["@yarnpkg/plugin-pnp",rj],["@yarnpkg/plugin-pnpm",Q5],["@yarnpkg/plugin-stage",O5],["@yarnpkg/plugin-typescript",U5],["@yarnpkg/plugin-version",G5],["@yarnpkg/plugin-workspace-tools",Y5]]),plugins:new Set(["@yarnpkg/plugin-essentials","@yarnpkg/plugin-compat","@yarnpkg/plugin-constraints","@yarnpkg/plugin-dlx","@yarnpkg/plugin-exec","@yarnpkg/plugin-file","@yarnpkg/plugin-git","@yarnpkg/plugin-github","@yarnpkg/plugin-http","@yarnpkg/plugin-init","@yarnpkg/plugin-interactive-tools","@yarnpkg/plugin-link","@yarnpkg/plugin-nm","@yarnpkg/plugin-npm","@yarnpkg/plugin-npm-cli","@yarnpkg/plugin-pack","@yarnpkg/plugin-patch","@yarnpkg/plugin-pnp","@yarnpkg/plugin-pnpm","@yarnpkg/plugin-stage","@yarnpkg/plugin-typescript","@yarnpkg/plugin-version","@yarnpkg/plugin-workspace-tools"])});function eve({cwd:t,pluginConfiguration:e}){let r=new Jo({binaryLabel:"Yarn Package Manager",binaryName:"yarn",binaryVersion:nn??"<unknown>"});return Object.assign(r,{defaultContext:{...Jo.defaultContext,cwd:t,plugins:e,quiet:!1,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr}})}function aPt(t){if(He.parseOptionalBoolean(process.env.YARN_IGNORE_NODE))return!0;let r=process.versions.node,o=">=18.12.0";if(Lr.satisfiesWithPrereleases(r,o))return!0;let a=new st(`This tool requires a Node version compatible with ${o} (got ${r}). Upgrade Node, or set \`YARN_IGNORE_NODE=1\` in your environment.`);return Jo.defaultContext.stdout.write(t.error(a)),!1}async function tve({selfPath:t,pluginConfiguration:e}){return await Ke.find(ue.toPortablePath(process.cwd()),e,{strict:!1,usePathCheck:t})}function lPt(t,e,{yarnPath:r}){if(!oe.existsSync(r))return t.error(new Error(`The "yarn-path" option has been set, but the specified location doesn't exist (${r}).`)),1;process.on("SIGINT",()=>{});let o={stdio:"inherit",env:{...process.env,YARN_IGNORE_PATH:"1"}};try{(0,ZBe.execFileSync)(process.execPath,[ue.fromPortablePath(r),...e],o)}catch(a){return a.status??1}return 0}function cPt(t,e){let r=null,o=e;return e.length>=2&&e[0]==="--cwd"?(r=ue.toPortablePath(e[1]),o=e.slice(2)):e.length>=1&&e[0].startsWith("--cwd=")?(r=ue.toPortablePath(e[0].slice(6)),o=e.slice(1)):e[0]==="add"&&e[e.length-2]==="--cwd"&&(r=ue.toPortablePath(e[e.length-1]),o=e.slice(0,e.length-2)),t.defaultContext.cwd=r!==null?K.resolve(r):K.cwd(),o}function uPt(t,{configuration:e}){if(!e.get("enableTelemetry")||$Be.isCI||!process.stdout.isTTY)return;Ke.telemetry=new Oy(e,"puba9cdc10ec5790a2cf4969dd413a47270");let o=/^@yarnpkg\/plugin-(.*)$/;for(let a of e.plugins.keys())Uy.has(a.match(o)?.[1]??"")&&Ke.telemetry?.reportPluginName(a);t.binaryVersion&&Ke.telemetry.reportVersion(t.binaryVersion)}function rve(t,{configuration:e}){for(let r of e.plugins.values())for(let o of r.commands||[])t.register(o)}async function APt(t,e,{selfPath:r,pluginConfiguration:o}){if(!aPt(t))return 1;let a=await tve({selfPath:r,pluginConfiguration:o}),n=a.get("yarnPath"),u=a.get("ignorePath");if(n&&!u)return lPt(t,e,{yarnPath:n});delete process.env.YARN_IGNORE_PATH;let A=cPt(t,e);uPt(t,{configuration:a}),rve(t,{configuration:a});let p=t.process(A,t.defaultContext);return p.help||Ke.telemetry?.reportCommandName(p.path.join(" ")),await t.run(p,t.defaultContext)}async function ihe({cwd:t=K.cwd(),pluginConfiguration:e=Hy()}={}){let r=eve({cwd:t,pluginConfiguration:e}),o=await tve({pluginConfiguration:e,selfPath:null});return rve(r,{configuration:o}),r}async function Wx(t,{cwd:e=K.cwd(),selfPath:r,pluginConfiguration:o}){let a=eve({cwd:e,pluginConfiguration:o});function n(){Jo.defaultContext.stdout.write(`ERROR: Yarn is terminating due to an unexpected empty event loop. +Please report this issue at https://github.com/yarnpkg/berry/issues.`)}process.once("beforeExit",n);try{process.exitCode=42,process.exitCode=await APt(a,t,{selfPath:r,pluginConfiguration:o})}catch(u){Jo.defaultContext.stdout.write(a.error(u)),process.exitCode=1}finally{process.off("beforeExit",n),await oe.rmtempPromise()}}Wx(process.argv.slice(2),{cwd:K.cwd(),selfPath:ue.toPortablePath(ue.resolve(process.argv[1])),pluginConfiguration:Hy()});})(); +/** + @license + Copyright (c) 2015, Rebecca Turner + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + */ +/** + @license + Copyright Node.js contributors. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ +/** + @license + The MIT License (MIT) + + Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +/** + @license + Copyright Joyent, Inc. and other Node contributors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the + following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +/*! Bundled license information: + +is-number/index.js: + (*! + * is-number <https://github.com/jonschlinkert/is-number> + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + *) + +to-regex-range/index.js: + (*! + * to-regex-range <https://github.com/micromatch/to-regex-range> + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + *) + +fill-range/index.js: + (*! + * fill-range <https://github.com/jonschlinkert/fill-range> + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + *) + +is-extglob/index.js: + (*! + * is-extglob <https://github.com/jonschlinkert/is-extglob> + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + *) + +is-glob/index.js: + (*! + * is-glob <https://github.com/jonschlinkert/is-glob> + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + *) + +queue-microtask/index.js: + (*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *) + +run-parallel/index.js: + (*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *) + +git-url-parse/lib/index.js: + (*! + * buildToken + * Builds OAuth token prefix (helper function) + * + * @name buildToken + * @function + * @param {GitUrl} obj The parsed Git url object. + * @return {String} token prefix + *) + +object-assign/index.js: + (* + object-assign + (c) Sindre Sorhus + @license MIT + *) + +react/cjs/react.production.min.js: + (** @license React v16.13.1 + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +scheduler/cjs/scheduler.production.min.js: + (** @license React v0.18.0 + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +react-reconciler/cjs/react-reconciler.production.min.js: + (** @license React v0.24.0 + * react-reconciler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +is-windows/index.js: + (*! + * is-windows <https://github.com/jonschlinkert/is-windows> + * + * Copyright © 2015-2018, Jon Schlinkert. + * Released under the MIT License. + *) +*/ diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarnrc.yml b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarnrc.yml new file mode 100644 index 000000000000..e41275af5f8f --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/engine/.yarnrc.yml @@ -0,0 +1,5 @@ +enableInlineHunks: true + +nodeLinker: node-modules + +yarnPath: .yarn/releases/yarn-4.4.0.cjs diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/last-layer-version.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/last-layer-version.ts new file mode 100644 index 000000000000..4dd6fef1a021 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/layers/last-layer-version.ts @@ -0,0 +1 @@ +export const LAST_LAYER_VERSION = 1; diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/local.driver.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts similarity index 73% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/local.driver.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts index 3c7f436cd2fa..00772cfd24a9 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/drivers/local.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/local.driver.ts @@ -1,28 +1,30 @@ import { fork } from 'child_process'; -import { promises as fs } from 'fs'; -import { tmpdir } from 'os'; +import { promises as fs, existsSync } from 'fs'; import { join } from 'path'; import { v4 } from 'uuid'; -import { FileStorageExceptionCode } from 'src/engine/integrations/file-storage/interfaces/file-storage-exception'; +import { FileStorageExceptionCode } from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; import { ServerlessDriver, ServerlessExecuteError, ServerlessExecuteResult, -} from 'src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface'; +} from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; -import { readFileContent } from 'src/engine/integrations/file-storage/utils/read-file-content'; -import { BaseServerlessDriver } from 'src/engine/integrations/serverless/drivers/base-serverless.driver'; -import { BUILD_FILE_NAME } from 'src/engine/integrations/serverless/drivers/constants/build-file-name'; -import { getServerlessFolder } from 'src/engine/integrations/serverless/utils/serverless-get-folder.utils'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { readFileContent } from 'src/engine/core-modules/file-storage/utils/read-file-content'; +import { BaseServerlessDriver } from 'src/engine/core-modules/serverless/drivers/base-serverless.driver'; +import { BUILD_FILE_NAME } from 'src/engine/core-modules/serverless/drivers/constants/build-file-name'; +import { getServerlessFolder } from 'src/engine/core-modules/serverless/utils/serverless-get-folder.utils'; import { ServerlessFunctionExecutionStatus } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function-execution-result.dto'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; import { ServerlessFunctionException, ServerlessFunctionExceptionCode, } from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; +import { COMMON_LAYER_NAME } from 'src/engine/core-modules/serverless/drivers/constants/common-layer-name'; +import { copyAndBuildDependencies } from 'src/engine/core-modules/serverless/drivers/utils/copy-and-build-dependencies'; +import { SERVERLESS_TMPDIR_FOLDER } from 'src/engine/core-modules/serverless/drivers/constants/serverless-tmpdir-folder'; export interface LocalDriverOptions { fileStorageService: FileStorageService; @@ -39,22 +41,40 @@ export class LocalDriver this.fileStorageService = options.fileStorageService; } + private getInMemoryLayerFolderPath = (version: number) => { + return join(SERVERLESS_TMPDIR_FOLDER, COMMON_LAYER_NAME, `${version}`); + }; + + private async createLayerIfNotExists(version: number) { + const inMemoryLastVersionLayerFolderPath = + this.getInMemoryLayerFolderPath(version); + + if (existsSync(inMemoryLastVersionLayerFolderPath)) { + return; + } + + await copyAndBuildDependencies(inMemoryLastVersionLayerFolderPath); + } + async delete() {} async build(serverlessFunction: ServerlessFunctionEntity) { + await this.createLayerIfNotExists(serverlessFunction.layerVersion); const javascriptCode = await this.getCompiledCode( serverlessFunction, this.fileStorageService, ); + const draftFolderPath = getServerlessFolder({ + serverlessFunction, + version: 'draft', + }); + await this.fileStorageService.write({ file: javascriptCode, name: BUILD_FILE_NAME, mimeType: undefined, - folder: getServerlessFolder({ - serverlessFunction, - version: 'draft', - }), + folder: draftFolderPath, }); } @@ -68,9 +88,11 @@ export class LocalDriver async execute( serverlessFunction: ServerlessFunctionEntity, - payload: object | undefined = undefined, + payload: object, version: string, ): Promise<ServerlessExecuteResult> { + await this.createLayerIfNotExists(serverlessFunction.layerVersion); + const startTime = Date.now(); let fileContent = ''; @@ -94,7 +116,15 @@ export class LocalDriver throw error; } - const tmpFilePath = join(tmpdir(), `${v4()}.js`); + const tmpFolderPath = join(SERVERLESS_TMPDIR_FOLDER, v4()); + + const tmpFilePath = join(tmpFolderPath, 'index.js'); + + await fs.symlink( + this.getInMemoryLayerFolderPath(serverlessFunction.layerVersion), + tmpFolderPath, + 'dir', + ); const modifiedContent = ` process.on('message', async (message) => { diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/utils/compile-typescript.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/compile-typescript.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/utils/compile-typescript.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/compile-typescript.ts diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/copy-and-build-dependencies.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/copy-and-build-dependencies.ts new file mode 100644 index 000000000000..0a7581bb8711 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/copy-and-build-dependencies.ts @@ -0,0 +1,40 @@ +import { statSync, promises as fs } from 'fs'; +import { promisify } from 'util'; +import { exec } from 'child_process'; +import { join } from 'path'; + +import { getLayerDependenciesDirName } from 'src/engine/core-modules/serverless/drivers/utils/get-layer-dependencies-dir-name'; + +const execPromise = promisify(exec); + +export const copyAndBuildDependencies = async (buildDirectory: string) => { + await fs.mkdir(buildDirectory, { + recursive: true, + }); + + await fs.cp(getLayerDependenciesDirName('latest'), buildDirectory, { + recursive: true, + }); + await fs.cp(getLayerDependenciesDirName('engine'), buildDirectory, { + recursive: true, + }); + + try { + await execPromise('yarn', { cwd: buildDirectory }); + } catch (error: any) { + throw new Error(error.stdout); + } + const objects = await fs.readdir(buildDirectory); + + objects.forEach((object) => { + const fullPath = join(buildDirectory, object); + + if (object === 'node_modules') return; + + if (statSync(fullPath).isDirectory()) { + fs.rm(fullPath, { recursive: true, force: true }); + } else { + fs.rm(fullPath); + } + }); +}; diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/utils/create-zip-file.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/create-zip-file.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/utils/create-zip-file.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/create-zip-file.ts diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-last-layer-dependencies.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-last-layer-dependencies.ts new file mode 100644 index 000000000000..75eba8888a71 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-last-layer-dependencies.ts @@ -0,0 +1,24 @@ +import fs from 'fs/promises'; +import { join } from 'path'; + +import { getLayerDependenciesDirName } from 'src/engine/core-modules/serverless/drivers/utils/get-layer-dependencies-dir-name'; + +export type LayerDependencies = { + packageJson: { dependencies: object }; + yarnLock: string; +}; + +export const getLastLayerDependencies = + async (): Promise<LayerDependencies> => { + const lastVersionLayerDirName = getLayerDependenciesDirName('latest'); + const packageJson = await fs.readFile( + join(lastVersionLayerDirName, 'package.json'), + 'utf8', + ); + const yarnLock = await fs.readFile( + join(lastVersionLayerDirName, 'yarn.lock'), + 'utf8', + ); + + return { packageJson: JSON.parse(packageJson), yarnLock }; + }; diff --git a/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-layer-dependencies-dir-name.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-layer-dependencies-dir-name.ts new file mode 100644 index 000000000000..3c6ee4e8b26e --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/get-layer-dependencies-dir-name.ts @@ -0,0 +1,12 @@ +import path from 'path'; + +import { LAST_LAYER_VERSION } from 'src/engine/core-modules/serverless/drivers/layers/last-layer-version'; + +// Can only be used in src/engine/integrations/serverless/drivers/utils folder +export const getLayerDependenciesDirName = ( + version: 'latest' | 'engine' | number, +): string => { + const formattedVersion = version === 'latest' ? LAST_LAYER_VERSION : version; + + return path.resolve(__dirname, `../layers/${formattedVersion}`); +}; diff --git a/packages/twenty-server/src/engine/integrations/serverless/drivers/services/build-directory-manager.service.ts b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/lambda-build-directory-manager.ts similarity index 50% rename from packages/twenty-server/src/engine/integrations/serverless/drivers/services/build-directory-manager.service.ts rename to packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/lambda-build-directory-manager.ts index 9f0d6b6a7715..b67811f9742f 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/drivers/services/build-directory-manager.service.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/drivers/utils/lambda-build-directory-manager.ts @@ -1,20 +1,22 @@ -import { Injectable } from '@nestjs/common'; - import { join } from 'path'; -import { tmpdir } from 'os'; -import fs from 'fs'; +import * as fs from 'fs/promises'; -import fsExtra from 'fs-extra'; import { v4 } from 'uuid'; -const TEMPORARY_LAMBDA_FOLDER = 'twenty-build-lambda-temp-folder'; +import { SERVERLESS_TMPDIR_FOLDER } from 'src/engine/core-modules/serverless/drivers/constants/serverless-tmpdir-folder'; + +export const NODE_LAYER_SUBFOLDER = 'nodejs'; + +const TEMPORARY_LAMBDA_FOLDER = 'lambda-build'; const TEMPORARY_LAMBDA_SOURCE_FOLDER = 'src'; const LAMBDA_ZIP_FILE_NAME = 'lambda.zip'; const LAMBDA_ENTRY_FILE_NAME = 'index.js'; -@Injectable() -export class BuildDirectoryManagerService { - private temporaryDir = join(tmpdir(), `${TEMPORARY_LAMBDA_FOLDER}_${v4()}`); +export class LambdaBuildDirectoryManager { + private temporaryDir = join( + SERVERLESS_TMPDIR_FOLDER, + `${TEMPORARY_LAMBDA_FOLDER}-${v4()}`, + ); private lambdaHandler = `${LAMBDA_ENTRY_FILE_NAME.split('.')[0]}.handler`; async init() { @@ -25,13 +27,7 @@ export class BuildDirectoryManagerService { const lambdaZipPath = join(this.temporaryDir, LAMBDA_ZIP_FILE_NAME); const javascriptFilePath = join(sourceTemporaryDir, LAMBDA_ENTRY_FILE_NAME); - if (!fs.existsSync(this.temporaryDir)) { - await fs.promises.mkdir(this.temporaryDir); - await fs.promises.mkdir(sourceTemporaryDir); - } else { - await fsExtra.emptyDir(this.temporaryDir); - await fs.promises.mkdir(sourceTemporaryDir); - } + await fs.mkdir(sourceTemporaryDir, { recursive: true }); return { sourceTemporaryDir, @@ -42,7 +38,6 @@ export class BuildDirectoryManagerService { } async clean() { - await fsExtra.emptyDir(this.temporaryDir); - await fs.promises.rmdir(this.temporaryDir); + await fs.rm(this.temporaryDir, { recursive: true, force: true }); } } diff --git a/packages/twenty-server/src/engine/integrations/serverless/serverless-module.factory.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts similarity index 78% rename from packages/twenty-server/src/engine/integrations/serverless/serverless-module.factory.ts rename to packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts index 817c46e2390f..e8c2d7baaf06 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/serverless-module.factory.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts @@ -1,17 +1,15 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; -import { BuildDirectoryManagerService } from 'src/engine/integrations/serverless/drivers/services/build-directory-manager.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { ServerlessDriverType, ServerlessModuleOptions, -} from 'src/engine/integrations/serverless/serverless.interface'; +} from 'src/engine/core-modules/serverless/serverless.interface'; export const serverlessModuleFactory = async ( environmentService: EnvironmentService, fileStorageService: FileStorageService, - buildDirectoryManagerService: BuildDirectoryManagerService, ): Promise<ServerlessModuleOptions> => { const driverType = environmentService.get('SERVERLESS_TYPE'); const options = { fileStorageService }; @@ -37,7 +35,6 @@ export const serverlessModuleFactory = async ( type: ServerlessDriverType.Lambda, options: { ...options, - buildDirectoryManagerService, credentials: accessKeyId ? { accessKeyId, diff --git a/packages/twenty-server/src/engine/integrations/serverless/serverless.constants.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless.constants.ts similarity index 100% rename from packages/twenty-server/src/engine/integrations/serverless/serverless.constants.ts rename to packages/twenty-server/src/engine/core-modules/serverless/serverless.constants.ts diff --git a/packages/twenty-server/src/engine/integrations/serverless/serverless.interface.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless.interface.ts similarity index 85% rename from packages/twenty-server/src/engine/integrations/serverless/serverless.interface.ts rename to packages/twenty-server/src/engine/core-modules/serverless/serverless.interface.ts index c1c4fb661723..be2cbb694b2f 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/serverless.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/serverless.interface.ts @@ -1,7 +1,7 @@ import { FactoryProvider, ModuleMetadata } from '@nestjs/common'; -import { LocalDriverOptions } from 'src/engine/integrations/serverless/drivers/local.driver'; -import { LambdaDriverOptions } from 'src/engine/integrations/serverless/drivers/lambda.driver'; +import { LocalDriverOptions } from 'src/engine/core-modules/serverless/drivers/local.driver'; +import { LambdaDriverOptions } from 'src/engine/core-modules/serverless/drivers/lambda.driver'; export enum ServerlessDriverType { Lambda = 'lambda', diff --git a/packages/twenty-server/src/engine/integrations/serverless/serverless.module.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless.module.ts similarity index 61% rename from packages/twenty-server/src/engine/integrations/serverless/serverless.module.ts rename to packages/twenty-server/src/engine/core-modules/serverless/serverless.module.ts index 7acd708ba9fd..de63788079f3 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/serverless.module.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/serverless.module.ts @@ -1,14 +1,13 @@ import { DynamicModule, Global } from '@nestjs/common'; -import { LambdaDriver } from 'src/engine/integrations/serverless/drivers/lambda.driver'; -import { LocalDriver } from 'src/engine/integrations/serverless/drivers/local.driver'; -import { BuildDirectoryManagerService } from 'src/engine/integrations/serverless/drivers/services/build-directory-manager.service'; -import { SERVERLESS_DRIVER } from 'src/engine/integrations/serverless/serverless.constants'; +import { LambdaDriver } from 'src/engine/core-modules/serverless/drivers/lambda.driver'; +import { LocalDriver } from 'src/engine/core-modules/serverless/drivers/local.driver'; +import { SERVERLESS_DRIVER } from 'src/engine/core-modules/serverless/serverless.constants'; import { ServerlessDriverType, ServerlessModuleAsyncOptions, -} from 'src/engine/integrations/serverless/serverless.interface'; -import { ServerlessService } from 'src/engine/integrations/serverless/serverless.service'; +} from 'src/engine/core-modules/serverless/serverless.interface'; +import { ServerlessService } from 'src/engine/core-modules/serverless/serverless.service'; @Global() export class ServerlessModule { @@ -28,7 +27,7 @@ export class ServerlessModule { return { module: ServerlessModule, imports: options.imports || [], - providers: [ServerlessService, BuildDirectoryManagerService, provider], + providers: [ServerlessService, provider], exports: [ServerlessService], }; } diff --git a/packages/twenty-server/src/engine/integrations/serverless/serverless.service.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless.service.ts similarity index 86% rename from packages/twenty-server/src/engine/integrations/serverless/serverless.service.ts rename to packages/twenty-server/src/engine/core-modules/serverless/serverless.service.ts index 747feae9a1c8..ee8fc93b4833 100644 --- a/packages/twenty-server/src/engine/integrations/serverless/serverless.service.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/serverless.service.ts @@ -3,9 +3,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { ServerlessDriver, ServerlessExecuteResult, -} from 'src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface'; +} from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface'; -import { SERVERLESS_DRIVER } from 'src/engine/integrations/serverless/serverless.constants'; +import { SERVERLESS_DRIVER } from 'src/engine/core-modules/serverless/serverless.constants'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; @Injectable() @@ -29,7 +29,7 @@ export class ServerlessService implements ServerlessDriver { async execute( serverlessFunction: ServerlessFunctionEntity, - payload: object | undefined = undefined, + payload: object, version: string, ): Promise<ServerlessExecuteResult> { return this.driver.execute(serverlessFunction, payload, version); diff --git a/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts b/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts new file mode 100644 index 000000000000..8dc4a97bf70f --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/serverless/utils/serverless-get-folder.utils.ts @@ -0,0 +1,23 @@ +import { join } from 'path'; + +import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; + +import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; + +export const getServerlessFolder = ({ + serverlessFunction, + version, +}: { + serverlessFunction: ServerlessFunctionEntity; + version?: string; +}) => { + const computedVersion = + version === 'latest' ? serverlessFunction.latestVersion : version; + + return join( + 'workspace-' + serverlessFunction.workspaceId, + FileFolder.ServerlessFunction, + serverlessFunction.id, + computedVersion || '', + ); +}; diff --git a/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.module.ts b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.module.ts new file mode 100644 index 000000000000..b9be5ec208d0 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.module.ts @@ -0,0 +1,15 @@ +import { HttpModule } from '@nestjs/axios'; +import { Module } from '@nestjs/common'; + +import { TelemetryService } from './telemetry.service'; + +@Module({ + providers: [TelemetryService], + imports: [ + HttpModule.register({ + baseURL: 'https://t.twenty.com/api/v2', + }), + ], + exports: [TelemetryService], +}) +export class TelemetryModule {} diff --git a/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts new file mode 100644 index 000000000000..6f59f9847811 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts @@ -0,0 +1,55 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable, Logger } from '@nestjs/common'; + +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; + +type CreateEventInput = { + action: string; + payload: object; +}; + +@Injectable() +export class TelemetryService { + private readonly logger = new Logger(TelemetryService.name); + + constructor( + private readonly environmentService: EnvironmentService, + private readonly httpService: HttpService, + ) {} + + async create( + createEventInput: CreateEventInput, + userId: string | null | undefined, + workspaceId: string | null | undefined, + ) { + if (!this.environmentService.get('TELEMETRY_ENABLED')) { + return { success: true }; + } + + const data = { + action: createEventInput.action, + timestamp: new Date().toISOString(), + version: '1', + payload: { + userId: userId, + workspaceId: workspaceId, + ...createEventInput.payload, + }, + }; + + try { + await this.httpService.axiosRef.post(`/selfHostingEvent`, data); + } catch (error) { + this.logger.error('Error occurred:', error); + if (error.response) { + this.logger.error( + `Error response body: ${JSON.stringify(error.response.data)}`, + ); + } + + return { success: false }; + } + + return { success: true }; + } +} diff --git a/packages/twenty-server/src/engine/core-modules/throttler/throttler.service.ts b/packages/twenty-server/src/engine/core-modules/throttler/throttler.service.ts index 5805db89aec6..925ffc8488f6 100644 --- a/packages/twenty-server/src/engine/core-modules/throttler/throttler.service.ts +++ b/packages/twenty-server/src/engine/core-modules/throttler/throttler.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { ThrottlerException, ThrottlerExceptionCode, } from 'src/engine/core-modules/throttler/throttler.exception'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; @Injectable() export class ThrottlerService { diff --git a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.module.ts b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.module.ts index 570c1103f831..c7967cd63d27 100644 --- a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.module.ts +++ b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.module.ts @@ -6,18 +6,24 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; -import { User } from 'src/engine/core-modules/user/user.entity'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { WorkspaceInvitationModule } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.module'; @Module({ imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ - NestjsQueryTypeOrmModule.forFeature([User, UserWorkspace], 'core'), + NestjsQueryTypeOrmModule.forFeature( + [User, UserWorkspace, AppToken], + 'core', + ), TypeORMModule, DataSourceModule, WorkspaceDataSourceModule, + WorkspaceInvitationModule, ], services: [UserWorkspaceService], }), diff --git a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.resolver.ts b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.resolver.ts index 065e0c4bd1d0..338b6e9499f6 100644 --- a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.resolver.ts @@ -4,23 +4,24 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceInviteHashValidInput } from 'src/engine/core-modules/auth/dto/workspace-invite-hash.input'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; -import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; +import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { WorkspaceInviteHashValidInput } from 'src/engine/core-modules/auth/dto/workspace-invite-hash.input'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; +import { WorkspaceInviteTokenInput } from 'src/engine/core-modules/auth/dto/workspace-invite-token.input'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver(() => UserWorkspace) export class UserWorkspaceResolver { constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository<Workspace>, - @InjectRepository(User, 'core') - private readonly userRepository: Repository<User>, private readonly userWorkspaceService: UserWorkspaceService, + private readonly workspaceInvitationService: WorkspaceInvitationService, ) {} @Mutation(() => User) @@ -36,6 +37,22 @@ export class UserWorkspaceResolver { return; } + await this.workspaceInvitationService.invalidateWorkspaceInvitation( + workspace.id, + user.email, + ); + return await this.userWorkspaceService.addUserToWorkspace(user, workspace); } + + @Mutation(() => User) + async addUserToWorkspaceByInviteToken( + @AuthUser() user: User, + @Args() workspaceInviteTokenInput: WorkspaceInviteTokenInput, + ) { + return this.userWorkspaceService.addUserToWorkspaceByInviteToken( + workspaceInviteTokenInput.inviteToken, + user, + ); + } } diff --git a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts index cc2727b3a118..4f26a8b0e0df 100644 --- a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts @@ -5,10 +5,15 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { Repository } from 'typeorm'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { + AppToken, + AppTokenType, +} from 'src/engine/core-modules/app-token/app-token.entity'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; +import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -20,8 +25,11 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> { private readonly userWorkspaceRepository: Repository<UserWorkspace>, @InjectRepository(User, 'core') private readonly userRepository: Repository<User>, + @InjectRepository(AppToken, 'core') + private readonly appTokenRepository: Repository<AppToken>, private readonly dataSourceService: DataSourceService, private readonly typeORMService: TypeORMService, + private readonly workspaceInvitationService: WorkspaceInvitationService, private workspaceEventEmitter: WorkspaceEventEmitter, ) { super(userWorkspaceRepository); @@ -105,6 +113,41 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> { }); } + async validateInvitation(inviteToken: string, email: string) { + const appToken = await this.appTokenRepository.findOne({ + where: { + value: inviteToken, + type: AppTokenType.InvitationToken, + }, + relations: ['workspace'], + }); + + if (!appToken) { + throw new Error('Invalid invitation token'); + } + + if (appToken.context?.email !== email) { + throw new Error('Email does not match the invitation'); + } + + if (new Date(appToken.expiresAt) < new Date()) { + throw new Error('Invitation expired'); + } + + return appToken; + } + + async addUserToWorkspaceByInviteToken(inviteToken: string, user: User) { + const appToken = await this.validateInvitation(inviteToken, user.email); + + await this.workspaceInvitationService.invalidateWorkspaceInvitation( + appToken.workspace.id, + user.email, + ); + + return await this.addUserToWorkspace(user, appToken.workspace); + } + public async getUserCount(workspaceId): Promise<number | undefined> { return await this.userWorkspaceRepository.countBy({ workspaceId, @@ -120,4 +163,18 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> { workspaceId, }); } + + async checkUserWorkspaceExistsByEmail(email: string, workspaceId: string) { + return this.userWorkspaceRepository.exists({ + where: { + workspaceId, + user: { + email, + }, + }, + relations: { + user: true, + }, + }); + } } diff --git a/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts b/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts index aec142d2655a..5a832e0eb6ca 100644 --- a/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts +++ b/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts @@ -6,13 +6,13 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { Repository } from 'typeorm'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; import { User } from 'src/engine/core-modules/user/user.entity'; import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @@ -32,17 +32,14 @@ export class UserService extends TypeOrmQueryService<User> { super(userRepository); } - async loadWorkspaceMember(user: User) { - if ( - user.defaultWorkspace.activationStatus !== - WorkspaceActivationStatus.ACTIVE - ) { + async loadWorkspaceMember(user: User, workspace: Workspace) { + if (workspace?.activationStatus !== WorkspaceActivationStatus.ACTIVE) { return null; } const workspaceMemberRepository = await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>( - user.defaultWorkspaceId, + workspace.id, 'workspaceMember', ); diff --git a/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts b/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts index eeb6b95bbb25..b5ff2c2c3c22 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts @@ -1,11 +1,11 @@ import { AutoResolverOpts, - ReadResolverOpts, PagingStrategies, + ReadResolverOpts, } from '@ptc-org/nestjs-query-graphql'; import { User } from 'src/engine/core-modules/user/user.entity'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; export const userAutoResolverOpts: AutoResolverOpts< any, @@ -33,6 +33,6 @@ export const userAutoResolverOpts: AutoResolverOpts< one: { disabled: true }, }, delete: { many: { disabled: true }, one: { disabled: true } }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], }, ]; diff --git a/packages/twenty-server/src/engine/core-modules/user/user.entity.ts b/packages/twenty-server/src/engine/core-modules/user/user.entity.ts index 56e99de429bb..fbd86f127622 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.entity.ts @@ -9,6 +9,7 @@ import { OneToMany, PrimaryGeneratedColumn, Relation, + Unique, UpdateDateColumn, } from 'typeorm'; @@ -27,6 +28,7 @@ registerEnumType(OnboardingStatus, { @Entity({ name: 'user', schema: 'core' }) @ObjectType('User') +@Unique('UQ_USER_EMAIL', ['email', 'deletedAt']) export class User { @IDField(() => UUIDScalarType) @PrimaryGeneratedColumn('uuid') diff --git a/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts b/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts index c77bb690baf7..d4304622af76 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts @@ -16,9 +16,10 @@ import { GraphQLJSONObject } from 'graphql-type-json'; import { FileUpload, GraphQLUpload } from 'graphql-upload'; import { Repository } from 'typeorm'; +import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; -import { SupportDriver } from 'src/engine/integrations/environment/interfaces/support.interface'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileService } from 'src/engine/core-modules/file/services/file.service'; import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum'; @@ -31,8 +32,7 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { streamToBuffer } from 'src/utils/stream-to-buffer'; const getHMACKey = (email?: string, key?: string | null) => { @@ -43,7 +43,7 @@ const getHMACKey = (email?: string, key?: string | null) => { return hmac.update(email).digest('hex'); }; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver(() => User) export class UserResolver { constructor( @@ -97,13 +97,19 @@ export class UserResolver { @ResolveField(() => WorkspaceMember, { nullable: true, }) - async workspaceMember(@Parent() user: User): Promise<WorkspaceMember | null> { - const workspaceMember = await this.userService.loadWorkspaceMember(user); + async workspaceMember( + @Parent() user: User, + @AuthWorkspace() workspace: Workspace, + ): Promise<WorkspaceMember | null> { + const workspaceMember = await this.userService.loadWorkspaceMember( + user, + workspace ?? user.defaultWorkspace, + ); if (workspaceMember && workspaceMember.avatarUrl) { const avatarUrlToken = await this.fileService.encodeFileToken({ workspace_member_id: workspaceMember.id, - workspace_id: user.defaultWorkspace.id, + workspace_id: user.defaultWorkspaceId, }); workspaceMember.avatarUrl = `${workspaceMember.avatarUrl}?token=${avatarUrlToken}`; diff --git a/packages/twenty-server/src/engine/core-modules/workflow/filters/workflow-trigger-graphql-api-exception.filter.ts b/packages/twenty-server/src/engine/core-modules/workflow/filters/workflow-trigger-graphql-api-exception.filter.ts index 1bbfdc27342c..a274ccd4370b 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/filters/workflow-trigger-graphql-api-exception.filter.ts +++ b/packages/twenty-server/src/engine/core-modules/workflow/filters/workflow-trigger-graphql-api-exception.filter.ts @@ -7,7 +7,7 @@ import { import { WorkflowTriggerException, WorkflowTriggerExceptionCode, -} from 'src/modules/workflow/workflow-trigger/workflow-trigger.exception'; +} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception'; @Catch(WorkflowTriggerException) export class WorkflowTriggerGraphqlApiExceptionFilter diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts index 82aa30498f0a..70cedd3f54a9 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts @@ -7,11 +7,12 @@ import { WorkflowRunDTO } from 'src/engine/core-modules/workflow/dtos/workflow-r import { WorkflowTriggerGraphqlApiExceptionFilter } from 'src/engine/core-modules/workflow/filters/workflow-trigger-graphql-api-exception.filter'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace-member-id.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workflow-trigger.workspace-service'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service'; @Resolver() -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard, UserAuthGuard) @UseFilters(WorkflowTriggerGraphqlApiExceptionFilter) export class WorkflowTriggerResolver { constructor( @@ -19,19 +20,19 @@ export class WorkflowTriggerResolver { ) {} @Mutation(() => Boolean) - async enableWorkflowTrigger( + async activateWorkflowVersion( @Args('workflowVersionId') workflowVersionId: string, ) { - return await this.workflowTriggerWorkspaceService.enableWorkflowTrigger( + return await this.workflowTriggerWorkspaceService.activateWorkflowVersion( workflowVersionId, ); } @Mutation(() => Boolean) - async disableWorkflowTrigger( + async deactivateWorkflowVersion( @Args('workflowVersionId') workflowVersionId: string, ) { - return await this.workflowTriggerWorkspaceService.disableWorkflowTrigger( + return await this.workflowTriggerWorkspaceService.deactivateWorkflowVersion( workflowVersionId, ); } diff --git a/packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.input.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.input.ts similarity index 86% rename from packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.input.ts rename to packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.input.ts index ac80111bab50..682a970ded2c 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.input.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.input.ts @@ -3,7 +3,7 @@ import { ArgsType, Field } from '@nestjs/graphql'; import { ArrayUnique, IsArray, IsEmail } from 'class-validator'; @ArgsType() -export class SendInviteLinkInput { +export class SendInvitationsInput { @Field(() => [String]) @IsArray() @IsEmail({}, { each: true }) diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.output.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.output.ts new file mode 100644 index 000000000000..aa72b2c61ce7 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/send-invitations.output.ts @@ -0,0 +1,17 @@ +import { Field, ObjectType } from '@nestjs/graphql'; + +import { WorkspaceInvitation } from 'src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto'; + +@ObjectType() +export class SendInvitationsOutput { + @Field(() => Boolean, { + description: 'Boolean that confirms query was dispatched', + }) + success: boolean; + + @Field(() => [String]) + errors: Array<string>; + + @Field(() => [WorkspaceInvitation]) + result: Array<WorkspaceInvitation>; +} diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto.ts new file mode 100644 index 000000000000..76f2f65f5cf0 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto.ts @@ -0,0 +1,17 @@ +import { Field, ObjectType } from '@nestjs/graphql'; + +import { IDField } from '@ptc-org/nestjs-query-graphql'; + +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; + +@ObjectType('WorkspaceInvitation') +export class WorkspaceInvitation { + @IDField(() => UUIDScalarType) + id: string; + + @Field({ nullable: false }) + email: string; + + @Field({ nullable: false }) + expiresAt: Date; +} diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts new file mode 100644 index 000000000000..3fce16c4c34b --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts @@ -0,0 +1,55 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; + +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; + +import { WorkspaceInvitationService } from './workspace-invitation.service'; + +describe('WorkspaceInvitationService', () => { + let service: WorkspaceInvitationService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + WorkspaceInvitationService, + { + provide: getRepositoryToken(AppToken, 'core'), + useValue: {}, + }, + { + provide: EnvironmentService, + useValue: {}, + }, + { + provide: EmailService, + useValue: {}, + }, + { + provide: TokenService, + useValue: {}, + }, + { + provide: getRepositoryToken(UserWorkspace, 'core'), + useValue: {}, + }, + { + provide: OnboardingService, + useValue: {}, + }, + ], + }).compile(); + + service = module.get<WorkspaceInvitationService>( + WorkspaceInvitationService, + ); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts new file mode 100644 index 000000000000..8c193efefaa6 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts @@ -0,0 +1,293 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { render } from '@react-email/render'; +import { SendInviteLinkEmail } from 'twenty-emails'; +import { IsNull, Repository } from 'typeorm'; + +import { + AppToken, + AppTokenType, +} from 'src/engine/core-modules/app-token/app-token.entity'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { SendInvitationsOutput } from 'src/engine/core-modules/workspace-invitation/dtos/send-invitations.output'; +import { + WorkspaceInvitationException, + WorkspaceInvitationExceptionCode, +} from 'src/engine/core-modules/workspace-invitation/workspace-invitation.exception'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; + +@Injectable() +// eslint-disable-next-line @nx/workspace-inject-workspace-repository +export class WorkspaceInvitationService { + constructor( + @InjectRepository(AppToken, 'core') + private readonly appTokenRepository: Repository<AppToken>, + private readonly environmentService: EnvironmentService, + private readonly emailService: EmailService, + private readonly tokenService: TokenService, + @InjectRepository(UserWorkspace, 'core') + private readonly userWorkspaceRepository: Repository<UserWorkspace>, + private readonly onboardingService: OnboardingService, + ) {} + + private async getOneWorkspaceInvitation(workspaceId: string, email: string) { + return await this.appTokenRepository + .createQueryBuilder('appToken') + .where('"appToken"."workspaceId" = :workspaceId', { + workspaceId, + }) + .andWhere('"appToken".type = :type', { + type: AppTokenType.InvitationToken, + }) + .andWhere('"appToken".context->>\'email\' = :email', { email }) + .getOne(); + } + + castAppTokenToWorkspaceInvitation(appToken: AppToken) { + if (appToken.type !== AppTokenType.InvitationToken) { + throw new WorkspaceInvitationException( + `Token type must be "${AppTokenType.InvitationToken}"`, + WorkspaceInvitationExceptionCode.INVALID_APP_TOKEN_TYPE, + ); + } + + if (!appToken.context?.email) { + throw new WorkspaceInvitationException( + `Invitation corrupted: Missing email in context`, + WorkspaceInvitationExceptionCode.INVITATION_CORRUPTED, + ); + } + + return { + id: appToken.id, + email: appToken.context.email, + expiresAt: appToken.expiresAt, + }; + } + + async createWorkspaceInvitation(email: string, workspace: Workspace) { + const maybeWorkspaceInvitation = await this.getOneWorkspaceInvitation( + workspace.id, + email.toLowerCase(), + ); + + if (maybeWorkspaceInvitation) { + throw new WorkspaceInvitationException( + `${email} already invited`, + WorkspaceInvitationExceptionCode.INVITATION_ALREADY_EXIST, + ); + } + + const isUserAlreadyInWorkspace = await this.userWorkspaceRepository.exists({ + where: { + workspaceId: workspace.id, + user: { + email, + }, + }, + relations: { + user: true, + }, + }); + + if (isUserAlreadyInWorkspace) { + throw new WorkspaceInvitationException( + `${email} is already in the workspace`, + WorkspaceInvitationExceptionCode.USER_ALREADY_EXIST, + ); + } + + return this.tokenService.generateInvitationToken(workspace.id, email); + } + + async loadWorkspaceInvitations(workspace: Workspace) { + const appTokens = await this.appTokenRepository.find({ + where: { + workspaceId: workspace.id, + type: AppTokenType.InvitationToken, + deletedAt: IsNull(), + }, + select: { + value: false, + }, + }); + + return appTokens.map(this.castAppTokenToWorkspaceInvitation); + } + + async deleteWorkspaceInvitation(appTokenId: string, workspaceId: string) { + const appToken = await this.appTokenRepository.findOne({ + where: { + id: appTokenId, + workspaceId, + type: AppTokenType.InvitationToken, + }, + }); + + if (!appToken) { + return 'error'; + } + + await this.appTokenRepository.delete(appToken.id); + + return 'success'; + } + + async invalidateWorkspaceInvitation(workspaceId: string, email: string) { + const appToken = await this.getOneWorkspaceInvitation(workspaceId, email); + + if (appToken) { + await this.appTokenRepository.delete(appToken.id); + } + } + + async resendWorkspaceInvitation( + appTokenId: string, + workspace: Workspace, + sender: User, + ) { + const appToken = await this.appTokenRepository.findOne({ + where: { + id: appTokenId, + workspaceId: workspace.id, + type: AppTokenType.InvitationToken, + }, + }); + + if (!appToken || !appToken.context || !('email' in appToken.context)) { + throw new WorkspaceInvitationException( + 'Invalid appToken', + WorkspaceInvitationExceptionCode.INVALID_INVITATION, + ); + } + + await this.appTokenRepository.delete(appToken.id); + + return this.sendInvitations([appToken.context.email], workspace, sender); + } + + async sendInvitations( + emails: string[], + workspace: Workspace, + sender: User, + usePersonalInvitation = true, + ): Promise<SendInvitationsOutput> { + if (!workspace?.inviteHash) { + return { + success: false, + errors: ['Workspace invite hash not found'], + result: [], + }; + } + + const invitationsPr = await Promise.allSettled( + emails.map(async (email) => { + if (usePersonalInvitation) { + const appToken = await this.createWorkspaceInvitation( + email, + workspace, + ); + + if (!appToken.context?.email) { + throw new WorkspaceInvitationException( + 'Invalid email', + WorkspaceInvitationExceptionCode.EMAIL_MISSING, + ); + } + + return { + isPersonalInvitation: true as const, + appToken, + email: appToken.context.email, + }; + } + + return { + isPersonalInvitation: false as const, + email, + }; + }), + ); + + const frontBaseURL = this.environmentService.get('FRONT_BASE_URL'); + + for (const invitation of invitationsPr) { + if (invitation.status === 'fulfilled') { + const link = new URL(`${frontBaseURL}/invite/${workspace?.inviteHash}`); + + if (invitation.value.isPersonalInvitation) { + link.searchParams.set('inviteToken', invitation.value.appToken.value); + } + const emailData = { + link: link.toString(), + workspace: { name: workspace.displayName, logo: workspace.logo }, + sender: { email: sender.email, firstName: sender.firstName }, + serverUrl: this.environmentService.get('SERVER_URL'), + }; + + const emailTemplate = SendInviteLinkEmail(emailData); + const html = render(emailTemplate, { + pretty: true, + }); + + const text = render(emailTemplate, { + plainText: true, + }); + + await this.emailService.send({ + from: `${this.environmentService.get( + 'EMAIL_FROM_NAME', + )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + to: invitation.value.email, + subject: 'Join your team on Twenty', + text, + html, + }); + } + } + + await this.onboardingService.setOnboardingInviteTeamPending({ + workspaceId: workspace.id, + value: false, + }); + + const result = invitationsPr.reduce<{ + errors: string[]; + result: ReturnType< + typeof this.workspaceInvitationService.createWorkspaceInvitation + >['status'] extends 'rejected' + ? never + : ReturnType< + typeof this.workspaceInvitationService.appTokenToWorkspaceInvitation + >; + }>( + (acc, invitation) => { + if (invitation.status === 'rejected') { + acc.errors.push(invitation.reason?.message ?? 'Unknown error'); + } else { + acc.result.push( + invitation.value.isPersonalInvitation + ? this.castAppTokenToWorkspaceInvitation( + invitation.value.appToken, + ) + : { email: invitation.value.email }, + ); + } + + return acc; + }, + { errors: [], result: [] }, + ); + + return { + success: result.errors.length === 0, + ...result, + }; + } +} diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.exception.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.exception.ts new file mode 100644 index 000000000000..6dce1ea3bc60 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.exception.ts @@ -0,0 +1,17 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkspaceInvitationException extends CustomException { + code: WorkspaceInvitationExceptionCode; + constructor(message: string, code: WorkspaceInvitationExceptionCode) { + super(message, code); + } +} + +export enum WorkspaceInvitationExceptionCode { + INVALID_APP_TOKEN_TYPE = 'INVALID_APP_TOKEN_TYPE', + INVITATION_CORRUPTED = 'INVITATION_CORRUPTED', + INVITATION_ALREADY_EXIST = 'INVITATION_ALREADY_EXIST', + USER_ALREADY_EXIST = 'USER_ALREADY_EXIST', + INVALID_INVITATION = 'INVALID_INVITATION', + EMAIL_MISSING = 'EMAIL_MISSING', +} diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.module.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.module.ts new file mode 100644 index 000000000000..f09bb770a39d --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.module.ts @@ -0,0 +1,21 @@ +import { Module } from '@nestjs/common'; + +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; + +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { TokenModule } from 'src/engine/core-modules/auth/token/token.module'; +import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module'; +import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; +import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; +import { WorkspaceInvitationResolver } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.resolver'; + +@Module({ + imports: [ + NestjsQueryTypeOrmModule.forFeature([AppToken, UserWorkspace], 'core'), + TokenModule, + OnboardingModule, + ], + exports: [WorkspaceInvitationService], + providers: [WorkspaceInvitationService, WorkspaceInvitationResolver], +}) +export class WorkspaceInvitationModule {} diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.resolver.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.resolver.ts new file mode 100644 index 000000000000..3faf6201cd1e --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/workspace-invitation.resolver.ts @@ -0,0 +1,66 @@ +import { UseGuards } from '@nestjs/common'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; + +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; +import { WorkspaceInvitation } from 'src/engine/core-modules/workspace-invitation/dtos/workspace-invitation.dto'; +import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { SendInvitationsOutput } from 'src/engine/core-modules/workspace-invitation/dtos/send-invitations.output'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; + +import { SendInvitationsInput } from './dtos/send-invitations.input'; + +@UseGuards(WorkspaceAuthGuard) +@Resolver() +export class WorkspaceInvitationResolver { + constructor( + private readonly workspaceInvitationService: WorkspaceInvitationService, + ) {} + + @Mutation(() => String) + async deleteWorkspaceInvitation( + @Args('appTokenId') appTokenId: string, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + return this.workspaceInvitationService.deleteWorkspaceInvitation( + appTokenId, + workspaceId, + ); + } + + @Mutation(() => SendInvitationsOutput) + @UseGuards(UserAuthGuard) + async resendWorkspaceInvitation( + @Args('appTokenId') appTokenId: string, + @AuthWorkspace() workspace: Workspace, + @AuthUser() user: User, + ) { + return this.workspaceInvitationService.resendWorkspaceInvitation( + appTokenId, + workspace, + user, + ); + } + + @Query(() => [WorkspaceInvitation]) + async findWorkspaceInvitations(@AuthWorkspace() workspace: Workspace) { + return this.workspaceInvitationService.loadWorkspaceInvitations(workspace); + } + + @Mutation(() => SendInvitationsOutput) + @UseGuards(UserAuthGuard) + async sendInvitations( + @Args() sendInviteLinkInput: SendInvitationsInput, + @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, + ): Promise<SendInvitationsOutput> { + return await this.workspaceInvitationService.sendInvitations( + sendInviteLinkInput.emails, + workspace, + user, + ); + } +} diff --git a/packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.entity.ts b/packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.entity.ts deleted file mode 100644 index bd3d11607707..000000000000 --- a/packages/twenty-server/src/engine/core-modules/workspace/dtos/send-invite-link.entity.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; - -@ObjectType() -export class SendInviteLink { - @Field(() => Boolean, { - description: 'Boolean that confirms query was dispatched', - }) - success: boolean; -} diff --git a/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts b/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts index 7e3bce067751..8d1193073c5d 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts @@ -1,7 +1,7 @@ import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; export type HandleWorkspaceMemberDeletedJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.spec.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.spec.ts index 4f3bd8008108..6a3d8b4400a6 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.spec.ts @@ -8,9 +8,10 @@ import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/use import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; +import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; import { WorkspaceService } from './workspace.service'; @@ -61,6 +62,10 @@ describe('WorkspaceService', () => { provide: OnboardingService, useValue: {}, }, + { + provide: WorkspaceInvitationService, + useValue: {}, + }, ], }).compile(); diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts index d0c04da42625..0be6fd02f97d 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts @@ -1,30 +1,26 @@ import { BadRequestException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ModuleRef } from '@nestjs/core'; import assert from 'assert'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; -import { render } from '@react-email/render'; -import { SendInviteLinkEmail } from 'twenty-emails'; import { Repository } from 'typeorm'; import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; -import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input'; -import { SendInviteLink } from 'src/engine/core-modules/workspace/dtos/send-invite-link.entity'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; // eslint-disable-next-line @nx/workspace-inject-workspace-repository export class WorkspaceService extends TypeOrmQueryService<Workspace> { + private userWorkspaceService: UserWorkspaceService; constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository<Workspace>, @@ -33,13 +29,13 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> { @InjectRepository(UserWorkspace, 'core') private readonly userWorkspaceRepository: Repository<UserWorkspace>, private readonly workspaceManagerService: WorkspaceManagerService, - private readonly userWorkspaceService: UserWorkspaceService, private readonly billingSubscriptionService: BillingSubscriptionService, - private readonly environmentService: EnvironmentService, - private readonly emailService: EmailService, - private readonly onboardingService: OnboardingService, + private moduleRef: ModuleRef, ) { super(workspaceRepository); + this.userWorkspaceService = this.moduleRef.get(UserWorkspaceService, { + strict: false, + }); } async activateWorkspace(user: User, data: ActivateWorkspaceInput) { @@ -48,7 +44,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> { } const existingWorkspace = await this.workspaceRepository.findOneBy({ - id: user.defaultWorkspace.id, + id: user.defaultWorkspaceId, }); if (!existingWorkspace) { @@ -66,24 +62,24 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> { existingWorkspace.activationStatus !== WorkspaceActivationStatus.PENDING_CREATION ) { - throw new Error('Worspace is not pending creation'); + throw new Error('Workspace is not pending creation'); } - await this.workspaceRepository.update(user.defaultWorkspace.id, { + await this.workspaceRepository.update(user.defaultWorkspaceId, { activationStatus: WorkspaceActivationStatus.ONGOING_CREATION, }); - await this.workspaceManagerService.init(user.defaultWorkspace.id); + await this.workspaceManagerService.init(user.defaultWorkspaceId); await this.userWorkspaceService.createWorkspaceMember( - user.defaultWorkspace.id, + user.defaultWorkspaceId, user, ); - await this.workspaceRepository.update(user.defaultWorkspace.id, { + await this.workspaceRepository.update(user.defaultWorkspaceId, { displayName: data.displayName, activationStatus: WorkspaceActivationStatus.ACTIVE, }); - return user.defaultWorkspace; + return existingWorkspace; } async softDeleteWorkspace(id: string) { @@ -123,53 +119,6 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> { await this.reassignOrRemoveUserDefaultWorkspace(workspaceId, userId); } - async sendInviteLink( - emails: string[], - workspace: Workspace, - sender: User, - ): Promise<SendInviteLink> { - if (!workspace?.inviteHash) { - return { success: false }; - } - - const frontBaseURL = this.environmentService.get('FRONT_BASE_URL'); - const inviteLink = `${frontBaseURL}/invite/${workspace.inviteHash}`; - - for (const email of emails) { - const emailData = { - link: inviteLink, - workspace: { name: workspace.displayName, logo: workspace.logo }, - sender: { email: sender.email, firstName: sender.firstName }, - serverUrl: this.environmentService.get('SERVER_URL'), - }; - const emailTemplate = SendInviteLinkEmail(emailData); - const html = render(emailTemplate, { - pretty: true, - }); - - const text = render(emailTemplate, { - plainText: true, - }); - - await this.emailService.send({ - from: `${this.environmentService.get( - 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, - to: email, - subject: 'Join your team on Funnelmink', - text, - html, - }); - } - - await this.onboardingService.setOnboardingInviteTeamPending({ - workspaceId: workspace.id, - value: false, - }); - - return { success: true }; - } - private async reassignOrRemoveUserDefaultWorkspace( workspaceId: string, userId: string, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace-workspace-member.listener.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace-workspace-member.listener.ts index fbc01935d467..ad3c2b7eec2f 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace-workspace-member.listener.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace-workspace-member.listener.ts @@ -6,11 +6,11 @@ import { HandleWorkspaceMemberDeletedJob, HandleWorkspaceMemberDeletedJobData, } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts index 50f7a0a5aa13..1f136422cf26 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts @@ -4,8 +4,8 @@ import { ReadResolverOpts, } from '@ptc-org/nestjs-query-graphql'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { Workspace } from './workspace.entity'; @@ -36,6 +36,6 @@ export const workspaceAutoResolverOpts: AutoResolverOpts< many: { disabled: true }, }, delete: { many: { disabled: true }, one: { disabled: true } }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], }, ]; diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts index 5c8e832661ec..040b945329d4 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts @@ -16,8 +16,9 @@ import { User } from 'src/engine/core-modules/user/user.entity'; import { WorkspaceWorkspaceMemberListener } from 'src/engine/core-modules/workspace/workspace-workspace-member.listener'; import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.resolver'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; -import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module'; import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; +import { WorkspaceInvitationModule } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.module'; import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts'; import { Workspace } from './workspace.entity'; @@ -32,7 +33,7 @@ import { WorkspaceService } from './services/workspace.service'; BillingModule, FileModule, FileUploadModule, - WorkspaceMetadataVersionModule, + WorkspaceMetadataCacheModule, NestjsQueryTypeOrmModule.forFeature( [User, Workspace, UserWorkspace, FeatureFlagEntity], 'core', @@ -42,6 +43,7 @@ import { WorkspaceService } from './services/workspace.service'; DataSourceModule, OnboardingModule, TypeORMModule, + WorkspaceInvitationModule, ], services: [WorkspaceService], resolvers: workspaceAutoResolverOpts, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts index bc995017ba60..958738005ae6 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts @@ -19,14 +19,12 @@ import { FileService } from 'src/engine/core-modules/file/services/file.service' import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input'; -import { SendInviteLink } from 'src/engine/core-modules/workspace/dtos/send-invite-link.entity'; -import { SendInviteLinkInput } from 'src/engine/core-modules/workspace/dtos/send-invite-link.input'; import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input'; import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { UserAuthGuard } from 'src/engine/guards/user-auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { assert } from 'src/utils/assert'; import { streamToBuffer } from 'src/utils/stream-to-buffer'; @@ -34,12 +32,11 @@ import { Workspace } from './workspace.entity'; import { WorkspaceService } from './services/workspace.service'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver(() => Workspace) export class WorkspaceResolver { constructor( private readonly workspaceService: WorkspaceService, - private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, private readonly userWorkspaceService: UserWorkspaceService, private readonly fileUploadService: FileUploadService, private readonly fileService: FileService, @@ -56,7 +53,7 @@ export class WorkspaceResolver { } @Mutation(() => Workspace) - @UseGuards(JwtAuthGuard) + @UseGuards(UserAuthGuard) async activateWorkspace( @Args('data') data: ActivateWorkspaceInput, @AuthUser() user: User, @@ -139,17 +136,4 @@ export class WorkspaceResolver { return workspace.logo ?? ''; } - - @Mutation(() => SendInviteLink) - async sendInviteLink( - @Args() sendInviteLinkInput: SendInviteLinkInput, - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, - ): Promise<SendInviteLink> { - return await this.workspaceService.sendInviteLink( - sendInviteLinkInput.emails, - workspace, - user, - ); - } } diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts index defdba21188a..90b4c9ef4d2a 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts @@ -1,7 +1,11 @@ import DataLoader from 'dataloader'; +import { RelationMetadataLoaderPayload } from 'src/engine/dataloaders/dataloader.service'; import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; export interface IDataloaders { - relationMetadataLoader: DataLoader<string, RelationMetadataEntity>; + relationMetadataLoader: DataLoader< + RelationMetadataLoaderPayload, + RelationMetadataEntity + >; } diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts index 4a12186c5dd0..e87f236db0c5 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts @@ -2,10 +2,20 @@ import { Injectable } from '@nestjs/common'; import DataLoader from 'dataloader'; +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; + import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface'; import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { RelationMetadataService } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.service'; +export type RelationMetadataLoaderPayload = { + workspaceId: string; + fieldMetadata: Pick< + FieldMetadataInterface, + 'type' | 'id' | 'objectMetadataId' + >; +}; + @Injectable() export class DataloaderService { constructor( @@ -14,12 +24,18 @@ export class DataloaderService { createLoaders(): IDataloaders { const relationMetadataLoader = new DataLoader< - string, + RelationMetadataLoaderPayload, RelationMetadataEntity - >(async (fieldMetadataIds: string[]) => { + >(async (dataLoaderParams: RelationMetadataLoaderPayload[]) => { + const workspaceId = dataLoaderParams[0].workspaceId; + const fieldMetadataItems = dataLoaderParams.map( + (dataLoaderParam) => dataLoaderParam.fieldMetadata, + ); + const relationsMetadataCollection = await this.relationMetadataService.findManyRelationMetadataByFieldMetadataIds( - fieldMetadataIds, + fieldMetadataItems, + workspaceId, ); return relationsMetadataCollection; diff --git a/packages/twenty-server/src/engine/decorators/auth/auth-user.decorator.ts b/packages/twenty-server/src/engine/decorators/auth/auth-user.decorator.ts index 77248f4fd422..75f3a982e949 100644 --- a/packages/twenty-server/src/engine/decorators/auth/auth-user.decorator.ts +++ b/packages/twenty-server/src/engine/decorators/auth/auth-user.decorator.ts @@ -14,10 +14,10 @@ export const AuthUser = createParamDecorator( (options: DecoratorOptions | undefined, ctx: ExecutionContext) => { const request = getRequest(ctx); - if (!options?.allowUndefined && (!request.user || !request.user.user)) { + if (!options?.allowUndefined && !request.user) { throw new ForbiddenException("You're not authorized to do this"); } - return request.user ? request.user.user : undefined; + return request.user; }, ); diff --git a/packages/twenty-server/src/engine/decorators/auth/auth-workspace.decorator.ts b/packages/twenty-server/src/engine/decorators/auth/auth-workspace.decorator.ts index f8fb2d35a388..3cbbf02d4d2b 100644 --- a/packages/twenty-server/src/engine/decorators/auth/auth-workspace.decorator.ts +++ b/packages/twenty-server/src/engine/decorators/auth/auth-workspace.decorator.ts @@ -6,6 +6,6 @@ export const AuthWorkspace = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = getRequest(ctx); - return request.user ? request.user.workspace : undefined; + return request.workspace; }, ); diff --git a/packages/twenty-server/src/engine/guards/demo.env.guard.ts b/packages/twenty-server/src/engine/guards/demo.env.guard.ts index 49fe9ae479dc..947d38d43791 100644 --- a/packages/twenty-server/src/engine/guards/demo.env.guard.ts +++ b/packages/twenty-server/src/engine/guards/demo.env.guard.ts @@ -1,27 +1,27 @@ import { - Injectable, + CanActivate, ExecutionContext, + Injectable, UnauthorizedException, } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; +import { GqlExecutionContext } from '@nestjs/graphql'; + +import { Observable } from 'rxjs'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { getRequest } from 'src/utils/extract-request'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() -export class DemoEnvGuard extends AuthGuard(['jwt']) { - constructor(private readonly environmentService: EnvironmentService) { - super(); - } +export class DemoEnvGuard implements CanActivate { + constructor(private readonly environmentService: EnvironmentService) {} - getRequest(context: ExecutionContext) { - return getRequest(context); - } + canActivate( + context: ExecutionContext, + ): boolean | Promise<boolean> | Observable<boolean> { + const ctx = GqlExecutionContext.create(context); + const request = ctx.getContext().req; - // TODO: input should be typed - handleRequest(err: any, user: any) { const demoWorkspaceIds = this.environmentService.get('DEMO_WORKSPACE_IDS'); - const currentUserWorkspaceId = user?.workspace?.id; + const currentUserWorkspaceId = request.workspace?.id; if (!currentUserWorkspaceId) { throw new UnauthorizedException('Unauthorized for not logged in user'); @@ -31,6 +31,6 @@ export class DemoEnvGuard extends AuthGuard(['jwt']) { throw new UnauthorizedException('Unauthorized for demo workspace'); } - return user; + return true; } } diff --git a/packages/twenty-server/src/engine/guards/jwt-auth.guard.ts b/packages/twenty-server/src/engine/guards/jwt-auth.guard.ts new file mode 100644 index 000000000000..d1f920848775 --- /dev/null +++ b/packages/twenty-server/src/engine/guards/jwt-auth.guard.ts @@ -0,0 +1,35 @@ +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; + +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; +import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; + +@Injectable() +export class JwtAuthGuard implements CanActivate { + constructor( + private readonly tokenService: TokenService, + private readonly workspaceStorageCacheService: WorkspaceCacheStorageService, + ) {} + + async canActivate(context: ExecutionContext): Promise<boolean> { + const request = context.switchToHttp().getRequest(); + + try { + const data = await this.tokenService.validateToken(request); + const metadataVersion = + await this.workspaceStorageCacheService.getMetadataVersion( + data.workspace.id, + ); + + request.user = data.user; + request.apiKey = data.apiKey; + request.workspace = data.workspace; + request.workspaceId = data.workspace.id; + request.workspaceMetadataVersion = metadataVersion; + request.workspaceMemberId = data.workspaceMemberId; + + return true; + } catch (error) { + return false; + } + } +} diff --git a/packages/twenty-server/src/engine/guards/jwt.auth.guard.ts b/packages/twenty-server/src/engine/guards/jwt.auth.guard.ts deleted file mode 100644 index dff0a5376b13..000000000000 --- a/packages/twenty-server/src/engine/guards/jwt.auth.guard.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - ExecutionContext, - Injectable, - UnauthorizedException, -} from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; - -import { JsonWebTokenError } from 'jsonwebtoken'; - -import { assert } from 'src/utils/assert'; -import { getRequest } from 'src/utils/extract-request'; - -@Injectable() -export class JwtAuthGuard extends AuthGuard(['jwt']) { - constructor() { - super(); - } - - getRequest(context: ExecutionContext) { - return getRequest(context); - } - - handleRequest(err: any, user: any, info: any) { - assert(user, '', UnauthorizedException); - - if (err) { - throw err; - } - - if (info && info instanceof Error) { - if (info instanceof JsonWebTokenError) { - info = String(info); - } - - throw new UnauthorizedException(info); - } - - return user; - } -} diff --git a/packages/twenty-server/src/engine/guards/optional-jwt.auth.guard.ts b/packages/twenty-server/src/engine/guards/optional-jwt.auth.guard.ts deleted file mode 100644 index 6090a55c68c7..000000000000 --- a/packages/twenty-server/src/engine/guards/optional-jwt.auth.guard.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ExecutionContext, Injectable } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; - -import { getRequest } from 'src/utils/extract-request'; - -@Injectable() -export class OptionalJwtAuthGuard extends AuthGuard(['jwt']) { - constructor() { - super(); - } - - getRequest(context: ExecutionContext) { - const request = getRequest(context); - - return request; - } - - handleRequest(err, user, info) { - if (err || info) return null; - - return user; - } -} diff --git a/packages/twenty-server/src/engine/guards/user-auth.guard.ts b/packages/twenty-server/src/engine/guards/user-auth.guard.ts new file mode 100644 index 000000000000..8aeef048c036 --- /dev/null +++ b/packages/twenty-server/src/engine/guards/user-auth.guard.ts @@ -0,0 +1,15 @@ +import { CanActivate, ExecutionContext } from '@nestjs/common'; +import { GqlExecutionContext } from '@nestjs/graphql'; + +import { Observable } from 'rxjs'; + +export class UserAuthGuard implements CanActivate { + canActivate( + context: ExecutionContext, + ): boolean | Promise<boolean> | Observable<boolean> { + const ctx = GqlExecutionContext.create(context); + const request = ctx.getContext().req; + + return request.user !== undefined; + } +} diff --git a/packages/twenty-server/src/engine/guards/workspace-auth.guard.ts b/packages/twenty-server/src/engine/guards/workspace-auth.guard.ts new file mode 100644 index 000000000000..6252d7b6f7e1 --- /dev/null +++ b/packages/twenty-server/src/engine/guards/workspace-auth.guard.ts @@ -0,0 +1,15 @@ +import { CanActivate, ExecutionContext } from '@nestjs/common'; +import { GqlExecutionContext } from '@nestjs/graphql'; + +import { Observable } from 'rxjs'; + +export class WorkspaceAuthGuard implements CanActivate { + canActivate( + context: ExecutionContext, + ): boolean | Promise<boolean> | Observable<boolean> { + const ctx = GqlExecutionContext.create(context); + const request = ctx.getContext().req; + + return request.workspace !== undefined; + } +} diff --git a/packages/twenty-server/src/engine/integrations/captcha/interfaces/index.ts b/packages/twenty-server/src/engine/integrations/captcha/interfaces/index.ts deleted file mode 100644 index bd85706d79c7..000000000000 --- a/packages/twenty-server/src/engine/integrations/captcha/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './captcha.interface'; diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-driver.interface.ts b/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-driver.interface.ts deleted file mode 100644 index 4c8af5c208e2..000000000000 --- a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/exception-handler-driver.interface.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ExceptionHandlerOptions } from './exception-handler-options.interface'; -import { ExceptionHandlerUser } from './exception-handler-user.interface'; - -export interface ExceptionHandlerDriverInterface { - captureExceptions( - exceptions: ReadonlyArray<any>, - options?: ExceptionHandlerOptions, - ): string[]; - captureMessage(message: string, user?: ExceptionHandlerUser): void; -} diff --git a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/index.ts b/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/index.ts deleted file mode 100644 index f3c1acc403be..000000000000 --- a/packages/twenty-server/src/engine/integrations/exception-handler/interfaces/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './exception-handler.interface'; -export * from './exception-handler-driver.interface'; diff --git a/packages/twenty-server/src/engine/integrations/file-storage/interfaces/index.ts b/packages/twenty-server/src/engine/integrations/file-storage/interfaces/index.ts deleted file mode 100644 index 6abeadb10050..000000000000 --- a/packages/twenty-server/src/engine/integrations/file-storage/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './file-storage.interface'; diff --git a/packages/twenty-server/src/engine/integrations/integrations.module.ts b/packages/twenty-server/src/engine/integrations/integrations.module.ts deleted file mode 100644 index 7b2422077b2c..000000000000 --- a/packages/twenty-server/src/engine/integrations/integrations.module.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Module } from '@nestjs/common'; -import { HttpAdapterHost } from '@nestjs/core'; -import { EventEmitterModule } from '@nestjs/event-emitter'; - -import { CacheStorageModule } from 'src/engine/integrations/cache-storage/cache-storage.module'; -import { CaptchaModule } from 'src/engine/integrations/captcha/captcha.module'; -import { captchaModuleFactory } from 'src/engine/integrations/captcha/captcha.module-factory'; -import { EmailModule } from 'src/engine/integrations/email/email.module'; -import { emailModuleFactory } from 'src/engine/integrations/email/email.module-factory'; -import { ExceptionHandlerModule } from 'src/engine/integrations/exception-handler/exception-handler.module'; -import { exceptionHandlerModuleFactory } from 'src/engine/integrations/exception-handler/exception-handler.module-factory'; -import { fileStorageModuleFactory } from 'src/engine/integrations/file-storage/file-storage.module-factory'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; -import { LLMChatModelModule } from 'src/engine/integrations/llm-chat-model/llm-chat-model.module'; -import { llmChatModelModuleFactory } from 'src/engine/integrations/llm-chat-model/llm-chat-model.module-factory'; -import { LLMTracingModule } from 'src/engine/integrations/llm-tracing/llm-tracing.module'; -import { llmTracingModuleFactory } from 'src/engine/integrations/llm-tracing/llm-tracing.module-factory'; -import { loggerModuleFactory } from 'src/engine/integrations/logger/logger.module-factory'; -import { messageQueueModuleFactory } from 'src/engine/integrations/message-queue/message-queue.module-factory'; -import { BuildDirectoryManagerService } from 'src/engine/integrations/serverless/drivers/services/build-directory-manager.service'; -import { serverlessModuleFactory } from 'src/engine/integrations/serverless/serverless-module.factory'; -import { ServerlessModule } from 'src/engine/integrations/serverless/serverless.module'; - -import { EnvironmentModule } from './environment/environment.module'; -import { EnvironmentService } from './environment/environment.service'; -import { FileStorageModule } from './file-storage/file-storage.module'; -import { LoggerModule } from './logger/logger.module'; -import { MessageQueueModule } from './message-queue/message-queue.module'; - -@Module({ - imports: [ - EnvironmentModule.forRoot({}), - FileStorageModule.forRootAsync({ - useFactory: fileStorageModuleFactory, - inject: [EnvironmentService], - }), - LoggerModule.forRootAsync({ - useFactory: loggerModuleFactory, - inject: [EnvironmentService], - }), - MessageQueueModule.registerAsync({ - useFactory: messageQueueModuleFactory, - inject: [EnvironmentService], - }), - ExceptionHandlerModule.forRootAsync({ - useFactory: exceptionHandlerModuleFactory, - inject: [EnvironmentService, HttpAdapterHost], - }), - EmailModule.forRoot({ - useFactory: emailModuleFactory, - inject: [EnvironmentService], - }), - CaptchaModule.forRoot({ - useFactory: captchaModuleFactory, - inject: [EnvironmentService], - }), - EventEmitterModule.forRoot({ - wildcard: true, - }), - CacheStorageModule, - LLMChatModelModule.forRoot({ - useFactory: llmChatModelModuleFactory, - inject: [EnvironmentService], - }), - LLMTracingModule.forRoot({ - useFactory: llmTracingModuleFactory, - inject: [EnvironmentService], - }), - ServerlessModule.forRootAsync({ - useFactory: serverlessModuleFactory, - inject: [ - EnvironmentService, - FileStorageService, - BuildDirectoryManagerService, - ], - }), - ], - exports: [], - providers: [], -}) -export class IntegrationsModule {} diff --git a/packages/twenty-server/src/engine/integrations/logger/interfaces/index.ts b/packages/twenty-server/src/engine/integrations/logger/interfaces/index.ts deleted file mode 100644 index 2e75a7e002ab..000000000000 --- a/packages/twenty-server/src/engine/integrations/logger/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './logger.interface'; diff --git a/packages/twenty-server/src/engine/integrations/message-queue/interfaces/index.ts b/packages/twenty-server/src/engine/integrations/message-queue/interfaces/index.ts deleted file mode 100644 index 4fdb52388cd2..000000000000 --- a/packages/twenty-server/src/engine/integrations/message-queue/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './message-queue-module-options.interface'; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/emails.composite-type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/emails.composite-type.ts index 3cee1f44127a..9ca5ceea55a6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/emails.composite-type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/emails.composite-type.ts @@ -22,5 +22,5 @@ export const emailsCompositeType: CompositeType = { export type EmailsMetadata = { primaryEmail: string; - additionalEmails: string[] | null; + additionalEmails: object | null; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts index f8a05964733e..de361576a7bb 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts @@ -7,6 +7,7 @@ import { emailsCompositeType } from 'src/engine/metadata-modules/field-metadata/ import { fullNameCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/full-name.composite-type'; import { linkCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/link.composite-type'; import { linksCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/links.composite-type'; +import { phonesCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; export const compositeTypeDefinitions = new Map< @@ -20,4 +21,5 @@ export const compositeTypeDefinitions = new Map< [FieldMetadataType.ADDRESS, addressCompositeType], [FieldMetadataType.ACTOR, actorCompositeType], [FieldMetadataType.EMAILS, emailsCompositeType], + [FieldMetadataType.PHONES, phonesCompositeType], ]); diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type.ts new file mode 100644 index 000000000000..a53661779b80 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type.ts @@ -0,0 +1,33 @@ +import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface'; + +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; + +export const phonesCompositeType: CompositeType = { + type: FieldMetadataType.PHONES, + properties: [ + { + name: 'primaryPhoneNumber', + type: FieldMetadataType.TEXT, + hidden: false, + isRequired: false, + }, + { + name: 'primaryPhoneCountryCode', + type: FieldMetadataType.TEXT, + hidden: false, + isRequired: false, + }, + { + name: 'additionalPhones', + type: FieldMetadataType.RAW_JSON, + hidden: false, + isRequired: false, + }, + ], +}; + +export type PhonesMetadata = { + primaryPhoneNumber: string; + primaryPhoneCountryCode: string; + additionalPhones: object | null; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/default-value.input.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/default-value.input.ts index 8a03f6b54bcf..a617f8ad971e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/default-value.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/default-value.input.ts @@ -183,5 +183,19 @@ export class FieldMetadataDefaultValueEmails { @ValidateIf((_object, value) => value !== null) @IsObject() - additionalEmails: string[] | null; + additionalEmails: object | null; +} + +export class FieldMetadataDefaultValuePhones { + @ValidateIf((_object, value) => value !== null) + @IsQuotedString() + primaryPhoneNumber: string | null; + + @ValidateIf((_object, value) => value !== null) + @IsQuotedString() + primaryPhoneCountryCode: string | null; + + @ValidateIf((_object, value) => value !== null) + @IsObject() + additionalPhones: object | null; } diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts index 157110b03a71..b81cf7a76b8b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts @@ -12,6 +12,7 @@ import { QueryOptions, Relation, } from '@ptc-org/nestjs-query-graphql'; +import { Transform } from 'class-transformer'; import { IsBoolean, IsDateString, @@ -30,11 +31,13 @@ import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadat import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator'; +import { FieldMetadataDefaultOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator'; import { IsFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-options.validator'; import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; import { RelationMetadataDTO } from 'src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto'; +import { transformEnumValue } from 'src/engine/utils/transform-enum-value'; registerEnumType(FieldMetadataType, { name: 'FieldMetadataType', @@ -44,7 +47,7 @@ registerEnumType(FieldMetadataType, { @ObjectType('field') @Authorize({ authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, + workspaceId: { eq: context?.req?.workspace?.id }, }), }) @QueryOptions({ @@ -120,6 +123,9 @@ export class FieldMetadataDTO< @Field(() => GraphQLJSON, { nullable: true }) defaultValue?: FieldMetadataDefaultValue<T>; + @Transform(({ value }) => + transformEnumValue(value as FieldMetadataDefaultOption[]), + ) @Validate(IsFieldMetadataOptions) @IsOptional() @Field(() => GraphQLJSON, { nullable: true }) @@ -132,6 +138,8 @@ export class FieldMetadataDTO< @HideField() workspaceId: string; + objectMetadataId: string; + @IsDateString() @Field() createdAt: Date; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts index 263790c7ca7d..3f5413aeb2b8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts @@ -25,6 +25,7 @@ export enum FieldMetadataType { UUID = 'UUID', TEXT = 'TEXT', PHONE = 'PHONE', + PHONES = 'PHONES', EMAIL = 'EMAIL', EMAILS = 'EMAILS', DATE_TIME = 'DATE_TIME', @@ -45,6 +46,7 @@ export enum FieldMetadataType { RAW_JSON = 'RAW_JSON', RICH_TEXT = 'RICH_TEXT', ACTOR = 'ACTOR', + ARRAY = 'ARRAY', } @Entity('fieldMetadata') diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.module.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.module.ts index 69cde9ae7c94..377575ba9bfd 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.module.ts @@ -9,18 +9,18 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { ActorModule } from 'src/engine/core-modules/actor/actor.module'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; import { FieldMetadataResolver } from 'src/engine/metadata-modules/field-metadata/field-metadata.resolver'; import { FieldMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/field-metadata/interceptors/field-metadata-graphql-api-exception.interceptor'; import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator'; import { IsFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-options.validator'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module'; -import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module'; import { FieldMetadataEntity } from './field-metadata.entity'; import { FieldMetadataService } from './field-metadata.service'; @@ -32,9 +32,11 @@ import { UpdateFieldInput } from './dtos/update-field.input'; imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ - NestjsQueryTypeOrmModule.forFeature([FieldMetadataEntity], 'metadata'), + NestjsQueryTypeOrmModule.forFeature( + [FieldMetadataEntity, ObjectMetadataEntity], + 'metadata', + ), WorkspaceMigrationModule, - WorkspaceStatusModule, WorkspaceMigrationRunnerModule, WorkspaceMetadataVersionModule, ObjectMetadataModule, @@ -65,7 +67,7 @@ import { UpdateFieldInput } from './dtos/update-field.input'; many: { disabled: true }, }, delete: { disabled: true }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], interceptors: [FieldMetadataGraphqlApiExceptionInterceptor], }, ], diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts index f92b8144b53e..2d9e4796132c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts @@ -15,7 +15,7 @@ import { import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { CreateOneFieldMetadataInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; import { DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input'; import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; @@ -25,7 +25,7 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/fi import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; import { fieldMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/field-metadata/utils/field-metadata-graphql-api-exception-handler.util'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver(() => FieldMetadataDTO) export class FieldMetadataResolver { constructor(private readonly fieldMetadataService: FieldMetadataService) {} @@ -103,6 +103,7 @@ export class FieldMetadataResolver { @ResolveField(() => RelationDefinitionDTO, { nullable: true }) async relationDefinition( + @AuthWorkspace() workspace: Workspace, @Parent() fieldMetadata: FieldMetadataDTO, @Context() context: { loaders: IDataloaders }, ): Promise<RelationDefinitionDTO | null | undefined> { @@ -112,7 +113,10 @@ export class FieldMetadataResolver { try { const relationMetadataItem = - await context.loaders.relationMetadataLoader.load(fieldMetadata.id); + await context.loaders.relationMetadataLoader.load({ + fieldMetadata, + workspaceId: workspace.id, + }); return await this.fieldMetadataService.getRelationDefinitionFromRelationMetadata( fieldMetadata, diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts index 6dc4122aad18..ac2c5b1d438d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts @@ -4,7 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import isEmpty from 'lodash.isempty'; import { DataSource, FindOneOptions, Repository } from 'typeorm'; -import { v4 as uuidV4 } from 'uuid'; +import { v4 as uuidV4, v4 } from 'uuid'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; @@ -41,7 +41,7 @@ import { NameTooLongException } from 'src/engine/metadata-modules/utils/exceptio import { exceedsDatabaseIdentifierMaximumLength } from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils'; import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils'; import { validateMetadataNameValidityOrThrow as validateFieldNameValidityOrThrow } from 'src/engine/metadata-modules/utils/validate-metadata-name-validity.utils'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; import { WorkspaceMigrationColumnActionType, @@ -72,6 +72,8 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit private readonly metadataDataSource: DataSource, @InjectRepository(FieldMetadataEntity, 'metadata') private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, private readonly objectMetadataService: ObjectMetadataService, private readonly workspaceMigrationFactory: WorkspaceMigrationFactory, private readonly workspaceMigrationService: WorkspaceMigrationService, @@ -87,6 +89,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit override async createOne( fieldMetadataInput: CreateFieldInput, ): Promise<FieldMetadataEntity> { + console.time('createOne'); const queryRunner = this.metadataDataSource.createQueryRunner(); await queryRunner.connect(); @@ -97,20 +100,23 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit queryRunner.manager.getRepository<FieldMetadataEntity>( FieldMetadataEntity, ); - const objectMetadata = - await this.objectMetadataService.findOneWithinWorkspace( - fieldMetadataInput.workspaceId, - { - where: { - id: fieldMetadataInput.objectMetadataId, - }, - }, - ); + + console.time('createOne query'); + const [objectMetadata] = await this.objectMetadataRepository.find({ + where: { + id: fieldMetadataInput.objectMetadataId, + workspaceId: fieldMetadataInput.workspaceId, + }, + relations: ['fields'], + order: {}, + }); + + console.timeEnd('createOne query'); if (!objectMetadata) { throw new FieldMetadataException( 'Object metadata does not exist', - FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, ); } @@ -155,22 +161,11 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit objectMetadata, ); - const fieldAlreadyExists = await fieldMetadataRepository.findOne({ - where: { - name: fieldMetadataInput.name, - objectMetadataId: fieldMetadataInput.objectMetadataId, - workspaceId: fieldMetadataInput.workspaceId, - }, - }); - - if (fieldAlreadyExists) { - throw new FieldMetadataException( - 'Field already exists', - FieldMetadataExceptionCode.FIELD_ALREADY_EXISTS, - ); - } - + console.time('createOne save'); const createdFieldMetadata = await fieldMetadataRepository.save({ + id: v4(), + createdAt: new Date(), + updatedAt: new Date(), ...fieldMetadataInput, isNullable: generateNullable( fieldMetadataInput.type, @@ -190,7 +185,10 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit isCustom: true, }); + console.timeEnd('createOne save'); + if (!fieldMetadataInput.isRemoteCreation) { + console.time('createOne migration create'); await this.workspaceMigrationService.createCustomMigration( generateMigrationName(`create-${createdFieldMetadata.name}`), fieldMetadataInput.workspaceId, @@ -206,11 +204,16 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit ], ); + console.timeEnd('createOne migration create'); + + console.time('createOne migration run'); await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( fieldMetadataInput.workspaceId, ); + console.timeEnd('createOne migration run'); } + console.time('createOne workspace viewField'); // TODO: Move viewField creation to a cdc scheduler const dataSourceMetadata = await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( @@ -270,8 +273,11 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit ); } } + console.timeEnd('createOne workspace viewField'); + console.time('createOne internal commit'); await workspaceQueryRunner.commitTransaction(); + console.timeEnd('createOne internal commit'); } catch (error) { await workspaceQueryRunner.rollbackTransaction(); throw error; @@ -279,7 +285,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit await workspaceQueryRunner.release(); } + console.time('createOne commit'); await queryRunner.commitTransaction(); + console.timeEnd('createOne commit'); return createdFieldMetadata; } catch (error) { @@ -287,9 +295,12 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit throw error; } finally { await queryRunner.release(); + console.time('createOne increment'); await this.workspaceMetadataVersionService.incrementMetadataVersion( fieldMetadataInput.workspaceId, ); + console.timeEnd('createOne increment'); + console.timeEnd('createOne'); } } @@ -308,7 +319,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit FieldMetadataEntity, ); - const existingFieldMetadata = await fieldMetadataRepository.findOne({ + const [existingFieldMetadata] = await fieldMetadataRepository.find({ where: { id, workspaceId: fieldMetadataInput.workspaceId, @@ -322,15 +333,14 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit ); } - const objectMetadata = - await this.objectMetadataService.findOneWithinWorkspace( - fieldMetadataInput.workspaceId, - { - where: { - id: existingFieldMetadata?.objectMetadataId, - }, - }, - ); + const [objectMetadata] = await this.objectMetadataRepository.find({ + where: { + id: existingFieldMetadata.objectMetadataId, + workspaceId: fieldMetadataInput.workspaceId, + }, + relations: ['fields'], + order: {}, + }); if (!objectMetadata) { throw new FieldMetadataException( @@ -475,7 +485,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit FieldMetadataEntity, ); - const fieldMetadata = await fieldMetadataRepository.findOne({ + const [fieldMetadata] = await fieldMetadataRepository.find({ where: { id: input.id, workspaceId: workspaceId, @@ -489,12 +499,13 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit ); } - const objectMetadata = - await this.objectMetadataService.findOneWithinWorkspace(workspaceId, { - where: { - id: fieldMetadata?.objectMetadataId, - }, - }); + const [objectMetadata] = await this.objectMetadataRepository.find({ + where: { + id: fieldMetadata.objectMetadataId, + }, + relations: ['fields'], + order: {}, + }); if (!objectMetadata) { throw new FieldMetadataException( @@ -583,7 +594,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit id: string, options?: FindOneOptions<FieldMetadataEntity>, ) { - const fieldMetadata = await this.fieldMetadataRepository.findOne({ + const [fieldMetadata] = await this.fieldMetadataRepository.find({ ...options, where: { ...options?.where, @@ -605,13 +616,15 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit workspaceId: string, options: FindOneOptions<FieldMetadataEntity>, ) { - return this.fieldMetadataRepository.findOne({ + const [fieldMetadata] = await this.fieldMetadataRepository.find({ ...options, where: { ...options.where, workspaceId, }, }); + + return fieldMetadata; } private buildUpdatableStandardFieldInput( diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts index d6e9e700215c..07f18bd4a2c6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts @@ -10,6 +10,7 @@ import { FieldMetadataDefaultValueLinks, FieldMetadataDefaultValueNowFunction, FieldMetadataDefaultValueNumber, + FieldMetadataDefaultValuePhones, FieldMetadataDefaultValueRawJson, FieldMetadataDefaultValueRichText, FieldMetadataDefaultValueString, @@ -27,6 +28,7 @@ type FieldMetadataDefaultValueMapping = { | FieldMetadataDefaultValueUuidFunction; [FieldMetadataType.TEXT]: FieldMetadataDefaultValueString; [FieldMetadataType.PHONE]: FieldMetadataDefaultValueString; + [FieldMetadataType.PHONES]: FieldMetadataDefaultValuePhones; [FieldMetadataType.EMAIL]: FieldMetadataDefaultValueString; [FieldMetadataType.EMAILS]: FieldMetadataDefaultValueEmails; [FieldMetadataType.DATE_TIME]: diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts index c79f33047386..7fa4f39c09f8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts @@ -14,8 +14,18 @@ type FieldMetadataNumberSettings = { dataType: NumberDataType; }; +type FieldMetadataDateSettings = { + displayAsRelativeDate?: boolean; +}; + +type FieldMetadataDateTimeSettings = { + displayAsRelativeDate?: boolean; +}; + type FieldMetadataSettingsMapping = { [FieldMetadataType.NUMBER]: FieldMetadataNumberSettings; + [FieldMetadataType.DATE]: FieldMetadataDateSettings; + [FieldMetadataType.DATE_TIME]: FieldMetadataDateTimeSettings; }; type SettingsByFieldMetadata<T extends FieldMetadataType | 'default'> = diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts index 2eac59ec319a..8d805dfe4a03 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface.ts @@ -20,5 +20,4 @@ export interface ObjectMetadataInterface { isAuditLogged: boolean; labelIdentifierFieldMetadataId?: string | null; imageIdentifierFieldMetadataId?: string | null; - isSoftDeletable?: boolean | null; } diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/generate-default-value.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/generate-default-value.ts index b031e4884675..958ff0e3212b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/generate-default-value.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/generate-default-value.ts @@ -47,6 +47,12 @@ export function generateDefaultValue( primaryLinkUrl: "''", secondaryLinks: null, }; + case FieldMetadataType.PHONES: + return { + primaryPhoneNumber: "''", + primaryPhoneCountryCode: "''", + additionalPhones: null, + }; default: return null; } diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts index 437310003d2c..110673bd1cf6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts @@ -9,7 +9,8 @@ export const isCompositeFieldMetadataType = ( | FieldMetadataType.ADDRESS | FieldMetadataType.LINKS | FieldMetadataType.ACTOR - | FieldMetadataType.EMAILS => { + | FieldMetadataType.EMAILS + | FieldMetadataType.PHONES => { return [ FieldMetadataType.LINK, FieldMetadataType.CURRENCY, @@ -18,5 +19,6 @@ export const isCompositeFieldMetadataType = ( FieldMetadataType.LINKS, FieldMetadataType.ACTOR, FieldMetadataType.EMAILS, + FieldMetadataType.PHONES, ].includes(type); }; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util.ts index ce254ffd7d7d..06303046259d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util.ts @@ -19,6 +19,7 @@ import { FieldMetadataDefaultValueLinks, FieldMetadataDefaultValueNowFunction, FieldMetadataDefaultValueNumber, + FieldMetadataDefaultValuePhones, FieldMetadataDefaultValueRawJson, FieldMetadataDefaultValueString, FieldMetadataDefaultValueStringArray, @@ -55,6 +56,7 @@ export const defaultValueValidatorsMap = { [FieldMetadataType.LINKS]: [FieldMetadataDefaultValueLinks], [FieldMetadataType.ACTOR]: [FieldMetadataDefaultActor], [FieldMetadataType.EMAILS]: [FieldMetadataDefaultValueEmails], + [FieldMetadataType.PHONES]: [FieldMetadataDefaultValuePhones], }; type ValidationResult = { diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator.ts index f68aea19e253..977358788c60 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator.ts @@ -14,7 +14,7 @@ import { FieldMetadataType, } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { validateDefaultValueForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util'; -import { LoggerService } from 'src/engine/integrations/logger/logger.service'; +import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; @Injectable() @ValidatorConstraint({ name: 'isFieldMetadataDefaultValue', async: true }) diff --git a/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.module.ts b/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.module.ts index 01cb4a3e6a92..c22a56dfb222 100644 --- a/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.module.ts @@ -2,10 +2,15 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; +import { IndexMetadataService } from 'src/engine/metadata-modules/index-metadata/index-metadata.service'; +import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; @Module({ - imports: [TypeOrmModule.forFeature([IndexMetadataEntity], 'metadata')], - providers: [], - exports: [], + imports: [ + TypeOrmModule.forFeature([IndexMetadataEntity], 'metadata'), + WorkspaceMigrationModule, + ], + providers: [IndexMetadataService], + exports: [IndexMetadataService], }) export class IndexMetadataModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.service.ts new file mode 100644 index 000000000000..97d9fdb9b3a7 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/index-metadata/index-metadata.service.ts @@ -0,0 +1,87 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; +import { generateDeterministicIndexName } from 'src/engine/metadata-modules/index-metadata/utils/generate-deterministic-index-name'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; +import { + WorkspaceMigrationIndexActionType, + WorkspaceMigrationTableAction, + WorkspaceMigrationTableActionType, +} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; +import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; +import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; + +@Injectable() +export class IndexMetadataService { + constructor( + @InjectRepository(IndexMetadataEntity, 'metadata') + private readonly indexMetadataRepository: Repository<IndexMetadataEntity>, + private readonly workspaceMigrationService: WorkspaceMigrationService, + ) {} + + async createIndex( + workspaceId: string, + objectMetadata: ObjectMetadataEntity, + fieldMetadataToIndex: Partial<FieldMetadataEntity>[], + ) { + const tableName = computeObjectTargetTable(objectMetadata); + + const columnNames: string[] = fieldMetadataToIndex.map( + (fieldMetadata) => fieldMetadata.name as string, + ); + + const indexName = `IDX_${generateDeterministicIndexName([tableName, ...columnNames])}`; + + let savedIndexMetadata: IndexMetadataEntity; + + try { + savedIndexMetadata = await this.indexMetadataRepository.save({ + name: indexName, + tableName, + indexFieldMetadatas: fieldMetadataToIndex.map( + (fieldMetadata, index) => { + return { + fieldMetadataId: fieldMetadata.id, + order: index, + }; + }, + ), + workspaceId, + objectMetadataId: objectMetadata.id, + }); + } catch (error) { + throw new Error( + `Failed to create index ${indexName} on object metadata ${objectMetadata.nameSingular}`, + ); + } + + if (!savedIndexMetadata) { + throw new Error( + `Failed to return saved index ${indexName} on object metadata ${objectMetadata.nameSingular}`, + ); + } + + const migration = { + name: tableName, + action: WorkspaceMigrationTableActionType.ALTER_INDEXES, + indexes: [ + { + action: WorkspaceMigrationIndexActionType.CREATE, + columns: columnNames, + name: indexName, + }, + ], + } satisfies WorkspaceMigrationTableAction; + + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName(`create-${objectMetadata.nameSingular}-index`), + workspaceId, + [migration], + ); + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto.ts index 217bc5e89217..6a494370d962 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto.ts @@ -16,7 +16,7 @@ import { BeforeDeleteOneObject } from 'src/engine/metadata-modules/object-metada @ObjectType('object') @Authorize({ authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, + workspaceId: { eq: context?.req?.workspace?.id }, }), }) @QueryOptions({ diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-create-one-object.hook.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-create-one-object.hook.ts index c8fd261826ed..53d917c26cee 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-create-one-object.hook.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-create-one-object.hook.ts @@ -15,7 +15,7 @@ export class BeforeCreateOneObject<T extends CreateObjectInput> instance: CreateOneInputType<T>, context: any, ): Promise<CreateOneInputType<T>> { - const workspaceId = context?.req?.user?.workspace?.id; + const workspaceId = context?.req?.workspace?.id; if (!workspaceId) { throw new UnauthorizedException(); diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-delete-one-object.hook.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-delete-one-object.hook.ts index 6f0147bf20e8..918001ebafe9 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-delete-one-object.hook.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/hooks/before-delete-one-object.hook.ts @@ -19,7 +19,7 @@ export class BeforeDeleteOneObject implements BeforeDeleteOneHook { instance: DeleteOneInputType, context: any, ): Promise<DeleteOneInputType> { - const workspaceId = context?.req?.user?.workspace?.id; + const workspaceId = context?.req?.workspace?.id; if (!workspaceId) { throw new UnauthorizedException(); diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts index ebbb188669b9..3d550b02fe5d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts @@ -69,9 +69,6 @@ export class ObjectMetadataEntity implements ObjectMetadataInterface { @Column({ default: true }) isAuditLogged: boolean; - @Column({ nullable: true, type: 'boolean' }) - isSoftDeletable?: boolean | null; - @Column({ nullable: true, type: 'uuid' }) labelIdentifierFieldMetadataId?: string | null; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts index b0d60f7593ab..94a721dec53d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts @@ -10,8 +10,7 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { BeforeUpdateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-update-one-object.hook'; @@ -44,7 +43,6 @@ import { UpdateObjectPayload } from './dtos/update-object.input'; WorkspaceMigrationModule, WorkspaceMigrationRunnerModule, WorkspaceMetadataVersionModule, - FeatureFlagModule, RemoteTableRelationsModule, ], services: [ObjectMetadataService], @@ -64,7 +62,7 @@ import { UpdateObjectPayload } from './dtos/update-object.input'; }, update: { disabled: true }, delete: { disabled: true }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], interceptors: [ObjectMetadataGraphqlApiExceptionInterceptor], }, ], diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts index 9ae44b1fe996..83d9a1548cb1 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts @@ -3,18 +3,18 @@ import { Args, Mutation, Resolver } from '@nestjs/graphql'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { DeleteOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/delete-object.input'; -import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; +import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; import { UpdateObjectPayload, UpdateOneObjectInput, } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input'; import { BeforeUpdateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-update-one-object.hook'; +import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { objectMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/object-metadata/utils/object-metadata-graphql-api-exception-handler.util'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver(() => ObjectMetadataDTO) export class ObjectMetadataResolver { constructor( diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts index 1a45f708e4e2..c0240c6c2f1b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts @@ -32,7 +32,7 @@ import { import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete'; import { RemoteTableRelationsService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service'; import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; import { WorkspaceMigrationColumnActionType, @@ -40,6 +40,7 @@ import { WorkspaceMigrationTableActionType, } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; import { computeTableName } from 'src/engine/utils/compute-table-name.util'; import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; @@ -57,6 +58,8 @@ import { createForeignKeyDeterministicUuid, createRelationDeterministicUuid, } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; +import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -81,6 +84,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt private readonly workspaceMigrationService: WorkspaceMigrationService, private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService, private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, ) { super(objectMetadataRepository); } @@ -138,6 +142,24 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt await this.deleteAllRelationsAndDropTable(objectMetadata, workspaceId); } + // DELETE VIEWS + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewWorkspaceEntity>( + workspaceId, + 'view', + ); + + const views = await viewRepository.find({ + where: { + objectMetadataId: objectMetadata.id, + }, + }); + + if (views.length > 0) { + await viewRepository.delete(views.map((view) => view.id)); + } + + // DELETE OBJECT await this.objectMetadataRepository.delete(objectMetadata.id); await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( @@ -209,7 +231,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt isCustom: isCustom, isSystem: false, isRemote: objectMetadataInput.isRemote, - isSoftDeletable: true, fields: isCustom ? // Creating default fields. // No need to create a custom migration for this though as the default columns are already @@ -269,6 +290,20 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt workspaceId: objectMetadataInput.workspaceId, defaultValue: 'now', }, + { + standardId: BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt, + type: FieldMetadataType.DATE_TIME, + name: 'deletedAt', + label: 'Deleted at', + icon: 'IconCalendarClock', + description: 'Deletion date', + isNullable: true, + isActive: true, + isCustom: false, + isSystem: false, + workspaceId: objectMetadataInput.workspaceId, + defaultValue: null, + }, { standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy, type: FieldMetadataType.ACTOR, @@ -342,7 +377,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt ); createdObjectMetadata.fields.map(async (field, index) => { - if (field.name === 'id') { + if (field.name === 'id' || field.name === 'deletedAt') { return; } @@ -355,6 +390,11 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt ); }); + await this.createViewWorkspaceFavorite( + objectMetadataInput.workspaceId, + view[0].id, + ); + await this.workspaceMetadataVersionService.incrementMetadataVersion( objectMetadataInput.workspaceId, ); @@ -1246,4 +1286,24 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt ); } } + + private async createViewWorkspaceFavorite( + workspaceId: string, + viewId: string, + ) { + const favoriteRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<FavoriteWorkspaceEntity>( + workspaceId, + 'favorite', + ); + + const favoriteCount = await favoriteRepository.count(); + + return favoriteRepository.insert( + favoriteRepository.create({ + viewId, + position: favoriteCount, + }), + ); + } } diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util.ts index 0db389d95fef..5a30ed4bf000 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util.ts @@ -6,7 +6,7 @@ import { } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; export const assertMutationNotOnRemoteObject = ( - objectMetadataItem: ObjectMetadataInterface, + objectMetadataItem: Pick<ObjectMetadataInterface, 'isRemote'>, ) => { if (objectMetadataItem.isRemote) { throw new ObjectMetadataException( diff --git a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts index b7d04156176e..eff07dce31f2 100644 --- a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts @@ -1,11 +1,10 @@ import { - ObjectType, Field, HideField, + ObjectType, registerEnumType, } from '@nestjs/graphql'; -import { CreateDateColumn, UpdateDateColumn } from 'typeorm'; import { Authorize, BeforeDeleteOne, @@ -13,11 +12,12 @@ import { QueryOptions, Relation, } from '@ptc-org/nestjs-query-graphql'; +import { CreateDateColumn, UpdateDateColumn } from 'typeorm'; +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { BeforeDeleteOneRelation } from 'src/engine/metadata-modules/relation-metadata/hooks/before-delete-one-relation.hook'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; registerEnumType(RelationMetadataType, { name: 'RelationMetadataType', @@ -27,7 +27,7 @@ registerEnumType(RelationMetadataType, { @ObjectType('relation') @Authorize({ authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, + workspaceId: { eq: context?.req?.workspace?.id }, }), }) @QueryOptions({ diff --git a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-create-one-relation.hook.ts b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-create-one-relation.hook.ts index d5e1223c05ae..dd11e95d59dc 100644 --- a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-create-one-relation.hook.ts +++ b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-create-one-relation.hook.ts @@ -15,7 +15,7 @@ export class BeforeCreateOneRelation<T extends CreateRelationInput> instance: CreateOneInputType<T>, context: any, ): Promise<CreateOneInputType<T>> { - const workspaceId = context?.req?.user?.workspace?.id; + const workspaceId = context?.req?.workspace?.id; if (!workspaceId) { throw new UnauthorizedException(); diff --git a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-delete-one-relation.hook.ts b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-delete-one-relation.hook.ts index 3f82928e6aae..df7880df5183 100644 --- a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-delete-one-relation.hook.ts +++ b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/hooks/before-delete-one-relation.hook.ts @@ -19,7 +19,7 @@ export class BeforeDeleteOneRelation implements BeforeDeleteOneHook { instance: DeleteOneInputType, context: any, ): Promise<DeleteOneInputType> { - const workspaceId = context?.req?.user?.workspace?.id; + const workspaceId = context?.req?.workspace?.id; if (!workspaceId) { throw new UnauthorizedException(); diff --git a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.module.ts b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.module.ts index 345ec66d762b..b1c954e8a245 100644 --- a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.module.ts @@ -6,14 +6,16 @@ import { } from '@ptc-org/nestjs-query-graphql'; import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; +import { IndexMetadataModule } from 'src/engine/metadata-modules/index-metadata/index-metadata.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { RelationMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/relation-metadata/interceptors/relation-metadata-graphql-api-exception.interceptor'; import { RelationMetadataResolver } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.resolver'; import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; +import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module'; import { RelationMetadataEntity } from './relation-metadata.entity'; @@ -32,8 +34,10 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto'; ), ObjectMetadataModule, FieldMetadataModule, + IndexMetadataModule, WorkspaceMigrationRunnerModule, WorkspaceMigrationModule, + WorkspaceCacheStorageModule, WorkspaceMetadataVersionModule, ], services: [RelationMetadataService], @@ -47,7 +51,7 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto'; create: { many: { disabled: true } }, update: { disabled: true }, delete: { disabled: true }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], interceptors: [RelationMetadataGraphqlApiExceptionInterceptor], }, ], diff --git a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.resolver.ts index 332f783e454d..b6f98d1eedd2 100644 --- a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.resolver.ts @@ -1,15 +1,15 @@ import { UseGuards } from '@nestjs/common'; import { Args, Mutation, Resolver } from '@nestjs/graphql'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { RelationMetadataService } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { RelationMetadataDTO } from 'src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { DeleteOneRelationInput } from 'src/engine/metadata-modules/relation-metadata/dtos/delete-relation.input'; +import { RelationMetadataDTO } from 'src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto'; +import { RelationMetadataService } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.service'; import { relationMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/relation-metadata/utils/relation-metadata-graphql-api-exception-handler.util'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver() export class RelationMetadataResolver { constructor( diff --git a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.service.ts index a08006adbf87..affe7e1b7772 100644 --- a/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/relation-metadata/relation-metadata.service.ts @@ -6,11 +6,14 @@ import camelCase from 'lodash.camelcase'; import { FindOneOptions, In, Repository } from 'typeorm'; import { v4 as uuidV4 } from 'uuid'; +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; + import { FieldMetadataEntity, FieldMetadataType, } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; +import { IndexMetadataService } from 'src/engine/metadata-modules/index-metadata/index-metadata.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { CreateRelationInput } from 'src/engine/metadata-modules/relation-metadata/dtos/create-relation.input'; @@ -21,7 +24,7 @@ import { import { InvalidStringException } from 'src/engine/metadata-modules/utils/exceptions/invalid-string.exception'; import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils'; import { validateMetadataNameValidityOrThrow } from 'src/engine/metadata-modules/utils/validate-metadata-name-validity.utils'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; import { WorkspaceMigrationColumnActionType, @@ -30,7 +33,9 @@ import { } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; +import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; +import { BASE_OBJECT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { RelationMetadataEntity, @@ -50,6 +55,8 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat private readonly workspaceMigrationService: WorkspaceMigrationService, private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService, private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, + private readonly indexMetadataService: IndexMetadataService, ) { super(relationMetadataRepository); } @@ -87,21 +94,22 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat const fromId = uuidV4(); const toId = uuidV4(); - await this.fieldMetadataService.createMany([ - this.createFieldMetadataForRelationMetadata( - relationMetadataInput, - 'from', - isCustom, - fromId, - ), - this.createFieldMetadataForRelationMetadata( - relationMetadataInput, - 'to', - isCustom, - toId, - ), - this.createForeignKeyFieldMetadata(relationMetadataInput, columnName), - ]); + const createdRelationFieldsMetadata = + await this.fieldMetadataService.createMany([ + this.createFieldMetadataForRelationMetadata( + relationMetadataInput, + 'from', + isCustom, + fromId, + ), + this.createFieldMetadataForRelationMetadata( + relationMetadataInput, + 'to', + isCustom, + toId, + ), + this.createForeignKeyFieldMetadata(relationMetadataInput, columnName), + ]); const createdRelationMetadata = await super.createOne({ ...relationMetadataInput, @@ -115,6 +123,38 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat columnName, ); + const toObjectMetadata = + objectMetadataMap[relationMetadataInput.toObjectMetadataId]; + + const foreignKeyFieldMetadata = createdRelationFieldsMetadata.find( + (fieldMetadata) => fieldMetadata.type === FieldMetadataType.UUID, + ); + + if (!foreignKeyFieldMetadata) { + throw new RelationMetadataException( + `ForeignKey field metadata not found`, + RelationMetadataExceptionCode.RELATION_METADATA_NOT_FOUND, + ); + } + + const deletedFieldMetadata = toObjectMetadata.fields.find( + (fieldMetadata) => + fieldMetadata.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt, + ); + + if (!deletedFieldMetadata) { + throw new RelationMetadataException( + `Deleted field metadata not found`, + RelationMetadataExceptionCode.RELATION_METADATA_NOT_FOUND, + ); + } + + await this.indexMetadataService.createIndex( + relationMetadataInput.workspaceId, + toObjectMetadata, + [foreignKeyFieldMetadata, deletedFieldMetadata], + ); + await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( relationMetadataInput.workspaceId, ); @@ -411,43 +451,73 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat } async findManyRelationMetadataByFieldMetadataIds( - fieldMetadataIds: string[], + fieldMetadataItems: Array< + Pick<FieldMetadataInterface, 'id' | 'type' | 'objectMetadataId'> + >, + workspaceId: string, ): Promise<(RelationMetadataEntity | NotFoundException)[]> { - const relationMetadataCollection = - await this.relationMetadataRepository.find({ - where: [ - { - fromFieldMetadataId: In(fieldMetadataIds), - }, - { - toFieldMetadataId: In(fieldMetadataIds), - }, - ], - relations: [ - 'fromObjectMetadata', - 'toObjectMetadata', - 'fromFieldMetadata', - 'toFieldMetadata', - ], - }); + const metadataVersion = + await this.workspaceCacheStorageService.getMetadataVersion(workspaceId); - const mappedResult = fieldMetadataIds.map((fieldMetadataId) => { - const foundRelationMetadataItem = relationMetadataCollection.find( - (relationMetadataItem) => - relationMetadataItem.fromFieldMetadataId === fieldMetadataId || - relationMetadataItem.toFieldMetadataId === fieldMetadataId, + if (!metadataVersion) { + throw new NotFoundException( + `Metadata version not found for workspace ${workspaceId}`, ); + } - return ( - foundRelationMetadataItem ?? - // TODO: return a relation metadata not found exception - new NotFoundException( - `RelationMetadata with fieldMetadataId ${fieldMetadataId} not found`, - ) + const objectMetadataMap = + await this.workspaceCacheStorageService.getObjectMetadataMap( + workspaceId, + metadataVersion, ); + + if (!objectMetadataMap) { + throw new NotFoundException( + `Object metadata map not found for workspace ${workspaceId} and metadata version ${metadataVersion}`, + ); + } + + const mappedResult = fieldMetadataItems.map((fieldMetadataItem) => { + const objectMetadata = + objectMetadataMap[fieldMetadataItem.objectMetadataId]; + + const fieldMetadata = objectMetadata.fields[fieldMetadataItem.id]; + + const relationMetadata = + fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata; + + if (!relationMetadata) { + return new NotFoundException( + `From object metadata not found for relation ${fieldMetadata?.id}`, + ); + } + + const fromObjectMetadata = + objectMetadataMap[relationMetadata.fromObjectMetadataId]; + + const toObjectMetadata = + objectMetadataMap[relationMetadata.toObjectMetadataId]; + + const fromFieldMetadata = + objectMetadataMap[fromObjectMetadata.id].fields[ + relationMetadata.fromFieldMetadataId + ]; + + const toFieldMetadata = + objectMetadataMap[toObjectMetadata.id].fields[ + relationMetadata.toFieldMetadataId + ]; + + return { + ...relationMetadata, + fromObjectMetadata, + toObjectMetadata, + fromFieldMetadata, + toFieldMetadata, + }; }); - return mappedResult; + return mappedResult as (RelationMetadataEntity | NotFoundException)[]; } private async deleteRelationWorkspaceCustomMigration( diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.resolver.ts index 262326669ea0..8bb6f6042eb3 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.resolver.ts @@ -1,9 +1,9 @@ import { UseGuards } from '@nestjs/common'; -import { Resolver, Args, Mutation, Query } from '@nestjs/graphql'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { CreateRemoteServerInput } from 'src/engine/metadata-modules/remote-server/dtos/create-remote-server.input'; import { RemoteServerIdInput } from 'src/engine/metadata-modules/remote-server/dtos/remote-server-id.input'; import { RemoteServerTypeInput } from 'src/engine/metadata-modules/remote-server/dtos/remote-server-type.input'; @@ -13,7 +13,7 @@ import { RemoteServerType } from 'src/engine/metadata-modules/remote-server/remo import { RemoteServerService } from 'src/engine/metadata-modules/remote-server/remote-server.service'; import { remoteServerGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/remote-server/utils/remote-server-graphql-api-exception-handler.util'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver() export class RemoteServerResolver { constructor( diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts index d1c241827882..8538eabcb41d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-server.service.ts @@ -10,7 +10,7 @@ import { RemoteServerEntity, RemoteServerType, } from 'src/engine/metadata-modules/remote-server/remote-server.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { encryptText } from 'src/engine/core-modules/auth/auth.util'; import { validateObjectAgainstInjections, diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service.ts index 4fed42713f6a..55e545ed837e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service.ts @@ -11,7 +11,7 @@ import { } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.exception'; import { getForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/utils/get-foreign-table-column-name.util'; import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; import { ReferencedTable, diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts index 7698f25d094f..c3be47ba7410 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts @@ -3,14 +3,14 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { FindManyRemoteTablesInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/find-many-remote-tables-input'; import { RemoteTableInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table-input'; import { RemoteTableDTO } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto'; import { RemoteTableService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.service'; import { remoteTableGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/remote-server/remote-table/utils/remote-table-graphql-api-exception-handler.util'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver() export class RemoteTableResolver { constructor(private readonly remoteTableService: RemoteTableService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts index 76127e49f820..d7d3b985af50 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts @@ -36,7 +36,7 @@ import { mapUdtNameToFieldType, } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util'; import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { WorkspaceMigrationColumnAction, WorkspaceMigrationColumnActionType, diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input.ts index 8a03a09aaccf..da71ce9afc26 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input.ts @@ -1,6 +1,6 @@ import { Field, InputType } from '@nestjs/graphql'; -import { IsNotEmpty, IsObject, IsOptional, IsUUID } from 'class-validator'; +import { IsNotEmpty, IsObject, IsUUID } from 'class-validator'; import graphqlTypeJson from 'graphql-type-json'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; @@ -16,11 +16,9 @@ export class ExecuteServerlessFunctionInput { @Field(() => graphqlTypeJson, { description: 'Payload in JSON format', - nullable: true, }) @IsObject() - @IsOptional() - payload?: JSON; + payload: JSON; @Field(() => String, { nullable: false, diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto.ts index d220a4f86861..092d2fce762c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto.ts @@ -29,7 +29,7 @@ registerEnumType(ServerlessFunctionSyncStatus, { @ObjectType('ServerlessFunction') @Authorize({ authorize: (context: any) => ({ - workspaceId: { eq: context?.req?.user?.workspace?.id }, + workspaceId: { eq: context?.req?.workspace?.id }, }), }) @QueryOptions({ @@ -43,7 +43,6 @@ export class ServerlessFunctionDTO { id: string; @IsString() - @IsNotEmpty() @Field() name: string; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input.ts index a757784e04ed..8c75bf25534c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input.ts @@ -14,7 +14,6 @@ export class UpdateServerlessFunctionInput { id: string; @IsString() - @IsNotEmpty() @Field() name: string; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts index 0351119428ff..782362bfba94 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts @@ -35,6 +35,9 @@ export class ServerlessFunctionEntity { @Column({ nullable: false, default: ServerlessFunctionRuntime.NODE18 }) runtime: ServerlessFunctionRuntime; + @Column({ nullable: true }) + layerVersion: number; + @Column({ nullable: false, default: ServerlessFunctionSyncStatus.NOT_READY, diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts index 02c76f596a25..076343f4d206 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.module.ts @@ -11,9 +11,9 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module'; import { FileModule } from 'src/engine/core-modules/file/file.module'; +import { ServerlessModule } from 'src/engine/core-modules/serverless/serverless.module'; import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.module'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { ServerlessModule } from 'src/engine/integrations/serverless/serverless.module'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { ServerlessFunctionDTO } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; import { ServerlessFunctionResolver } from 'src/engine/metadata-modules/serverless-function/serverless-function.resolver'; @@ -45,7 +45,7 @@ import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverles create: { disabled: true }, update: { disabled: true }, delete: { disabled: true }, - guards: [JwtAuthGuard], + guards: [WorkspaceAuthGuard], }, ], }), diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.resolver.ts index cd1a232c24be..14f4ed48478d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.resolver.ts @@ -2,6 +2,7 @@ import { UseGuards } from '@nestjs/common'; import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { InjectRepository } from '@nestjs/typeorm'; +import graphqlTypeJson from 'graphql-type-json'; import { FileUpload, GraphQLUpload } from 'graphql-upload'; import { Repository } from 'typeorm'; @@ -9,11 +10,13 @@ import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/featu import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { CreateServerlessFunctionFromFileInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function-from-file.input'; import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input'; import { DeleteServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/delete-serverless-function.input'; import { ExecuteServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input'; +import { GetServerlessFunctionSourceCodeInput } from 'src/engine/metadata-modules/serverless-function/dtos/get-serverless-function-source-code.input'; +import { PublishServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/publish-serverless-function.input'; import { ServerlessFunctionExecutionResultDTO } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function-execution-result.dto'; import { ServerlessFunctionDTO } from 'src/engine/metadata-modules/serverless-function/dtos/serverless-function.dto'; import { UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input'; @@ -23,10 +26,8 @@ import { } from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service'; import { serverlessFunctionGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/serverless-function/utils/serverless-function-graphql-api-exception-handler.utils'; -import { GetServerlessFunctionSourceCodeInput } from 'src/engine/metadata-modules/serverless-function/dtos/get-serverless-function-source-code.input'; -import { PublishServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/publish-serverless-function.input'; -@UseGuards(JwtAuthGuard) +@UseGuards(WorkspaceAuthGuard) @Resolver() export class ServerlessFunctionResolver { constructor( @@ -51,7 +52,18 @@ export class ServerlessFunctionResolver { } } - @Query(() => String) + @Query(() => graphqlTypeJson) + async getAvailablePackages(@AuthWorkspace() { id: workspaceId }: Workspace) { + try { + await this.checkFeatureFlag(workspaceId); + + return await this.serverlessFunctionService.getAvailablePackages(); + } catch (error) { + serverlessFunctionGraphQLApiExceptionHandler(error); + } + } + + @Query(() => String, { nullable: true }) async getServerlessFunctionSourceCode( @Args('input') input: GetServerlessFunctionSourceCodeInput, @AuthWorkspace() { id: workspaceId }: Workspace, diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts index a3af2da35964..d7c591eb0c8c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts @@ -5,16 +5,16 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { FileUpload } from 'graphql-upload'; import { Repository } from 'typeorm'; -import { FileStorageExceptionCode } from 'src/engine/integrations/file-storage/interfaces/file-storage-exception'; -import { ServerlessExecuteResult } from 'src/engine/integrations/serverless/drivers/interfaces/serverless-driver.interface'; +import { FileStorageExceptionCode } from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; +import { ServerlessExecuteResult } from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface'; import { ThrottlerService } from 'src/engine/core-modules/throttler/throttler.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service'; -import { readFileContent } from 'src/engine/integrations/file-storage/utils/read-file-content'; -import { SOURCE_FILE_NAME } from 'src/engine/integrations/serverless/drivers/constants/source-file-name'; -import { ServerlessService } from 'src/engine/integrations/serverless/serverless.service'; -import { getServerlessFolder } from 'src/engine/integrations/serverless/utils/serverless-get-folder.utils'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { readFileContent } from 'src/engine/core-modules/file-storage/utils/read-file-content'; +import { SOURCE_FILE_NAME } from 'src/engine/core-modules/serverless/drivers/constants/source-file-name'; +import { ServerlessService } from 'src/engine/core-modules/serverless/serverless.service'; +import { getServerlessFolder } from 'src/engine/core-modules/serverless/utils/serverless-get-folder.utils'; import { CreateServerlessFunctionFromFileInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function-from-file.input'; import { UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input'; import { @@ -27,6 +27,8 @@ import { } from 'src/engine/metadata-modules/serverless-function/serverless-function.exception'; import { serverlessFunctionCreateHash } from 'src/engine/metadata-modules/serverless-function/utils/serverless-function-create-hash.utils'; import { isDefined } from 'src/utils/is-defined'; +import { getLastLayerDependencies } from 'src/engine/core-modules/serverless/drivers/utils/get-last-layer-dependencies'; +import { LAST_LAYER_VERSION } from 'src/engine/core-modules/serverless/drivers/layers/last-layer-version'; @Injectable() export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFunctionEntity> { @@ -46,22 +48,21 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun id: string, version: string, ) { - try { - const serverlessFunction = - await this.serverlessFunctionRepository.findOne({ - where: { - id, - workspaceId, - }, - }); - - if (!serverlessFunction) { - throw new ServerlessFunctionException( - `Function does not exist`, - ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, - ); - } + const serverlessFunction = await this.serverlessFunctionRepository.findOne({ + where: { + id, + workspaceId, + }, + }); + if (!serverlessFunction) { + throw new ServerlessFunctionException( + `Function does not exist`, + ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, + ); + } + + try { const folderPath = getServerlessFolder({ serverlessFunction, version, @@ -75,10 +76,7 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun return await readFileContent(fileStream); } catch (error) { if (error.code === FileStorageExceptionCode.FILE_NOT_FOUND) { - throw new ServerlessFunctionException( - `Function Version '${version}' does not exist`, - ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND, - ); + return; } throw error; } @@ -87,7 +85,7 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun async executeOneServerlessFunction( id: string, workspaceId: string, - payload: object | undefined = undefined, + payload: object, version = 'latest', ): Promise<ServerlessExecuteResult> { await this.throttleExecution(workspaceId); @@ -106,15 +104,6 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun ); } - if ( - functionToExecute.syncStatus === ServerlessFunctionSyncStatus.NOT_READY - ) { - await this.serverlessService.build(functionToExecute, version); - await super.updateOne(functionToExecute.id, { - syncStatus: ServerlessFunctionSyncStatus.READY, - }); - } - return this.serverlessService.execute(functionToExecute, payload, version); } @@ -144,8 +133,8 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun ); if ( - serverlessFunctionCreateHash(latestCode) === - serverlessFunctionCreateHash(draftCode) + serverlessFunctionCreateHash(latestCode || '') === + serverlessFunctionCreateHash(draftCode || '') ) { throw new Error( 'Cannot publish a new version when code has not changed', @@ -224,6 +213,9 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun name: serverlessFunctionInput.name, description: serverlessFunctionInput.description, syncStatus: ServerlessFunctionSyncStatus.NOT_READY, + sourceCodeHash: serverlessFunctionCreateHash( + serverlessFunctionInput.code, + ), }); const fileFolder = getServerlessFolder({ @@ -238,9 +230,34 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun folder: fileFolder, }); + await this.serverlessService.build(existingServerlessFunction, 'draft'); + await super.updateOne(existingServerlessFunction.id, { + syncStatus: ServerlessFunctionSyncStatus.READY, + }); + return await this.findById(existingServerlessFunction.id); } + async getAvailablePackages() { + const { packageJson, yarnLock } = await getLastLayerDependencies(); + + const packageVersionRegex = /^"([^@]+)@.*?":\n\s+version: (.+)$/gm; + const versions: Record<string, string> = {}; + + let match: RegExpExecArray | null; + + while ((match = packageVersionRegex.exec(yarnLock)) !== null) { + const packageName = match[1].split('@', 1)[0]; + const version = match[2]; + + if (packageJson.dependencies[packageName]) { + versions[packageName] = version; + } + } + + return versions; + } + async createOneServerlessFunction( serverlessFunctionInput: CreateServerlessFunctionFromFileInput, code: FileUpload | string, @@ -258,6 +275,7 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun ...serverlessFunctionInput, workspaceId, sourceCodeHash: serverlessFunctionCreateHash(typescriptCode), + layerVersion: LAST_LAYER_VERSION, }); const draftFileFolder = getServerlessFolder({ @@ -272,6 +290,8 @@ export class ServerlessFunctionService extends TypeOrmQueryService<ServerlessFun folder: draftFileFolder, }); + await this.serverlessService.build(createdServerlessFunction, 'draft'); + return await this.findById(createdServerlessFunction.id); } diff --git a/packages/twenty-server/src/engine/metadata-modules/utils/generate-object-metadata-map.util.ts b/packages/twenty-server/src/engine/metadata-modules/utils/generate-object-metadata-map.util.ts new file mode 100644 index 000000000000..3455efa5ff13 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/utils/generate-object-metadata-map.util.ts @@ -0,0 +1,36 @@ +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; +import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; + +export type FieldMetadataMap = Record<string, FieldMetadataInterface>; + +export type ObjectMetadataMapItem = Omit<ObjectMetadataInterface, 'fields'> & { + fields: FieldMetadataMap; +}; + +export type ObjectMetadataMap = Record<string, ObjectMetadataMapItem>; + +export const generateObjectMetadataMap = ( + objectMetadataCollection: ObjectMetadataInterface[], +): ObjectMetadataMap => { + const objectMetadataMap: ObjectMetadataMap = {}; + + for (const objectMetadata of objectMetadataCollection) { + const fieldsMap: FieldMetadataMap = {}; + + for (const fieldMetadata of objectMetadata.fields) { + fieldsMap[fieldMetadata.name] = fieldMetadata; + fieldsMap[fieldMetadata.id] = fieldMetadata; + } + + const processedObjectMetadata: ObjectMetadataMapItem = { + ...objectMetadata, + fields: fieldsMap, + }; + + objectMetadataMap[objectMetadata.id] = processedObjectMetadata; + objectMetadataMap[objectMetadata.nameSingular] = processedObjectMetadata; + objectMetadataMap[objectMetadata.namePlural] = processedObjectMetadata; + } + + return objectMetadataMap; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/utils/validate-field-name-availability.utils.ts b/packages/twenty-server/src/engine/metadata-modules/utils/validate-field-name-availability.utils.ts index 07db05aacfbd..974971fbcbf1 100644 --- a/packages/twenty-server/src/engine/metadata-modules/utils/validate-field-name-availability.utils.ts +++ b/packages/twenty-server/src/engine/metadata-modules/utils/validate-field-name-availability.utils.ts @@ -32,6 +32,10 @@ export const validateFieldNameAvailabilityOrThrow = ( const reservedCompositeFieldsNames = getReservedCompositeFieldNames(objectMetadata); + if (objectMetadata.fields.some((field) => field.name === name)) { + throw new NameNotAvailableException(name); + } + if (reservedCompositeFieldsNames.includes(name)) { throw new NameNotAvailableException(name); } diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/exceptions/workspace-metadata-cache.exception.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/exceptions/workspace-metadata-cache.exception.ts new file mode 100644 index 000000000000..04dc3e013740 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/exceptions/workspace-metadata-cache.exception.ts @@ -0,0 +1,12 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkspaceMetadataCacheException extends CustomException { + code: WorkspaceMetadataCacheExceptionCode; + constructor(message: string, code: WorkspaceMetadataCacheExceptionCode) { + super(message, code); + } +} + +export enum WorkspaceMetadataCacheExceptionCode { + METADATA_VERSION_NOT_FOUND = 'METADATA_VERSION_NOT_FOUND', +} diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service.ts new file mode 100644 index 000000000000..e1d5a0ae9667 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service.ts @@ -0,0 +1,120 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { LogExecutionTime } from 'src/engine/decorators/observability/log-execution-time.decorator'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { generateObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { + WorkspaceMetadataCacheException, + WorkspaceMetadataCacheExceptionCode, +} from 'src/engine/metadata-modules/workspace-metadata-cache/exceptions/workspace-metadata-cache.exception'; +import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; + +@Injectable() +export class WorkspaceMetadataCacheService { + logger = new Logger(WorkspaceMetadataCacheService.name); + + constructor( + @InjectRepository(Workspace, 'core') + private readonly workspaceRepository: Repository<Workspace>, + private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + ) {} + + @LogExecutionTime() + async recomputeMetadataCache({ + workspaceId, + ignoreLock = false, + }: { + workspaceId: string; + ignoreLock?: boolean; + }): Promise<void> { + const currentCacheVersion = + await this.getMetadataVersionFromCache(workspaceId); + + const currentDatabaseVersion = + await this.getMetadataVersionFromDatabase(workspaceId); + + if (currentDatabaseVersion === undefined) { + throw new WorkspaceMetadataCacheException( + 'Metadata version not found in the database', + WorkspaceMetadataCacheExceptionCode.METADATA_VERSION_NOT_FOUND, + ); + } + + const isAlreadyCaching = + await this.workspaceCacheStorageService.getObjectMetadataOngoingCachingLock( + workspaceId, + currentDatabaseVersion, + ); + + if (!ignoreLock && isAlreadyCaching) { + return; + } + + if (currentCacheVersion !== undefined) { + this.workspaceCacheStorageService.flush(workspaceId, currentCacheVersion); + } + + await this.workspaceCacheStorageService.addObjectMetadataCollectionOngoingCachingLock( + workspaceId, + currentDatabaseVersion, + ); + + await this.workspaceCacheStorageService.setMetadataVersion( + workspaceId, + currentDatabaseVersion, + ); + + console.time('fetching object metadata'); + const objectMetadataItems = await this.objectMetadataRepository.find({ + where: { workspaceId }, + relations: [ + 'fields', + 'fields.fromRelationMetadata', + 'fields.toRelationMetadata', + ], + }); + + console.timeEnd('fetching object metadata'); + + console.time('generating object metadata map'); + const freshObjectMetadataMap = + generateObjectMetadataMap(objectMetadataItems); + + console.timeEnd('generating object metadata map'); + + await this.workspaceCacheStorageService.setObjectMetadataMap( + workspaceId, + currentDatabaseVersion, + freshObjectMetadataMap, + ); + + await this.workspaceCacheStorageService.removeObjectMetadataOngoingCachingLock( + workspaceId, + currentDatabaseVersion, + ); + } + + private async getMetadataVersionFromDatabase( + workspaceId: string, + ): Promise<number | undefined> { + const workspace = await this.workspaceRepository.findOne({ + where: { id: workspaceId }, + }); + + return workspace?.metadataVersion; + } + + private async getMetadataVersionFromCache( + workspaceId: string, + ): Promise<number | undefined> { + return await this.workspaceCacheStorageService.getMetadataVersion( + workspaceId, + ); + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module.ts new file mode 100644 index 000000000000..a0dd5058bc42 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; +import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Workspace], 'core'), + TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), + WorkspaceCacheStorageModule, + ], + exports: [WorkspaceMetadataCacheService], + providers: [WorkspaceMetadataCacheService], +}) +export class WorkspaceMetadataCacheModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/exceptions/workspace-metadata-version.exception.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/exceptions/workspace-metadata-version.exception.ts new file mode 100644 index 000000000000..76a3df1673ed --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/exceptions/workspace-metadata-version.exception.ts @@ -0,0 +1,12 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkspaceMetadataVersionException extends CustomException { + code: WorkspaceMetadataVersionExceptionCode; + constructor(message: string, code: WorkspaceMetadataVersionExceptionCode) { + super(message, code); + } +} + +export enum WorkspaceMetadataVersionExceptionCode { + METADATA_VERSION_NOT_FOUND = 'METADATA_VERSION_NOT_FOUND', +} diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service.ts new file mode 100644 index 000000000000..c34f4577fcad --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service.ts @@ -0,0 +1,52 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { LogExecutionTime } from 'src/engine/decorators/observability/log-execution-time.decorator'; +import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; +import { + WorkspaceMetadataVersionException, + WorkspaceMetadataVersionExceptionCode, +} from 'src/engine/metadata-modules/workspace-metadata-version/exceptions/workspace-metadata-version.exception'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; + +@Injectable() +export class WorkspaceMetadataVersionService { + logger = new Logger(WorkspaceMetadataCacheService.name); + + constructor( + @InjectRepository(Workspace, 'core') + private readonly workspaceRepository: Repository<Workspace>, + private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) {} + + @LogExecutionTime() + async incrementMetadataVersion(workspaceId: string): Promise<void> { + const workspace = await this.workspaceRepository.findOne({ + where: { id: workspaceId }, + }); + + const metadataVersion = workspace?.metadataVersion; + + if (metadataVersion === undefined) { + throw new WorkspaceMetadataVersionException( + 'Metadata version not found', + WorkspaceMetadataVersionExceptionCode.METADATA_VERSION_NOT_FOUND, + ); + } + + const newMetadataVersion = metadataVersion + 1; + + await this.workspaceRepository.update( + { id: workspaceId }, + { metadataVersion: newMetadataVersion }, + ); + + await this.workspaceMetadataCacheService.recomputeMetadataCache({ + workspaceId, + }); + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module.ts index 4064872a17e2..350d22b56b3d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module.ts @@ -2,13 +2,15 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; @Module({ imports: [ TypeOrmModule.forFeature([Workspace], 'core'), WorkspaceCacheStorageModule, + WorkspaceMetadataCacheModule, ], exports: [WorkspaceMetadataVersionService], providers: [WorkspaceMetadataVersionService], diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service.ts deleted file mode 100644 index d3986e8db2d5..000000000000 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; - -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; - -@Injectable() -export class WorkspaceMetadataVersionService { - logger = new Logger(WorkspaceMetadataVersionService.name); - - constructor( - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository<Workspace>, - private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, - ) {} - - async flushCacheIfMetadataVersionIsOutdated( - workspaceId: string, - ): Promise<void> { - const currentVersion = - (await this.workspaceCacheStorageService.getMetadataVersion( - workspaceId, - )) ?? 1; - - let latestVersion = await this.getMetadataVersion(workspaceId); - - if (latestVersion === undefined || currentVersion !== latestVersion) { - this.logger.log( - `Metadata version mismatch detected for workspace ${workspaceId}. Current version: ${currentVersion}. Latest version: ${latestVersion}. Invalidating cache...`, - ); - - await this.workspaceCacheStorageService.flush(workspaceId); - - latestVersion = await this.incrementMetadataVersion(workspaceId); - - await this.workspaceCacheStorageService.setMetadataVersion( - workspaceId, - latestVersion, - ); - } - } - - async incrementMetadataVersion(workspaceId: string): Promise<number> { - const metadataVersion = (await this.getMetadataVersion(workspaceId)) ?? 0; - const newMetadataVersion = metadataVersion + 1; - - await this.workspaceRepository.update( - { id: workspaceId }, - { metadataVersion: newMetadataVersion }, - ); - - await this.workspaceCacheStorageService.flush(workspaceId); - - await this.workspaceCacheStorageService.setMetadataVersion( - workspaceId, - newMetadataVersion, - ); - - return newMetadataVersion; - } - - async getMetadataVersion(workspaceId: string): Promise<number | undefined> { - const workspace = await this.workspaceRepository.findOne({ - where: { id: workspaceId }, - }); - - return workspace?.metadataVersion; - } - - async resetMetadataVersion(workspaceId: string): Promise<void> { - await this.workspaceRepository.update( - { id: workspaceId }, - { metadataVersion: 1 }, - ); - - await this.workspaceCacheStorageService.flush(workspaceId); - await this.workspaceCacheStorageService.setMetadataVersion(workspaceId, 1); - } -} diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/basic-column-action.factory.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/basic-column-action.factory.ts index f44115669dd7..643819ddcb7d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/basic-column-action.factory.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/basic-column-action.factory.ts @@ -29,7 +29,8 @@ export type BasicFieldMetadataType = | FieldMetadataType.POSITION | FieldMetadataType.DATE_TIME | FieldMetadataType.DATE - | FieldMetadataType.POSITION; + | FieldMetadataType.POSITION + | FieldMetadataType.ARRAY; @Injectable() export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicFieldMetadataType> { @@ -48,6 +49,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF action: WorkspaceMigrationColumnActionType.CREATE, columnName, columnType: fieldMetadataTypeToColumnType(fieldMetadata.type), + isArray: fieldMetadata.type === FieldMetadataType.ARRAY, isNullable: fieldMetadata.isNullable ?? true, defaultValue: serializedDefaultValue, }, @@ -81,6 +83,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF currentColumnDefinition: { columnName: currentColumnName, columnType: fieldMetadataTypeToColumnType(currentFieldMetadata.type), + isArray: currentFieldMetadata.type === FieldMetadataType.ARRAY, isNullable: currentFieldMetadata.isNullable ?? true, defaultValue: serializeDefaultValue( currentFieldMetadata.defaultValue, @@ -89,6 +92,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF alteredColumnDefinition: { columnName: alteredColumnName, columnType: fieldMetadataTypeToColumnType(alteredFieldMetadata.type), + isArray: alteredFieldMetadata.type === FieldMetadataType.ARRAY, isNullable: alteredFieldMetadata.isNullable ?? true, defaultValue: serializedDefaultValue, }, diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory.ts index dc913233c3ca..9af3e89d4b04 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory.ts @@ -24,7 +24,8 @@ export type CompositeFieldMetadataType = | FieldMetadataType.FULL_NAME | FieldMetadataType.LINK | FieldMetadataType.LINKS - | FieldMetadataType.EMAILS; + | FieldMetadataType.EMAILS + | FieldMetadataType.PHONES; @Injectable() export class CompositeColumnActionFactory extends ColumnActionAbstractFactory<CompositeFieldMetadataType> { diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util.ts index b1de619efb4c..9d3ff6276cf9 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util.ts @@ -16,6 +16,7 @@ export const fieldMetadataTypeToColumnType = <Type extends FieldMetadataType>( return 'uuid'; case FieldMetadataType.TEXT: case FieldMetadataType.RICH_TEXT: + case FieldMetadataType.ARRAY: return 'text'; case FieldMetadataType.PHONE: case FieldMetadataType.EMAIL: diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.factory.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.factory.ts index d495051d703d..6f33cf0137e3 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.factory.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.factory.ts @@ -97,10 +97,15 @@ export class WorkspaceMigrationFactory { ], [FieldMetadataType.LINKS, { factory: this.compositeColumnActionFactory }], [FieldMetadataType.ACTOR, { factory: this.compositeColumnActionFactory }], + [FieldMetadataType.ARRAY, { factory: this.basicColumnActionFactory }], [ FieldMetadataType.EMAILS, { factory: this.compositeColumnActionFactory }, ], + [ + FieldMetadataType.PHONES, + { factory: this.compositeColumnActionFactory }, + ], ]); } diff --git a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.service.ts b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.service.ts index a0e91b25b37c..dd795e36528b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/workspace-migration/workspace-migration.service.ts @@ -60,10 +60,10 @@ export class WorkspaceMigrationService { workspaceId: string, migration: WorkspaceMigrationEntity, ) { - await this.workspaceMigrationRepository.save({ - id: migration.id, - appliedAt: new Date(), - }); + await this.workspaceMigrationRepository.update( + { id: migration.id, workspaceId }, + { appliedAt: new Date() }, + ); } /** diff --git a/packages/twenty-server/src/engine/middlewares/graphql-hydrate-request-from-token.middleware.ts b/packages/twenty-server/src/engine/middlewares/graphql-hydrate-request-from-token.middleware.ts index c510f3e4a3b7..7375c64a8e4b 100644 --- a/packages/twenty-server/src/engine/middlewares/graphql-hydrate-request-from-token.middleware.ts +++ b/packages/twenty-server/src/engine/middlewares/graphql-hydrate-request-from-token.middleware.ts @@ -3,12 +3,11 @@ import { Injectable, NestMiddleware } from '@nestjs/common'; import { NextFunction, Request, Response } from 'express'; import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter'; -import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; +import { TokenService } from 'src/engine/core-modules/auth/token/services/token.service'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util'; - +import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; class GraphqlTokenValidationProxy { private tokenService: TokenService; @@ -33,7 +32,7 @@ export class GraphQLHydrateRequestFromTokenMiddleware { constructor( private readonly tokenService: TokenService, - private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + private readonly workspaceStorageCacheService: WorkspaceCacheStorageService, private readonly exceptionHandlerService: ExceptionHandlerService, ) {} @@ -73,7 +72,7 @@ export class GraphQLHydrateRequestFromTokenMiddleware data = await graphqlTokenValidationProxy.validateToken(req); const metadataVersion = - await this.workspaceMetadataVersionService.getMetadataVersion( + await this.workspaceStorageCacheService.getMetadataVersion( data.workspace.id, ); diff --git a/packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts b/packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts index f122f29c47a5..d9a19a689301 100644 --- a/packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts +++ b/packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts @@ -25,6 +25,9 @@ export abstract class BaseWorkspaceEntity { description: 'Creation date', icon: 'IconCalendar', defaultValue: 'now', + settings: { + displayAsRelativeDate: true, + }, }) createdAt: string; @@ -35,6 +38,9 @@ export abstract class BaseWorkspaceEntity { description: 'Last time the record was changed', icon: 'IconCalendarClock', defaultValue: 'now', + settings: { + displayAsRelativeDate: true, + }, }) updatedAt: string; @@ -44,6 +50,9 @@ export abstract class BaseWorkspaceEntity { label: 'Deleted at', description: 'Date when the record was deleted', icon: 'IconCalendarMinus', + settings: { + displayAsRelativeDate: true, + }, }) @WorkspaceIsNullable() deletedAt?: string | null; diff --git a/packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts b/packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts index 92085ec61151..0b9b5201d2b7 100644 --- a/packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts +++ b/packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts @@ -21,9 +21,7 @@ import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/not import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; -@WorkspaceCustomEntity({ - softDelete: true, -}) +@WorkspaceCustomEntity() export class CustomWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name, diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-entity.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-entity.decorator.ts index 74f1ff0295be..651a01ad793b 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-entity.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-entity.decorator.ts @@ -1,13 +1,7 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; import { TypedReflect } from 'src/utils/typed-reflect'; -interface WorkspaceCustomEntityOptions { - softDelete?: boolean; -} - -export function WorkspaceCustomEntity( - options: WorkspaceCustomEntityOptions = {}, -): ClassDecorator { +export function WorkspaceCustomEntity(options = {}): ClassDecorator { return (target) => { const gate = TypedReflect.getMetadata( 'workspace:gate-metadata-args', @@ -17,7 +11,6 @@ export function WorkspaceCustomEntity( metadataArgsStorage.addExtendedEntities({ target, gate, - softDelete: options.softDelete, }); }; } diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts index 3b9e5b6f1d66..5e56de14008c 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-entity.decorator.ts @@ -12,7 +12,6 @@ interface WorkspaceEntityOptions { icon?: string; labelIdentifierStandardId?: string; imageIdentifierStandardId?: string; - softDelete?: boolean; } export function WorkspaceEntity( @@ -48,7 +47,6 @@ export function WorkspaceEntity( isAuditLogged, isSystem, gate, - softDelete: options.softDelete, }); }; } diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts index fd2b280fde60..c6dd8bfd7a4f 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts @@ -69,6 +69,7 @@ export function WorkspaceField<T extends FieldMetadataType>( icon: options.icon, defaultValue, options: options.options, + settings: options.settings, isPrimary, isNullable, isSystem, diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-index.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-index.decorator.ts index 5ede935f4926..bf2e43201c30 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-index.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-index.decorator.ts @@ -38,9 +38,9 @@ export function WorkspaceIndex( metadataArgsStorage.addIndexes({ name: `IDX_${generateDeterministicIndexName([ convertClassNameToObjectMetadataName(target.constructor.name), - propertyKey.toString(), + ...[propertyKey.toString(), 'deletedAt'], ])}`, - columns: [propertyKey.toString()], + columns: [propertyKey.toString(), 'deletedAt'], target: target.constructor, gate, }); diff --git a/packages/twenty-server/src/engine/twenty-orm/exceptions/twenty-orm.exception.ts b/packages/twenty-server/src/engine/twenty-orm/exceptions/twenty-orm.exception.ts new file mode 100644 index 000000000000..25a717af09ca --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/exceptions/twenty-orm.exception.ts @@ -0,0 +1,15 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class TwentyORMException extends CustomException { + code: TwentyORMExceptionCode; + constructor(message: string, code: TwentyORMExceptionCode) { + super(message, code); + } +} + +export enum TwentyORMExceptionCode { + METADATA_VERSION_NOT_FOUND = 'METADATA_VERSION_NOT_FOUND', + METADATA_VERSION_MISMATCH = 'METADATA_VERSION_MISMATCH', + METADATA_COLLECTION_NOT_FOUND = 'METADATA_COLLECTION_NOT_FOUND', + WORKSPACE_SCHEMA_NOT_FOUND = 'WORKSPACE_SCHEMA_NOT_FOUND', +} diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts index 6b4564efaaea..db67298f1e95 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts @@ -2,15 +2,15 @@ import { Injectable } from '@nestjs/common'; import { ColumnType, EntitySchemaColumnOptions } from 'typeorm'; +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; + import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; -import { - FieldMetadataEntity, - FieldMetadataType, -} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util'; import { serializeDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-default-value'; +import { FieldMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util'; import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; @@ -20,20 +20,14 @@ type EntitySchemaColumnMap = { @Injectable() export class EntitySchemaColumnFactory { - create( - fieldMetadataCollection: FieldMetadataEntity[], - softDelete: boolean, - ): EntitySchemaColumnMap { + create(fieldMetadataMap: FieldMetadataMap): EntitySchemaColumnMap { let entitySchemaColumnMap: EntitySchemaColumnMap = {}; + const fieldMetadataCollection = Object.values(fieldMetadataMap); + for (const fieldMetadata of fieldMetadataCollection) { const key = fieldMetadata.name; - // Skip deletedAt column if soft delete is not enabled - if (!softDelete && key === 'deletedAt') { - continue; - } - if (isRelationFieldMetadataType(fieldMetadata.type)) { const relationMetadata = fieldMetadata.fromRelationMetadata ?? @@ -85,6 +79,7 @@ export class EntitySchemaColumnFactory { nullable: fieldMetadata.isNullable, createDate: key === 'createdAt', updateDate: key === 'updatedAt', + deleteDate: key === 'deletedAt', array: fieldMetadata.type === FieldMetadataType.MULTI_SELECT, default: defaultValue, }; @@ -102,7 +97,7 @@ export class EntitySchemaColumnFactory { } private createCompositeColumns( - fieldMetadata: FieldMetadataEntity, + fieldMetadata: FieldMetadataInterface, ): EntitySchemaColumnMap { const entitySchemaColumnMap: EntitySchemaColumnMap = {}; const compositeType = compositeTypeDefinitions.get(fieldMetadata.type); diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts index fc8755ecc533..f6fc88de34f2 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts @@ -2,10 +2,12 @@ import { Injectable } from '@nestjs/common'; import { EntitySchemaRelationOptions } from 'typeorm'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { + FieldMetadataMap, + ObjectMetadataMap, +} from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { determineRelationDetails } from 'src/engine/twenty-orm/utils/determine-relation-details.util'; import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; -import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; type EntitySchemaRelationMap = { [key: string]: EntitySchemaRelationOptions; @@ -13,16 +15,16 @@ type EntitySchemaRelationMap = { @Injectable() export class EntitySchemaRelationFactory { - constructor( - private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, - ) {} + constructor() {} async create( - workspaceId: string, - fieldMetadataCollection: FieldMetadataEntity[], + fieldMetadataMap: FieldMetadataMap, + objectMetadataMap: ObjectMetadataMap, ): Promise<EntitySchemaRelationMap> { const entitySchemaRelationMap: EntitySchemaRelationMap = {}; + const fieldMetadataCollection = Object.values(fieldMetadataMap); + for (const fieldMetadata of fieldMetadataCollection) { if (!isRelationFieldMetadataType(fieldMetadata.type)) { continue; @@ -37,19 +39,10 @@ export class EntitySchemaRelationFactory { ); } - const objectMetadataCollection = - await this.workspaceCacheStorageService.getObjectMetadataCollection( - workspaceId, - ); - - if (!objectMetadataCollection) { - throw new Error('Object metadata collection not found'); - } - const relationDetails = await determineRelationDetails( fieldMetadata, relationMetadata, - objectMetadataCollection, + objectMetadataMap, ); entitySchemaRelationMap[fieldMetadata.name] = { diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts index 249f14091139..eeb697e8867e 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts @@ -2,7 +2,10 @@ import { Injectable } from '@nestjs/common'; import { EntitySchema } from 'typeorm'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { + ObjectMetadataMap, + ObjectMetadataMapItem, +} from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { EntitySchemaColumnFactory } from 'src/engine/twenty-orm/factories/entity-schema-column.factory'; import { EntitySchemaRelationFactory } from 'src/engine/twenty-orm/factories/entity-schema-relation.factory'; import { WorkspaceEntitiesStorage } from 'src/engine/twenty-orm/storage/workspace-entities.storage'; @@ -17,16 +20,17 @@ export class EntitySchemaFactory { async create( workspaceId: string, - objectMetadata: ObjectMetadataEntity, + metadataVersion: number, + objectMetadata: ObjectMetadataMapItem, + objectMetadataMap: ObjectMetadataMap, ): Promise<EntitySchema> { const columns = this.entitySchemaColumnFactory.create( objectMetadata.fields, - objectMetadata.isSoftDeletable ?? false, ); const relations = await this.entitySchemaRelationFactory.create( - workspaceId, objectMetadata.fields, + objectMetadataMap, ); const entitySchema = new EntitySchema({ diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-context.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-context.factory.ts index bf70156a94e0..44b6cd1ed032 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-context.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-context.factory.ts @@ -11,11 +11,11 @@ export class ScopedWorkspaceContextFactory { public create(): { workspaceId: string | null; - workspaceMetadataVersion: string | null; + workspaceMetadataVersion: number | null; } { const workspaceId: string | undefined = this.request?.['req']?.['workspaceId']; - const workspaceMetadataVersion: string | undefined = + const workspaceMetadataVersion: number | undefined = this.request?.['req']?.['workspaceMetadataVersion']; return { diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts index 5bf31109605a..60aecca27029 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts @@ -1,161 +1,229 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; +import { Injectable, Logger } from '@nestjs/common'; -import { EntitySchema, Repository } from 'typeorm'; +import { EntitySchema } from 'typeorm'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; +import { + TwentyORMException, + TwentyORMExceptionCode, +} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception'; import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory'; import { CacheManager } from 'src/engine/twenty-orm/storage/cache-manager.storage'; import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; @Injectable() export class WorkspaceDatasourceFactory { + private readonly logger = new Logger(WorkspaceDatasourceFactory.name); private cacheManager = new CacheManager<WorkspaceDataSource>(); + private cachedDatasourcePromise: Record<string, Promise<WorkspaceDataSource>>; constructor( private readonly dataSourceService: DataSourceService, private readonly environmentService: EnvironmentService, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, - private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, - @InjectRepository(ObjectMetadataEntity, 'metadata') - private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, private readonly entitySchemaFactory: EntitySchemaFactory, - ) {} + ) { + this.cachedDatasourcePromise = {}; + } public async create( workspaceId: string, - workspaceMetadataVersion: string | null, + workspaceMetadataVersion: number | null, + failOnMetadataCacheMiss = true, ): Promise<WorkspaceDataSource> { - const latestWorkspaceMetadataVersion = - await this.workspaceMetadataVersionService.getMetadataVersion( + const cachedWorkspaceMetadataVersion = + await this.getWorkspaceMetadataVersionFromCache( workspaceId, + failOnMetadataCacheMiss, ); - const desiredWorkspaceMetadataVersion = - workspaceMetadataVersion ?? latestWorkspaceMetadataVersion; - - if (!desiredWorkspaceMetadataVersion) { - throw new Error( - `Desired workspace metadata version not found while creating workspace data source for workspace ${workspaceId}`, + if ( + workspaceMetadataVersion !== null && + cachedWorkspaceMetadataVersion !== workspaceMetadataVersion + ) { + throw new TwentyORMException( + `Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${cachedWorkspaceMetadataVersion}. Desired version: ${workspaceMetadataVersion}`, + TwentyORMExceptionCode.METADATA_VERSION_MISMATCH, ); } - if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) { - throw new Error( - `Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`, - ); - } + const cacheKey = `${workspaceId}-${cachedWorkspaceMetadataVersion}`; - const workspaceDataSource = await this.cacheManager.execute( - `${workspaceId}-${latestWorkspaceMetadataVersion}`, - async () => { - let cachedObjectMetadataCollection = - await this.workspaceCacheStorageService.getObjectMetadataCollection( - workspaceId, - ); - - if (!cachedObjectMetadataCollection) { - const freshObjectMetadataCollection = - await this.objectMetadataRepository.find({ - where: { workspaceId }, - relations: [ - 'fields.object', - 'fields', - 'fields.fromRelationMetadata', - 'fields.toRelationMetadata', - 'fields.fromRelationMetadata.toObjectMetadata', - ], - }); - - await this.workspaceCacheStorageService.setObjectMetadataCollection( - workspaceId, - freshObjectMetadataCollection, - ); - - cachedObjectMetadataCollection = freshObjectMetadataCollection; - } + if (cacheKey in this.cachedDatasourcePromise) { + return this.cachedDatasourcePromise[cacheKey]; + } - const dataSourceMetadata = - await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( - workspaceId, - ); + const creationPromise = (async (): Promise<WorkspaceDataSource> => { + try { + const result = await this.cacheManager.execute( + cacheKey as '`${string}-${string}`', + async () => { + this.logger.log( + `Creating workspace data source for workspace ${workspaceId} and metadata version ${cachedWorkspaceMetadataVersion}`, + ); + + const dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( + workspaceId, + ); + + if (!dataSourceMetadata) { + throw new TwentyORMException( + `Workspace Schema not found for workspace ${workspaceId}`, + TwentyORMExceptionCode.WORKSPACE_SCHEMA_NOT_FOUND, + ); + } + + const cachedEntitySchemaOptions = + await this.workspaceCacheStorageService.getORMEntitySchema( + workspaceId, + cachedWorkspaceMetadataVersion, + ); + + let cachedEntitySchemas: EntitySchema[]; + + const cachedObjectMetadataMap = + await this.workspaceCacheStorageService.getObjectMetadataMap( + workspaceId, + cachedWorkspaceMetadataVersion, + ); + + if (!cachedObjectMetadataMap) { + throw new TwentyORMException( + `Workspace Schema not found for workspace ${workspaceId}`, + TwentyORMExceptionCode.METADATA_COLLECTION_NOT_FOUND, + ); + } + + if (cachedEntitySchemaOptions) { + cachedEntitySchemas = cachedEntitySchemaOptions.map( + (option) => new EntitySchema(option), + ); + } else { + const entitySchemas = await Promise.all( + Object.values(cachedObjectMetadataMap).map((objectMetadata) => + this.entitySchemaFactory.create( + workspaceId, + cachedWorkspaceMetadataVersion, + objectMetadata, + cachedObjectMetadataMap, + ), + ), + ); + + await this.workspaceCacheStorageService.setORMEntitySchema( + workspaceId, + cachedWorkspaceMetadataVersion, + entitySchemas.map((entitySchema) => entitySchema.options), + ); + + cachedEntitySchemas = entitySchemas; + } + + const workspaceDataSource = new WorkspaceDataSource( + { + workspaceId, + objectMetadataMap: cachedObjectMetadataMap, + }, + { + url: + dataSourceMetadata.url ?? + this.environmentService.get('PG_DATABASE_URL'), + type: 'postgres', + logging: this.environmentService.get('DEBUG_MODE') + ? ['query', 'error'] + : ['error'], + schema: dataSourceMetadata.schema, + entities: cachedEntitySchemas, + ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ? { + rejectUnauthorized: false, + } + : undefined, + }, + ); + + await workspaceDataSource.initialize(); + + return workspaceDataSource; + }, + async (dataSource) => { + try { + await dataSource.destroy(); + } catch (error) { + // Ignore error if pool has already been destroyed which is a common race condition case + if (error.message === 'Called end on pool more than once') { + return; + } + + throw error; + } + }, + ); - if (!dataSourceMetadata) { + if (result === null) { throw new Error( - `Data source metadata not found for workspace ${workspaceId}`, + `Failed to create WorkspaceDataSource for ${cacheKey}`, ); } - if (!cachedObjectMetadataCollection) { - throw new Error( - `Object metadata collection not found for workspace ${workspaceId}`, - ); - } + return result; + } finally { + delete this.cachedDatasourcePromise[cacheKey]; + } + })(); - const cachedEntitySchemaOptions = - await this.workspaceCacheStorageService.getORMEntitySchema( - workspaceId, - ); + this.cachedDatasourcePromise[cacheKey] = creationPromise; - let cachedEntitySchemas: EntitySchema[]; - - if (cachedEntitySchemaOptions) { - cachedEntitySchemas = cachedEntitySchemaOptions.map( - (option) => new EntitySchema(option), - ); - } else { - const entitySchemas = await Promise.all( - cachedObjectMetadataCollection.map((objectMetadata) => - this.entitySchemaFactory.create(workspaceId, objectMetadata), - ), - ); + return creationPromise; + } - await this.workspaceCacheStorageService.setORMEntitySchema( - workspaceId, - entitySchemas.map((entitySchema) => entitySchema.options), - ); + public async destroy(workspaceId: string): Promise<void> { + const cachedWorkspaceMetadataVersion = + await this.workspaceCacheStorageService.getMetadataVersion(workspaceId); - cachedEntitySchemas = entitySchemas; - } + await this.cacheManager.clearKey( + `${workspaceId}-${cachedWorkspaceMetadataVersion}`, + ); + } - const workspaceDataSource = new WorkspaceDataSource( - { - workspaceId, - objectMetadataCollection: cachedObjectMetadataCollection, - }, - { - url: - dataSourceMetadata.url ?? - this.environmentService.get('PG_DATABASE_URL'), - type: 'postgres', - logging: this.environmentService.get('DEBUG_MODE') - ? ['query', 'error'] - : ['error'], - schema: dataSourceMetadata.schema, - entities: cachedEntitySchemas, - ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') - ? { - rejectUnauthorized: false, - } - : undefined, - }, - ); + private async getWorkspaceMetadataVersionFromCache( + workspaceId: string, + failOnMetadataCacheMiss = true, + ): Promise<number> { + let latestWorkspaceMetadataVersion = + await this.workspaceCacheStorageService.getMetadataVersion(workspaceId); - await workspaceDataSource.initialize(); + if (latestWorkspaceMetadataVersion === undefined) { + await this.workspaceMetadataCacheService.recomputeMetadataCache({ + workspaceId, + ignoreLock: !failOnMetadataCacheMiss, + }); - return workspaceDataSource; - }, - (dataSource) => dataSource.destroy(), - ); + if (failOnMetadataCacheMiss) { + throw new TwentyORMException( + `Metadata version not found for workspace ${workspaceId}`, + TwentyORMExceptionCode.METADATA_VERSION_NOT_FOUND, + ); + } else { + latestWorkspaceMetadataVersion = + await this.workspaceCacheStorageService.getMetadataVersion( + workspaceId, + ); + } + } - if (!workspaceDataSource) { - throw new Error('Workspace data source not found'); + if (!latestWorkspaceMetadataVersion) { + throw new TwentyORMException( + `Metadata version not found after recompute for workspace ${workspaceId}`, + TwentyORMExceptionCode.METADATA_VERSION_NOT_FOUND, + ); } - return workspaceDataSource; + return latestWorkspaceMetadataVersion; } } diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts index 0f506c5e25a1..4cc710be2682 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts @@ -60,9 +60,4 @@ export interface WorkspaceEntityMetadataArgs { * Image identifier. */ readonly imageIdentifierStandardId: string | null; - - /** - * Enable soft delete. - */ - readonly softDelete?: boolean; } diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts index fe29d8c15e86..12706f004849 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts @@ -13,9 +13,4 @@ export interface WorkspaceExtendedEntityMetadataArgs { * Entity gate. */ readonly gate?: Gate; - - /** - * Enable soft delete. - */ - readonly softDelete?: boolean; } diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts index 862d72a25117..09c339c936e5 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts @@ -1,5 +1,6 @@ import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface'; import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface'; +import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @@ -54,6 +55,11 @@ export interface WorkspaceFieldMetadataArgs { */ readonly options?: FieldMetadataOptions; + /** + * Field settings. + */ + readonly settings?: FieldMetadataSettings; + /** * Is primary field. */ diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-internal-context.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-internal-context.interface.ts index 266c60324f23..f68611f678db 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-internal-context.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-internal-context.interface.ts @@ -1,6 +1,6 @@ -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; export interface WorkspaceInternalContext { workspaceId: string; - objectMetadataCollection: ObjectMetadataEntity[]; + objectMetadataMap: ObjectMetadataMap; } diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts index 6a436ced71aa..ea3c3f9e84bc 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts @@ -1,5 +1,3 @@ -import { isPlainObject } from '@nestjs/common/utils/shared.utils'; - import { DeepPartial, DeleteResult, @@ -24,13 +22,10 @@ import { UpsertOptions } from 'typeorm/repository/UpsertOptions'; import { WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface'; -import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; -import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; -import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { ObjectMetadataMapItem } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { WorkspaceEntitiesStorage } from 'src/engine/twenty-orm/storage/workspace-entities.storage'; -import { computeRelationType } from 'src/engine/twenty-orm/utils/compute-relation-type.util'; -import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; +import { formatData } from 'src/engine/twenty-orm/utils/format-data.util'; +import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; export class WorkspaceRepository< Entity extends ObjectLiteral, @@ -427,9 +422,13 @@ export class WorkspaceRepository< const formatedEntity = await this.formatData(entity); const result = await manager.insert(this.target, formatedEntity); - const formattedResult = await this.formatResult(result); + const formattedResult = await this.formatResult(result.generatedMaps); - return formattedResult; + return { + raw: result.raw, + generatedMaps: formattedResult, + identifiers: result.identifiers, + }; } /** @@ -469,11 +468,19 @@ export class WorkspaceRepository< const formattedEntityOrEntities = await this.formatData(entityOrEntities); - return manager.upsert( + const result = await manager.upsert( this.target, formattedEntityOrEntities, conflictPathsOrOptions, ); + + const formattedResult = await this.formatResult(result.generatedMaps); + + return { + raw: result.raw, + generatedMaps: formattedResult, + identifiers: result.identifiers, + }; } /** @@ -623,31 +630,20 @@ export class WorkspaceRepository< throw new Error('Object metadata name is missing'); } - const objectMetadata = this.internalContext.objectMetadataCollection.find( - (objectMetadata) => objectMetadata.nameSingular === objectMetadataName, - ); + const objectMetadata = + this.internalContext.objectMetadataMap[objectMetadataName]; if (!objectMetadata) { throw new Error( `Object metadata for object "${objectMetadataName}" is missing ` + `in workspace "${this.internalContext.workspaceId}" ` + - `with object metadata collection length: ${this.internalContext.objectMetadataCollection.length}`, + `with object metadata collection length: ${this.internalContext.objectMetadataMap.length}`, ); } return objectMetadata; } - private async getCompositeFieldMetadataCollection( - objectMetadata: ObjectMetadataEntity, - ) { - const compositeFieldMetadataCollection = objectMetadata.fields.filter( - (fieldMetadata) => isCompositeFieldMetadataType(fieldMetadata.type), - ); - - return compositeFieldMetadataCollection; - } - private async transformOptions< T extends FindManyOptions<Entity> | FindOneOptions<Entity> | undefined, >(options: T): Promise<T> { @@ -663,190 +659,19 @@ export class WorkspaceRepository< } private async formatData<T>(data: T): Promise<T> { - if (!data) { - return data; - } - - if (Array.isArray(data)) { - return Promise.all( - data.map((item) => this.formatData(item)), - ) as Promise<T>; - } - const objectMetadata = await this.getObjectMetadataFromTarget(); - const compositeFieldMetadataCollection = - await this.getCompositeFieldMetadataCollection(objectMetadata); - const compositeFieldMetadataMap = new Map( - compositeFieldMetadataCollection.map((fieldMetadata) => [ - fieldMetadata.name, - fieldMetadata, - ]), - ); - const newData: object = {}; - - for (const [key, value] of Object.entries(data)) { - const fieldMetadata = compositeFieldMetadataMap.get(key); - - if (!fieldMetadata) { - if (isPlainObject(value)) { - newData[key] = await this.formatData(value); - } else { - newData[key] = value; - } - continue; - } - - const compositeType = compositeTypeDefinitions.get(fieldMetadata.type); - - if (!compositeType) { - continue; - } - - for (const compositeProperty of compositeType.properties) { - const compositeKey = computeCompositeColumnName( - fieldMetadata.name, - compositeProperty, - ); - const value = data?.[key]?.[compositeProperty.name]; - - if (value === undefined || value === null) { - continue; - } - - newData[compositeKey] = data[key][compositeProperty.name]; - } - } - - return newData as T; + return formatData(data, objectMetadata) as T; } private async formatResult<T>( data: T, - objectMetadata?: ObjectMetadataEntity, + objectMetadata?: ObjectMetadataMapItem, ): Promise<T> { objectMetadata ??= await this.getObjectMetadataFromTarget(); - if (!data) { - return data; - } - - if (Array.isArray(data)) { - // If the data is an array, map each item in the array, format result is a promise - return Promise.all( - data.map((item) => this.formatResult(item, objectMetadata)), - ) as Promise<T>; - } - - if (!isPlainObject(data)) { - return data; - } - - if (!objectMetadata) { - throw new Error('Object metadata is missing'); - } - - const compositeFieldMetadataCollection = - await this.getCompositeFieldMetadataCollection(objectMetadata); - - const compositeFieldMetadataMap = new Map( - compositeFieldMetadataCollection.flatMap((fieldMetadata) => { - const compositeType = compositeTypeDefinitions.get(fieldMetadata.type); - - if (!compositeType) return []; - - // Map each composite property to a [key, value] pair - return compositeType.properties.map((compositeProperty) => [ - computeCompositeColumnName(fieldMetadata.name, compositeProperty), - { - parentField: fieldMetadata.name, - ...compositeProperty, - }, - ]); - }), - ); - - const relationMetadataMap = new Map( - objectMetadata.fields - .filter(({ type }) => isRelationFieldMetadataType(type)) - .map((fieldMetadata) => [ - fieldMetadata.name, - { - relationMetadata: - fieldMetadata.fromRelationMetadata ?? - fieldMetadata.toRelationMetadata, - relationType: computeRelationType( - fieldMetadata, - fieldMetadata.fromRelationMetadata ?? - fieldMetadata.toRelationMetadata, - ), - }, - ]), - ); - const newData: object = {}; - - for (const [key, value] of Object.entries(data)) { - const compositePropertyArgs = compositeFieldMetadataMap.get(key); - const { relationMetadata, relationType } = - relationMetadataMap.get(key) ?? {}; - - if (!compositePropertyArgs && !relationMetadata) { - if (isPlainObject(value)) { - newData[key] = await this.formatResult(value); - } else { - newData[key] = value; - } - continue; - } - - if (relationMetadata) { - const toObjectMetadata = - this.internalContext.objectMetadataCollection.find( - (objectMetadata) => - objectMetadata.id === relationMetadata.toObjectMetadataId, - ); - - const fromObjectMetadata = - this.internalContext.objectMetadataCollection.find( - (objectMetadata) => - objectMetadata.id === relationMetadata.fromObjectMetadataId, - ); - - if (!toObjectMetadata) { - throw new Error( - `Object metadata for object metadataId "${relationMetadata.toObjectMetadataId}" is missing`, - ); - } - - if (!fromObjectMetadata) { - throw new Error( - `Object metadata for object metadataId "${relationMetadata.fromObjectMetadataId}" is missing`, - ); - } - - newData[key] = await this.formatResult( - value, - - relationType === 'one-to-many' - ? toObjectMetadata - : fromObjectMetadata, - ); - continue; - } - - if (!compositePropertyArgs) { - continue; - } - - const { parentField, ...compositeProperty } = compositePropertyArgs; - - if (!newData[parentField]) { - newData[parentField] = {}; - } - - newData[parentField][compositeProperty.name] = value; - } + const objectMetadataMap = this.internalContext.objectMetadataMap; - return newData as T; + return formatResult(data, objectMetadata, objectMetadataMap) as T; } } diff --git a/packages/twenty-server/src/engine/twenty-orm/storage/cache-manager.storage.ts b/packages/twenty-server/src/engine/twenty-orm/storage/cache-manager.storage.ts index fcd40d6f38ee..d73b61a36f62 100644 --- a/packages/twenty-server/src/engine/twenty-orm/storage/cache-manager.storage.ts +++ b/packages/twenty-server/src/engine/twenty-orm/storage/cache-manager.storage.ts @@ -34,6 +34,16 @@ export class CacheManager<T> { return value; } + async clearKey( + cacheKey: CacheKey, + onDelete?: (value: T) => Promise<void> | void, + ): Promise<void> { + if (this.cache.has(cacheKey)) { + await onDelete?.(this.cache.get(cacheKey)!); + this.cache.delete(cacheKey); + } + } + async clear(onDelete?: (value: T) => Promise<void> | void): Promise<void> { for (const value of this.cache.values()) { await onDelete?.(value); diff --git a/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts b/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts index 7ea7f9d76840..69807d28d2a0 100644 --- a/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts +++ b/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts @@ -1,12 +1,12 @@ /* eslint-disable @typescript-eslint/ban-types */ import { WorkspaceDynamicRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface'; -import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface'; import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface'; -import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; import { WorkspaceExtendedEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface'; +import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface'; import { WorkspaceIndexMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-index-metadata-args.interface'; import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; +import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; export class MetadataArgsStorage { private readonly entities: WorkspaceEntityMetadataArgs[] = []; diff --git a/packages/twenty-server/src/engine/twenty-orm/twenty-orm-global.manager.ts b/packages/twenty-server/src/engine/twenty-orm/twenty-orm-global.manager.ts index f4d8190c556d..acfaabb18f9a 100644 --- a/packages/twenty-server/src/engine/twenty-orm/twenty-orm-global.manager.ts +++ b/packages/twenty-server/src/engine/twenty-orm/twenty-orm-global.manager.ts @@ -15,16 +15,19 @@ export class TwentyORMGlobalManager { async getRepositoryForWorkspace<T extends ObjectLiteral>( workspaceId: string, workspaceEntity: Type<T>, + failOnMetadataCacheMiss?: boolean, ): Promise<WorkspaceRepository<T>>; async getRepositoryForWorkspace<T extends ObjectLiteral>( workspaceId: string, objectMetadataName: string, + failOnMetadataCacheMiss?: boolean, ): Promise<WorkspaceRepository<T>>; async getRepositoryForWorkspace<T extends ObjectLiteral>( workspaceId: string, workspaceEntityOrobjectMetadataName: Type<T> | string, + failOnMetadataCacheMiss = true, ): Promise<WorkspaceRepository<T>> { let objectMetadataName: string; @@ -39,6 +42,7 @@ export class TwentyORMGlobalManager { const workspaceDataSource = await this.workspaceDataSourceFactory.create( workspaceId, null, + failOnMetadataCacheMiss, ); const repository = workspaceDataSource.getRepository<T>(objectMetadataName); @@ -47,6 +51,10 @@ export class TwentyORMGlobalManager { } async getDataSourceForWorkspace(workspaceId: string) { - return this.workspaceDataSourceFactory.create(workspaceId, null); + return await this.workspaceDataSourceFactory.create(workspaceId, null); + } + + async destroyDataSourceForWorkspace(workspaceId: string) { + await this.workspaceDataSourceFactory.destroy(workspaceId); } } diff --git a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts index 923400c44e56..7e514fb64666 100644 --- a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts +++ b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts @@ -3,7 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module'; import { entitySchemaFactories } from 'src/engine/twenty-orm/factories'; import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; @@ -16,7 +16,7 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/ TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), DataSourceModule, WorkspaceCacheStorageModule, - WorkspaceMetadataVersionModule, + WorkspaceMetadataCacheModule, ], providers: [ ...entitySchemaFactories, diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/compute-relation-type.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/compute-relation-type.util.ts index 8836edbf2cf7..aeaa2abc0940 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/compute-relation-type.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/compute-relation-type.util.ts @@ -1,15 +1,16 @@ -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; + import { RelationMetadataEntity, RelationMetadataType, } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { - deduceRelationDirection, RelationDirection, + deduceRelationDirection, } from 'src/engine/utils/deduce-relation-direction.util'; export const computeRelationType = ( - fieldMetadata: FieldMetadataEntity, + fieldMetadata: FieldMetadataInterface, relationMetadata: RelationMetadataEntity, ) => { const relationDirection = deduceRelationDirection( diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/determine-relation-details.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/determine-relation-details.util.ts index b5876783b7bd..783995afb0a9 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/determine-relation-details.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/determine-relation-details.util.ts @@ -1,8 +1,9 @@ import { RelationType } from 'typeorm/metadata/types/RelationTypes'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; + import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; import { computeRelationType } from 'src/engine/twenty-orm/utils/compute-relation-type.util'; interface RelationDetails { @@ -13,37 +14,28 @@ interface RelationDetails { } export async function determineRelationDetails( - fieldMetadata: FieldMetadataEntity, + fieldMetadata: FieldMetadataInterface, relationMetadata: RelationMetadataEntity, - objectMetadataCollection: ObjectMetadataEntity[], + objectMetadataMap: ObjectMetadataMap, ): Promise<RelationDetails> { const relationType = computeRelationType(fieldMetadata, relationMetadata); - let fromObjectMetadata: ObjectMetadataEntity | undefined = - fieldMetadata.object; - let toObjectMetadata: ObjectMetadataEntity | undefined = - objectMetadataCollection.find( - (objectMetadata) => - objectMetadata.id === relationMetadata.toObjectMetadataId, - ); + const fromObjectMetadata = objectMetadataMap[fieldMetadata.objectMetadataId]; + let toObjectMetadata = objectMetadataMap[relationMetadata.toObjectMetadataId]; // RelationMetadata always store the relation from the perspective of the `from` object, MANY_TO_ONE relations are not stored yet if (relationType === 'many-to-one') { - fromObjectMetadata = fieldMetadata.object; - - toObjectMetadata = objectMetadataCollection.find( - (objectMetadata) => - objectMetadata.id === relationMetadata.fromObjectMetadataId, - ); + toObjectMetadata = objectMetadataMap[relationMetadata.fromObjectMetadataId]; } if (!fromObjectMetadata || !toObjectMetadata) { throw new Error('Object metadata not found'); } - const toFieldMetadata = toObjectMetadata.fields.find((field) => - relationType === 'many-to-one' - ? field.id === relationMetadata.fromFieldMetadataId - : field.id === relationMetadata.toFieldMetadataId, + const toFieldMetadata = Object.values(toObjectMetadata.fields).find( + (field) => + relationType === 'many-to-one' + ? field.id === relationMetadata.fromFieldMetadataId + : field.id === relationMetadata.toFieldMetadataId, ); if (!toFieldMetadata) { diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/format-data.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/format-data.util.ts new file mode 100644 index 000000000000..f6f31f32c9db --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/utils/format-data.util.ts @@ -0,0 +1,65 @@ +import { isPlainObject } from '@nestjs/common/utils/shared.utils'; + +import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; +import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { ObjectMetadataMapItem } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { getCompositeFieldMetadataCollection } from 'src/engine/twenty-orm/utils/get-composite-field-metadata-collection'; + +export function formatData<T>( + data: T, + objectMetadata: ObjectMetadataMapItem, +): T { + if (!data) { + return data; + } + + if (Array.isArray(data)) { + return data.map((item) => formatData(item, objectMetadata)) as T; + } + + const compositeFieldMetadataCollection = + getCompositeFieldMetadataCollection(objectMetadata); + + const compositeFieldMetadataMap = new Map( + compositeFieldMetadataCollection.map((fieldMetadata) => [ + fieldMetadata.name, + fieldMetadata, + ]), + ); + const newData: object = {}; + + for (const [key, value] of Object.entries(data)) { + const fieldMetadata = compositeFieldMetadataMap.get(key); + + if (!fieldMetadata) { + if (isPlainObject(value)) { + newData[key] = formatData(value, objectMetadata); + } else { + newData[key] = value; + } + continue; + } + + const compositeType = compositeTypeDefinitions.get(fieldMetadata.type); + + if (!compositeType) { + continue; + } + + for (const compositeProperty of compositeType.properties) { + const compositeKey = computeCompositeColumnName( + fieldMetadata.name, + compositeProperty, + ); + const value = data?.[key]?.[compositeProperty.name]; + + if (value === undefined || value === null) { + continue; + } + + newData[compositeKey] = data[key][compositeProperty.name]; + } + } + + return newData as T; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts new file mode 100644 index 000000000000..81949e0743a3 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/utils/format-result.util.ts @@ -0,0 +1,131 @@ +import { isPlainObject } from '@nestjs/common/utils/shared.utils'; + +import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; +import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { + ObjectMetadataMap, + ObjectMetadataMapItem, +} from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; +import { computeRelationType } from 'src/engine/twenty-orm/utils/compute-relation-type.util'; +import { getCompositeFieldMetadataCollection } from 'src/engine/twenty-orm/utils/get-composite-field-metadata-collection'; +import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; + +export function formatResult<T>( + data: T, + objectMetadata: ObjectMetadataMapItem, + objectMetadataMap: ObjectMetadataMap, +): T { + if (!data) { + return data; + } + + if (Array.isArray(data)) { + return data.map((item) => + formatResult(item, objectMetadata, objectMetadataMap), + ) as T; + } + + if (!isPlainObject(data)) { + return data; + } + + if (!objectMetadata) { + throw new Error('Object metadata is missing'); + } + + const compositeFieldMetadataCollection = + getCompositeFieldMetadataCollection(objectMetadata); + + const compositeFieldMetadataMap = new Map( + compositeFieldMetadataCollection.flatMap((fieldMetadata) => { + const compositeType = compositeTypeDefinitions.get(fieldMetadata.type); + + if (!compositeType) return []; + + // Map each composite property to a [key, value] pair + return compositeType.properties.map((compositeProperty) => [ + computeCompositeColumnName(fieldMetadata.name, compositeProperty), + { + parentField: fieldMetadata.name, + ...compositeProperty, + }, + ]); + }), + ); + + const relationMetadataMap = new Map( + Object.values(objectMetadata.fields) + .filter(({ type }) => isRelationFieldMetadataType(type)) + .map((fieldMetadata) => [ + fieldMetadata.name, + { + relationMetadata: + fieldMetadata.fromRelationMetadata ?? + fieldMetadata.toRelationMetadata, + relationType: computeRelationType( + fieldMetadata, + fieldMetadata.fromRelationMetadata ?? + (fieldMetadata.toRelationMetadata as RelationMetadataEntity), + ), + }, + ]), + ); + const newData: object = {}; + + for (const [key, value] of Object.entries(data)) { + const compositePropertyArgs = compositeFieldMetadataMap.get(key); + const { relationMetadata, relationType } = + relationMetadataMap.get(key) ?? {}; + + if (!compositePropertyArgs && !relationMetadata) { + if (isPlainObject(value)) { + newData[key] = formatResult(value, objectMetadata, objectMetadataMap); + } else { + newData[key] = value; + } + continue; + } + + if (relationMetadata) { + const toObjectMetadata = + objectMetadataMap[relationMetadata.toObjectMetadataId]; + + const fromObjectMetadata = + objectMetadataMap[relationMetadata.fromObjectMetadataId]; + + if (!toObjectMetadata) { + throw new Error( + `Object metadata for object metadataId "${relationMetadata.toObjectMetadataId}" is missing`, + ); + } + + if (!fromObjectMetadata) { + throw new Error( + `Object metadata for object metadataId "${relationMetadata.fromObjectMetadataId}" is missing`, + ); + } + + newData[key] = formatResult( + value, + relationType === 'one-to-many' ? toObjectMetadata : fromObjectMetadata, + objectMetadataMap, + ); + continue; + } + + if (!compositePropertyArgs) { + continue; + } + + const { parentField, ...compositeProperty } = compositePropertyArgs; + + if (!newData[parentField]) { + newData[parentField] = {}; + } + + newData[parentField][compositeProperty.name] = value; + } + + return newData as T; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/get-composite-field-metadata-collection.ts b/packages/twenty-server/src/engine/twenty-orm/utils/get-composite-field-metadata-collection.ts new file mode 100644 index 000000000000..88ac2820c1b1 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/utils/get-composite-field-metadata-collection.ts @@ -0,0 +1,12 @@ +import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; +import { ObjectMetadataMapItem } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; + +export function getCompositeFieldMetadataCollection( + objectMetadata: ObjectMetadataMapItem, +) { + const compositeFieldMetadataCollection = Object.values( + objectMetadata.fields, + ).filter((fieldMetadata) => isCompositeFieldMetadataType(fieldMetadata.type)); + + return compositeFieldMetadataCollection; +} diff --git a/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts b/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts index f5462b87fd8c..77a30372ae2f 100644 --- a/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts +++ b/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts @@ -23,6 +23,8 @@ export const getResolverName = ( return `update${pascalCase(objectMetadata.nameSingular)}`; case 'deleteOne': return `delete${pascalCase(objectMetadata.nameSingular)}`; + case 'destroyOne': + return `destroy${pascalCase(objectMetadata.nameSingular)}`; case 'updateMany': return `update${pascalCase(objectMetadata.namePlural)}`; case 'restoreMany': diff --git a/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts b/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts index 7bb281278a9b..3a938d4ce7ba 100644 --- a/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts @@ -2,7 +2,7 @@ import { HttpException } from '@nestjs/common'; import { GraphQLError } from 'graphql'; -import { ExceptionHandlerUser } from 'src/engine/integrations/exception-handler/interfaces/exception-handler-user.interface'; +import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; import { AuthenticationError, @@ -15,7 +15,7 @@ import { TimeoutError, ValidationError, } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; const graphQLPredefinedExceptions = { 400: ValidationError, diff --git a/packages/twenty-server/src/engine/utils/transform-enum-value.ts b/packages/twenty-server/src/engine/utils/transform-enum-value.ts new file mode 100644 index 000000000000..20eb24e49309 --- /dev/null +++ b/packages/twenty-server/src/engine/utils/transform-enum-value.ts @@ -0,0 +1,14 @@ +import { FieldMetadataDefaultOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input'; + +export function transformEnumValue(options?: FieldMetadataDefaultOption[]) { + return options?.map((option) => { + if (/^\d/.test(option.value)) { + return { + ...option, + value: `_${option.value}`, + }; + } + + return option; + }); +} diff --git a/packages/twenty-server/src/engine/workspace-cache-storage/workspace-cache-storage.service.ts b/packages/twenty-server/src/engine/workspace-cache-storage/workspace-cache-storage.service.ts index c15991fe681b..9d3da728566f 100644 --- a/packages/twenty-server/src/engine/workspace-cache-storage/workspace-cache-storage.service.ts +++ b/packages/twenty-server/src/engine/workspace-cache-storage/workspace-cache-storage.service.ts @@ -2,17 +2,18 @@ import { Injectable } from '@nestjs/common'; import { EntitySchemaOptions } from 'typeorm'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util'; -enum WorkspaceCacheKeys { +export enum WorkspaceCacheKeys { GraphQLTypeDefs = 'graphql:type-defs', GraphQLUsedScalarNames = 'graphql:used-scalar-names', GraphQLOperations = 'graphql:operations', ORMEntitySchemas = 'orm:entity-schemas', - MetadataObjectMetadataCollection = 'metadata:object-metadata-collection', + MetadataObjectMetadataMap = 'metadata:object-metadata-map', + MetadataObjectMetadataOngoingCachingLock = 'metadata:object-metadata-ongoing-caching-lock', MetadataVersion = 'metadata:workspace-metadata-version', } @@ -25,26 +26,31 @@ export class WorkspaceCacheStorageService { setORMEntitySchema( workspaceId: string, + metadataVersion: number, entitySchemas: EntitySchemaOptions<any>[], ) { return this.cacheStorageService.set<EntitySchemaOptions<any>[]>( - `${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`, + `${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}:${metadataVersion}`, entitySchemas, ); } getORMEntitySchema( workspaceId: string, + metadataVersion: number, ): Promise<EntitySchemaOptions<any>[] | undefined> { return this.cacheStorageService.get<EntitySchemaOptions<any>[]>( - `${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`, + `${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}:${metadataVersion}`, ); } - setMetadataVersion(workspaceId: string, version: number): Promise<void> { + setMetadataVersion( + workspaceId: string, + metadataVersion: number, + ): Promise<void> { return this.cacheStorageService.set<number>( `${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`, - version, + metadataVersion, ); } @@ -54,70 +60,113 @@ export class WorkspaceCacheStorageService { ); } - setObjectMetadataCollection( + addObjectMetadataCollectionOngoingCachingLock( + workspaceId: string, + metadataVersion: number, + ) { + return this.cacheStorageService.set<boolean>( + `${WorkspaceCacheKeys.MetadataObjectMetadataOngoingCachingLock}:${workspaceId}:${metadataVersion}`, + true, + ); + } + + removeObjectMetadataOngoingCachingLock( workspaceId: string, - objectMetadataCollection: ObjectMetadataEntity[], + metadataVersion: number, ) { - return this.cacheStorageService.set<ObjectMetadataEntity[]>( - `${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`, - objectMetadataCollection, + return this.cacheStorageService.del( + `${WorkspaceCacheKeys.MetadataObjectMetadataOngoingCachingLock}:${workspaceId}:${metadataVersion}`, + ); + } + + getObjectMetadataOngoingCachingLock( + workspaceId: string, + metadataVersion: number, + ): Promise<boolean | undefined> { + return this.cacheStorageService.get<boolean>( + `${WorkspaceCacheKeys.MetadataObjectMetadataOngoingCachingLock}:${workspaceId}:${metadataVersion}`, ); } - getObjectMetadataCollection( + setObjectMetadataMap( workspaceId: string, - ): Promise<ObjectMetadataEntity[] | undefined> { - return this.cacheStorageService.get<ObjectMetadataEntity[]>( - `${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`, + metadataVersion: number, + objectMetadataMap: ObjectMetadataMap, + ) { + return this.cacheStorageService.set<ObjectMetadataMap>( + `${WorkspaceCacheKeys.MetadataObjectMetadataMap}:${workspaceId}:${metadataVersion}`, + objectMetadataMap, ); } - setGraphQLTypeDefs(workspaceId: string, typeDefs: string): Promise<void> { + getObjectMetadataMap( + workspaceId: string, + metadataVersion: number, + ): Promise<ObjectMetadataMap | undefined> { + return this.cacheStorageService.get<ObjectMetadataMap>( + `${WorkspaceCacheKeys.MetadataObjectMetadataMap}:${workspaceId}:${metadataVersion}`, + ); + } + + setGraphQLTypeDefs( + workspaceId: string, + metadataVersion: number, + typeDefs: string, + ): Promise<void> { return this.cacheStorageService.set<string>( - `${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`, + `${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}:${metadataVersion}`, typeDefs, ); } - getGraphQLTypeDefs(workspaceId: string): Promise<string | undefined> { + getGraphQLTypeDefs( + workspaceId: string, + metadataVersion: number, + ): Promise<string | undefined> { return this.cacheStorageService.get<string>( - `${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`, + `${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}:${metadataVersion}`, ); } setGraphQLUsedScalarNames( workspaceId: string, + metadataVersion: number, usedScalarNames: string[], ): Promise<void> { return this.cacheStorageService.set<string[]>( - `${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`, + `${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}:${metadataVersion}`, usedScalarNames, ); } getGraphQLUsedScalarNames( workspaceId: string, + metadataVersion: number, ): Promise<string[] | undefined> { return this.cacheStorageService.get<string[]>( - `${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`, + `${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}:${metadataVersion}`, ); } - async flush(workspaceId: string): Promise<void> { + async flush(workspaceId: string, metadataVersion: number): Promise<void> { await this.cacheStorageService.del( - `${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`, + `${WorkspaceCacheKeys.MetadataObjectMetadataMap}:${workspaceId}:${metadataVersion}`, ); await this.cacheStorageService.del( - `${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`, + `${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}:${metadataVersion}`, ); await this.cacheStorageService.del( - `${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`, + `${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}:${metadataVersion}`, ); await this.cacheStorageService.del( - `${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`, + `${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}:${metadataVersion}`, ); await this.cacheStorageService.del( - `${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`, + `${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}:${metadataVersion}`, + ); + + await this.cacheStorageService.del( + `${WorkspaceCacheKeys.MetadataObjectMetadataOngoingCachingLock}:${workspaceId}:${metadataVersion}`, ); } } diff --git a/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/demo-objects-prefill-data.ts b/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/demo-objects-prefill-data.ts index 1b4b4ec8b908..226e5557c82b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/demo-objects-prefill-data.ts +++ b/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/demo-objects-prefill-data.ts @@ -1,16 +1,18 @@ import { DataSource, EntityManager } from 'typeorm'; +import { seedWorkspaceFavorites } from 'src/database/typeorm-seeds/workspace/favorites'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { workspaceMemberPrefillData } from 'src/engine/workspace-manager/demo-objects-prefill-data/workspace-member'; -import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view'; import { companyPrefillDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/company'; -import { personPrefillDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/person'; import { opportunityPrefillDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/opportunity'; +import { personPrefillDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/person'; +import { workspaceMemberPrefillData } from 'src/engine/workspace-manager/demo-objects-prefill-data/workspace-member'; +import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view'; export const demoObjectsPrefillData = async ( workspaceDataSource: DataSource, schemaName: string, objectMetadata: ObjectMetadataEntity[], + isWorkflowEnabled: boolean, ) => { const objectMetadataMap = objectMetadata.reduce((acc, object) => { acc[object.standardId ?? ''] = { @@ -31,8 +33,20 @@ export const demoObjectsPrefillData = async ( await personPrefillDemoData(entityManager, schemaName); await opportunityPrefillDemoData(entityManager, schemaName); - await viewPrefillData(entityManager, schemaName, objectMetadataMap); + const viewDefinitionsWithId = await viewPrefillData( + entityManager, + schemaName, + objectMetadataMap, + isWorkflowEnabled, + ); + await seedWorkspaceFavorites( + viewDefinitionsWithId + .filter((view) => view.key === 'INDEX') + .map((view) => view.id), + entityManager, + schemaName, + ); await workspaceMemberPrefillData(entityManager, schemaName); }, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/person.ts b/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/person.ts index e5edac40e94b..9eb733d990e3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/person.ts +++ b/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/person.ts @@ -14,7 +14,7 @@ export const personPrefillDemoData = async ( const people = peopleDemo.map((person, index) => ({ nameFirstName: person.firstName, nameLastName: person.lastName, - email: person.email, + emailsPrimaryEmail: person.email, linkedinLinkPrimaryLinkUrl: person.linkedinUrl, jobTitle: person.jobTitle, avatarUrl: person.avatarUrl, @@ -31,7 +31,7 @@ export const personPrefillDemoData = async ( .into(`${schemaName}.person`, [ 'nameFirstName', 'nameLastName', - 'email', + 'emailsPrimaryEmail', 'linkedinLinkPrimaryLinkUrl', 'jobTitle', 'avatarUrl', diff --git a/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/workspace-member.ts b/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/workspace-member.ts index b31f52e94732..3e6b5fb2a3d3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/workspace-member.ts +++ b/packages/twenty-server/src/engine/workspace-manager/demo-objects-prefill-data/workspace-member.ts @@ -5,7 +5,7 @@ import { DEMO_SEED_USER_IDS } from 'src/database/typeorm-seeds/core/demo/users'; export const DEMO_SEED_WORKSPACE_MEMBER_IDS = { NOAH: '20202020-0687-4c41-b707-ed1bfca972a2', HUGO: '20202020-77d5-4cb6-b60a-f4a835a85d62', - JULIA: '20202020-1553-45c6-a028-5a9064cce07e', + TIM: '20202020-1553-45c6-a028-5a9064cce07e', }; export const workspaceMemberPrefillData = async ( @@ -21,6 +21,7 @@ export const workspaceMemberPrefillData = async ( 'nameLastName', 'locale', 'colorScheme', + 'userEmail', 'userId', ]) .orIgnore() @@ -31,6 +32,7 @@ export const workspaceMemberPrefillData = async ( nameLastName: 'A', locale: 'en', colorScheme: 'Light', + userEmail: 'noah@demo.dev', userId: DEMO_SEED_USER_IDS.NOAH, }, { @@ -39,15 +41,17 @@ export const workspaceMemberPrefillData = async ( nameLastName: 'I', locale: 'en', colorScheme: 'Light', + userEmail: 'hugo@demo.dev', userId: DEMO_SEED_USER_IDS.HUGO, }, { - id: DEMO_SEED_WORKSPACE_MEMBER_IDS.JULIA, - nameFirstName: 'Julia', - nameLastName: 'S', + id: DEMO_SEED_WORKSPACE_MEMBER_IDS.TIM, + nameFirstName: 'Tim', + nameLastName: 'Apple', locale: 'en', colorScheme: 'Light', - userId: DEMO_SEED_USER_IDS.JULIA, + userEmail: 'tim@apple.dev', + userId: DEMO_SEED_USER_IDS.TIM, }, ]) .execute(); diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts index 8d5a24a1eef8..2f3966e1043e 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/company.ts @@ -1,5 +1,11 @@ import { EntityManager } from 'typeorm'; +export const AIRBNB_ID = 'c776ee49-f608-4a77-8cc8-6fe96ae1e43f'; +export const QONTO_ID = 'f45ee421-8a3e-4aa5-a1cf-7207cc6754e1'; +export const STRIPE_ID = '1f70157c-4ea5-4d81-bc49-e1401abfbb94'; +export const FIGMA_ID = '9d5bcf43-7d38-4e88-82cb-d6d4ce638bf0'; +export const NOTION_ID = '06290608-8bf0-4806-99ae-a715a6a93fad'; + export const companyPrefillData = async ( entityManager: EntityManager, schemaName: string, @@ -8,6 +14,7 @@ export const companyPrefillData = async ( .createQueryBuilder() .insert() .into(`${schemaName}.company`, [ + 'id', 'name', 'domainNamePrimaryLinkUrl', 'addressAddressStreet1', @@ -25,6 +32,7 @@ export const companyPrefillData = async ( .orIgnore() .values([ { + id: AIRBNB_ID, name: 'Airbnb', domainNamePrimaryLinkUrl: 'https://airbnb.com', addressAddressStreet1: '888 Brannan St', @@ -40,6 +48,7 @@ export const companyPrefillData = async ( createdByName: 'System', }, { + id: QONTO_ID, name: 'Qonto', domainNamePrimaryLinkUrl: 'https://qonto.com', addressAddressStreet1: '18 rue de navarrin', @@ -55,6 +64,7 @@ export const companyPrefillData = async ( createdByName: 'System', }, { + id: STRIPE_ID, name: 'Stripe', domainNamePrimaryLinkUrl: 'https://stripe.com', addressAddressStreet1: 'Eutaw Street', @@ -70,6 +80,7 @@ export const companyPrefillData = async ( createdByName: 'System', }, { + id: FIGMA_ID, name: 'Figma', domainNamePrimaryLinkUrl: 'https://figma.com', addressAddressStreet1: '760 Market St', @@ -85,6 +96,7 @@ export const companyPrefillData = async ( createdByName: 'System', }, { + id: NOTION_ID, name: 'Notion', domainNamePrimaryLinkUrl: 'https://notion.com', addressAddressStreet1: '2300 Harrison St', diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/person.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/person.ts index ae2be090b81b..ec07c61f15b2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/person.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/person.ts @@ -1,5 +1,13 @@ import { EntityManager } from 'typeorm'; +import { + AIRBNB_ID, + FIGMA_ID, + NOTION_ID, + QONTO_ID, + STRIPE_ID, +} from 'src/engine/workspace-manager/standard-objects-prefill-data/company'; + // FixMe: Is this file a duplicate of src/database/typeorm-seeds/workspace/people.ts export const personPrefillData = async ( entityManager: EntityManager, @@ -11,69 +19,93 @@ export const personPrefillData = async ( .into(`${schemaName}.person`, [ 'nameFirstName', 'nameLastName', - 'email', + 'city', + 'emailsPrimaryEmail', 'avatarUrl', 'position', 'createdBySource', 'createdByWorkspaceMemberId', 'createdByName', + 'phonesPrimaryPhoneNumber', + 'phonesPrimaryPhoneCountryCode', + 'companyId', ]) .orIgnore() .values([ { nameFirstName: 'Brian', nameLastName: 'Chesky', - email: 'chesky@airbnb.com', + city: 'San Francisco', + emailsPrimaryEmail: 'chesky@airbnb.com', avatarUrl: 'https://twentyhq.github.io/placeholder-images/people/image-3.png', position: 1, createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: 'System', + phonesPrimaryPhoneNumber: '1234567890', + phonesPrimaryPhoneCountryCode: '+1', + companyId: AIRBNB_ID, }, { nameFirstName: 'Alexandre', nameLastName: 'Prot', - email: 'prot@qonto.com', + city: 'Paris', + emailsPrimaryEmail: 'prot@qonto.com', avatarUrl: 'https://twentyhq.github.io/placeholder-images/people/image-89.png', position: 2, createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: 'System', + phonesPrimaryPhoneNumber: '677118822', + phonesPrimaryPhoneCountryCode: '+33', + companyId: QONTO_ID, }, { nameFirstName: 'Patrick', nameLastName: 'Collison', - email: 'collison@stripe.com', + city: 'San Francisco', + emailsPrimaryEmail: 'collison@stripe.com', avatarUrl: 'https://twentyhq.github.io/placeholder-images/people/image-47.png', position: 3, createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: 'System', + phonesPrimaryPhoneNumber: '987625341', + phonesPrimaryPhoneCountryCode: '+1', + companyId: STRIPE_ID, }, { nameFirstName: 'Dylan', nameLastName: 'Field', - email: 'field@figma.com', + city: 'San Francisco', + emailsPrimaryEmail: 'field@figma.com', avatarUrl: 'https://twentyhq.github.io/placeholder-images/people/image-40.png', position: 4, createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: 'System', + phonesPrimaryPhoneNumber: '09882261', + phonesPrimaryPhoneCountryCode: '+1', + companyId: FIGMA_ID, }, { nameFirstName: 'Ivan', nameLastName: 'Zhao', - email: 'zhao@notion.com', + city: 'San Francisco', + emailsPrimaryEmail: 'zhao@notion.com', avatarUrl: 'https://twentyhq.github.io/placeholder-images/people/image-68.png', position: 5, createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: 'System', + phonesPrimaryPhoneNumber: '88226173', + phonesPrimaryPhoneCountryCode: '+1', + companyId: NOTION_ID, }, ]) .returning('*') diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts index 19ab7a0554e6..7198fe4ef1e6 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts @@ -1,5 +1,6 @@ import { DataSource, EntityManager } from 'typeorm'; +import { seedWorkspaceFavorites } from 'src/database/typeorm-seeds/workspace/favorites'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { companyPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/company'; import { personPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/person'; @@ -9,6 +10,7 @@ export const standardObjectsPrefillData = async ( workspaceDataSource: DataSource, schemaName: string, objectMetadata: ObjectMetadataEntity[], + isWorkflowEnabled: boolean, ) => { const objectMetadataMap = objectMetadata.reduce((acc, object) => { if (!object.standardId) { @@ -34,6 +36,19 @@ export const standardObjectsPrefillData = async ( workspaceDataSource.transaction(async (entityManager: EntityManager) => { await companyPrefillData(entityManager, schemaName); await personPrefillData(entityManager, schemaName); - await viewPrefillData(entityManager, schemaName, objectMetadataMap); + const viewDefinitionsWithId = await viewPrefillData( + entityManager, + schemaName, + objectMetadataMap, + isWorkflowEnabled, + ); + + await seedWorkspaceFavorites( + viewDefinitionsWithId + .filter((view) => view.key === 'INDEX') + .map((view) => view.id), + entityManager, + schemaName, + ); }); }; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts index ca97ed67539c..7d7cc24000e2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts @@ -1,10 +1,7 @@ import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { activitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/activities-all.view'; import { companiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view'; import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view'; import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view'; @@ -26,19 +23,13 @@ export const viewPrefillData = async ( entityManager: EntityManager, schemaName: string, objectMetadataMap: Record<string, ObjectMetadataEntity>, - featureFlags?: FeatureFlagEntity[], + isWorkflowEnabled: boolean, ) => { - const isWorkflowEnabled = - featureFlags?.find( - (featureFlag) => featureFlag.key === FeatureFlagKey.IsWorkflowEnabled, - )?.value ?? false; - const viewDefinitions = [ await companiesAllView(objectMetadataMap), await peopleAllView(objectMetadataMap), await opportunitiesAllView(objectMetadataMap), await opportunitiesByStageView(objectMetadataMap), - await activitiesAllView(objectMetadataMap), await notesAllView(objectMetadataMap), await tasksAllView(objectMetadataMap), await tasksByStatusView(objectMetadataMap), @@ -144,4 +135,6 @@ export const viewPrefillData = async ( .execute(); } } + + return viewDefinitionsWithId; }; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/activities-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/activities-all.view.ts deleted file mode 100644 index 8988b760635c..000000000000 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/activities-all.view.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { - ACTIVITY_STANDARD_FIELD_IDS, - BASE_OBJECT_STANDARD_FIELD_IDS, -} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; - -export const activitiesAllView = async ( - objectMetadataMap: Record<string, ObjectMetadataEntity>, -) => { - return { - name: 'All', - objectMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.activity].id, - type: 'table', - key: 'INDEX', - position: 1, - icon: 'IconList', - kanbanFieldMetadataId: '', - filters: [], - fields: [ - { - fieldMetadataId: - objectMetadataMap[STANDARD_OBJECT_IDS.activity].fields[ - ACTIVITY_STANDARD_FIELD_IDS.title - ], - position: 0, - isVisible: true, - size: 210, - }, - { - fieldMetadataId: - objectMetadataMap[STANDARD_OBJECT_IDS.activity].fields[ - ACTIVITY_STANDARD_FIELD_IDS.type - ], - position: 0, - isVisible: true, - size: 150, - }, - { - fieldMetadataId: - objectMetadataMap[STANDARD_OBJECT_IDS.activity].fields[ - ACTIVITY_STANDARD_FIELD_IDS.body - ], - position: 0, - isVisible: true, - size: 150, - }, - { - fieldMetadataId: - objectMetadataMap[STANDARD_OBJECT_IDS.activity].fields[ - BASE_OBJECT_STANDARD_FIELD_IDS.createdAt - ], - position: 0, - isVisible: true, - size: 150, - }, - /* - TODO: Add later, since we don't have real-time it probably doesn't work well? - { - fieldMetadataId: - objectMetadataMap[STANDARD_OBJECT_IDS.activity].fields[ - BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt - ], - position: 0, - isVisible: true, - size: 210, - }, - */ - ], - }; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts index 764b93995b7c..97354aa1f2ff 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts @@ -12,7 +12,7 @@ export const notesAllView = async ( name: 'All Notes', objectMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.note].id, type: 'table', - key: null, + key: 'INDEX', position: 0, icon: 'IconNotes', kanbanFieldMetadataId: '', @@ -30,7 +30,7 @@ export const notesAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[ - NOTE_STANDARD_FIELD_IDS.body + NOTE_STANDARD_FIELD_IDS.noteTargets ], position: 1, isVisible: true, @@ -39,7 +39,7 @@ export const notesAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[ - NOTE_STANDARD_FIELD_IDS.createdBy + NOTE_STANDARD_FIELD_IDS.body ], position: 2, isVisible: true, @@ -48,12 +48,21 @@ export const notesAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[ - BASE_OBJECT_STANDARD_FIELD_IDS.createdAt + NOTE_STANDARD_FIELD_IDS.createdBy ], position: 3, isVisible: true, size: 150, }, + { + fieldMetadataId: + objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[ + BASE_OBJECT_STANDARD_FIELD_IDS.createdAt + ], + position: 4, + isVisible: true, + size: 150, + }, /* TODO: Add later, since we don't have real-time it probably doesn't work well? { diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts index 5b27233334e4..4c0607437ee2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts @@ -30,7 +30,7 @@ export const peopleAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.person].fields[ - PERSON_STANDARD_FIELD_IDS.email + PERSON_STANDARD_FIELD_IDS.emails ], position: 1, isVisible: true, @@ -57,7 +57,7 @@ export const peopleAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.person].fields[ - PERSON_STANDARD_FIELD_IDS.phone + PERSON_STANDARD_FIELD_IDS.phones ], position: 4, isVisible: true, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts index c623c07e9f7a..3d9a0ffadf71 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts @@ -12,7 +12,7 @@ export const tasksAllView = async ( name: 'All Tasks', objectMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.task].id, type: 'table', - key: null, + key: 'INDEX', position: 0, icon: 'IconCheckbox', kanbanFieldMetadataId: '', @@ -49,7 +49,7 @@ export const tasksAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[ - TASK_STANDARD_FIELD_IDS.createdBy + TASK_STANDARD_FIELD_IDS.taskTargets ], position: 3, isVisible: true, @@ -58,7 +58,7 @@ export const tasksAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[ - TASK_STANDARD_FIELD_IDS.dueAt + TASK_STANDARD_FIELD_IDS.createdBy ], position: 4, isVisible: true, @@ -67,7 +67,7 @@ export const tasksAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[ - TASK_STANDARD_FIELD_IDS.assignee + TASK_STANDARD_FIELD_IDS.dueAt ], position: 5, isVisible: true, @@ -76,7 +76,7 @@ export const tasksAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[ - TASK_STANDARD_FIELD_IDS.body + TASK_STANDARD_FIELD_IDS.assignee ], position: 6, isVisible: true, @@ -85,12 +85,21 @@ export const tasksAllView = async ( { fieldMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[ - BASE_OBJECT_STANDARD_FIELD_IDS.createdAt + TASK_STANDARD_FIELD_IDS.body ], position: 7, isVisible: true, size: 150, }, + { + fieldMetadataId: + objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[ + BASE_OBJECT_STANDARD_FIELD_IDS.createdAt + ], + position: 8, + isVisible: true, + size: 150, + }, /* TODO: Add later, since we don't have real-time it probably doesn't work well? { diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts index 280b512d3355..8eba4bdc4442 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts @@ -9,7 +9,7 @@ export const workflowsAllView = async ( name: 'All Workflows', objectMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.workflow].id, type: 'table', - key: null, + key: 'INDEX', position: 0, icon: 'IconSettingsAutomation', kanbanFieldMetadataId: '', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/clean-inactive-workspaces.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/clean-inactive-workspaces.command.ts index 79b805c607cf..744f37bfbce3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/clean-inactive-workspaces.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/clean-inactive-workspaces.command.ts @@ -1,8 +1,8 @@ import { Command, CommandRunner, Option } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job'; export type CleanInactiveWorkspacesCommandOptions = { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/start-clean-inactive-workspaces.cron.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/start-clean-inactive-workspaces.cron.command.ts index daee64136210..d93cbf6b3c9a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/start-clean-inactive-workspaces.cron.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/start-clean-inactive-workspaces.cron.command.ts @@ -1,8 +1,8 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { cleanInactiveWorkspaceCronPattern } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.cron.pattern'; import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/stop-clean-inactive-workspaces.cron.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/stop-clean-inactive-workspaces.cron.command.ts index 0fa47c6fb59c..fa0fd6668ce2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/stop-clean-inactive-workspaces.cron.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/stop-clean-inactive-workspaces.cron.command.ts @@ -1,8 +1,8 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { cleanInactiveWorkspaceCronPattern } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.cron.pattern'; import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts index ea492334a38e..0ebd5a207cc6 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts @@ -11,11 +11,11 @@ import { In, Repository } from 'typeorm'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EmailService } from 'src/engine/integrations/email/email.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-manager.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-manager.module.ts index 34023275cd59..82b4cc54f73b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-manager.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-manager.module.ts @@ -1,11 +1,11 @@ import { Module } from '@nestjs/common'; +import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { WorkspaceHealthModule } from 'src/engine/workspace-manager/workspace-health/workspace-health.module'; -import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module'; import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module'; import { WorkspaceManagerService } from './workspace-manager.service'; @@ -18,9 +18,9 @@ import { WorkspaceManagerService } from './workspace-manager.service'; DataSourceModule, WorkspaceSyncMetadataModule, WorkspaceHealthModule, - WorkspaceStatusModule, + FeatureFlagModule, ], exports: [WorkspaceManagerService], providers: [WorkspaceManagerService], }) -export class WorkspaceManagerModule {} \ No newline at end of file +export class WorkspaceManagerModule {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts index 000b37d372f9..5532ef5ed193 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-manager.service.ts @@ -1,5 +1,7 @@ import { Injectable } from '@nestjs/common'; +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; @@ -17,6 +19,7 @@ export class WorkspaceManagerService { private readonly objectMetadataService: ObjectMetadataService, private readonly dataSourceService: DataSourceService, private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService, + private readonly featureFlagService: FeatureFlagService, ) {} /** @@ -117,10 +120,16 @@ export class WorkspaceManagerService { const createdObjectMetadata = await this.objectMetadataService.findManyWithinWorkspace(workspaceId); + const isWorkflowEnabled = await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IsWorkflowEnabled, + workspaceId, + ); + await standardObjectsPrefillData( workspaceDataSource, dataSourceMetadata.schema, createdObjectMetadata, + isWorkflowEnabled, ); } @@ -147,10 +156,16 @@ export class WorkspaceManagerService { const createdObjectMetadata = await this.objectMetadataService.findManyWithinWorkspace(workspaceId); + const isWorkflowEnabled = await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IsWorkflowEnabled, + workspaceId, + ); + await demoObjectsPrefillData( workspaceDataSource, dataSourceMetadata.schema, createdObjectMetadata, + isWorkflowEnabled, ); } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-status/services/workspace-status.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-status/services/workspace-status.service.ts deleted file mode 100644 index 28b4d035ae03..000000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-status/services/workspace-status.service.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Any, Repository } from 'typeorm'; - -import { - BillingSubscription, - SubscriptionStatus, -} from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; - -@Injectable() -export class WorkspaceStatusService { - constructor( - private readonly environmentService: EnvironmentService, - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository<Workspace>, - @InjectRepository(BillingSubscription, 'core') - private readonly billingSubscriptionRepository: Repository<BillingSubscription>, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository<FeatureFlagEntity>, - ) {} - - async getActiveWorkspaceIds(): Promise<string[]> { - const workspaces = await this.workspaceRepository.find(); - const workspaceIds = workspaces.map((workspace) => workspace.id); - - if (!this.environmentService.get('IS_BILLING_ENABLED')) { - return workspaceIds; - } - - const billingSubscriptionForWorkspaces = - await this.billingSubscriptionRepository.find({ - where: { - workspaceId: Any(workspaceIds), - status: Any([ - SubscriptionStatus.PastDue, - SubscriptionStatus.Active, - SubscriptionStatus.Trialing, - ]), - }, - }); - - const workspaceIdsWithActiveSubscription = - billingSubscriptionForWorkspaces.map( - (billingSubscription) => billingSubscription.workspaceId, - ); - - const freeAccessEnabledFeatureFlagForWorkspace = - await this.featureFlagRepository.find({ - where: { - workspaceId: Any(workspaceIds), - key: FeatureFlagKey.IsFreeAccessEnabled, - value: true, - }, - }); - - const workspaceIdsWithFreeAccessEnabled = - freeAccessEnabledFeatureFlagForWorkspace.map( - (featureFlag) => featureFlag.workspaceId, - ); - - return workspaceIds.filter( - (workspaceId) => - workspaceIdsWithActiveSubscription.includes(workspaceId) || - workspaceIdsWithFreeAccessEnabled.includes(workspaceId), - ); - } -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-status/workspace-manager.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-status/workspace-manager.module.ts deleted file mode 100644 index ac39a9e0c322..000000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-status/workspace-manager.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; -import { WorkspaceStatusService } from 'src/engine/workspace-manager/workspace-status/services/workspace-status.service'; - -@Module({ - imports: [ - EnvironmentModule, - TypeOrmModule.forFeature( - [Workspace, BillingSubscription, FeatureFlagEntity], - 'core', - ), - ], - exports: [WorkspaceStatusService], - providers: [WorkspaceStatusService], -}) -export class WorkspaceStatusModule {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command.ts index 2c7eb944a278..20bf710eecbf 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command.ts @@ -1,11 +1,12 @@ -import { Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; -import isEmpty from 'lodash.isempty'; -import { Command, CommandRunner, Option } from 'nest-commander'; +import { Command, Option } from 'nest-commander'; +import { Repository } from 'typeorm'; +import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { WorkspaceHealthService } from 'src/engine/workspace-manager/workspace-health/workspace-health.service'; -import { WorkspaceStatusService } from 'src/engine/workspace-manager/workspace-status/services/workspace-status.service'; import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service'; import { SyncWorkspaceLoggerService } from './services/sync-workspace-logger.service'; @@ -21,35 +22,24 @@ interface RunWorkspaceMigrationsOptions { name: 'workspace:sync-metadata', description: 'Sync metadata', }) -export class SyncWorkspaceMetadataCommand extends CommandRunner { - private readonly logger = new Logger(SyncWorkspaceMetadataCommand.name); - +export class SyncWorkspaceMetadataCommand extends ActiveWorkspacesCommandRunner { constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository<Workspace>, private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService, private readonly workspaceHealthService: WorkspaceHealthService, private readonly dataSourceService: DataSourceService, private readonly syncWorkspaceLoggerService: SyncWorkspaceLoggerService, - private readonly workspaceStatusService: WorkspaceStatusService, ) { - super(); + super(workspaceRepository); } - async run( + async executeActiveWorkspacesCommand( _passedParam: string[], options: RunWorkspaceMigrationsOptions, + workspaceIds: string[], ): Promise<void> { - // TODO: re-implement load index from workspaceService, this is breaking the logger - let workspaceIds = options.workspaceId ? [options.workspaceId] : []; - - if (isEmpty(workspaceIds)) { - const activeWorkspaceIds = - await this.workspaceStatusService.getActiveWorkspaceIds(); - - workspaceIds = activeWorkspaceIds; - this.logger.log( - `Attempting to sync ${activeWorkspaceIds.length} workspaces.`, - ); - } + this.logger.log(`Attempting to sync ${workspaceIds.length} workspaces.`); let count = 1; @@ -138,15 +128,6 @@ export class SyncWorkspaceMetadataCommand extends CommandRunner { ); } - @Option({ - flags: '-w, --workspace-id [workspace_id]', - description: 'workspace id', - required: false, - }) - parseWorkspaceId(value: string): string { - return value; - } - @Option({ flags: '-d, --dry-run', description: 'Dry run without applying changes', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module.ts index 8d9dda506804..6ae43c404146 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module.ts @@ -6,7 +6,6 @@ import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.mod import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { WorkspaceHealthModule } from 'src/engine/workspace-manager/workspace-health/workspace-health.module'; -import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module'; import { ConvertRecordPositionsToIntegers } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/convert-record-positions-to-integers.command'; import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module'; @@ -22,7 +21,6 @@ import { SyncWorkspaceLoggerService } from './services/sync-workspace-logger.ser DataSourceModule, WorkspaceDataSourceModule, TypeOrmModule.forFeature([Workspace], 'core'), - WorkspaceStatusModule, ], providers: [ SyncWorkspaceMetadataCommand, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts index cec8dad8fe9e..da833cd88f1b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts @@ -207,6 +207,7 @@ export const FAVORITE_STANDARD_FIELD_IDS = { workflow: '20202020-b11b-4dc8-999a-6bd0a947b463', task: '20202020-1b1b-4b3b-8b1b-7f8d6a1d7d5c', note: '20202020-1f25-43fe-8b00-af212fdde824', + view: '20202020-5a93-4fa9-acce-e73481a0bbdf', custom: '20202020-855a-4bc8-9861-79deef37011f', }; @@ -308,11 +309,13 @@ export const OPPORTUNITY_STANDARD_FIELD_IDS = { export const PERSON_STANDARD_FIELD_IDS = { name: '20202020-3875-44d5-8c33-a6239011cab8', email: '20202020-a740-42bb-8849-8980fb3f12e1', + emails: '20202020-3c51-43fa-8b6e-af39e29368ab', linkedinLink: '20202020-f1af-48f7-893b-2007a73dd508', xLink: '20202020-8fc2-487c-b84a-55a99b145cfd', jobTitle: '20202020-b0d0-415a-bef9-640a26dacd9b', phone: '20202020-4564-4b8b-a09f-05445f2e0bce', - // city: '20202020-5243-4ffb-afc5-2c675da41346', + phones: '20202020-0638-448e-8825-439134618022', + city: '20202020-5243-4ffb-afc5-2c675da41346', avatarUrl: '20202020-b8a6-40df-961c-373dc5d2ec21', position: '20202020-fcd5-4231-aff5-fff583eaa0b1', createdBy: '20202020-f6ab-4d98-af24-a3d5b664148a', @@ -387,6 +390,7 @@ export const VIEW_STANDARD_FIELD_IDS = { viewFields: '20202020-542b-4bdc-b177-b63175d48edf', viewFilters: '20202020-ff23-4154-b63c-21fb36cd0967', viewSorts: '20202020-891b-45c3-9fe1-80a75b4aa043', + favorites: '20202020-c818-4a86-8284-9ec0ef0a59a5', }; export const WEBHOOK_STANDARD_FIELD_IDS = { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index 9012a590033d..9cbe04fd173f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -150,14 +150,6 @@ export class StandardFieldFactory { return []; } - if ( - workspaceFieldMetadataArgs.name === 'deletedAt' && - workspaceEntityMetadataArgs && - !workspaceEntityMetadataArgs.softDelete - ) { - return []; - } - return [ { type: workspaceFieldMetadataArgs.type, @@ -168,6 +160,7 @@ export class StandardFieldFactory { description: workspaceFieldMetadataArgs.description, defaultValue: workspaceFieldMetadataArgs.defaultValue, options: workspaceFieldMetadataArgs.options, + settings: workspaceFieldMetadataArgs.settings, workspaceId: context.workspaceId, isNullable: workspaceFieldMetadataArgs.isNullable, isCustom: workspaceFieldMetadataArgs.isDeprecated ? true : false, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts index da2c8318b8fa..c3156881dc64 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; -import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; -import { PartialWorkspaceEntity } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface'; import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface'; +import { PartialWorkspaceEntity } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface'; +import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; -import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; +import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util'; @Injectable() export class StandardObjectFactory { @@ -54,7 +54,6 @@ export class StandardObjectFactory { isCustom: false, isRemote: false, isSystem: workspaceEntityMetadataArgs.isSystem ?? false, - isSoftDeletable: workspaceEntityMetadataArgs.softDelete ?? false, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service.ts index bd85f4c20944..6e035b99c07f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service.ts @@ -6,7 +6,7 @@ import { DataSource, QueryFailedError } from 'typeorm'; import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service'; diff --git a/packages/twenty-server/src/funnelmink/entities/funnelmink-crew.workspace-entity.ts b/packages/twenty-server/src/funnelmink/entities/funnelmink-crew.workspace-entity.ts index 7bb0e6336f1f..7dbb0327a8a2 100644 --- a/packages/twenty-server/src/funnelmink/entities/funnelmink-crew.workspace-entity.ts +++ b/packages/twenty-server/src/funnelmink/entities/funnelmink-crew.workspace-entity.ts @@ -37,7 +37,6 @@ import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace- description: 'A Crew', icon: FUNNELMINK_ICONS.crew, labelIdentifierStandardId: FUNNELMINK_IDS.crewName, - softDelete: true, }) export class CrewWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ diff --git a/packages/twenty-server/src/funnelmink/entities/funnelmink-job.workspace-entity.ts b/packages/twenty-server/src/funnelmink/entities/funnelmink-job.workspace-entity.ts index 3b0fff4da89d..885183d48ede 100644 --- a/packages/twenty-server/src/funnelmink/entities/funnelmink-job.workspace-entity.ts +++ b/packages/twenty-server/src/funnelmink/entities/funnelmink-job.workspace-entity.ts @@ -39,7 +39,6 @@ import { CrewWorkspaceEntity } from './funnelmink-crew.workspace-entity'; description: 'A Job', icon: FUNNELMINK_ICONS.job, labelIdentifierStandardId: FUNNELMINK_IDS.jobName, - softDelete: true, }) export class JobWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ diff --git a/packages/twenty-server/src/funnelmink/entities/funnelmink-material.workspace-entity.ts b/packages/twenty-server/src/funnelmink/entities/funnelmink-material.workspace-entity.ts index 6b3599170564..469bbab73313 100644 --- a/packages/twenty-server/src/funnelmink/entities/funnelmink-material.workspace-entity.ts +++ b/packages/twenty-server/src/funnelmink/entities/funnelmink-material.workspace-entity.ts @@ -35,7 +35,6 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o description: 'A Material', icon: FUNNELMINK_ICONS.material, labelIdentifierStandardId: FUNNELMINK_IDS.materialName, - softDelete: true, }) export class MaterialWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ diff --git a/packages/twenty-server/src/funnelmink/entities/funnelmink-service.workspace-entity.ts b/packages/twenty-server/src/funnelmink/entities/funnelmink-service.workspace-entity.ts index b4a4a260570e..de3a2236b6f7 100644 --- a/packages/twenty-server/src/funnelmink/entities/funnelmink-service.workspace-entity.ts +++ b/packages/twenty-server/src/funnelmink/entities/funnelmink-service.workspace-entity.ts @@ -35,7 +35,6 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o description: 'A Service', icon: FUNNELMINK_ICONS.service, labelIdentifierStandardId: FUNNELMINK_IDS.serviceName, - softDelete: true, }) export class ServiceWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ diff --git a/packages/twenty-server/src/funnelmink/entities/funnelmink-workorder.workspace-entity.ts b/packages/twenty-server/src/funnelmink/entities/funnelmink-workorder.workspace-entity.ts index e2839120232c..1698e5beabc7 100644 --- a/packages/twenty-server/src/funnelmink/entities/funnelmink-workorder.workspace-entity.ts +++ b/packages/twenty-server/src/funnelmink/entities/funnelmink-workorder.workspace-entity.ts @@ -39,7 +39,6 @@ import { JobWorkspaceEntity } from 'src/funnelmink/entities/funnelmink-job.works description: 'A Work Order', icon: FUNNELMINK_ICONS.workOrder, labelIdentifierStandardId: FUNNELMINK_IDS.workOrderName, - softDelete: true, }) export class WorkOrderWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ diff --git a/packages/twenty-server/src/instrument.ts b/packages/twenty-server/src/instrument.ts new file mode 100644 index 000000000000..2fdbe0263e56 --- /dev/null +++ b/packages/twenty-server/src/instrument.ts @@ -0,0 +1,29 @@ +import * as Sentry from '@sentry/nestjs'; +import { nodeProfilingIntegration } from '@sentry/profiling-node'; + +import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; +import { WorkspaceCacheKeys } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; + +if (process.env.EXCEPTION_HANDLER_DRIVER === ExceptionHandlerDriver.Sentry) { + Sentry.init({ + environment: process.env.SENTRY_ENVIRONMENT, + release: process.env.SENTRY_RELEASE, + dsn: process.env.SENTRY_DSN, + integrations: [ + // TODO: Redis integration doesn't seem to work - investigate why + Sentry.redisIntegration({ + cachePrefixes: Object.values(WorkspaceCacheKeys).map( + (key) => `engine:${key}:`, + ), + }), + Sentry.httpIntegration(), + Sentry.expressIntegration(), + Sentry.graphqlIntegration(), + Sentry.postgresIntegration(), + nodeProfilingIntegration(), + ], + tracesSampleRate: 0.1, + profilesSampleRate: 0.3, + debug: process.env.DEBUG_MODE === 'true', + }); +} diff --git a/packages/twenty-server/src/main.ts b/packages/twenty-server/src/main.ts index 47df9c69a4ff..b00532747154 100644 --- a/packages/twenty-server/src/main.ts +++ b/packages/twenty-server/src/main.ts @@ -2,18 +2,17 @@ import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; -import * as Sentry from '@sentry/node'; -import '@sentry/tracing'; import bytes from 'bytes'; import { useContainer } from 'class-validator'; import { graphqlUploadExpress } from 'graphql-upload'; +import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; import { ApplyCorsToExceptions } from 'src/utils/apply-cors-to-exceptions'; import { AppModule } from './app.module'; +import './instrument'; import { settings } from './engine/constants/settings'; -import { LoggerService } from './engine/integrations/logger/logger.service'; import { generateFrontConfig } from './utils/generate-front-config'; const bootstrap = async () => { @@ -35,11 +34,6 @@ const bootstrap = async () => { // Use our logger app.useLogger(logger); - if (Sentry.isInitialized()) { - app.use(Sentry.Handlers.requestHandler()); - app.use(Sentry.Handlers.tracingHandler()); - } - app.useGlobalFilters(new ApplyCorsToExceptions()); // Apply validation pipes globally diff --git a/packages/twenty-server/src/modules/blocklist/utils/__tests__/is-email-blocklisted.util.spec.ts b/packages/twenty-server/src/modules/blocklist/utils/__tests__/is-email-blocklisted.util.spec.ts index 4f33e4d3744b..9f8c35ee71e9 100644 --- a/packages/twenty-server/src/modules/blocklist/utils/__tests__/is-email-blocklisted.util.spec.ts +++ b/packages/twenty-server/src/modules/blocklist/utils/__tests__/is-email-blocklisted.util.spec.ts @@ -2,67 +2,67 @@ import { isEmailBlocklisted } from 'src/modules/blocklist/utils/is-email-blockli describe('isEmailBlocklisted', () => { it('should return true if email is blocklisted', () => { - const channelHandle = 'abc@example.com'; + const channelHandles = ['abc@example.com']; const email = 'hello@twenty.com'; const blocklist = ['hello@twenty.com', 'hey@twenty.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(true); }); it('should return false if email is not blocklisted', () => { - const channelHandle = 'abc@example.com'; + const channelHandles = ['abc@example.com']; const email = 'hello@twenty.com'; const blocklist = ['hey@example.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(false); }); it('should return false if email is null', () => { - const channelHandle = 'abc@twenty.com'; + const channelHandles = ['abc@twenty.com']; const email = null; const blocklist = ['@example.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(false); }); it('should return true for subdomains', () => { - const channelHandle = 'abc@example.com'; + const channelHandles = ['abc@example.com']; const email = 'hello@twenty.twenty.com'; const blocklist = ['@twenty.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(true); }); it('should return false for domains which end with blocklisted domain but are not subdomains', () => { - const channelHandle = 'abc@example.com'; + const channelHandles = ['abc@example.com']; const email = 'hello@twentytwenty.com'; const blocklist = ['@twenty.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(false); }); it('should return false if email is undefined', () => { - const channelHandle = 'abc@example.com'; + const channelHandles = ['abc@example.com']; const email = undefined; const blocklist = ['@twenty.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(false); }); it('should return true if email ends with blocklisted domain', () => { - const channelHandle = 'abc@example.com'; + const channelHandles = ['abc@example.com']; const email = 'hello@twenty.com'; const blocklist = ['@twenty.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(true); }); it('should return false if email is same as channel handle', () => { - const channelHandle = 'hello@twenty.com'; + const channelHandles = ['hello@twenty.com']; const email = 'hello@twenty.com'; const blocklist = ['@twenty.com']; - const result = isEmailBlocklisted(channelHandle, email, blocklist); + const result = isEmailBlocklisted(channelHandles, email, blocklist); expect(result).toBe(false); }); diff --git a/packages/twenty-server/src/modules/blocklist/utils/is-email-blocklisted.util.ts b/packages/twenty-server/src/modules/blocklist/utils/is-email-blocklisted.util.ts index 1ba64ee19fc6..642df70acdf0 100644 --- a/packages/twenty-server/src/modules/blocklist/utils/is-email-blocklisted.util.ts +++ b/packages/twenty-server/src/modules/blocklist/utils/is-email-blocklisted.util.ts @@ -1,11 +1,9 @@ -// TODO: Move inside blocklist module - export const isEmailBlocklisted = ( - channelHandle: string, + channelHandle: string[], email: string | null | undefined, blocklist: string[], ): boolean => { - if (!email || email === channelHandle) { + if (!email || channelHandle.includes(email)) { return false; } diff --git a/packages/twenty-server/src/modules/calendar/blocklist-manager/calendar-blocklist-manager.module.ts b/packages/twenty-server/src/modules/calendar/blocklist-manager/calendar-blocklist-manager.module.ts index 57497f1d279e..8f1224d5a5a2 100644 --- a/packages/twenty-server/src/modules/calendar/blocklist-manager/calendar-blocklist-manager.module.ts +++ b/packages/twenty-server/src/modules/calendar/blocklist-manager/calendar-blocklist-manager.module.ts @@ -4,10 +4,10 @@ import { BlocklistItemDeleteCalendarEventsJob } from 'src/modules/calendar/block import { BlocklistReimportCalendarEventsJob } from 'src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job'; import { CalendarBlocklistListener } from 'src/modules/calendar/blocklist-manager/listeners/calendar-blocklist.listener'; import { CalendarEventCleanerModule } from 'src/modules/calendar/calendar-event-cleaner/calendar-event-cleaner.module'; -import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module'; +import { CalendarCommonModule } from 'src/modules/calendar/common/calendar-common.module'; @Module({ - imports: [CalendarEventCleanerModule, CalendarEventImportManagerModule], + imports: [CalendarEventCleanerModule, CalendarCommonModule], providers: [ CalendarBlocklistListener, BlocklistItemDeleteCalendarEventsJob, diff --git a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts index 9f9777328aec..f21e87d76b8b 100644 --- a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts +++ b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts @@ -1,20 +1,21 @@ import { Logger, Scope } from '@nestjs/common'; -import { Any, ILike } from 'typeorm'; +import { And, Any, ILike, In, Not, Or } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { CalendarEventCleanerService } from 'src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service'; +import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; +import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -export type BlocklistItemDeleteCalendarEventsJobData = { - workspaceId: string; - blocklistItemId: string; -}; +export type BlocklistItemDeleteCalendarEventsJobData = WorkspaceEventBatch< + ObjectRecordCreateEvent<BlocklistWorkspaceEntity> +>; @Processor({ queueName: MessageQueue.calendarQueue, @@ -27,77 +28,133 @@ export class BlocklistItemDeleteCalendarEventsJob { constructor( private readonly twentyORMManager: TwentyORMManager, - @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) - private readonly blocklistRepository: BlocklistRepository, private readonly calendarEventCleanerService: CalendarEventCleanerService, ) {} @Process(BlocklistItemDeleteCalendarEventsJob.name) async handle(data: BlocklistItemDeleteCalendarEventsJobData): Promise<void> { - const { workspaceId, blocklistItemId } = data; + const workspaceId = data.workspaceId; - const blocklistItem = await this.blocklistRepository.getById( - blocklistItemId, - workspaceId, + const blocklistItemIds = data.events.map( + (eventPayload) => eventPayload.recordId, ); - if (!blocklistItem) { - this.logger.log( - `Blocklist item with id ${blocklistItemId} not found in workspace ${workspaceId}`, + const blocklistRepository = + await this.twentyORMManager.getRepository<BlocklistWorkspaceEntity>( + 'blocklist', ); - return; - } - - const { handle, workspaceMemberId } = blocklistItem; + const blocklist = await blocklistRepository.find({ + where: { + id: Any(blocklistItemIds), + }, + }); - this.logger.log( - `Deleting calendar events from ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, - ); + const handlesToDeleteByWorkspaceMemberIdMap = blocklist.reduce( + (acc, blocklistItem) => { + const { handle, workspaceMemberId } = blocklistItem; - if (!workspaceMemberId) { - throw new Error( - `Workspace member ID is undefined for blocklist item ${blocklistItemId} in workspace ${workspaceId}`, - ); - } + if (!acc.has(workspaceMemberId)) { + acc.set(workspaceMemberId, []); + } - const calendarChannelRepository = - await this.twentyORMManager.getRepository('calendarChannel'); + acc.get(workspaceMemberId)?.push(handle); - const calendarChannels = await calendarChannelRepository.find({ - where: { - connectedAccount: { - accountOwnerId: workspaceMemberId, - }, + return acc; }, - }); - - const calendarChannelIds = calendarChannels.map(({ id }) => id); + new Map<string, string[]>(), + ); - const isHandleDomain = handle.startsWith('@'); + const calendarChannelRepository = + await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( + 'calendarChannel', + ); const calendarChannelEventAssociationRepository = - await this.twentyORMManager.getRepository( + await this.twentyORMManager.getRepository<CalendarChannelEventAssociationWorkspaceEntity>( 'calendarChannelEventAssociation', ); - await calendarChannelEventAssociationRepository.delete({ - calendarEvent: { - calendarEventParticipants: { - handle: isHandleDomain ? ILike(`%${handle}`) : handle, + for (const workspaceMemberId of handlesToDeleteByWorkspaceMemberIdMap.keys()) { + const handles = + handlesToDeleteByWorkspaceMemberIdMap.get(workspaceMemberId); + + if (!handles) { + continue; + } + + this.logger.log( + `Deleting calendar events from ${handles.join( + ', ', + )} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, + ); + + const calendarChannels = await calendarChannelRepository.find({ + select: { + id: true, + handle: true, + connectedAccount: { + handleAliases: true, + }, }, - calendarChannelEventAssociations: { - calendarChannelId: Any(calendarChannelIds), + where: { + connectedAccount: { + accountOwnerId: workspaceMemberId, + }, }, - }, - }); + relations: ['connectedAccount'], + }); + + for (const calendarChannel of calendarChannels) { + const calendarChannelHandles = [calendarChannel.handle]; + + if (calendarChannel.connectedAccount.handleAliases) { + calendarChannelHandles.push( + ...calendarChannel.connectedAccount.handleAliases.split(','), + ); + } + + const handleConditions = handles.map((handle) => { + const isHandleDomain = handle.startsWith('@'); + + return isHandleDomain + ? { + handle: And( + Or(ILike(`%${handle}`), ILike(`%.${handle.slice(1)}`)), + Not(In(calendarChannelHandles)), + ), + } + : { handle }; + }); + + const calendarEventsAssociationsToDelete = + await calendarChannelEventAssociationRepository.find({ + where: { + calendarChannelId: calendarChannel.id, + calendarEvent: { + calendarEventParticipants: handleConditions, + }, + }, + }); + + if (calendarEventsAssociationsToDelete.length === 0) { + continue; + } + + await calendarChannelEventAssociationRepository.delete( + calendarEventsAssociationsToDelete.map(({ id }) => id), + ); + } + + this.logger.log( + `Deleted calendar events from handle ${handles.join( + ', ', + )} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, + ); + } await this.calendarEventCleanerService.cleanWorkspaceCalendarEvents( workspaceId, ); - - this.logger.log( - `Deleted calendar events from handle ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, - ); } } diff --git a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts index a9501ad2f21f..434a6aa5332b 100644 --- a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts +++ b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts @@ -1,23 +1,23 @@ import { Scope } from '@nestjs/common'; -import { Any } from 'typeorm'; +import { Not } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; +import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; +import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; import { CalendarChannelSyncStage, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -export type BlocklistReimportCalendarEventsJobData = { - workspaceId: string; - workspaceMemberId: string; -}; +export type BlocklistReimportCalendarEventsJobData = WorkspaceEventBatch< + ObjectRecordDeleteEvent<BlocklistWorkspaceEntity> +>; @Processor({ queueName: MessageQueue.calendarQueue, @@ -26,39 +26,38 @@ export type BlocklistReimportCalendarEventsJobData = { export class BlocklistReimportCalendarEventsJob { constructor( private readonly twentyORMManager: TwentyORMManager, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, + private readonly calendarChannelSyncStatusService: CalendarChannelSyncStatusService, ) {} @Process(BlocklistReimportCalendarEventsJob.name) async handle(data: BlocklistReimportCalendarEventsJobData): Promise<void> { - const { workspaceId, workspaceMemberId } = data; - - const connectedAccounts = - await this.connectedAccountRepository.getAllByWorkspaceMemberId( - workspaceMemberId, - workspaceId, - ); - - if (!connectedAccounts || connectedAccounts.length === 0) { - return; - } + const workspaceId = data.workspaceId; const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update( - { - connectedAccountId: Any( - connectedAccounts.map((connectedAccount) => connectedAccount.id), - ), - }, - { - syncStage: - CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING, - }, - ); + for (const eventPayload of data.events) { + const workspaceMemberId = + eventPayload.properties.before.workspaceMemberId; + + const calendarChannels = await calendarChannelRepository.find({ + select: ['id'], + where: { + connectedAccount: { + accountOwnerId: workspaceMemberId, + }, + syncStage: Not( + CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING, + ), + }, + }); + + await this.calendarChannelSyncStatusService.resetAndScheduleFullCalendarEventListFetch( + calendarChannels.map((calendarChannel) => calendarChannel.id), + workspaceId, + ); + } } } diff --git a/packages/twenty-server/src/modules/calendar/blocklist-manager/listeners/calendar-blocklist.listener.ts b/packages/twenty-server/src/modules/calendar/blocklist-manager/listeners/calendar-blocklist.listener.ts index 7a2b7e0e8389..886321725912 100644 --- a/packages/twenty-server/src/modules/calendar/blocklist-manager/listeners/calendar-blocklist.listener.ts +++ b/packages/twenty-server/src/modules/calendar/blocklist-manager/listeners/calendar-blocklist.listener.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { @@ -31,16 +31,9 @@ export class CalendarBlocklistListener { ObjectRecordCreateEvent<BlocklistWorkspaceEntity> >, ) { - await Promise.all( - payload.events.map((eventPayload) => - this.messageQueueService.add<BlocklistItemDeleteCalendarEventsJobData>( - BlocklistItemDeleteCalendarEventsJob.name, - { - workspaceId: payload.workspaceId, - blocklistItemId: eventPayload.recordId, - }, - ), - ), + await this.messageQueueService.add<BlocklistItemDeleteCalendarEventsJobData>( + BlocklistItemDeleteCalendarEventsJob.name, + payload, ); } @@ -50,17 +43,9 @@ export class CalendarBlocklistListener { ObjectRecordDeleteEvent<BlocklistWorkspaceEntity> >, ) { - await Promise.all( - payload.events.map((eventPayload) => - this.messageQueueService.add<BlocklistReimportCalendarEventsJobData>( - BlocklistReimportCalendarEventsJob.name, - { - workspaceId: payload.workspaceId, - workspaceMemberId: - eventPayload.properties.before.workspaceMember.id, - }, - ), - ), + await this.messageQueueService.add<BlocklistReimportCalendarEventsJobData>( + BlocklistReimportCalendarEventsJob.name, + payload, ); } @@ -70,31 +55,14 @@ export class CalendarBlocklistListener { ObjectRecordUpdateEvent<BlocklistWorkspaceEntity> >, ) { - await Promise.all( - payload.events.reduce((acc: Promise<void>[], eventPayload) => { - acc.push( - this.messageQueueService.add<BlocklistItemDeleteCalendarEventsJobData>( - BlocklistItemDeleteCalendarEventsJob.name, - { - workspaceId: payload.workspaceId, - blocklistItemId: eventPayload.recordId, - }, - ), - ); - - acc.push( - this.messageQueueService.add<BlocklistReimportCalendarEventsJobData>( - BlocklistReimportCalendarEventsJob.name, - { - workspaceId: payload.workspaceId, - workspaceMemberId: - eventPayload.properties.after.workspaceMember.id, - }, - ), - ); + await this.messageQueueService.add<BlocklistItemDeleteCalendarEventsJobData>( + BlocklistItemDeleteCalendarEventsJob.name, + payload, + ); - return acc; - }, []), + await this.messageQueueService.add<BlocklistReimportCalendarEventsJobData>( + BlocklistReimportCalendarEventsJob.name, + payload, ); } } diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/jobs/delete-connected-account-associated-calendar-data.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/jobs/delete-connected-account-associated-calendar-data.job.ts index 481814595542..cd8409ea8fe9 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/jobs/delete-connected-account-associated-calendar-data.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/jobs/delete-connected-account-associated-calendar-data.job.ts @@ -1,8 +1,8 @@ import { Logger } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { CalendarEventCleanerService } from 'src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service'; export type DeleteConnectedAccountAssociatedCalendarDataJobData = { diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/listeners/calendar-event-cleaner-connected-account.listener.ts b/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/listeners/calendar-event-cleaner-connected-account.listener.ts index 0c14b6b60655..1406d442d02c 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/listeners/calendar-event-cleaner-connected-account.listener.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/listeners/calendar-event-cleaner-connected-account.listener.ts @@ -1,10 +1,10 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { DeleteConnectedAccountAssociatedCalendarDataJob, @@ -19,8 +19,8 @@ export class CalendarEventCleanerConnectedAccountListener { private readonly calendarQueueService: MessageQueueService, ) {} - @OnEvent('connectedAccount.deleted') - async handleDeletedEvent( + @OnEvent('connectedAccount.destroyed') + async handleDestroyedEvent( payload: WorkspaceEventBatch< ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity> >, diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts index 1e2ff015a3ed..0e472d465e9c 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts @@ -16,12 +16,13 @@ import { CalendarOngoingStaleCronJob } from 'src/modules/calendar/calendar-event import { GoogleCalendarDriverModule } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module'; import { CalendarEventListFetchJob } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job'; import { CalendarOngoingStaleJob } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job'; -import { CalendarChannelSyncStatusService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service'; import { CalendarEventImportErrorHandlerService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-exception-handler.service'; import { CalendarEventsImportService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service'; import { CalendarGetCalendarEventsService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-get-events.service'; import { CalendarSaveEventsService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service'; import { CalendarEventParticipantManagerModule } from 'src/modules/calendar/calendar-event-participant-manager/calendar-event-participant-manager.module'; +import { CalendarCommonModule } from 'src/modules/calendar/common/calendar-common.module'; +import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module'; import { RefreshAccessTokenManagerModule } from 'src/modules/connected-account/refresh-access-token-manager/refresh-access-token-manager.module'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; @@ -44,6 +45,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta RefreshAccessTokenManagerModule, CalendarEventParticipantManagerModule, ConnectedAccountModule, + CalendarCommonModule, ], providers: [ CalendarChannelSyncStatusService, diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command.ts index 87d139aa48d9..d49131893a42 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command.ts @@ -1,11 +1,12 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { CalendarEventListFetchCronJob } from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job'; - -const CALENDAR_EVENTS_IMPORT_CRON_PATTERN = '*/5 * * * *'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { + CALENDAR_EVENTS_IMPORT_CRON_PATTERN, + CalendarEventListFetchCronJob, +} from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job'; @Command({ name: 'cron:calendar:calendar-event-list-fetch', diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-ongoing-stale.cron.command.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-ongoing-stale.cron.command.ts index 3164e0a760dc..133077ce6f96 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-ongoing-stale.cron.command.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-ongoing-stale.cron.command.ts @@ -1,11 +1,12 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { CalendarOngoingStaleCronJob } from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job'; - -const CALENDAR_ONGOING_STALE_CRON_PATTERN = '0 * * * *'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { + CALENDAR_ONGOING_STALE_CRON_PATTERN, + CalendarOngoingStaleCronJob, +} from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job'; @Command({ name: 'cron:calendar:ongoing-stale', diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts index 9d5f88f421f0..d59e9db71dc0 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts @@ -2,16 +2,17 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Any, Repository } from 'typeorm'; +import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { CalendarEventListFetchJob, @@ -19,6 +20,8 @@ import { } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job'; import { CalendarChannelSyncStage } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; +export const CALENDAR_EVENTS_IMPORT_CRON_PATTERN = '*/5 * * * *'; + @Processor({ queueName: MessageQueue.cronQueue, }) @@ -33,6 +36,10 @@ export class CalendarEventListFetchCronJob { ) {} @Process(CalendarEventListFetchCronJob.name) + @SentryCronMonitor( + CalendarEventListFetchCronJob.name, + CALENDAR_EVENTS_IMPORT_CRON_PATTERN, + ) async handle(): Promise<void> { console.time('CalendarEventListFetchCronJob time'); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job.ts index d3e5370b52d6..7987a8f1c718 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job.ts @@ -2,21 +2,24 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { CalendarOngoingStaleJob, CalendarOngoingStaleJobData, } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job'; +export const CALENDAR_ONGOING_STALE_CRON_PATTERN = '0 * * * *'; + @Processor(MessageQueue.cronQueue) export class CalendarOngoingStaleCronJob { constructor( @@ -28,6 +31,10 @@ export class CalendarOngoingStaleCronJob { ) {} @Process(CalendarOngoingStaleCronJob.name) + @SentryCronMonitor( + CalendarOngoingStaleCronJob.name, + CALENDAR_ONGOING_STALE_CRON_PATTERN, + ) async handle(): Promise<void> { const activeWorkspaces = await this.workspaceRepository.find({ where: { diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts index 46b209ef9af4..d76a6642df6a 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { GoogleCalendarClientProvider } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/providers/google-calendar.provider'; import { GoogleCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/services/google-calendar-get-events.service'; import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module'; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts index 402661b93981..406e717021ac 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts @@ -1,8 +1,8 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarEventsImportService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service'; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job.ts index bcf5805d14fd..0ddd02960861 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job.ts @@ -2,12 +2,12 @@ import { Logger, Scope } from '@nestjs/common'; import { In } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { CalendarChannelSyncStatusService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service'; import { isSyncStale } from 'src/modules/calendar/calendar-event-import-manager/utils/is-sync-stale.util'; +import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; import { CalendarChannelSyncStage, CalendarChannelWorkspaceEntity, @@ -54,19 +54,19 @@ export class CalendarOngoingStaleJob { this.logger.log( `Sync for calendar channel ${calendarChannel.id} and workspace ${workspaceId} is stale. Setting sync stage to pending`, ); - await this.calendarChannelSyncStatusService.resetSyncStageStartedAt( + await this.calendarChannelSyncStatusService.resetSyncStageStartedAt([ calendarChannel.id, - ); + ]); switch (calendarChannel.syncStage) { case CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_ONGOING: await this.calendarChannelSyncStatusService.schedulePartialCalendarEventListFetch( - calendarChannel.id, + [calendarChannel.id], ); break; case CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_ONGOING: await this.calendarChannelSyncStatusService.scheduleCalendarEventsImport( - calendarChannel.id, + [calendarChannel.id], ); break; default: diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-exception-handler.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-exception-handler.service.ts index 8f1de59aa7dd..0bb40aa6b898 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-exception-handler.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-exception-handler.service.ts @@ -10,7 +10,7 @@ import { CalendarEventImportException, CalendarEventImportExceptionCode, } from 'src/modules/calendar/calendar-event-import-manager/exceptions/calendar-event-import.exception'; -import { CalendarChannelSyncStatusService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service'; +import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; export enum CalendarEventImportSyncStep { @@ -81,7 +81,7 @@ export class CalendarEventImportErrorHandlerService { calendarChannel.throttleFailureCount >= CALENDAR_THROTTLE_MAX_ATTEMPTS ) { await this.calendarChannelSyncStatusService.markAsFailedUnknownAndFlushCalendarEventsToImport( - calendarChannel.id, + [calendarChannel.id], workspaceId, ); @@ -104,19 +104,19 @@ export class CalendarEventImportErrorHandlerService { switch (syncStep) { case CalendarEventImportSyncStep.FULL_CALENDAR_EVENT_LIST_FETCH: await this.calendarChannelSyncStatusService.scheduleFullCalendarEventListFetch( - calendarChannel.id, + [calendarChannel.id], ); break; case CalendarEventImportSyncStep.PARTIAL_CALENDAR_EVENT_LIST_FETCH: await this.calendarChannelSyncStatusService.schedulePartialCalendarEventListFetch( - calendarChannel.id, + [calendarChannel.id], ); break; case CalendarEventImportSyncStep.CALENDAR_EVENTS_IMPORT: await this.calendarChannelSyncStatusService.scheduleCalendarEventsImport( - calendarChannel.id, + [calendarChannel.id], ); break; @@ -130,7 +130,7 @@ export class CalendarEventImportErrorHandlerService { workspaceId: string, ): Promise<void> { await this.calendarChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushCalendarEventsToImport( - calendarChannel.id, + [calendarChannel.id], workspaceId, ); } @@ -141,7 +141,7 @@ export class CalendarEventImportErrorHandlerService { workspaceId: string, ): Promise<void> { await this.calendarChannelSyncStatusService.markAsFailedUnknownAndFlushCalendarEventsToImport( - calendarChannel.id, + [calendarChannel.id], workspaceId, ); @@ -163,7 +163,7 @@ export class CalendarEventImportErrorHandlerService { } await this.calendarChannelSyncStatusService.resetAndScheduleFullCalendarEventListFetch( - calendarChannel.id, + [calendarChannel.id], workspaceId, ); } diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts index d2b7a6181f57..0dd215b88857 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts @@ -7,7 +7,6 @@ import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { CalendarEventCleanerService } from 'src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service'; -import { CalendarChannelSyncStatusService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service'; import { CalendarEventImportErrorHandlerService, CalendarEventImportSyncStep, @@ -18,6 +17,7 @@ import { } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-get-events.service'; import { CalendarSaveEventsService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service'; import { filterEventsAndReturnCancelledEvents } from 'src/modules/calendar/calendar-event-import-manager/utils/filter-events.util'; +import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; import { CalendarChannelSyncStage, @@ -50,7 +50,7 @@ export class CalendarEventsImportService { : CalendarEventImportSyncStep.PARTIAL_CALENDAR_EVENT_LIST_FETCH; await this.calendarChannelSyncStatusService.markAsCalendarEventListFetchOngoing( - calendarChannel.id, + [calendarChannel.id], ); let calendarEvents: GetCalendarEventsResponse['calendarEvents'] = []; let nextSyncCursor: GetCalendarEventsResponse['nextSyncCursor'] = ''; @@ -81,7 +81,7 @@ export class CalendarEventsImportService { ); await this.calendarChannelSyncStatusService.schedulePartialCalendarEventListFetch( - calendarChannel.id, + [calendarChannel.id], ); } @@ -92,7 +92,10 @@ export class CalendarEventsImportService { const { filteredEvents, cancelledEvents } = filterEventsAndReturnCancelledEvents( - calendarChannel, + [ + calendarChannel.handle, + ...connectedAccount.handleAliases.split(','), + ], calendarEvents, blocklist.map((blocklist) => blocklist.handle), ); @@ -133,8 +136,8 @@ export class CalendarEventsImportService { }, ); - await this.calendarChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( - calendarChannel.id, + await this.calendarChannelSyncStatusService.markAsCompletedAndSchedulePartialCalendarEventListFetch( + [calendarChannel.id], ); } catch (error) { await this.calendarEventImportErrorHandlerService.handleDriverException( diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts index 3f22e0c781ac..8c71c73f1fc8 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts @@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common'; import { Any } from 'typeorm'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-events.util.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-events.util.ts index b3e7e0d1d221..2cc28f3a09b7 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-events.util.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-events.util.ts @@ -1,9 +1,8 @@ import { filterOutBlocklistedEvents } from 'src/modules/calendar/calendar-event-import-manager/utils/filter-out-blocklisted-events.util'; -import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { CalendarEventWithParticipants } from 'src/modules/calendar/common/types/calendar-event'; export const filterEventsAndReturnCancelledEvents = ( - calendarChannel: Pick<CalendarChannelWorkspaceEntity, 'handle'>, + calendarChannelHandles: string[], events: CalendarEventWithParticipants[], blocklist: string[], ): { @@ -11,7 +10,7 @@ export const filterEventsAndReturnCancelledEvents = ( cancelledEvents: CalendarEventWithParticipants[]; } => { const filteredEvents = filterOutBlocklistedEvents( - calendarChannel.handle, + calendarChannelHandles, events, blocklist, ); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-out-blocklisted-events.util.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-out-blocklisted-events.util.ts index c850f653d003..d6a82a978ac6 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-out-blocklisted-events.util.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/utils/filter-out-blocklisted-events.util.ts @@ -2,7 +2,7 @@ import { isEmailBlocklisted } from 'src/modules/blocklist/utils/is-email-blockli import { CalendarEventWithParticipants } from 'src/modules/calendar/common/types/calendar-event'; export const filterOutBlocklistedEvents = ( - calendarChannelHandle: string, + calendarChannelHandles: string[], events: CalendarEventWithParticipants[], blocklist: string[], ) => { @@ -13,7 +13,7 @@ export const filterOutBlocklistedEvents = ( return event.participants.every( (attendee) => - !isEmailBlocklisted(calendarChannelHandle, attendee.handle, blocklist), + !isEmailBlocklisted(calendarChannelHandles, attendee.handle, blocklist), ); }); }; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts index 877fa0f457b7..1aadb2088f8f 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts @@ -2,9 +2,9 @@ import { Logger, Scope } from '@nestjs/common'; import { IsNull } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-match-participant.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-match-participant.job.ts index be60d5e650bc..1342448145f5 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-match-participant.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-match-participant.job.ts @@ -4,9 +4,9 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service'; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-unmatch-participant.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-unmatch-participant.job.ts index 3c41ab2a1062..9d3af14865a1 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-unmatch-participant.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-event-participant-unmatch-participant.job.ts @@ -1,8 +1,8 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service'; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-person.listener.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-person.listener.ts index 49389974f04f..e2124ab2a9e6 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-person.listener.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-person.listener.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { CalendarEventParticipantMatchParticipantJob, @@ -32,7 +32,10 @@ export class CalendarEventParticipantPersonListener { >, ) { for (const eventPayload of payload.events) { - if (!eventPayload.properties.after.email) { + if ( + eventPayload.properties.after.emails?.primaryEmail === null && + eventPayload.properties.after.email === null + ) { continue; } @@ -41,7 +44,9 @@ export class CalendarEventParticipantPersonListener { CalendarEventParticipantMatchParticipantJob.name, { workspaceId: payload.workspaceId, - email: eventPayload.properties.after.email, + email: + eventPayload.properties.after.emails?.primaryEmail ?? + eventPayload.properties.after.email, // TODO personId: eventPayload.recordId, }, ); @@ -66,7 +71,9 @@ export class CalendarEventParticipantPersonListener { CalendarEventParticipantUnmatchParticipantJob.name, { workspaceId: payload.workspaceId, - email: eventPayload.properties.before.email, + email: + eventPayload.properties.before.emails?.primaryEmail ?? + eventPayload.properties.before.email, personId: eventPayload.recordId, }, ); @@ -75,7 +82,9 @@ export class CalendarEventParticipantPersonListener { CalendarEventParticipantMatchParticipantJob.name, { workspaceId: payload.workspaceId, - email: eventPayload.properties.after.email, + email: + eventPayload.properties.after.emails?.primaryEmail ?? + eventPayload.properties.after.email, personId: eventPayload.recordId, }, ); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-workspace-member.listener.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-workspace-member.listener.ts index 6016c78c9673..31d292124df9 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-workspace-member.listener.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/listeners/calendar-event-participant-workspace-member.listener.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { CalendarEventParticipantMatchParticipantJob, diff --git a/packages/twenty-server/src/modules/calendar/calendar.module.ts b/packages/twenty-server/src/modules/calendar/calendar.module.ts index ebcd340e4e90..de5759c1849c 100644 --- a/packages/twenty-server/src/modules/calendar/calendar.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar.module.ts @@ -4,6 +4,7 @@ import { CalendarBlocklistManagerModule } from 'src/modules/calendar/blocklist-m import { CalendarEventCleanerModule } from 'src/modules/calendar/calendar-event-cleaner/calendar-event-cleaner.module'; import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module'; import { CalendarEventParticipantManagerModule } from 'src/modules/calendar/calendar-event-participant-manager/calendar-event-participant-manager.module'; +import { CalendarCommonModule } from 'src/modules/calendar/common/calendar-common.module'; @Module({ imports: [ @@ -11,6 +12,7 @@ import { CalendarEventParticipantManagerModule } from 'src/modules/calendar/cale CalendarEventCleanerModule, CalendarEventImportManagerModule, CalendarEventParticipantManagerModule, + CalendarCommonModule, ], providers: [], exports: [], diff --git a/packages/twenty-server/src/modules/calendar/common/calendar-common.module.ts b/packages/twenty-server/src/modules/calendar/common/calendar-common.module.ts new file mode 100644 index 000000000000..9227a352025f --- /dev/null +++ b/packages/twenty-server/src/modules/calendar/common/calendar-common.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; +import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; +import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module'; + +@Module({ + imports: [ + WorkspaceDataSourceModule, + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + ConnectedAccountModule, + ], + providers: [CalendarChannelSyncStatusService], + exports: [CalendarChannelSyncStatusService], +}) +export class CalendarCommonModule {} diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts b/packages/twenty-server/src/modules/calendar/common/services/calendar-channel-sync-status.service.ts similarity index 54% rename from packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts rename to packages/twenty-server/src/modules/calendar/common/services/calendar-channel-sync-status.service.ts index 01345eebb013..4940c1db01eb 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts +++ b/packages/twenty-server/src/modules/calendar/common/services/calendar-channel-sync-status.service.ts @@ -1,13 +1,11 @@ import { Injectable } from '@nestjs/common'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { Any } from 'typeorm'; + +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { - CalendarEventImportException, - CalendarEventImportExceptionCode, -} from 'src/modules/calendar/calendar-event-import-manager/exceptions/calendar-event-import.exception'; import { CalendarChannelSyncStage, CalendarChannelSyncStatus, @@ -26,39 +24,55 @@ export class CalendarChannelSyncStatusService { private readonly accountsToReconnectService: AccountsToReconnectService, ) {} - public async scheduleFullCalendarEventListFetch(calendarChannelId: string) { + public async scheduleFullCalendarEventListFetch( + calendarChannelIds: string[], + ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStage: CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING, }); } public async schedulePartialCalendarEventListFetch( - calendarChannelId: string, + calendarChannelIds: string[], ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStage: CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING, }); } - public async markAsCalendarEventListFetchOngoing(calendarChannelId: string) { + public async markAsCalendarEventListFetchOngoing( + calendarChannelIds: string[], + ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStage: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_ONGOING, syncStatus: CalendarChannelSyncStatus.ONGOING, syncStageStartedAt: new Date().toISOString(), @@ -66,58 +80,92 @@ export class CalendarChannelSyncStatusService { } public async resetAndScheduleFullCalendarEventListFetch( - calendarChannelId: string, + calendarChannelIds: string[], workspaceId: string, ) { - await this.cacheStorage.del( - `calendar-events-to-import:${workspaceId}:google-calendar:${calendarChannelId}`, - ); + if (!calendarChannelIds.length) { + return; + } + + for (const calendarChannelId of calendarChannelIds) { + await this.cacheStorage.del( + `calendar-events-to-import:${workspaceId}:${calendarChannelId}`, + ); + } const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncCursor: '', syncStageStartedAt: null, throttleFailureCount: 0, }); - await this.scheduleFullCalendarEventListFetch(calendarChannelId); + await this.scheduleFullCalendarEventListFetch(calendarChannelIds); } - public async resetSyncStageStartedAt(calendarChannelId: string) { + public async resetSyncStageStartedAt(calendarChannelIds: string[]) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStageStartedAt: null, }); } - public async scheduleCalendarEventsImport(calendarChannelId: string) { + public async scheduleCalendarEventsImport(calendarChannelIds: string[]) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStage: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_PENDING, }); } - public async markAsCompletedAndSchedulePartialMessageListFetch( - calendarChannelId: string, + public async markAsCalendarEventsImportOngoing(calendarChannelIds: string[]) { + if (!calendarChannelIds.length) { + return; + } + + const calendarChannelRepository = + await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelIds, { + syncStage: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_ONGOING, + syncStatus: CalendarChannelSyncStatus.ONGOING, + }); + } + + public async markAsCompletedAndSchedulePartialCalendarEventListFetch( + calendarChannelIds: string[], ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStage: CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING, syncStatus: CalendarChannelSyncStatus.ACTIVE, @@ -125,42 +173,53 @@ export class CalendarChannelSyncStatusService { syncStageStartedAt: null, }); - await this.schedulePartialCalendarEventListFetch(calendarChannelId); + await this.schedulePartialCalendarEventListFetch(calendarChannelIds); } public async markAsFailedUnknownAndFlushCalendarEventsToImport( - calendarChannelId: string, + calendarChannelIds: string[], workspaceId: string, ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await this.cacheStorage.del( - `calendar-events-to-import:${workspaceId}:google-calendar:${calendarChannelId}`, - ); + for (const calendarChannelId of calendarChannelIds) { + await this.cacheStorage.del( + `calendar-events-to-import:${workspaceId}:${calendarChannelId}`, + ); + } - await calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelIds, { syncStatus: CalendarChannelSyncStatus.FAILED_UNKNOWN, syncStage: CalendarChannelSyncStage.FAILED, }); } public async markAsFailedInsufficientPermissionsAndFlushCalendarEventsToImport( - calendarChannelId: string, + calendarChannelIds: string[], workspaceId: string, ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - await this.cacheStorage.del( - `calendar-events-to-import:${workspaceId}:google-calendar:${calendarChannelId}`, - ); - - await calendarChannelRepository.update(calendarChannelId, { + for (const calendarChannelId of calendarChannelIds) { + await this.cacheStorage.del( + `calendar-events-to-import:${workspaceId}:${calendarChannelId}`, + ); + } + await calendarChannelRepository.update(calendarChannelIds, { syncStatus: CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS, syncStage: CalendarChannelSyncStage.FAILED, }); @@ -170,41 +229,44 @@ export class CalendarChannelSyncStatusService { 'connectedAccount', ); - const calendarChannel = await calendarChannelRepository.findOne({ - where: { id: calendarChannelId }, + const calendarChannels = await calendarChannelRepository.find({ + select: ['id', 'connectedAccountId'], + where: { id: Any(calendarChannelIds) }, }); - if (!calendarChannel) { - throw new CalendarEventImportException( - `Calendar channel ${calendarChannelId} not found in workspace ${workspaceId}`, - CalendarEventImportExceptionCode.CALENDAR_CHANNEL_NOT_FOUND, - ); - } - - const connectedAccountId = calendarChannel.connectedAccountId; + const connectedAccountIds = calendarChannels.map( + (calendarChannel) => calendarChannel.connectedAccountId, + ); await connectedAccountRepository.update( - { id: connectedAccountId }, + { id: Any(connectedAccountIds) }, { authFailedAt: new Date(), }, ); - await this.addToAccountsToReconnect(calendarChannelId, workspaceId); + await this.addToAccountsToReconnect( + calendarChannels.map((calendarChannel) => calendarChannel.id), + workspaceId, + ); } private async addToAccountsToReconnect( - calendarChannelId: string, + calendarChannelIds: string[], workspaceId: string, ) { + if (!calendarChannelIds.length) { + return; + } + const calendarChannelRepository = await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>( 'calendarChannel', ); - const calendarChannel = await calendarChannelRepository.findOne({ + const calendarChannels = await calendarChannelRepository.find({ where: { - id: calendarChannelId, + id: Any(calendarChannelIds), }, relations: { connectedAccount: { @@ -213,18 +275,16 @@ export class CalendarChannelSyncStatusService { }, }); - if (!calendarChannel) { - return; - } - - const userId = calendarChannel.connectedAccount.accountOwner.userId; - const connectedAccountId = calendarChannel.connectedAccount.id; + for (const calendarChannel of calendarChannels) { + const userId = calendarChannel.connectedAccount.accountOwner.userId; + const connectedAccountId = calendarChannel.connectedAccount.id; - await this.accountsToReconnectService.addAccountToReconnectByKey( - AccountsToReconnectKeys.ACCOUNTS_TO_RECONNECT_INSUFFICIENT_PERMISSIONS, - userId, - workspaceId, - connectedAccountId, - ); + await this.accountsToReconnectService.addAccountToReconnectByKey( + AccountsToReconnectKeys.ACCOUNTS_TO_RECONNECT_INSUFFICIENT_PERMISSIONS, + userId, + workspaceId, + connectedAccountId, + ); + } } } diff --git a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts index 25c528f99a76..b6bb2b803af7 100644 --- a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts @@ -1,3 +1,5 @@ +import { registerEnumType } from '@nestjs/graphql'; + import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @@ -47,6 +49,22 @@ export enum CalendarChannelContactAutoCreationPolicy { NONE = 'NONE', } +registerEnumType(CalendarChannelVisibility, { + name: 'CalendarChannelVisibility', +}); + +registerEnumType(CalendarChannelSyncStatus, { + name: 'CalendarChannelSyncStatus', +}); + +registerEnumType(CalendarChannelSyncStage, { + name: 'CalendarChannelSyncStage', +}); + +registerEnumType(CalendarChannelContactAutoCreationPolicy, { + name: 'CalendarChannelContactAutoCreationPolicy', +}); + @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.calendarChannel, namePlural: 'calendarChannels', diff --git a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts index ee797c981c18..e36a1727b085 100644 --- a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts +++ b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts @@ -45,7 +45,6 @@ import { WorkOrderWorkspaceEntity } from 'src/funnelmink/entities/funnelmink-wor description: 'A company', icon: 'IconBuildingSkyscraper', labelIdentifierStandardId: COMPANY_STANDARD_FIELD_IDS.name, - softDelete: true, }) export class CompanyWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ diff --git a/packages/twenty-server/src/modules/connected-account/listeners/connected-account.listener.ts b/packages/twenty-server/src/modules/connected-account/listeners/connected-account.listener.ts index 455721d817f6..62ee28d1bede 100644 --- a/packages/twenty-server/src/modules/connected-account/listeners/connected-account.listener.ts +++ b/packages/twenty-server/src/modules/connected-account/listeners/connected-account.listener.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service'; @@ -15,8 +15,8 @@ export class ConnectedAccountListener { private readonly accountsToReconnectService: AccountsToReconnectService, ) {} - @OnEvent('connectedAccount.deleted') - async handleDeletedEvent( + @OnEvent('connectedAccount.destroyed') + async handleDestroyedEvent( payload: WorkspaceEventBatch< ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity> >, diff --git a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts index ef577eafc702..e5020f25427b 100644 --- a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts +++ b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { OAuth2Client } from 'google-auth-library'; import { google } from 'googleapis'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class GoogleOAuth2ClientManagerService { diff --git a/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts index 0812c0e33ea0..f49db465d04b 100644 --- a/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts @@ -3,12 +3,12 @@ import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; -@WorkspaceQueryHook(`connectedAccount.deleteOne`) +@WorkspaceQueryHook(`connectedAccount.destroyOne`) export class ConnectedAccountDeleteOnePreQueryHook implements WorkspaceQueryHookInstance { @@ -34,7 +34,7 @@ export class ConnectedAccountDeleteOnePreQueryHook }); this.workspaceEventEmitter.emit( - 'messageChannel.deleted', + 'messageChannel.destroyed', messageChannels.map( (messageChannel) => ({ diff --git a/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/services/google-api-refresh-access-token.service.ts b/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/services/google-api-refresh-access-token.service.ts index 3a5d015be990..0afb78d719e8 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/services/google-api-refresh-access-token.service.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/services/google-api-refresh-access-token.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; @Injectable() export class GoogleAPIRefreshAccessTokenService { diff --git a/packages/twenty-server/src/modules/contact-creation-manager/contact-creation-manager.module.ts b/packages/twenty-server/src/modules/contact-creation-manager/contact-creation-manager.module.ts index 6f6a1a677c45..536f0c3a2328 100644 --- a/packages/twenty-server/src/modules/contact-creation-manager/contact-creation-manager.module.ts +++ b/packages/twenty-server/src/modules/contact-creation-manager/contact-creation-manager.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; @@ -17,7 +18,10 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]), WorkspaceDataSourceModule, TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'), + TypeOrmModule.forFeature( + [ObjectMetadataEntity, FieldMetadataEntity], + 'metadata', + ), ], providers: [ CreateCompanyService, diff --git a/packages/twenty-server/src/modules/contact-creation-manager/jobs/create-company-and-contact.job.ts b/packages/twenty-server/src/modules/contact-creation-manager/jobs/create-company-and-contact.job.ts index 0a00c1ec9af3..a9024bb5b569 100644 --- a/packages/twenty-server/src/modules/contact-creation-manager/jobs/create-company-and-contact.job.ts +++ b/packages/twenty-server/src/modules/contact-creation-manager/jobs/create-company-and-contact.job.ts @@ -1,6 +1,6 @@ -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { CreateCompanyAndContactService } from 'src/modules/contact-creation-manager/services/create-company-and-contact.service'; diff --git a/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-calendar-channel.listener.ts b/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-calendar-channel.listener.ts index 5dd7497d009b..50a24f1d1f64 100644 --- a/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-calendar-channel.listener.ts +++ b/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-calendar-channel.listener.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { objectRecordChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { objectRecordChangedProperties } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { CalendarCreateCompanyAndContactAfterSyncJob, diff --git a/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-message-channel.listener.ts b/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-message-channel.listener.ts index ac2511f745c0..6ed36b4be2ee 100644 --- a/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-message-channel.listener.ts +++ b/packages/twenty-server/src/modules/contact-creation-manager/listeners/auto-companies-and-contacts-creation-message-channel.listener.ts @@ -1,11 +1,11 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { objectRecordChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { objectRecordChangedProperties } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { diff --git a/packages/twenty-server/src/modules/contact-creation-manager/services/create-company-and-contact.service.ts b/packages/twenty-server/src/modules/contact-creation-manager/services/create-company-and-contact.service.ts index db6a6328bb29..7b4447b40584 100644 --- a/packages/twenty-server/src/modules/contact-creation-manager/services/create-company-and-contact.service.ts +++ b/packages/twenty-server/src/modules/contact-creation-manager/services/create-company-and-contact.service.ts @@ -1,16 +1,19 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { isDefined } from 'class-validator'; import chunk from 'lodash.chunk'; import compact from 'lodash.compact'; import { Any, EntityManager, Repository } from 'typeorm'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; +import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { CONTACTS_CREATION_BATCH_SIZE } from 'src/modules/contact-creation-manager/constants/contacts-creation-batch-size.constant'; @@ -35,6 +38,8 @@ export class CreateCompanyAndContactService { private readonly workspaceEventEmitter: WorkspaceEventEmitter, @InjectRepository(ObjectMetadataEntity, 'metadata') private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, private readonly twentyORMGlobalManager: TwentyORMGlobalManager, ) {} @@ -49,6 +54,13 @@ export class CreateCompanyAndContactService { return []; } + const emailsFieldMetadata = await this.fieldMetadataRepository.findOne({ + where: { + workspaceId: workspaceId, + standardId: PERSON_STANDARD_FIELD_IDS.emails, + }, + }); + const personRepository = await this.twentyORMGlobalManager.getRepositoryForWorkspace( workspaceId, @@ -77,14 +89,16 @@ export class CreateCompanyAndContactService { } const alreadyCreatedContacts = await personRepository.find({ - where: { - email: Any(uniqueHandles), - }, + where: isDefined(emailsFieldMetadata) + ? { + emails: { primaryEmail: Any(uniqueHandles) }, + } + : { email: Any(uniqueHandles) }, }); - const alreadyCreatedContactEmails: string[] = alreadyCreatedContacts?.map( - ({ email }) => email, - ); + const alreadyCreatedContactEmails: string[] = isDefined(emailsFieldMetadata) + ? alreadyCreatedContacts?.map(({ emails }) => emails?.primaryEmail) + : alreadyCreatedContacts?.map(({ email }) => email); const filteredContactsToCreate = uniqueContacts.filter( (participant) => diff --git a/packages/twenty-server/src/modules/contact-creation-manager/services/create-contact.service.ts b/packages/twenty-server/src/modules/contact-creation-manager/services/create-contact.service.ts index 7aad43da10eb..400573dddafd 100644 --- a/packages/twenty-server/src/modules/contact-creation-manager/services/create-contact.service.ts +++ b/packages/twenty-server/src/modules/contact-creation-manager/services/create-contact.service.ts @@ -46,7 +46,7 @@ export class CreateContactService { return { id, - email: handle, + emails: { primaryEmail: handle, additionalEmails: null }, name: { firstName, lastName, diff --git a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts index 9c2772b5e601..016d0ce4759b 100644 --- a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts +++ b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts @@ -21,6 +21,7 @@ import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.work import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { WorkOrderWorkspaceEntity } from 'src/funnelmink/entities/funnelmink-workorder.workspace-entity'; @@ -61,6 +62,7 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity { inverseSideFieldKey: 'favorites', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, }) + @WorkspaceIsNullable() workspaceMember: Relation<WorkspaceMemberWorkspaceEntity>; @WorkspaceJoinColumn('workspaceMember') @@ -162,6 +164,21 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceJoinColumn('note') noteId: string; + @WorkspaceRelation({ + standardId: FAVORITE_STANDARD_FIELD_IDS.view, + type: RelationMetadataType.MANY_TO_ONE, + label: 'View', + description: 'Favorite view', + icon: 'IconLayoutCollage', + inverseSideTarget: () => ViewWorkspaceEntity, + inverseSideFieldKey: 'favorites', + }) + @WorkspaceIsNullable() + view: Relation<ViewWorkspaceEntity> | null; + + @WorkspaceJoinColumn('view') + viewId: string; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/mail-sender/workflow-actions/send-email.workflow-action.ts b/packages/twenty-server/src/modules/mail-sender/workflow-actions/send-email.workflow-action.ts new file mode 100644 index 000000000000..3a17c77cf92d --- /dev/null +++ b/packages/twenty-server/src/modules/mail-sender/workflow-actions/send-email.workflow-action.ts @@ -0,0 +1,77 @@ +import { Injectable, Logger } from '@nestjs/common'; + +import { z } from 'zod'; +import Handlebars from 'handlebars'; +import { JSDOM } from 'jsdom'; +import DOMPurify from 'dompurify'; +import { WorkflowActionEmail } from 'twenty-emails'; +import { render } from '@react-email/components'; + +import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/types/workflow-action-result.type'; +import { WorkflowSendEmailStep } from 'src/modules/workflow/workflow-executor/types/workflow-action.type'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; + +@Injectable() +export class SendEmailWorkflowAction { + private readonly logger = new Logger(SendEmailWorkflowAction.name); + constructor( + private readonly environmentService: EnvironmentService, + private readonly emailService: EmailService, + ) {} + + async execute({ + step, + payload, + }: { + step: WorkflowSendEmailStep; + payload: { + email: string; + [key: string]: string; + }; + }): Promise<WorkflowActionResult> { + try { + const emailSchema = z.string().trim().email('Invalid email'); + + const result = emailSchema.safeParse(payload.email); + + if (!result.success) { + this.logger.warn(`Email '${payload.email}' invalid`); + + return { result: { success: false } }; + } + + const mainText = Handlebars.compile(step.settings.template)(payload); + + const window = new JSDOM('').window; + const purify = DOMPurify(window); + const safeHTML = purify.sanitize(mainText || ''); + + const email = WorkflowActionEmail({ + dangerousHTML: safeHTML, + title: step.settings.title, + callToAction: step.settings.callToAction, + }); + const html = render(email, { + pretty: true, + }); + const text = render(email, { + plainText: true, + }); + + await this.emailService.send({ + from: `${this.environmentService.get( + 'EMAIL_FROM_NAME', + )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + to: payload.email, + subject: step.settings.subject || '', + text, + html, + }); + + return { result: { success: true } }; + } catch (error) { + return { error }; + } + } +} diff --git a/packages/twenty-server/src/modules/match-participant/match-participant.module.ts b/packages/twenty-server/src/modules/match-participant/match-participant.module.ts index 7f0904d7d3a3..1b01665f7a10 100644 --- a/packages/twenty-server/src/modules/match-participant/match-participant.module.ts +++ b/packages/twenty-server/src/modules/match-participant/match-participant.module.ts @@ -1,10 +1,12 @@ import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service'; @Module({ - imports: [], + imports: [TypeOrmModule.forFeature([FieldMetadataEntity], 'metadata')], providers: [ScopedWorkspaceContextFactory, MatchParticipantService], exports: [MatchParticipantService], }) diff --git a/packages/twenty-server/src/modules/match-participant/match-participant.service.ts b/packages/twenty-server/src/modules/match-participant/match-participant.service.ts index 509bbfe6b6ab..195a88ea4e3c 100644 --- a/packages/twenty-server/src/modules/match-participant/match-participant.service.ts +++ b/packages/twenty-server/src/modules/match-participant/match-participant.service.ts @@ -1,10 +1,13 @@ import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; -import { Any, EntityManager } from 'typeorm'; +import { Any, EntityManager, Repository } from 'typeorm'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; +import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; @@ -20,6 +23,8 @@ export class MatchParticipantService< private readonly workspaceEventEmitter: WorkspaceEventEmitter, private readonly twentyORMManager: TwentyORMManager, private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>, ) {} private async getParticipantRepository( @@ -55,19 +60,35 @@ export class MatchParticipantService< ...new Set(participants.map((participant) => participant.handle)), ]; + const emailsFieldMetadata = await this.fieldMetadataRepository.findOne({ + where: { + workspaceId: workspaceId, + standardId: PERSON_STANDARD_FIELD_IDS.emails, + }, + }); + const personRepository = await this.twentyORMManager.getRepository<PersonWorkspaceEntity>( 'person', ); - const people = await personRepository.find( - { - where: { - email: Any(uniqueParticipantsHandles), - }, - }, - transactionManager, - ); + const people = emailsFieldMetadata + ? await personRepository.find( + { + where: { + emails: Any(uniqueParticipantsHandles), + }, + }, + transactionManager, + ) + : await personRepository.find( + { + where: { + email: Any(uniqueParticipantsHandles), + }, + }, + transactionManager, + ); const workspaceMemberRepository = await this.twentyORMManager.getRepository<WorkspaceMemberWorkspaceEntity>( @@ -84,7 +105,11 @@ export class MatchParticipantService< ); for (const handle of uniqueParticipantsHandles) { - const person = people.find((person) => person.email === handle); + const person = people.find((person) => + emailsFieldMetadata + ? person.emails?.primaryEmail === handle + : person.email === handle, + ); const workspaceMember = workspaceMembers.find( (workspaceMember) => workspaceMember.userEmail === handle, diff --git a/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts index 3c7d37204761..8fedb4c73cb9 100644 --- a/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts @@ -1,21 +1,21 @@ import { Logger, Scope } from '@nestjs/common'; -import { Any } from 'typeorm'; +import { And, Any, ILike, In, Not, Or } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; -export type BlocklistItemDeleteMessagesJobData = { - workspaceId: string; - blocklistItemId: string; -}; +export type BlocklistItemDeleteMessagesJobData = WorkspaceEventBatch< + ObjectRecordCreateEvent<BlocklistWorkspaceEntity> +>; @Processor({ queueName: MessageQueue.messagingQueue, @@ -25,66 +25,135 @@ export class BlocklistItemDeleteMessagesJob { private readonly logger = new Logger(BlocklistItemDeleteMessagesJob.name); constructor( - @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) - private readonly blocklistRepository: BlocklistRepository, private readonly threadCleanerService: MessagingMessageCleanerService, private readonly twentyORMManager: TwentyORMManager, ) {} @Process(BlocklistItemDeleteMessagesJob.name) async handle(data: BlocklistItemDeleteMessagesJobData): Promise<void> { - const { workspaceId, blocklistItemId } = data; + const workspaceId = data.workspaceId; - const blocklistItem = await this.blocklistRepository.getById( - blocklistItemId, - workspaceId, + const blocklistItemIds = data.events.map( + (eventPayload) => eventPayload.recordId, ); - if (!blocklistItem) { - this.logger.log( - `Blocklist item with id ${blocklistItemId} not found in workspace ${workspaceId}`, + const blocklistRepository = + await this.twentyORMManager.getRepository<BlocklistWorkspaceEntity>( + 'blocklist', ); - return; - } + const blocklist = await blocklistRepository.find({ + where: { + id: Any(blocklistItemIds), + }, + }); + + const handlesToDeleteByWorkspaceMemberIdMap = blocklist.reduce( + (acc, blocklistItem) => { + const { handle, workspaceMemberId } = blocklistItem; + + if (!acc.has(workspaceMemberId)) { + acc.set(workspaceMemberId, []); + } - const { handle, workspaceMemberId } = blocklistItem; + acc.get(workspaceMemberId)?.push(handle); - this.logger.log( - `Deleting messages from ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, + return acc; + }, + new Map<string, string[]>(), ); - if (!workspaceMemberId) { - throw new Error( - `Workspace member ID is not defined for blocklist item ${blocklistItemId} in workspace ${workspaceId}`, + const messageChannelRepository = + await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( + 'messageChannel', ); - } const messageChannelMessageAssociationRepository = await this.twentyORMManager.getRepository<MessageChannelMessageAssociationWorkspaceEntity>( 'messageChannelMessageAssociation', ); - const rolesToDelete: ('from' | 'to')[] = ['from', 'to']; + for (const workspaceMemberId of handlesToDeleteByWorkspaceMemberIdMap.keys()) { + const handles = + handlesToDeleteByWorkspaceMemberIdMap.get(workspaceMemberId); + + if (!handles) { + continue; + } + + this.logger.log( + `Deleting messages from ${handles.join( + ', ', + )} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, + ); + + const rolesToDelete: ('from' | 'to')[] = ['from', 'to']; - await messageChannelMessageAssociationRepository.delete({ - messageChannel: { - connectedAccount: { - accountOwnerId: workspaceMemberId, + const messageChannels = await messageChannelRepository.find({ + select: { + id: true, + handle: true, + connectedAccount: { + handleAliases: true, + }, }, - }, - message: { - messageParticipants: { - handle, - role: Any(rolesToDelete), + where: { + connectedAccount: { + accountOwnerId: workspaceMemberId, + }, }, - }, - }); + relations: ['connectedAccount'], + }); + + for (const messageChannel of messageChannels) { + const messageChannelHandles = [messageChannel.handle]; + + if (messageChannel.connectedAccount.handleAliases) { + messageChannelHandles.push( + ...messageChannel.connectedAccount.handleAliases.split(','), + ); + } + + const handleConditions = handles.map((handle) => { + const isHandleDomain = handle.startsWith('@'); + + return isHandleDomain + ? { + handle: And( + Or(ILike(`%${handle}`), ILike(`%.${handle.slice(1)}`)), + Not(In(messageChannelHandles)), + ), + role: In(rolesToDelete), + } + : { handle, role: In(rolesToDelete) }; + }); + + const messageChannelMessageAssociationsToDelete = + await messageChannelMessageAssociationRepository.find({ + where: { + messageChannelId: messageChannel.id, + message: { + messageParticipants: handleConditions, + }, + }, + }); + + if (messageChannelMessageAssociationsToDelete.length === 0) { + continue; + } + + await messageChannelMessageAssociationRepository.delete( + messageChannelMessageAssociationsToDelete.map(({ id }) => id), + ); + } - await this.threadCleanerService.cleanWorkspaceThreads(workspaceId); + this.logger.log( + `Deleted messages from handle ${handles.join( + ', ', + )} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, + ); + } - this.logger.log( - `Deleted messages from handle ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`, - ); + await this.threadCleanerService.cleanWorkspaceThreads(workspaceId); } } diff --git a/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts new file mode 100644 index 000000000000..0b84b473c97b --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts @@ -0,0 +1,63 @@ +import { Scope } from '@nestjs/common'; + +import { Not } from 'typeorm'; + +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; +import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; +import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service'; +import { + MessageChannelSyncStage, + MessageChannelWorkspaceEntity, +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; + +export type BlocklistReimportMessagesJobData = WorkspaceEventBatch< + ObjectRecordDeleteEvent<BlocklistWorkspaceEntity> +>; + +@Processor({ + queueName: MessageQueue.messagingQueue, + scope: Scope.REQUEST, +}) +export class BlocklistReimportMessagesJob { + constructor( + private readonly twentyORMManager: TwentyORMManager, + private readonly messagingChannelSyncStatusService: MessageChannelSyncStatusService, + ) {} + + @Process(BlocklistReimportMessagesJob.name) + async handle(data: BlocklistReimportMessagesJobData): Promise<void> { + const workspaceId = data.workspaceId; + + const messageChannelRepository = + await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( + 'messageChannel', + ); + + for (const eventPayload of data.events) { + const workspaceMemberId = + eventPayload.properties.before.workspaceMemberId; + + const messageChannels = await messageChannelRepository.find({ + select: ['id'], + where: { + connectedAccount: { + accountOwnerId: workspaceMemberId, + }, + syncStage: Not( + MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING, + ), + }, + }); + + await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch( + messageChannels.map((messageChannel) => messageChannel.id), + workspaceId, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts index 4335cf29db5b..d232e9040b83 100644 --- a/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts @@ -1,34 +1,28 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Scope } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { BlocklistItemDeleteMessagesJob, BlocklistItemDeleteMessagesJobData, } from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { + BlocklistReimportMessagesJob, + BlocklistReimportMessagesJobData, +} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job'; -@Injectable() +@Injectable({ scope: Scope.REQUEST }) export class MessagingBlocklistListener { constructor( @InjectMessageQueue(MessageQueue.messagingQueue) private readonly messageQueueService: MessageQueueService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly messagingChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly twentyORMManager: TwentyORMManager, ) {} @OnEvent('blocklist.created') @@ -37,17 +31,9 @@ export class MessagingBlocklistListener { ObjectRecordCreateEvent<BlocklistWorkspaceEntity> >, ) { - await Promise.all( - payload.events.map((eventPayload) => - // TODO: modify to pass an array of blocklist items - this.messageQueueService.add<BlocklistItemDeleteMessagesJobData>( - BlocklistItemDeleteMessagesJob.name, - { - workspaceId: payload.workspaceId, - blocklistItemId: eventPayload.recordId, - }, - ), - ), + await this.messageQueueService.add<BlocklistItemDeleteMessagesJobData>( + BlocklistItemDeleteMessagesJob.name, + payload, ); } @@ -57,38 +43,10 @@ export class MessagingBlocklistListener { ObjectRecordDeleteEvent<BlocklistWorkspaceEntity> >, ) { - const workspaceId = payload.workspaceId; - - for (const eventPayload of payload.events) { - const workspaceMemberId = - eventPayload.properties.before.workspaceMember.id; - - const connectedAccount = - await this.connectedAccountRepository.getAllByWorkspaceMemberId( - workspaceMemberId, - workspaceId, - ); - - if (!connectedAccount || connectedAccount.length === 0) { - return; - } - - const messageChannelRepository = - await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( - 'messageChannel', - ); - - const messageChannel = await messageChannelRepository.findOneOrFail({ - where: { - connectedAccountId: connectedAccount[0].id, - }, - }); - - await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch( - messageChannel.id, - workspaceId, - ); - } + await this.messageQueueService.add<BlocklistReimportMessagesJobData>( + BlocklistReimportMessagesJob.name, + payload, + ); } @OnEvent('blocklist.updated') @@ -97,45 +55,14 @@ export class MessagingBlocklistListener { ObjectRecordUpdateEvent<BlocklistWorkspaceEntity> >, ) { - const workspaceId = payload.workspaceId; - - for (const eventPayload of payload.events) { - const workspaceMemberId = - eventPayload.properties.before.workspaceMember.id; - - await this.messageQueueService.add<BlocklistItemDeleteMessagesJobData>( - BlocklistItemDeleteMessagesJob.name, - { - workspaceId, - blocklistItemId: eventPayload.recordId, - }, - ); - - const connectedAccount = - await this.connectedAccountRepository.getAllByWorkspaceMemberId( - workspaceMemberId, - workspaceId, - ); - - if (!connectedAccount || connectedAccount.length === 0) { - continue; - } - - const messageChannelRepository = - await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( - 'messageChannel', - ); - - const messageChannel = await messageChannelRepository.findOneOrFail({ - where: { - connectedAccountId: connectedAccount[0].id, - }, - }); + await this.messageQueueService.add<BlocklistItemDeleteMessagesJobData>( + BlocklistItemDeleteMessagesJob.name, + payload, + ); - await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch( - messageChannel.id, - workspaceId, - ); - } + await this.messageQueueService.add<BlocklistReimportMessagesJobData>( + BlocklistReimportMessagesJob.name, + payload, + ); } } diff --git a/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts index 0ed9ad1fe66a..716f67b88005 100644 --- a/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts @@ -1,6 +1,7 @@ import { Module } from '@nestjs/common'; import { BlocklistItemDeleteMessagesJob } from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job'; +import { BlocklistReimportMessagesJob } from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job'; import { MessagingBlocklistListener } from 'src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener'; import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; import { MessagingMessageCleanerModule } from 'src/modules/messaging/message-cleaner/messaging-message-cleaner.module'; @@ -9,10 +10,8 @@ import { MessagingMessageCleanerModule } from 'src/modules/messaging/message-cle imports: [MessagingCommonModule, MessagingMessageCleanerModule], providers: [ MessagingBlocklistListener, - { - provide: BlocklistItemDeleteMessagesJob.name, - useClass: BlocklistItemDeleteMessagesJob, - }, + BlocklistItemDeleteMessagesJob, + BlocklistReimportMessagesJob, ], exports: [], }) diff --git a/packages/twenty-server/src/modules/messaging/common/services/message-channel-sync-status.service.ts b/packages/twenty-server/src/modules/messaging/common/services/message-channel-sync-status.service.ts index 6be3ad36a65e..19e6746ce1a3 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/message-channel-sync-status.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/message-channel-sync-status.service.ts @@ -1,8 +1,10 @@ import { Injectable } from '@nestjs/common'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { Any } from 'typeorm'; + +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; @@ -12,10 +14,6 @@ import { MessageChannelSyncStatus, MessageChannelWorkspaceEntity, } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; -import { - MessageImportException, - MessageImportExceptionCode, -} from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception'; @Injectable() export class MessageChannelSyncStatusService { @@ -26,216 +24,237 @@ export class MessageChannelSyncStatusService { private readonly accountsToReconnectService: AccountsToReconnectService, ) {} - public async scheduleFullMessageListFetch(messageChannelId: string) { + public async scheduleFullMessageListFetch(messageChannelIds: string[]) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING, + }); } - public async schedulePartialMessageListFetch(messageChannelId: string) { + public async schedulePartialMessageListFetch(messageChannelIds: string[]) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING, + }); } - public async scheduleMessagesImport(messageChannelId: string) { + public async scheduleMessagesImport(messageChannelIds: string[]) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_PENDING, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_PENDING, + }); } public async resetAndScheduleFullMessageListFetch( - messageChannelId: string, + messageChannelIds: string[], workspaceId: string, ) { - await this.cacheStorage.del( - `messages-to-import:${workspaceId}:gmail:${messageChannelId}`, - ); + if (!messageChannelIds.length) { + return; + } + + for (const messageChannelId of messageChannelIds) { + await this.cacheStorage.del( + `messages-to-import:${workspaceId}:${messageChannelId}`, + ); + } const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncCursor: '', - syncStageStartedAt: null, - throttleFailureCount: 0, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncCursor: '', + syncStageStartedAt: null, + throttleFailureCount: 0, + }); - await this.scheduleFullMessageListFetch(messageChannelId); + await this.scheduleFullMessageListFetch(messageChannelIds); } - public async resetSyncStageStartedAt(messageChannelId: string) { + public async resetSyncStageStartedAt(messageChannelIds: string[]) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStageStartedAt: null, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStageStartedAt: null, + }); } - public async markAsMessagesListFetchOngoing(messageChannelId: string) { + public async markAsMessagesListFetchOngoing(messageChannelIds: string[]) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING, - syncStatus: MessageChannelSyncStatus.ONGOING, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING, + syncStatus: MessageChannelSyncStatus.ONGOING, + syncStageStartedAt: new Date().toISOString(), + }); } public async markAsCompletedAndSchedulePartialMessageListFetch( - messageChannelId: string, + messageChannelIds: string[], ) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStatus: MessageChannelSyncStatus.ACTIVE, - }, - ); - - await this.schedulePartialMessageListFetch(messageChannelId); + await messageChannelRepository.update(messageChannelIds, { + syncStatus: MessageChannelSyncStatus.ACTIVE, + syncStage: MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING, + throttleFailureCount: 0, + syncStageStartedAt: null, + }); } - public async markAsMessagesImportOngoing(messageChannelId: string) { + public async markAsMessagesImportOngoing(messageChannelIds: string[]) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING, + }); } public async markAsFailedUnknownAndFlushMessagesToImport( - messageChannelId: string, + messageChannelIds: string[], workspaceId: string, ) { - await this.cacheStorage.del( - `messages-to-import:${workspaceId}:gmail:${messageChannelId}`, - ); + if (!messageChannelIds.length) { + return; + } + + for (const messageChannelId of messageChannelIds) { + await this.cacheStorage.del( + `messages-to-import:${workspaceId}:${messageChannelId}`, + ); + } const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.FAILED, - syncStatus: MessageChannelSyncStatus.FAILED_UNKNOWN, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.FAILED, + syncStatus: MessageChannelSyncStatus.FAILED_UNKNOWN, + }); } public async markAsFailedInsufficientPermissionsAndFlushMessagesToImport( - messageChannelId: string, + messageChannelIds: string[], workspaceId: string, ) { - await this.cacheStorage.del( - `messages-to-import:${workspaceId}:gmail:${messageChannelId}`, - ); + if (!messageChannelIds.length) { + return; + } + + for (const messageChannelId of messageChannelIds) { + await this.cacheStorage.del( + `messages-to-import:${workspaceId}:${messageChannelId}`, + ); + } const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - await messageChannelRepository.update( - { id: messageChannelId }, - { - syncStage: MessageChannelSyncStage.FAILED, - syncStatus: MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS, - }, - ); + await messageChannelRepository.update(messageChannelIds, { + syncStage: MessageChannelSyncStage.FAILED, + syncStatus: MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS, + }); const connectedAccountRepository = await this.twentyORMManager.getRepository<ConnectedAccountWorkspaceEntity>( 'connectedAccount', ); - const messageChannel = await messageChannelRepository.findOne({ - where: { id: messageChannelId }, + const messageChannels = await messageChannelRepository.find({ + select: ['id', 'connectedAccountId'], + where: { id: Any(messageChannelIds) }, }); - if (!messageChannel) { - throw new MessageImportException( - `Message channel ${messageChannelId} not found in workspace ${workspaceId}`, - MessageImportExceptionCode.MESSAGE_CHANNEL_NOT_FOUND, - ); - } - - const connectedAccountId = messageChannel.connectedAccountId; + const connectedAccountIds = messageChannels.map( + (messageChannel) => messageChannel.connectedAccountId, + ); await connectedAccountRepository.update( - { id: connectedAccountId }, + { id: Any(connectedAccountIds) }, { authFailedAt: new Date(), }, ); - await this.addToAccountsToReconnect(messageChannelId, workspaceId); + await this.addToAccountsToReconnect( + messageChannels.map((messageChannel) => messageChannel.id), + workspaceId, + ); } private async addToAccountsToReconnect( - messageChannelId: string, + messageChannelIds: string[], workspaceId: string, ) { + if (!messageChannelIds.length) { + return; + } + const messageChannelRepository = await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>( 'messageChannel', ); - const messageChannel = await messageChannelRepository.findOne({ - where: { id: messageChannelId }, + const messageChannels = await messageChannelRepository.find({ + where: { id: Any(messageChannelIds) }, relations: { connectedAccount: { accountOwner: true, @@ -243,18 +262,16 @@ export class MessageChannelSyncStatusService { }, }); - if (!messageChannel) { - return; - } - - const userId = messageChannel.connectedAccount.accountOwner.userId; - const connectedAccountId = messageChannel.connectedAccount.id; + for (const messageChannel of messageChannels) { + const userId = messageChannel.connectedAccount.accountOwner.userId; + const connectedAccountId = messageChannel.connectedAccount.id; - await this.accountsToReconnectService.addAccountToReconnectByKey( - AccountsToReconnectKeys.ACCOUNTS_TO_RECONNECT_INSUFFICIENT_PERMISSIONS, - userId, - workspaceId, - connectedAccountId, - ); + await this.accountsToReconnectService.addAccountToReconnectByKey( + AccountsToReconnectKeys.ACCOUNTS_TO_RECONNECT_INSUFFICIENT_PERMISSIONS, + userId, + workspaceId, + connectedAccountId, + ); + } } } diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts index f5051f7c99b7..3b5b6e3a6cce 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts @@ -1,3 +1,5 @@ +import { registerEnumType } from '@nestjs/graphql'; + import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @@ -52,6 +54,26 @@ export enum MessageChannelContactAutoCreationPolicy { NONE = 'NONE', } +registerEnumType(MessageChannelVisibility, { + name: 'MessageChannelVisibility', +}); + +registerEnumType(MessageChannelSyncStatus, { + name: 'MessageChannelSyncStatus', +}); + +registerEnumType(MessageChannelSyncStage, { + name: 'MessageChannelSyncStage', +}); + +registerEnumType(MessageChannelType, { + name: 'MessageChannelType', +}); + +registerEnumType(MessageChannelContactAutoCreationPolicy, { + name: 'MessageChannelContactAutoCreationPolicy', +}); + @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageChannel, namePlural: 'messageChannels', diff --git a/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts index c9cc4e9e993e..2523c180485c 100644 --- a/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts @@ -1,9 +1,9 @@ import { Logger, Scope } from '@nestjs/common'; import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; export type MessagingConnectedAccountDeletionCleanupJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts index 8caf65c58857..c5c3a033dedc 100644 --- a/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts @@ -1,10 +1,10 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { @@ -19,8 +19,8 @@ export class MessagingMessageCleanerConnectedAccountListener { private readonly messageQueueService: MessageQueueService, ) {} - @OnEvent('connectedAccount.deleted') - async handleDeletedEvent( + @OnEvent('connectedAccount.destroyed') + async handleDestroyedEvent( payload: WorkspaceEventBatch< ObjectRecordDeleteEvent<ConnectedAccountWorkspaceEntity> >, diff --git a/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts index bb9524b41c47..751504050ce7 100644 --- a/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { EntityManager } from 'typeorm'; +import { EntityManager, IsNull } from 'typeorm'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; @@ -22,67 +22,77 @@ export class MessagingMessageCleanerService { 'message', ); - await deleteUsingPagination( - workspaceId, - 500, - async ( - limit: number, - offset: number, - workspaceId: string, - transactionManager?: EntityManager, - ) => { - const nonAssociatedMessages = await messageRepository.find( - { - where: { - messageChannelMessageAssociations: [], + const workspaceDataSource = await this.twentyORMManager.getDatasource(); + + await workspaceDataSource.transaction(async (transactionManager) => { + await deleteUsingPagination( + workspaceId, + 500, + async ( + limit: number, + offset: number, + workspaceId: string, + transactionManager: EntityManager, + ) => { + const nonAssociatedMessages = await messageRepository.find( + { + where: { + messageChannelMessageAssociations: { + id: IsNull(), + }, + }, + take: limit, + skip: offset, + relations: ['messageChannelMessageAssociations'], }, - take: limit, - skip: offset, - relations: ['messageChannelMessageAssociations'], - }, - transactionManager, - ); + transactionManager, + ); - return nonAssociatedMessages.map(({ id }) => id); - }, - async ( - ids: string[], - workspaceId: string, - transactionManager?: EntityManager, - ) => { - await messageRepository.delete(ids, transactionManager); - }, - ); + return nonAssociatedMessages.map(({ id }) => id); + }, + async ( + ids: string[], + workspaceId: string, + transactionManager?: EntityManager, + ) => { + await messageRepository.delete(ids, transactionManager); + }, + transactionManager, + ); - await deleteUsingPagination( - workspaceId, - 500, - async ( - limit: number, - offset: number, - workspaceId: string, - transactionManager?: EntityManager, - ) => { - const orphanThreads = await messageThreadRepository.find( - { - where: { - messages: [], + await deleteUsingPagination( + workspaceId, + 500, + async ( + limit: number, + offset: number, + workspaceId: string, + transactionManager?: EntityManager, + ) => { + const orphanThreads = await messageThreadRepository.find( + { + where: { + messages: { + id: IsNull(), + }, + }, + take: limit, + skip: offset, }, - take: limit, - skip: offset, - }, - transactionManager, - ); + transactionManager, + ); - return orphanThreads.map(({ id }) => id); - }, - async ( - ids: string[], - workspaceId: string, - transactionManager?: EntityManager, - ) => { - await messageThreadRepository.delete(ids, transactionManager); - }, - ); + return orphanThreads.map(({ id }) => id); + }, + async ( + ids: string[], + workspaceId: string, + transactionManager?: EntityManager, + ) => { + await messageThreadRepository.delete(ids, transactionManager); + }, + transactionManager, + ); + }); } } diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-single-message-import.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-single-message-import.command.ts index c55465f7dedc..77e4f776fe4a 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-single-message-import.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-single-message-import.command.ts @@ -1,8 +1,8 @@ import { Command, CommandRunner, Option } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { MessagingAddSingleMessageToCacheForImportJob, MessagingAddSingleMessageToCacheForImportJobData, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts index d8e2253bd1d1..d0a721ccc367 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts @@ -1,11 +1,12 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { MessagingMessageListFetchCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job'; - -const MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { + MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN, + MessagingMessageListFetchCronJob, +} from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job'; @Command({ name: 'cron:messaging:message-list-fetch', diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts index 11ef7211d76a..9e115565f470 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts @@ -1,11 +1,12 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { MessagingMessagesImportCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job'; - -const MESSAGING_MESSAGES_IMPORT_CRON_PATTERN = '*/1 * * * *'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { + MESSAGING_MESSAGES_IMPORT_CRON_PATTERN, + MessagingMessagesImportCronJob, +} from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job'; @Command({ name: 'cron:messaging:messages-import', diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-ongoing-stale.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-ongoing-stale.cron.command.ts index ed77d79555b8..1df4ef8ce12b 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-ongoing-stale.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-ongoing-stale.cron.command.ts @@ -1,11 +1,12 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { MessagingOngoingStaleCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job'; - -const MESSAGING_ONGOING_STALE_CRON_PATTERN = '0 * * * *'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { + MESSAGING_ONGOING_STALE_CRON_PATTERN, + MessagingOngoingStaleCronJob, +} from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job'; @Command({ name: 'cron:messaging:ongoing-stale', diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts index 43ca1ae757a0..30c41ab7424f 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts @@ -2,16 +2,17 @@ import { InjectRepository } from '@nestjs/typeorm'; import { In, Repository } from 'typeorm'; +import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { MessageChannelSyncStage, @@ -22,6 +23,8 @@ import { MessagingMessageListFetchJobData, } from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; +export const MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *'; + @Processor(MessageQueue.cronQueue) export class MessagingMessageListFetchCronJob { constructor( @@ -34,6 +37,10 @@ export class MessagingMessageListFetchCronJob { ) {} @Process(MessagingMessageListFetchCronJob.name) + @SentryCronMonitor( + MessagingMessageListFetchCronJob.name, + MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN, + ) async handle(): Promise<void> { console.time('MessagingMessageListFetchCronJob time'); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts index f22783294595..c580e5df67fc 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts @@ -2,16 +2,17 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { MessageChannelSyncStage, @@ -22,6 +23,8 @@ import { MessagingMessagesImportJobData, } from 'src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job'; +export const MESSAGING_MESSAGES_IMPORT_CRON_PATTERN = '*/1 * * * *'; + @Processor(MessageQueue.cronQueue) export class MessagingMessagesImportCronJob { constructor( @@ -34,6 +37,10 @@ export class MessagingMessagesImportCronJob { ) {} @Process(MessagingMessagesImportCronJob.name) + @SentryCronMonitor( + MessagingMessagesImportCronJob.name, + MESSAGING_MESSAGES_IMPORT_CRON_PATTERN, + ) async handle(): Promise<void> { console.time('MessagingMessagesImportCronJob time'); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job.ts index 08ca244cc202..3dcdb3bac311 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job.ts @@ -2,21 +2,24 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { MessagingOngoingStaleJob, MessagingOngoingStaleJobData, } from 'src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job'; +export const MESSAGING_ONGOING_STALE_CRON_PATTERN = '0 * * * *'; + @Processor(MessageQueue.cronQueue) export class MessagingOngoingStaleCronJob { constructor( @@ -28,6 +31,10 @@ export class MessagingOngoingStaleCronJob { ) {} @Process(MessagingOngoingStaleCronJob.name) + @SentryCronMonitor( + MessagingOngoingStaleCronJob.name, + MESSAGING_ONGOING_STALE_CRON_PATTERN, + ) async handle(): Promise<void> { const activeWorkspaces = await this.workspaceRepository.find({ where: { diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts index 8229618a2354..3fc555a87c96 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts @@ -4,7 +4,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-add-single-message-to-cache-for-import.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-add-single-message-to-cache-for-import.job.ts index 3f2c2a537901..79c5242b9bc5 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-add-single-message-to-cache-for-import.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-add-single-message-to-cache-for-import.job.ts @@ -1,9 +1,9 @@ -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export type MessagingAddSingleMessageToCacheForImportJobData = { messageExternalId: string; @@ -25,7 +25,7 @@ export class MessagingAddSingleMessageToCacheForImportJob { const { messageExternalId, messageChannelId, workspaceId } = data; await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${messageChannelId}`, + `messages-to-import:${workspaceId}:${messageChannelId}`, [messageExternalId], ); } diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-clean-cache.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-clean-cache.ts index 24e048ce01b3..edb32a3fd717 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-clean-cache.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-clean-cache.ts @@ -1,11 +1,11 @@ import { Logger } from '@nestjs/common'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; export type MessagingCleanCacheJobData = { workspaceId: string; @@ -28,7 +28,7 @@ export class MessagingCleanCacheJob { ); await this.cacheStorage.del( - `messages-to-import:${data.workspaceId}:gmail:${data.messageChannelId}`, + `messages-to-import:${data.workspaceId}:${data.messageChannelId}`, ); this.logger.log( diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts index a51bd35a085b..cc66a1ff5dbc 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts @@ -1,8 +1,8 @@ import { Logger, Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts index f62dc3a1b0cd..a22e1b26a769 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts @@ -1,8 +1,8 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts index 20d23e71a57f..f8ec658d39c8 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts @@ -2,9 +2,9 @@ import { Logger, Scope } from '@nestjs/common'; import { In } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service'; import { @@ -55,20 +55,20 @@ export class MessagingOngoingStaleJob { `Sync for message channel ${messageChannel.id} and workspace ${workspaceId} is stale. Setting sync stage to MESSAGES_IMPORT_PENDING`, ); - await this.messageChannelSyncStatusService.resetSyncStageStartedAt( + await this.messageChannelSyncStatusService.resetSyncStageStartedAt([ messageChannel.id, - ); + ]); switch (messageChannel.syncStage) { case MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING: await this.messageChannelSyncStatusService.schedulePartialMessageListFetch( - messageChannel.id, + [messageChannel.id], ); break; case MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING: - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messageChannelSyncStatusService.scheduleMessagesImport([ messageChannel.id, - ); + ]); break; default: break; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/listeners/messaging-import-manager-message-channel.listener.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/listeners/messaging-import-manager-message-channel.listener.ts index b81118d3a20f..80802c3fb2c4 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/listeners/messaging-import-manager-message-channel.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/listeners/messaging-import-manager-message-channel.listener.ts @@ -1,10 +1,10 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { @@ -19,8 +19,8 @@ export class MessagingMessageImportManagerMessageChannelListener { private readonly messageQueueService: MessageQueueService, ) {} - @OnEvent('messageChannel.deleted') - async handleDeletedEvent( + @OnEvent('messageChannel.destroyed') + async handleDestroyedEvent( payload: WorkspaceEventBatch< ObjectRecordDeleteEvent<MessageChannelWorkspaceEntity> >, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts index b9042cd2fb68..c13c9485cbfc 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts @@ -9,6 +9,7 @@ import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/works import { EmailAliasManagerModule } from 'src/modules/connected-account/email-alias-manager/email-alias-manager.module'; import { RefreshAccessTokenManagerModule } from 'src/modules/connected-account/refresh-access-token-manager/refresh-access-token-manager.module'; import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; +import { MessagingMessageCleanerModule } from 'src/modules/messaging/message-cleaner/messaging-message-cleaner.module'; import { MessagingSingleMessageImportCommand } from 'src/modules/messaging/message-import-manager/commands/messaging-single-message-import.command'; import { MessagingMessageListFetchCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command'; import { MessagingMessagesImportCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command'; @@ -47,6 +48,7 @@ import { MessagingMonitoringModule } from 'src/modules/messaging/monitoring/mess FeatureFlagModule, MessageParticipantManagerModule, MessagingMonitoringModule, + MessagingMessageCleanerModule, ], providers: [ MessagingMessageListFetchCronCommand, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/message-import-exception-handler.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/message-import-exception-handler.service.ts index 55cff5f1660f..6e0dd24fb4f2 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/message-import-exception-handler.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/message-import-exception-handler.service.ts @@ -79,7 +79,7 @@ export class MessageImportExceptionHandlerService { ): Promise<void> { if (messageChannel.throttleFailureCount >= CALENDAR_THROTTLE_MAX_ATTEMPTS) { await this.messageChannelSyncStatusService.markAsFailedUnknownAndFlushMessagesToImport( - messageChannel.id, + [messageChannel.id], workspaceId, ); @@ -92,9 +92,7 @@ export class MessageImportExceptionHandlerService { ); await messageChannelRepository.increment( - { - id: messageChannel.id, - }, + { id: messageChannel.id }, 'throttleFailureCount', 1, ); @@ -102,20 +100,20 @@ export class MessageImportExceptionHandlerService { switch (syncStep) { case MessageImportSyncStep.FULL_MESSAGE_LIST_FETCH: await this.messageChannelSyncStatusService.scheduleFullMessageListFetch( - messageChannel.id, + [messageChannel.id], ); break; case MessageImportSyncStep.PARTIAL_MESSAGE_LIST_FETCH: await this.messageChannelSyncStatusService.schedulePartialMessageListFetch( - messageChannel.id, + [messageChannel.id], ); break; case MessageImportSyncStep.MESSAGES_IMPORT: - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messageChannelSyncStatusService.scheduleMessagesImport([ messageChannel.id, - ); + ]); break; default: @@ -128,7 +126,7 @@ export class MessageImportExceptionHandlerService { workspaceId: string, ): Promise<void> { await this.messageChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( - messageChannel.id, + [messageChannel.id], workspaceId, ); } @@ -139,7 +137,7 @@ export class MessageImportExceptionHandlerService { workspaceId: string, ): Promise<void> { await this.messageChannelSyncStatusService.markAsFailedUnknownAndFlushMessagesToImport( - messageChannel.id, + [messageChannel.id], workspaceId, ); @@ -159,7 +157,7 @@ export class MessageImportExceptionHandlerService { } await this.messageChannelSyncStatusService.resetAndScheduleFullMessageListFetch( - messageChannel.id, + [messageChannel.id], workspaceId, ); } diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service.ts index fbb0d39191b3..8b9072bbefe1 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service.ts @@ -1,15 +1,16 @@ import { Injectable } from '@nestjs/common'; -import { Any } from 'typeorm'; +import { In } from 'typeorm'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; import { MessageImportExceptionHandlerService, MessageImportSyncStep, @@ -25,6 +26,7 @@ export class MessagingFullMessageListFetchService { private readonly twentyORMManager: TwentyORMManager, private readonly messagingGetMessageListService: MessagingGetMessageListService, private readonly messageImportErrorHandlerService: MessageImportExceptionHandlerService, + private readonly messagingMessageCleanerService: MessagingMessageCleanerService, ) {} public async processMessageListFetch( @@ -34,7 +36,7 @@ export class MessagingFullMessageListFetchService { ) { try { await this.messageChannelSyncStatusService.markAsMessagesListFetchOngoing( - messageChannel.id, + [messageChannel.id], ); const { messageExternalIds, nextSyncCursor } = @@ -51,7 +53,6 @@ export class MessagingFullMessageListFetchService { await messageChannelMessageAssociationRepository.find({ where: { messageChannelId: messageChannel.id, - messageExternalId: Any(messageExternalIds), }, }); @@ -61,17 +62,35 @@ export class MessagingFullMessageListFetchService { messageChannelMessageAssociation.messageExternalId, ); - const messageIdsToImport = messageExternalIds.filter( + const messageExternalIdsToImport = messageExternalIds.filter( (messageExternalId) => !existingMessageChannelMessageAssociationsExternalIds.includes( messageExternalId, ), ); - if (messageIdsToImport.length) { + const messageExternalIdsToDelete = + existingMessageChannelMessageAssociationsExternalIds.filter( + (existingMessageCMAExternalId) => + existingMessageCMAExternalId && + !messageExternalIds.includes(existingMessageCMAExternalId), + ); + + if (messageExternalIdsToDelete.length) { + await messageChannelMessageAssociationRepository.delete({ + messageChannelId: messageChannel.id, + messageExternalId: In(messageExternalIdsToDelete), + }); + + await this.messagingMessageCleanerService.cleanWorkspaceThreads( + workspaceId, + ); + } + + if (messageExternalIdsToImport.length) { await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${messageChannel.id}`, - messageIdsToImport, + `messages-to-import:${workspaceId}:${messageChannel.id}`, + messageExternalIdsToImport, ); } @@ -95,9 +114,9 @@ export class MessagingFullMessageListFetchService { }, ); - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messageChannelSyncStatusService.scheduleMessagesImport([ messageChannel.id, - ); + ]); } catch (error) { await this.messageImportErrorHandlerService.handleDriverException( error, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts index dcb590d08597..6017441003ae 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts @@ -1,10 +1,8 @@ import { Injectable, Logger } from '@nestjs/common'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; -import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; @@ -44,7 +42,6 @@ export class MessagingMessagesImportService { @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) private readonly blocklistRepository: BlocklistRepository, private readonly emailAliasManagerService: EmailAliasManagerService, - private readonly isFeatureEnabledService: FeatureFlagService, private readonly twentyORMManager: TwentyORMManager, private readonly messagingGetMessagesService: MessagingGetMessagesService, private readonly messageImportErrorHandlerService: MessageImportExceptionHandlerService, @@ -76,9 +73,9 @@ export class MessagingMessagesImportService { `Messaging import for workspace ${workspaceId} and account ${connectedAccount.id} starting...`, ); - await this.messageChannelSyncStatusService.markAsMessagesImportOngoing( + await this.messageChannelSyncStatusService.markAsMessagesImportOngoing([ messageChannel.id, - ); + ]); try { connectedAccount.accessToken = @@ -111,26 +108,19 @@ export class MessagingMessagesImportService { } } - if ( - await this.isFeatureEnabledService.isFeatureEnabled( - FeatureFlagKey.IsMessagingAliasFetchingEnabled, - workspaceId, - ) - ) { - await this.emailAliasManagerService.refreshHandleAliases( - connectedAccount, - workspaceId, - ); - } + await this.emailAliasManagerService.refreshHandleAliases( + connectedAccount, + workspaceId, + ); messageIdsToFetch = await this.cacheStorage.setPop( - `messages-to-import:${workspaceId}:gmail:${messageChannel.id}`, + `messages-to-import:${workspaceId}:${messageChannel.id}`, MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, ); if (!messageIdsToFetch?.length) { await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( - messageChannel.id, + [messageChannel.id], ); return await this.trackMessageImportCompleted( @@ -151,7 +141,7 @@ export class MessagingMessagesImportService { ); const messagesToSave = filterEmails( - messageChannel.handle, + [messageChannel.handle, ...connectedAccount.handleAliases.split(',')], allMessages, blocklist.map((blocklistItem) => blocklistItem.handle), ); @@ -167,12 +157,12 @@ export class MessagingMessagesImportService { messageIdsToFetch.length < MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE ) { await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( - messageChannel.id, + [messageChannel.id], ); } else { - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messageChannelSyncStatusService.scheduleMessagesImport([ messageChannel.id, - ); + ]); } const messageChannelRepository = @@ -196,7 +186,7 @@ export class MessagingMessagesImportService { ); } catch (error) { await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${messageChannel.id}`, + `messages-to-import:${workspaceId}:${messageChannel.id}`, messageIdsToFetch, ); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-partial-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-partial-message-list-fetch.service.ts index e1ec39c775e0..bdf13895045a 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-partial-message-list-fetch.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-partial-message-list-fetch.service.ts @@ -1,15 +1,16 @@ import { Injectable, Logger } from '@nestjs/common'; -import { Any } from 'typeorm'; +import { In } from 'typeorm'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; import { MessageImportExceptionHandlerService, MessageImportSyncStep, @@ -29,6 +30,7 @@ export class MessagingPartialMessageListFetchService { private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, private readonly twentyORMManager: TwentyORMManager, private readonly messageImportErrorHandlerService: MessageImportExceptionHandlerService, + private readonly messagingMessageCleanerService: MessagingMessageCleanerService, ) {} public async processMessageListFetch( @@ -38,7 +40,7 @@ export class MessagingPartialMessageListFetchService { ): Promise<void> { try { await this.messageChannelSyncStatusService.markAsMessagesListFetchOngoing( - messageChannel.id, + [messageChannel.id], ); const messageChannelRepository = @@ -70,14 +72,14 @@ export class MessagingPartialMessageListFetchService { ); await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( - messageChannel.id, + [messageChannel.id], ); return; } await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${messageChannel.id}`, + `messages-to-import:${workspaceId}:${messageChannel.id}`, messageExternalIds, ); @@ -90,10 +92,16 @@ export class MessagingPartialMessageListFetchService { 'messageChannelMessageAssociation', ); - await messageChannelMessageAssociationRepository.delete({ - messageChannelId: messageChannel.id, - messageExternalId: Any(messageExternalIdsToDelete), - }); + if (messageExternalIdsToDelete.length) { + await messageChannelMessageAssociationRepository.delete({ + messageChannelId: messageChannel.id, + messageExternalId: In(messageExternalIdsToDelete), + }); + + await this.messagingMessageCleanerService.cleanWorkspaceThreads( + workspaceId, + ); + } this.logger.log( `Deleted ${messageExternalIdsToDelete.length} messages for workspace ${workspaceId} and account ${connectedAccount.id}`, @@ -110,9 +118,9 @@ export class MessagingPartialMessageListFetchService { ); } - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messageChannelSyncStatusService.scheduleMessagesImport([ messageChannel.id, - ); + ]); } catch (error) { await this.messageImportErrorHandlerService.handleDriverException( error, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-save-messages-and-enqueue-contact-creation.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-save-messages-and-enqueue-contact-creation.service.ts index 79f93b3e0b51..4080dc08f71f 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-save-messages-and-enqueue-contact-creation.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-save-messages-and-enqueue-contact-creation.service.ts @@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts index 6641ae0a66e8..4278fab5cdf4 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts @@ -3,19 +3,19 @@ import { MessageWithParticipants } from 'src/modules/messaging/message-import-ma // Todo: refactor this into several utils export const filterEmails = ( - messageChannelHandle: string, + messageChannelHandles: string[], messages: MessageWithParticipants[], blocklist: string[], ) => { return filterOutBlocklistedMessages( - messageChannelHandle, + messageChannelHandles, filterOutIcsAttachments(messages), blocklist, ); }; const filterOutBlocklistedMessages = ( - messageChannelHandle: string, + messageChannelHandles: string[], messages: MessageWithParticipants[], blocklist: string[], ) => { @@ -27,7 +27,7 @@ const filterOutBlocklistedMessages = ( return message.participants.every( (participant) => !isEmailBlocklisted( - messageChannelHandle, + messageChannelHandles, participant.handle, blocklist, ), diff --git a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job.ts b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job.ts index 9b3f4b6bfe9f..a72f4671b6ef 100644 --- a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job.ts @@ -1,8 +1,8 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; diff --git a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job.ts b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job.ts index 78f2b80d8937..8d7cc46b2049 100644 --- a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job.ts @@ -1,8 +1,8 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; diff --git a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts index e6b7c59f21c4..8529ebaef6f4 100644 --- a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts @@ -2,9 +2,9 @@ import { Logger } from '@nestjs/common'; import { Any, IsNull } from 'typeorm'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; diff --git a/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-person.listener.ts b/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-person.listener.ts index 8e42990c90c5..1d4a0c6c38aa 100644 --- a/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-person.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-person.listener.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { MessageParticipantMatchParticipantJob, @@ -32,7 +32,10 @@ export class MessageParticipantPersonListener { >, ) { for (const eventPayload of payload.events) { - if (!eventPayload.properties.after.email) { + if ( + !eventPayload.properties.after.emails?.primaryEmail && + !eventPayload.properties.after.email + ) { continue; } @@ -40,7 +43,9 @@ export class MessageParticipantPersonListener { MessageParticipantMatchParticipantJob.name, { workspaceId: payload.workspaceId, - email: eventPayload.properties.after.email, + email: + eventPayload.properties.after.emails?.primaryEmail ?? + eventPayload.properties.after.email, personId: eventPayload.recordId, }, ); @@ -58,13 +63,19 @@ export class MessageParticipantPersonListener { objectRecordUpdateEventChangedProperties( eventPayload.properties.before, eventPayload.properties.after, - ).includes('email') + ).includes('email') || + objectRecordUpdateEventChangedProperties( + eventPayload.properties.before, + eventPayload.properties.after, + ).includes('emails') ) { await this.messageQueueService.add<MessageParticipantUnmatchParticipantJobData>( MessageParticipantUnmatchParticipantJob.name, { workspaceId: payload.workspaceId, - email: eventPayload.properties.before.email, + email: + eventPayload.properties.before.emails?.primaryEmail ?? + eventPayload.properties.before.email, personId: eventPayload.recordId, }, ); @@ -73,7 +84,9 @@ export class MessageParticipantPersonListener { MessageParticipantMatchParticipantJob.name, { workspaceId: payload.workspaceId, - email: eventPayload.properties.after.email, + email: + eventPayload.properties.after.emails?.primaryEmail ?? + eventPayload.properties.after.email, personId: eventPayload.recordId, }, ); diff --git a/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-workspace-member.listener.ts b/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-workspace-member.listener.ts index aeec32548adb..6d093a1cc0a8 100644 --- a/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-workspace-member.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-participant-manager/listeners/message-participant-workspace-member.listener.ts @@ -8,12 +8,12 @@ import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-properties.util'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { MessageParticipantMatchParticipantJob, diff --git a/packages/twenty-server/src/modules/messaging/monitoring/crons/commands/messaging-message-channel-sync-status-monitoring.cron.command.ts b/packages/twenty-server/src/modules/messaging/monitoring/crons/commands/messaging-message-channel-sync-status-monitoring.cron.command.ts index d90fd0b5be45..8553d7cb8909 100644 --- a/packages/twenty-server/src/modules/messaging/monitoring/crons/commands/messaging-message-channel-sync-status-monitoring.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/monitoring/crons/commands/messaging-message-channel-sync-status-monitoring.cron.command.ts @@ -1,12 +1,12 @@ import { Command, CommandRunner } from 'nest-commander'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { MessagingMessageChannelSyncStatusMonitoringCronJob } from 'src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron'; - -const MESSAGING_MESSAGE_CHANNEL_SYNC_STATUS_MONITORING_CRON_PATTERN = - '2/10 * * * *'; //Every 10 minutes, starting at 2 minutes past the hour +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { + MESSAGING_MESSAGE_CHANNEL_SYNC_STATUS_MONITORING_CRON_PATTERN, + MessagingMessageChannelSyncStatusMonitoringCronJob, +} from 'src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.job'; @Command({ name: 'cron:messaging:monitoring:message-channel-sync-status', diff --git a/packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.ts b/packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.job.ts similarity index 51% rename from packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.ts rename to packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.job.ts index 94ac094ffb24..04c1fe6affef 100644 --- a/packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.ts +++ b/packages/twenty-server/src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.job.ts @@ -4,17 +4,22 @@ import { InjectRepository } from '@nestjs/typeorm'; import snakeCase from 'lodash.snakecase'; import { Repository } from 'typeorm'; +import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessagingTelemetryService } from 'src/modules/messaging/monitoring/services/messaging-telemetry.service'; +export const MESSAGING_MESSAGE_CHANNEL_SYNC_STATUS_MONITORING_CRON_PATTERN = + '2/10 * * * *'; //Every 10 minutes, starting at 2 minutes past the hour + @Processor(MessageQueue.cronQueue) export class MessagingMessageChannelSyncStatusMonitoringCronJob { private readonly logger = new Logger( @@ -26,9 +31,14 @@ export class MessagingMessageChannelSyncStatusMonitoringCronJob { private readonly workspaceRepository: Repository<Workspace>, private readonly messagingTelemetryService: MessagingTelemetryService, private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + private readonly exceptionHandlerService: ExceptionHandlerService, ) {} @Process(MessagingMessageChannelSyncStatusMonitoringCronJob.name) + @SentryCronMonitor( + MessagingMessageChannelSyncStatusMonitoringCronJob.name, + MESSAGING_MESSAGE_CHANNEL_SYNC_STATUS_MONITORING_CRON_PATTERN, + ) async handle(): Promise<void> { this.logger.log('Starting message channel sync status monitoring...'); @@ -46,27 +56,35 @@ export class MessagingMessageChannelSyncStatusMonitoringCronJob { }); for (const activeWorkspace of activeWorkspaces) { - const messageChannelRepository = - await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>( - activeWorkspace.id, - 'messageChannel', - ); - const messageChannels = await messageChannelRepository.find({ - select: ['id', 'syncStatus', 'connectedAccountId'], - }); + try { + const messageChannelRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>( + activeWorkspace.id, + 'messageChannel', + ); + const messageChannels = await messageChannelRepository.find({ + select: ['id', 'syncStatus', 'connectedAccountId'], + }); - for (const messageChannel of messageChannels) { - if (!messageChannel.syncStatus) { - continue; + for (const messageChannel of messageChannels) { + if (!messageChannel.syncStatus) { + continue; + } + await this.messagingTelemetryService.track({ + eventName: `message_channel.monitoring.sync_status.${snakeCase( + messageChannel.syncStatus, + )}`, + workspaceId: activeWorkspace.id, + connectedAccountId: messageChannel.connectedAccountId, + messageChannelId: messageChannel.id, + message: messageChannel.syncStatus, + }); } - await this.messagingTelemetryService.track({ - eventName: `message_channel.monitoring.sync_status.${snakeCase( - messageChannel.syncStatus, - )}`, - workspaceId: activeWorkspace.id, - connectedAccountId: messageChannel.connectedAccountId, - messageChannelId: messageChannel.id, - message: messageChannel.syncStatus, + } catch (error) { + this.exceptionHandlerService.captureExceptions([error], { + user: { + workspaceId: activeWorkspace.id, + }, }); } } diff --git a/packages/twenty-server/src/modules/messaging/monitoring/messaging-monitoring.module.ts b/packages/twenty-server/src/modules/messaging/monitoring/messaging-monitoring.module.ts index 8173ff26d053..e0e77771222d 100644 --- a/packages/twenty-server/src/modules/messaging/monitoring/messaging-monitoring.module.ts +++ b/packages/twenty-server/src/modules/messaging/monitoring/messaging-monitoring.module.ts @@ -7,7 +7,7 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; import { MessagingMessageChannelSyncStatusMonitoringCronCommand } from 'src/modules/messaging/monitoring/crons/commands/messaging-message-channel-sync-status-monitoring.cron.command'; -import { MessagingMessageChannelSyncStatusMonitoringCronJob } from 'src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron'; +import { MessagingMessageChannelSyncStatusMonitoringCronJob } from 'src/modules/messaging/monitoring/crons/jobs/messaging-message-channel-sync-status-monitoring.cron.job'; import { MessagingTelemetryService } from 'src/modules/messaging/monitoring/services/messaging-telemetry.service'; @Module({ diff --git a/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts b/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts index 0234f7fbcb4e..d9455ed17bcd 100644 --- a/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts +++ b/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; type MessagingTelemetryTrackInput = { eventName: string; @@ -29,8 +29,8 @@ export class MessagingTelemetryService { }: MessagingTelemetryTrackInput): Promise<void> { await this.analyticsService.create( { - type: 'track', - data: { + action: 'monitoring', + payload: { eventName: `messaging.${eventName}`, workspaceId, userId, @@ -41,9 +41,6 @@ export class MessagingTelemetryService { }, userId, workspaceId, - '', // voluntarely not retrieving this - '', // to avoid slowing down - this.environmentService.get('SERVER_URL'), ); } } diff --git a/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts b/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts index 25bd9c53c294..99507c32dcfc 100644 --- a/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts @@ -32,7 +32,6 @@ import { JobWorkspaceEntity } from 'src/funnelmink/entities/funnelmink-job.works labelPlural: 'Note Targets', description: 'A note target', icon: 'IconCheckbox', - softDelete: true, }) @WorkspaceIsSystem() export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts b/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts index a8aa5b9342c4..997e8aca194c 100644 --- a/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts +++ b/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts @@ -30,7 +30,6 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o description: 'A note', icon: 'IconNotes', labelIdentifierStandardId: NOTE_STANDARD_FIELD_IDS.title, - softDelete: true, }) export class NoteWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ @@ -78,15 +77,14 @@ export class NoteWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceRelation({ standardId: NOTE_STANDARD_FIELD_IDS.noteTargets, - label: 'Targets', + label: 'Relations', description: 'Note targets', - icon: 'IconCheckbox', + icon: 'IconArrowUpRight', type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => NoteTargetWorkspaceEntity, onDelete: RelationOnDeleteAction.SET_NULL, }) @WorkspaceIsNullable() - @WorkspaceIsSystem() noteTargets: Relation<NoteTargetWorkspaceEntity[]>; @WorkspaceRelation({ diff --git a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts index 3acd4dc88ebd..142b000b9a0d 100644 --- a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts @@ -39,7 +39,6 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o description: 'An opportunity', icon: 'IconTargetArrow', labelIdentifierStandardId: OPPORTUNITY_STANDARD_FIELD_IDS.name, - softDelete: true, }) @WorkspaceIsNotAuditLogged() export class OpportunityWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts index 362380d76a33..666cb9c66157 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts @@ -4,8 +4,10 @@ import { ActorMetadata, FieldActorSource, } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; +import { EmailsMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/emails.composite-type'; import { FullNameMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/full-name.composite-type'; import { LinksMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/links.composite-type'; +import { PhonesMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { RelationMetadataType, @@ -14,6 +16,7 @@ import { import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @@ -35,7 +38,6 @@ import { FUNNELMINK_IDS, } from 'src/funnelmink/funnelmink-server-constants'; import { WorkOrderWorkspaceEntity } from 'src/funnelmink/entities/funnelmink-workorder.workspace-entity'; -import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator'; import { AddressMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/address.composite-type'; @WorkspaceEntity({ @@ -47,7 +49,6 @@ import { AddressMetadata } from 'src/engine/metadata-modules/field-metadata/comp icon: 'IconUser', labelIdentifierStandardId: PERSON_STANDARD_FIELD_IDS.name, imageIdentifierStandardId: PERSON_STANDARD_FIELD_IDS.avatarUrl, - softDelete: true, }) export class PersonWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ @@ -67,8 +68,18 @@ export class PersonWorkspaceEntity extends BaseWorkspaceEntity { description: 'Contact’s Email', icon: 'IconMail', }) + @WorkspaceIsDeprecated() email: string; + @WorkspaceField({ + standardId: PERSON_STANDARD_FIELD_IDS.emails, + type: FieldMetadataType.EMAILS, + label: 'Emails', + description: 'Contact’s Emails', + icon: 'IconMail', + }) + emails: EmailsMetadata; + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.linkedinLink, type: FieldMetadataType.LINKS, @@ -105,8 +116,27 @@ export class PersonWorkspaceEntity extends BaseWorkspaceEntity { description: 'Contact’s phone number', icon: 'IconPhone', }) + @WorkspaceIsDeprecated() phone: string; + @WorkspaceField({ + standardId: PERSON_STANDARD_FIELD_IDS.phones, + type: FieldMetadataType.PHONES, + label: 'Phones', + description: 'Contact’s phone numbers', + icon: 'IconPhone', + }) + phones: PhonesMetadata; + + @WorkspaceField({ + standardId: PERSON_STANDARD_FIELD_IDS.city, + type: FieldMetadataType.TEXT, + label: 'City', + description: 'Contact’s city', + icon: 'IconMap', + }) + city: string; + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.avatarUrl, type: FieldMetadataType.TEXT, diff --git a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor.ts b/packages/twenty-server/src/modules/serverless/workflow-actions/code.workflow-action.ts similarity index 65% rename from packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor.ts rename to packages/twenty-server/src/modules/serverless/workflow-actions/code.workflow-action.ts index fb9dbf5cb664..1e42dcf81eb0 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor.ts +++ b/packages/twenty-server/src/modules/serverless/workflow-actions/code.workflow-action.ts @@ -2,16 +2,15 @@ import { Injectable } from '@nestjs/common'; import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service'; import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; -import { WorkflowResult } from 'src/modules/workflow/common/types/workflow-result.type'; -import { WorkflowCodeStep } from 'src/modules/workflow/common/types/workflow-step.type'; +import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/types/workflow-action-result.type'; +import { WorkflowCodeStep } from 'src/modules/workflow/workflow-executor/types/workflow-action.type'; import { WorkflowStepExecutorException, WorkflowStepExecutorExceptionCode, -} from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.exception'; -import { WorkflowStepExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.interface'; +} from 'src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception'; @Injectable() -export class CodeActionExecutor implements WorkflowStepExecutor { +export class CodeWorkflowAction { constructor( private readonly serverlessFunctionService: ServerlessFunctionService, private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory, @@ -23,7 +22,7 @@ export class CodeActionExecutor implements WorkflowStepExecutor { }: { step: WorkflowCodeStep; payload?: object; - }): Promise<WorkflowResult> { + }): Promise<WorkflowActionResult> { const { workspaceId } = this.scopedWorkspaceContextFactory.create(); if (!workspaceId) { @@ -37,9 +36,13 @@ export class CodeActionExecutor implements WorkflowStepExecutor { await this.serverlessFunctionService.executeOneServerlessFunction( step.settings.serverlessFunctionId, workspaceId, - payload, + payload || {}, ); - return { data: result.data, ...(result.error && { error: result.error }) }; + if (result.error) { + return { error: result.error }; + } + + return { result: result.data || {} }; } } diff --git a/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts b/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts index 22ed24d89f41..9d2fdd518bb0 100644 --- a/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts @@ -32,7 +32,6 @@ import { JobWorkspaceEntity } from 'src/funnelmink/entities/funnelmink-job.works labelPlural: 'Task Targets', description: 'An task target', icon: 'IconCheckbox', - softDelete: true, }) @WorkspaceIsSystem() export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts b/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts index d087d69c6fbd..d498636b99f0 100644 --- a/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts +++ b/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts @@ -32,7 +32,6 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta description: 'A task', icon: 'IconCheckbox', labelIdentifierStandardId: TASK_STANDARD_FIELD_IDS.title, - softDelete: true, }) export class TaskWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceField({ @@ -116,15 +115,14 @@ export class TaskWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceRelation({ standardId: TASK_STANDARD_FIELD_IDS.taskTargets, - label: 'Targets', + label: 'Relations', description: 'Task targets', - icon: 'IconCheckbox', + icon: 'IconArrowUpRight', type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => TaskTargetWorkspaceEntity, onDelete: RelationOnDeleteAction.SET_NULL, }) @WorkspaceIsNullable() - @WorkspaceIsSystem() taskTargets: Relation<TaskTargetWorkspaceEntity[]>; @WorkspaceRelation({ diff --git a/packages/twenty-server/src/modules/timeline/jobs/create-audit-log-from-internal-event.ts b/packages/twenty-server/src/modules/timeline/jobs/create-audit-log-from-internal-event.ts index d820020d3efc..b831c0c3815d 100644 --- a/packages/twenty-server/src/modules/timeline/jobs/create-audit-log-from-internal-event.ts +++ b/packages/twenty-server/src/modules/timeline/jobs/create-audit-log-from-internal-event.ts @@ -1,7 +1,7 @@ -import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { AuditLogRepository } from 'src/modules/timeline/repositiories/audit-log.repository'; diff --git a/packages/twenty-server/src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job.ts b/packages/twenty-server/src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job.ts index c73479745c7c..89d3721632bb 100644 --- a/packages/twenty-server/src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job.ts +++ b/packages/twenty-server/src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job.ts @@ -1,7 +1,7 @@ -import { ObjectRecordBaseEvent } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { TimelineActivityService } from 'src/modules/timeline/services/timeline-activity.service'; diff --git a/packages/twenty-server/src/modules/timeline/repositiories/timeline-activity.repository.ts b/packages/twenty-server/src/modules/timeline/repositiories/timeline-activity.repository.ts index 1ab962ea9cf1..ec858797e536 100644 --- a/packages/twenty-server/src/modules/timeline/repositiories/timeline-activity.repository.ts +++ b/packages/twenty-server/src/modules/timeline/repositiories/timeline-activity.repository.ts @@ -5,7 +5,7 @@ import { EntityManager } from 'typeorm'; import { Record } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { objectRecordDiffMerge } from 'src/engine/integrations/event-emitter/utils/object-record-diff-merge'; +import { objectRecordDiffMerge } from 'src/engine/core-modules/event-emitter/utils/object-record-diff-merge'; @Injectable() export class TimelineActivityRepository { diff --git a/packages/twenty-server/src/modules/timeline/services/timeline-activity.service.ts b/packages/twenty-server/src/modules/timeline/services/timeline-activity.service.ts index 963a65d5f35f..12dfe5a52f17 100644 --- a/packages/twenty-server/src/modules/timeline/services/timeline-activity.service.ts +++ b/packages/twenty-server/src/modules/timeline/services/timeline-activity.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { ObjectRecordBaseEventWithNameAndWorkspaceId } from 'src/engine/integrations/event-emitter/types/object-record.base.event'; +import { ObjectRecordBaseEventWithNameAndWorkspaceId } from 'src/engine/core-modules/event-emitter/types/object-record.base.event'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository'; diff --git a/packages/twenty-server/src/modules/view/services/view.service.ts b/packages/twenty-server/src/modules/view/services/view.service.ts index ed34f8e81dc4..92044d999c0d 100644 --- a/packages/twenty-server/src/modules/view/services/view.service.ts +++ b/packages/twenty-server/src/modules/view/services/view.service.ts @@ -23,7 +23,7 @@ export class ViewService { fieldId: string; viewsIds: string[]; positions?: { - [key: string]: number; + [viewId: string]: number; }[]; size?: number; }) { @@ -98,4 +98,26 @@ export class ViewService { ); } } + + async getViewsIdsForObjectMetadataId({ + workspaceId, + objectMetadataId, + }: { + workspaceId: string; + objectMetadataId: string; + }) { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'view', + ); + + return viewRepository + .find({ + where: { + objectMetadataId: objectMetadataId, + }, + }) + .then((views) => views.map((view) => view.id)); + } } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts index 149171e6eb7f..3e45fee95d60 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts @@ -1,18 +1,18 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { VIEW_FILTER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; -import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { VIEW_FILTER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewFilter, diff --git a/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts index be3bd0a1274b..8c8431c00e22 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; import { ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/view-filter.workspace-entity'; import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; @@ -135,4 +136,16 @@ export class ViewWorkspaceEntity extends BaseWorkspaceEntity { }) @WorkspaceIsNullable() viewSorts: Relation<ViewSortWorkspaceEntity[]>; + + @WorkspaceRelation({ + standardId: VIEW_STANDARD_FIELD_IDS.favorites, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Favorites', + description: 'Favorites linked to the view', + icon: 'IconHeart', + inverseSideTarget: () => FavoriteWorkspaceEntity, + onDelete: RelationOnDeleteAction.CASCADE, + }) + @WorkspaceIsSystem() + favorites: Relation<FavoriteWorkspaceEntity[]>; } diff --git a/packages/twenty-server/src/modules/workflow/common/exceptions/workflow-query-validation.exception.ts b/packages/twenty-server/src/modules/workflow/common/exceptions/workflow-query-validation.exception.ts new file mode 100644 index 000000000000..7ff0fb35daa8 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/exceptions/workflow-query-validation.exception.ts @@ -0,0 +1,11 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkflowQueryValidationException extends CustomException { + constructor(message: string, code: WorkflowQueryValidationExceptionCode) { + super(message, code); + } +} + +export enum WorkflowQueryValidationExceptionCode { + FORBIDDEN = 'FORBIDDEN', +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.post-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.post-query.hook.ts new file mode 100644 index 000000000000..6d163d03c2e4 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.post-query.hook.ts @@ -0,0 +1,42 @@ +import { WorkspaceQueryPostHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { + WorkflowVersionStatus, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +@WorkspaceQueryHook({ + key: `workflow.createMany`, + type: WorkspaceQueryHookType.PostHook, +}) +export class WorkflowCreateManyPostQueryHook + implements WorkspaceQueryPostHookInstance +{ + constructor(private readonly twentyORMManager: TwentyORMManager) {} + + async execute( + _authContext: AuthContext, + _objectName: string, + payload: WorkflowWorkspaceEntity[], + ): Promise<void> { + const workflowVersionRepository = + await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( + 'workflowVersion', + ); + + await Promise.all( + payload.map((workflow) => { + return workflowVersionRepository.insert({ + workflowId: workflow.id, + status: WorkflowVersionStatus.DRAFT, + name: 'v1', + }); + }), + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.pre-query.hook.ts new file mode 100644 index 000000000000..ecff415a8097 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-many.pre-query.hook.ts @@ -0,0 +1,24 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { assertWorkflowStatusesNotSetOrEmpty } from 'src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +@WorkspaceQueryHook(`workflow.createMany`) +export class WorkflowCreateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute( + _authContext: AuthContext, + _objectName: string, + payload: CreateManyResolverArgs<WorkflowWorkspaceEntity>, + ): Promise<CreateManyResolverArgs<WorkflowWorkspaceEntity>> { + payload.data.forEach((workflow) => { + assertWorkflowStatusesNotSetOrEmpty(workflow.statuses); + }); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.post-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.post-query.hook.ts new file mode 100644 index 000000000000..78f7f98123be --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.post-query.hook.ts @@ -0,0 +1,40 @@ +import { WorkspaceQueryPostHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { + WorkflowVersionStatus, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +@WorkspaceQueryHook({ + key: `workflow.createOne`, + type: WorkspaceQueryHookType.PostHook, +}) +export class WorkflowCreateOnePostQueryHook + implements WorkspaceQueryPostHookInstance +{ + constructor(private readonly twentyORMManager: TwentyORMManager) {} + + async execute( + _authContext: AuthContext, + _objectName: string, + payload: WorkflowWorkspaceEntity[], + ): Promise<void> { + const workflow = payload[0]; + + const workflowVersionRepository = + await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( + 'workflowVersion', + ); + + await workflowVersionRepository.insert({ + workflowId: workflow.id, + status: WorkflowVersionStatus.DRAFT, + name: 'v1', + }); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.pre-query.hook.ts new file mode 100644 index 000000000000..f00b9515b6e1 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-create-one.pre-query.hook.ts @@ -0,0 +1,22 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { assertWorkflowStatusesNotSetOrEmpty } from 'src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +@WorkspaceQueryHook(`workflow.createOne`) +export class WorkflowCreateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute( + _authContext: AuthContext, + _objectName: string, + payload: CreateOneResolverArgs<WorkflowWorkspaceEntity>, + ): Promise<CreateOneResolverArgs<WorkflowWorkspaceEntity>> { + assertWorkflowStatusesNotSetOrEmpty(payload.data.statuses); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-query-hook.module.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-query-hook.module.ts new file mode 100644 index 000000000000..bbcde310b9c3 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-query-hook.module.ts @@ -0,0 +1,38 @@ +import { Module } from '@nestjs/common'; + +import { WorkflowCreateManyPostQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-create-many.post-query.hook'; +import { WorkflowCreateManyPreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-create-many.pre-query.hook'; +import { WorkflowCreateOnePreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-create-one.pre-query.hook'; +import { WorkflowRunCreateManyPreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-run-create-many.pre-query.hook'; +import { WorkflowRunCreateOnePreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-run-create-one.pre-query.hook'; +import { WorkflowUpdateManyPreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-update-many.pre-query.hook'; +import { WorkflowUpdateOnePreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-update-one.pre-query.hook'; +import { WorkflowVersionCreateManyPreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-version-create-many.pre-query.hook'; +import { WorkflowVersionCreateOnePreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-version-create-one.pre-query.hook'; +import { WorkflowVersionDeleteManyPreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-version-delete-many.pre-query.hook'; +import { WorkflowVersionDeleteOnePreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-version-delete-one.pre-query.hook'; +import { WorkflowVersionUpdateManyPreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-version-update-many.pre-query.hook'; +import { WorkflowVersionUpdateOnePreQueryHook } from 'src/modules/workflow/common/query-hooks/workflow-version-update-one.pre-query.hook'; +import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; +import { WorkflowVersionValidationWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service'; + +@Module({ + providers: [ + WorkflowCreateOnePreQueryHook, + WorkflowCreateManyPreQueryHook, + WorkflowUpdateOnePreQueryHook, + WorkflowUpdateManyPreQueryHook, + WorkflowRunCreateOnePreQueryHook, + WorkflowRunCreateManyPreQueryHook, + WorkflowVersionCreateOnePreQueryHook, + WorkflowVersionCreateManyPreQueryHook, + WorkflowVersionUpdateOnePreQueryHook, + WorkflowVersionUpdateManyPreQueryHook, + WorkflowVersionDeleteOnePreQueryHook, + WorkflowVersionDeleteManyPreQueryHook, + WorkflowCreateManyPostQueryHook, + WorkflowVersionValidationWorkspaceService, + WorkflowCommonWorkspaceService, + ], +}) +export class WorkflowQueryHookModule {} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-many.pre-query.hook.ts new file mode 100644 index 000000000000..b598f43a73be --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-many.pre-query.hook.ts @@ -0,0 +1,21 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; + +@WorkspaceQueryHook(`workflowRun.createMany`) +export class WorkflowRunCreateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<CreateManyResolverArgs<WorkflowRunWorkspaceEntity>> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-one.pre-query.hook.ts new file mode 100644 index 000000000000..0f103947727d --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-create-one.pre-query.hook.ts @@ -0,0 +1,21 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; + +@WorkspaceQueryHook(`workflowRun.createOne`) +export class WorkflowRunCreateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<CreateOneResolverArgs<WorkflowRunWorkspaceEntity>> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-many.pre-query.hook.ts new file mode 100644 index 000000000000..4f791dcad095 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-many.pre-query.hook.ts @@ -0,0 +1,21 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { DeleteManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; + +@WorkspaceQueryHook(`workflowRun.deleteMany`) +export class WorkflowRunDeleteManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<DeleteManyResolverArgs<WorkflowRunWorkspaceEntity>> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-one.pre-query.hook.ts new file mode 100644 index 000000000000..29bd27814742 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-delete-one.pre-query.hook.ts @@ -0,0 +1,20 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; + +@WorkspaceQueryHook(`workflowRun.deleteOne`) +export class WorkflowRunDeleteOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<DeleteOneResolverArgs> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-many.pre-query.hook.ts new file mode 100644 index 000000000000..ceb835b42553 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-many.pre-query.hook.ts @@ -0,0 +1,21 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { UpdateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; + +@WorkspaceQueryHook(`workflowRun.updateMany`) +export class WorkflowRunUpdateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<UpdateManyResolverArgs<WorkflowRunWorkspaceEntity>> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-one.pre-query.hook.ts new file mode 100644 index 000000000000..385da0f9dbce --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-run-update-one.pre-query.hook.ts @@ -0,0 +1,21 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; + +@WorkspaceQueryHook(`workflowRun.updateOne`) +export class WorkflowRunUpdateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<UpdateOneResolverArgs<WorkflowRunWorkspaceEntity>> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-many.pre-query.hook.ts new file mode 100644 index 000000000000..fa802edb2fa0 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-many.pre-query.hook.ts @@ -0,0 +1,21 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { UpdateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +@WorkspaceQueryHook(`workflow.updateMany`) +export class WorkflowUpdateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise<UpdateManyResolverArgs<WorkflowWorkspaceEntity>> { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-one.pre-query.hook.ts new file mode 100644 index 000000000000..0c57c119cc90 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-update-one.pre-query.hook.ts @@ -0,0 +1,22 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { assertWorkflowStatusesNotSet } from 'src/modules/workflow/common/utils/assert-workflow-statuses-not-set'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +@WorkspaceQueryHook(`workflow.updateOne`) +export class WorkflowUpdateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute( + _authContext: AuthContext, + _objectName: string, + payload: UpdateOneResolverArgs<WorkflowWorkspaceEntity>, + ): Promise<UpdateOneResolverArgs<WorkflowWorkspaceEntity>> { + assertWorkflowStatusesNotSet(payload.data.statuses); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-many.pre-query.hook.ts new file mode 100644 index 000000000000..51849295a70f --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-many.pre-query.hook.ts @@ -0,0 +1,37 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { + CreateManyResolverArgs, + CreateOneResolverArgs, +} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { WorkflowVersionValidationWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +@WorkspaceQueryHook(`workflowVersion.createMany`) +export class WorkflowVersionCreateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + constructor( + private readonly workflowVersionValidationWorkspaceService: WorkflowVersionValidationWorkspaceService, + ) {} + + async execute( + _authContext: AuthContext, + _objectName: string, + payload: CreateManyResolverArgs<WorkflowVersionWorkspaceEntity>, + ): Promise<CreateManyResolverArgs<WorkflowVersionWorkspaceEntity>> { + await Promise.all( + payload.data.map(async (workflowVersion) => { + await this.workflowVersionValidationWorkspaceService.validateWorkflowVersionForCreateOne( + { + data: workflowVersion, + } satisfies CreateOneResolverArgs<WorkflowVersionWorkspaceEntity>, + ); + }), + ); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-one.pre-query.hook.ts new file mode 100644 index 000000000000..0741ec96d39d --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-create-one.pre-query.hook.ts @@ -0,0 +1,28 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { WorkflowVersionValidationWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +@WorkspaceQueryHook(`workflowVersion.createOne`) +export class WorkflowVersionCreateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + constructor( + private readonly workflowVersionValidationWorkspaceService: WorkflowVersionValidationWorkspaceService, + ) {} + + async execute( + _authContext: AuthContext, + _objectName: string, + payload: CreateOneResolverArgs<WorkflowVersionWorkspaceEntity>, + ): Promise<CreateOneResolverArgs<WorkflowVersionWorkspaceEntity>> { + await this.workflowVersionValidationWorkspaceService.validateWorkflowVersionForCreateOne( + payload, + ); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-many.pre-query.hook.ts new file mode 100644 index 000000000000..35279e1e347c --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-many.pre-query.hook.ts @@ -0,0 +1,23 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { DeleteManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +@WorkspaceQueryHook(`workflowVersion.deleteMany`) +export class WorkflowVersionDeleteManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise< + DeleteManyResolverArgs<WorkflowVersionWorkspaceEntity> + > { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-one.pre-query.hook.ts new file mode 100644 index 000000000000..75304e77e24c --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-delete-one.pre-query.hook.ts @@ -0,0 +1,27 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { WorkflowVersionValidationWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service'; + +@WorkspaceQueryHook(`workflowVersion.deleteOne`) +export class WorkflowVersionDeleteOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + constructor( + private readonly workflowVersionValidationWorkspaceService: WorkflowVersionValidationWorkspaceService, + ) {} + + async execute( + _authContext: AuthContext, + _objectName: string, + payload: DeleteOneResolverArgs, + ): Promise<DeleteOneResolverArgs> { + await this.workflowVersionValidationWorkspaceService.validateWorkflowVersionForDeleteOne( + payload, + ); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-many.pre-query.hook.ts new file mode 100644 index 000000000000..5a8e52060f6a --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-many.pre-query.hook.ts @@ -0,0 +1,23 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { UpdateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +@WorkspaceQueryHook(`workflowVersion.updateMany`) +export class WorkflowVersionUpdateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ + async execute(): Promise< + UpdateManyResolverArgs<WorkflowVersionWorkspaceEntity> + > { + throw new WorkflowQueryValidationException( + 'Method not allowed.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-one.pre-query.hook.ts new file mode 100644 index 000000000000..584e834d82db --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/query-hooks/workflow-version-update-one.pre-query.hook.ts @@ -0,0 +1,28 @@ +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { WorkflowVersionValidationWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +@WorkspaceQueryHook(`workflowVersion.updateOne`) +export class WorkflowVersionUpdateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ + constructor( + private readonly workflowVersionValidationWorkspaceService: WorkflowVersionValidationWorkspaceService, + ) {} + + async execute( + _authContext: AuthContext, + _objectName: string, + payload: UpdateOneResolverArgs<WorkflowVersionWorkspaceEntity>, + ): Promise<UpdateOneResolverArgs<WorkflowVersionWorkspaceEntity>> { + await this.workflowVersionValidationWorkspaceService.validateWorkflowVersionForUpdateOne( + payload, + ); + + return payload; + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts index 5324aaf6323f..80545fe7897d 100644 --- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts @@ -21,16 +21,17 @@ import { import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; -import { WorkflowStep } from 'src/modules/workflow/common/types/workflow-step.type'; -import { WorkflowTrigger } from 'src/modules/workflow/common/types/workflow-trigger.type'; +import { WorkflowStep } from 'src/modules/workflow/workflow-executor/types/workflow-action.type'; +import { WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type'; export enum WorkflowVersionStatus { DRAFT = 'DRAFT', ACTIVE = 'ACTIVE', DEACTIVATED = 'DEACTIVATED', + ARCHIVED = 'ARCHIVED', } -export const WorkflowVersionStatusOptions = [ +const WorkflowVersionStatusOptions = [ { value: WorkflowVersionStatus.DRAFT, label: 'Draft', @@ -47,7 +48,13 @@ export const WorkflowVersionStatusOptions = [ value: WorkflowVersionStatus.DEACTIVATED, label: 'Deactivated', position: 2, - color: 'gray', + color: 'red', + }, + { + value: WorkflowVersionStatus.ARCHIVED, + label: 'Archived', + position: 3, + color: 'grey', }, ]; diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts index 455a7e02ba38..98dd40417e35 100644 --- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts @@ -18,11 +18,34 @@ import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity'; import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; -import { - WorkflowVersionStatus, - WorkflowVersionStatusOptions, - WorkflowVersionWorkspaceEntity, -} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +export enum WorkflowStatus { + DRAFT = 'DRAFT', + ACTIVE = 'ACTIVE', + DEACTIVATED = 'DEACTIVATED', +} + +const WorkflowStatusOptions = [ + { + value: WorkflowStatus.DRAFT, + label: 'Draft', + position: 0, + color: 'yellow', + }, + { + value: WorkflowStatus.ACTIVE, + label: 'Active', + position: 1, + color: 'green', + }, + { + value: WorkflowStatus.DEACTIVATED, + label: 'Deactivated', + position: 2, + color: 'grey', + }, +]; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.workflow, @@ -61,10 +84,10 @@ export class WorkflowWorkspaceEntity extends BaseWorkspaceEntity { type: FieldMetadataType.MULTI_SELECT, label: 'Statuses', description: 'The current statuses of the workflow versions', - options: WorkflowVersionStatusOptions, + options: WorkflowStatusOptions, }) @WorkspaceIsNullable() - statuses: WorkflowVersionStatus[] | null; + statuses: WorkflowStatus[] | null; @WorkspaceField({ standardId: WORKFLOW_STANDARD_FIELD_IDS.position, diff --git a/packages/twenty-server/src/modules/workflow/common/types/workflow-result.type.ts b/packages/twenty-server/src/modules/workflow/common/types/workflow-result.type.ts deleted file mode 100644 index 613ad5a99018..000000000000 --- a/packages/twenty-server/src/modules/workflow/common/types/workflow-result.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -type WorkflowError = { - errorType: string; - errorMessage: string; - stackTrace: string; -}; - -export type WorkflowResult = { - data: object | null; - error?: WorkflowError; -}; diff --git a/packages/twenty-server/src/modules/workflow/common/types/workflow-settings.type.ts b/packages/twenty-server/src/modules/workflow/common/types/workflow-settings.type.ts deleted file mode 100644 index dde3025dfe6e..000000000000 --- a/packages/twenty-server/src/modules/workflow/common/types/workflow-settings.type.ts +++ /dev/null @@ -1,14 +0,0 @@ -type BaseWorkflowSettings = { - errorHandlingOptions: { - retryOnFailure: { - value: boolean; - }; - continueOnFailure: { - value: boolean; - }; - }; -}; - -export type WorkflowCodeSettings = BaseWorkflowSettings & { - serverlessFunctionId: string; -}; diff --git a/packages/twenty-server/src/modules/workflow/common/types/workflow-step.type.ts b/packages/twenty-server/src/modules/workflow/common/types/workflow-step.type.ts deleted file mode 100644 index ef3c7069662f..000000000000 --- a/packages/twenty-server/src/modules/workflow/common/types/workflow-step.type.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { WorkflowCodeSettings } from 'src/modules/workflow/common/types/workflow-settings.type'; - -export enum WorkflowStepType { - CODE_ACTION = 'CODE_ACTION', -} - -type BaseWorkflowStep = { - id: string; - name: string; - valid: boolean; -}; - -export type WorkflowCodeStep = BaseWorkflowStep & { - type: WorkflowStepType.CODE_ACTION; - settings: WorkflowCodeSettings; -}; - -export type WorkflowStep = WorkflowCodeStep; diff --git a/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty.ts b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty.ts new file mode 100644 index 000000000000..ca9b73197581 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set-or-empty.ts @@ -0,0 +1,16 @@ +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +export const assertWorkflowStatusesNotSetOrEmpty = ( + statuses?: WorkflowStatus[] | null, +) => { + if (statuses && statuses.length > 0) { + throw new WorkflowQueryValidationException( + 'Statuses cannot be set manually.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +}; diff --git a/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set.ts b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set.ts new file mode 100644 index 000000000000..e16f026c787d --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-statuses-not-set.ts @@ -0,0 +1,16 @@ +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +export const assertWorkflowStatusesNotSet = ( + statuses?: WorkflowStatus[] | null, +) => { + if (statuses) { + throw new WorkflowQueryValidationException( + 'Statuses cannot be set manually.', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +}; diff --git a/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-is-draft.util.ts b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-is-draft.util.ts new file mode 100644 index 000000000000..563a3d942cc2 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-is-draft.util.ts @@ -0,0 +1,19 @@ +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { + WorkflowVersionStatus, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; + +export const assertWorkflowVersionIsDraft = ( + workflowVersion: WorkflowVersionWorkspaceEntity, +) => { + if (workflowVersion.status !== WorkflowVersionStatus.DRAFT) { + throw new WorkflowQueryValidationException( + 'Workflow version is not in draft status', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } +}; diff --git a/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-trigger-is-defined.util.ts b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-trigger-is-defined.util.ts new file mode 100644 index 000000000000..c102f9ecedbf --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/utils/assert-workflow-version-trigger-is-defined.util.ts @@ -0,0 +1,22 @@ +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { + WorkflowTriggerException, + WorkflowTriggerExceptionCode, +} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception'; +import { WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type'; + +export function assertWorkflowVersionTriggerIsDefined( + workflowVersion: WorkflowVersionWorkspaceEntity, +): asserts workflowVersion is Omit< + WorkflowVersionWorkspaceEntity, + 'trigger' +> & { + trigger: WorkflowTrigger; +} { + if (!workflowVersion.trigger) { + throw new WorkflowTriggerException( + 'Workflow version does not contain trigger', + WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/common/workflow-common.module.ts b/packages/twenty-server/src/modules/workflow/common/workflow-common.module.ts index 009da5aa8119..fc23aa8ff88a 100644 --- a/packages/twenty-server/src/modules/workflow/common/workflow-common.module.ts +++ b/packages/twenty-server/src/modules/workflow/common/workflow-common.module.ts @@ -1,8 +1,10 @@ import { Module } from '@nestjs/common'; -import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workflow-common.workspace-service'; +import { WorkflowQueryHookModule } from 'src/modules/workflow/common/query-hooks/workflow-query-hook.module'; +import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; @Module({ + imports: [WorkflowQueryHookModule], providers: [WorkflowCommonWorkspaceService], exports: [WorkflowCommonWorkspaceService], }) diff --git a/packages/twenty-server/src/modules/workflow/common/workflow-common.workspace-service.ts b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts similarity index 53% rename from packages/twenty-server/src/modules/workflow/common/workflow-common.workspace-service.ts rename to packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts index cfb44ea261cc..a9688e0a9cce 100644 --- a/packages/twenty-server/src/modules/workflow/common/workflow-common.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts @@ -2,21 +2,25 @@ import { Injectable } from '@nestjs/common'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; -import { WorkflowTrigger } from 'src/modules/workflow/common/types/workflow-trigger.type'; import { WorkflowTriggerException, WorkflowTriggerExceptionCode, -} from 'src/modules/workflow/workflow-trigger/workflow-trigger.exception'; +} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception'; @Injectable() export class WorkflowCommonWorkspaceService { constructor(private readonly twentyORMManager: TwentyORMManager) {} - async getWorkflowVersionOrFail(workflowVersionId: string): Promise< - Omit<WorkflowVersionWorkspaceEntity, 'trigger'> & { - trigger: WorkflowTrigger; + async getWorkflowVersionOrFail( + workflowVersionId: string, + ): Promise<WorkflowVersionWorkspaceEntity> { + if (!workflowVersionId) { + throw new WorkflowTriggerException( + 'Workflow version ID is required', + WorkflowTriggerExceptionCode.INVALID_INPUT, + ); } - > { + const workflowVersionRepository = await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( 'workflowVersion', @@ -28,6 +32,12 @@ export class WorkflowCommonWorkspaceService { }, }); + return this.getValidWorkflowVersionOrFail(workflowVersion); + } + + async getValidWorkflowVersionOrFail( + workflowVersion: WorkflowVersionWorkspaceEntity | null, + ): Promise<WorkflowVersionWorkspaceEntity> { if (!workflowVersion) { throw new WorkflowTriggerException( 'Workflow version not found', @@ -35,12 +45,13 @@ export class WorkflowCommonWorkspaceService { ); } - if (!workflowVersion.trigger) { - throw new WorkflowTriggerException( - 'Workflow version does not contains trigger', - WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION, - ); - } + // FIXME: For now we will make the trigger optional. Later, we'll have to ensure the trigger is defined when publishing the flow. + // if (!workflowVersion.trigger) { + // throw new WorkflowTriggerException( + // 'Workflow version does not contains trigger', + // WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION, + // ); + // } return { ...workflowVersion, trigger: workflowVersion.trigger }; } diff --git a/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service.ts b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service.ts new file mode 100644 index 000000000000..fda5d1298fc8 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-version-validation.workspace-service.ts @@ -0,0 +1,112 @@ +import { Injectable } from '@nestjs/common'; + +import { IsNull, Not } from 'typeorm'; + +import { + CreateOneResolverArgs, + DeleteOneResolverArgs, + UpdateOneResolverArgs, +} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { + WorkflowQueryValidationException, + WorkflowQueryValidationExceptionCode, +} from 'src/modules/workflow/common/exceptions/workflow-query-validation.exception'; +import { + WorkflowVersionStatus, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { assertWorkflowVersionIsDraft } from 'src/modules/workflow/common/utils/assert-workflow-version-is-draft.util'; +import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; + +@Injectable() +export class WorkflowVersionValidationWorkspaceService { + constructor( + private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService, + private readonly twentyORMManager: TwentyORMManager, + ) {} + + async validateWorkflowVersionForCreateOne( + payload: CreateOneResolverArgs<WorkflowVersionWorkspaceEntity>, + ) { + if ( + payload.data.status && + payload.data.status !== WorkflowVersionStatus.DRAFT + ) { + throw new WorkflowQueryValidationException( + 'Cannot create workflow version with status other than draft', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } + + const workflowVersionRepository = + await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( + 'workflowVersion', + ); + + const workflowAlreadyHasDraftVersion = + await workflowVersionRepository.exists({ + where: { + workflowId: payload.data.workflowId, + status: WorkflowVersionStatus.DRAFT, + // FIXME: soft-deleted rows selection will have to be improved globally + deletedAt: IsNull(), + }, + }); + + if (workflowAlreadyHasDraftVersion) { + throw new WorkflowQueryValidationException( + 'Cannot create multiple draft versions for the same workflow', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } + } + + async validateWorkflowVersionForUpdateOne( + payload: UpdateOneResolverArgs<WorkflowVersionWorkspaceEntity>, + ) { + const workflowVersion = + await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail( + payload.id, + ); + + assertWorkflowVersionIsDraft(workflowVersion); + + if (payload.data.status && payload.data.status !== workflowVersion.status) { + throw new WorkflowQueryValidationException( + 'Cannot update workflow version status manually', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } + } + + async validateWorkflowVersionForDeleteOne(payload: DeleteOneResolverArgs) { + const workflowVersion = + await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail( + payload.id, + ); + + assertWorkflowVersionIsDraft(workflowVersion); + + const workflowVersionRepository = + await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( + 'workflowVersion', + ); + + const otherWorkflowVersionsExist = await workflowVersionRepository.exists({ + where: { + workflowId: workflowVersion.workflowId, + deletedAt: IsNull(), + id: Not(workflowVersion.id), + }, + }); + + if (!otherWorkflowVersionsExist) { + throw new WorkflowQueryValidationException( + 'The initial version of a workflow can not be deleted', + WorkflowQueryValidationExceptionCode.FORBIDDEN, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.exception.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/exceptions/workflow-executor.exception.ts similarity index 100% rename from packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.exception.ts rename to packages/twenty-server/src/modules/workflow/workflow-executor/exceptions/workflow-executor.exception.ts diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception.ts new file mode 100644 index 000000000000..327a472f1ab7 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception.ts @@ -0,0 +1,13 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkflowStepExecutorException extends CustomException { + code: WorkflowStepExecutorExceptionCode; + constructor(message: string, code: WorkflowStepExecutorExceptionCode) { + super(message, code); + } +} + +export enum WorkflowStepExecutorExceptionCode { + SCOPED_WORKSPACE_NOT_FOUND = 'SCOPED_WORKSPACE_NOT_FOUND', + INVALID_STEP_TYPE = 'INVALID_STEP_TYPE', +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts new file mode 100644 index 000000000000..5c23d81d31f4 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/factories/workflow-action.factory.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; + +import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/types/workflow-action.type'; +import { + WorkflowStepExecutorException, + WorkflowStepExecutorExceptionCode, +} from 'src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception'; +import { CodeWorkflowAction } from 'src/modules/serverless/workflow-actions/code.workflow-action'; +import { SendEmailWorkflowAction } from 'src/modules/mail-sender/workflow-actions/send-email.workflow-action'; + +@Injectable() +export class WorkflowActionFactory { + constructor( + private readonly codeWorkflowAction: CodeWorkflowAction, + private readonly sendEmailWorkflowAction: SendEmailWorkflowAction, + ) {} + + get(stepType: WorkflowActionType): WorkflowAction { + switch (stepType) { + case WorkflowActionType.CODE: + return this.codeWorkflowAction; + case WorkflowActionType.SEND_EMAIL: + return this.sendEmailWorkflowAction; + default: + throw new WorkflowStepExecutorException( + `Workflow step executor not found for step type '${stepType}'`, + WorkflowStepExecutorExceptionCode.INVALID_STEP_TYPE, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/interfaces/workflow-action.interface.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/interfaces/workflow-action.interface.ts new file mode 100644 index 000000000000..47b481949a76 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/interfaces/workflow-action.interface.ts @@ -0,0 +1,12 @@ +import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/types/workflow-action-result.type'; +import { WorkflowStep } from 'src/modules/workflow/workflow-executor/types/workflow-action.type'; + +export interface WorkflowAction { + execute({ + step, + payload, + }: { + step: WorkflowStep; + payload?: object; + }): Promise<WorkflowActionResult>; +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action-result.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action-result.type.ts new file mode 100644 index 000000000000..b856dfb75311 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action-result.type.ts @@ -0,0 +1,10 @@ +type WorkflowActionError = { + errorType: string; + errorMessage: string; + stackTrace: string; +}; + +export type WorkflowActionResult = { + result?: object; + error?: WorkflowActionError; +}; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action.type.ts new file mode 100644 index 000000000000..aeacb337704a --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-action.type.ts @@ -0,0 +1,27 @@ +import { + WorkflowCodeStepSettings, + WorkflowSendEmailStepSettings, +} from 'src/modules/workflow/workflow-executor/types/workflow-step-settings.type'; + +export enum WorkflowActionType { + CODE = 'CODE', + SEND_EMAIL = 'SEND_EMAIL', +} + +type BaseWorkflowStep = { + id: string; + name: string; + valid: boolean; +}; + +export type WorkflowCodeStep = BaseWorkflowStep & { + type: WorkflowActionType.CODE; + settings: WorkflowCodeStepSettings; +}; + +export type WorkflowSendEmailStep = BaseWorkflowStep & { + type: WorkflowActionType.SEND_EMAIL; + settings: WorkflowSendEmailStepSettings; +}; + +export type WorkflowStep = WorkflowCodeStep | WorkflowSendEmailStep; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-step-settings.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-step-settings.type.ts new file mode 100644 index 000000000000..99b334d0f5f5 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/types/workflow-step-settings.type.ts @@ -0,0 +1,24 @@ +type BaseWorkflowStepSettings = { + errorHandlingOptions: { + retryOnFailure: { + value: boolean; + }; + continueOnFailure: { + value: boolean; + }; + }; +}; + +export type WorkflowCodeStepSettings = BaseWorkflowStepSettings & { + serverlessFunctionId: string; +}; + +export type WorkflowSendEmailStepSettings = BaseWorkflowStepSettings & { + subject?: string; + template?: string; + title?: string; + callToAction?: { + value: string; + href: string; + }; +}; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.module.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.module.ts index d01b7aa11d99..0f68b2917c89 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.module.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.module.ts @@ -1,12 +1,22 @@ import { Module } from '@nestjs/common'; import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module'; -import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workflow-executor.workspace-service'; -import { WorkflowStepExecutorModule } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.module'; +import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service'; +import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory'; +import { CodeWorkflowAction } from 'src/modules/serverless/workflow-actions/code.workflow-action'; +import { SendEmailWorkflowAction } from 'src/modules/mail-sender/workflow-actions/send-email.workflow-action'; +import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module'; +import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; @Module({ - imports: [WorkflowCommonModule, WorkflowStepExecutorModule], - providers: [WorkflowExecutorWorkspaceService], + imports: [WorkflowCommonModule, ServerlessFunctionModule], + providers: [ + WorkflowExecutorWorkspaceService, + ScopedWorkspaceContextFactory, + WorkflowActionFactory, + CodeWorkflowAction, + SendEmailWorkflowAction, + ], exports: [WorkflowExecutorWorkspaceService], }) export class WorkflowExecutorModule {} diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts similarity index 71% rename from packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.workspace-service.ts rename to packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts index b157a8d14cf2..593543047e06 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-executor.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts @@ -1,24 +1,22 @@ import { Injectable } from '@nestjs/common'; -import { WorkflowStep } from 'src/modules/workflow/common/types/workflow-step.type'; +import { WorkflowStep } from 'src/modules/workflow/workflow-executor/types/workflow-action.type'; import { WorkflowExecutorException, WorkflowExecutorExceptionCode, -} from 'src/modules/workflow/workflow-executor/workflow-executor.exception'; -import { WorkflowStepExecutorFactory } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.factory'; +} from 'src/modules/workflow/workflow-executor/exceptions/workflow-executor.exception'; +import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory'; const MAX_RETRIES_ON_FAILURE = 3; export type WorkflowExecutionOutput = { - data?: object; + result?: object; error?: object; }; @Injectable() export class WorkflowExecutorWorkspaceService { - constructor( - private readonly workflowStepExecutorFactory: WorkflowStepExecutorFactory, - ) {} + constructor(private readonly workflowActionFactory: WorkflowActionFactory) {} async execute({ currentStepIndex, @@ -33,26 +31,24 @@ export class WorkflowExecutorWorkspaceService { }): Promise<WorkflowExecutionOutput> { if (currentStepIndex >= steps.length) { return { - data: payload, + result: payload, }; } const step = steps[currentStepIndex]; - const workflowStepExecutor = this.workflowStepExecutorFactory.get( - step.type, - ); + const workflowAction = this.workflowActionFactory.get(step.type); - const result = await workflowStepExecutor.execute({ + const result = await workflowAction.execute({ step, payload, }); - if (result.data) { + if (result.result) { return await this.execute({ currentStepIndex: currentStepIndex + 1, steps, - payload: result.data, + payload: result.result, }); } diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/exceptions/workflow-run.exception.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/exceptions/workflow-run.exception.ts new file mode 100644 index 000000000000..02f50928dec6 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/exceptions/workflow-run.exception.ts @@ -0,0 +1,14 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkflowRunException extends CustomException { + code: WorkflowRunExceptionCode; + constructor(message: string, code: WorkflowRunExceptionCode) { + super(message, code); + } +} + +export enum WorkflowRunExceptionCode { + WORKFLOW_RUN_NOT_FOUND = 'WORKFLOW_RUN_NOT_FOUND', + INVALID_OPERATION = 'INVALID_OPERATION', + INVALID_INPUT = 'INVALID_INPUT', +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts index 7c544974fd87..0ca2a3107a6e 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts @@ -1,12 +1,12 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; import { WorkflowRunStatus } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; -import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workflow-common.workspace-service'; -import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workflow-executor.workspace-service'; -import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service'; +import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service'; +import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service'; export type RunWorkflowJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.module.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.module.ts deleted file mode 100644 index 55a987bc97fe..000000000000 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module'; -import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service'; - -@Module({ - imports: [WorkflowCommonModule], - providers: [WorkflowRunWorkspaceService], - exports: [WorkflowRunWorkspaceService], -}) -export class WorkflowRunModule {} diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.module.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.module.ts index bf33e5b21f02..72871ae837e4 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.module.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.module.ts @@ -3,12 +3,16 @@ import { Module } from '@nestjs/common'; import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module'; import { WorkflowExecutorModule } from 'src/modules/workflow/workflow-executor/workflow-executor.module'; import { RunWorkflowJob } from 'src/modules/workflow/workflow-runner/jobs/run-workflow.job'; -import { WorkflowRunModule } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.module'; -import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-runner.workspace-service'; +import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service'; +import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service'; @Module({ - imports: [WorkflowRunModule, WorkflowCommonModule, WorkflowExecutorModule], - providers: [WorkflowRunnerWorkspaceService, RunWorkflowJob], + imports: [WorkflowCommonModule, WorkflowExecutorModule], + providers: [ + WorkflowRunnerWorkspaceService, + WorkflowRunWorkspaceService, + RunWorkflowJob, + ], exports: [WorkflowRunnerWorkspaceService], }) export class WorkflowRunnerModule {} diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service.ts similarity index 95% rename from packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts rename to packages/twenty-server/src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service.ts index ba71af333d48..00162c595f96 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service.ts @@ -2,15 +2,15 @@ import { Injectable } from '@nestjs/common'; import { ActorMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; import { WorkflowRunStatus, WorkflowRunWorkspaceEntity, } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; -import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workflow-common.workspace-service'; import { WorkflowRunException, WorkflowRunExceptionCode, -} from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.exception'; +} from 'src/modules/workflow/workflow-runner/exceptions/workflow-run.exception'; @Injectable() export class WorkflowRunWorkspaceService { diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service.ts similarity index 82% rename from packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.workspace-service.ts rename to packages/twenty-server/src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service.ts index bc43bd1b5a0d..e0e0020b19d0 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-runner.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service.ts @@ -1,14 +1,14 @@ import { Injectable } from '@nestjs/common'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { ActorMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { RunWorkflowJob, RunWorkflowJobData, } from 'src/modules/workflow/workflow-runner/jobs/run-workflow.job'; -import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service'; +import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service'; @Injectable() export class WorkflowRunnerWorkspaceService { diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/constants/workflow-status.constants.ts b/packages/twenty-server/src/modules/workflow/workflow-status/constants/workflow-status.constants.ts new file mode 100644 index 000000000000..48feac7a65eb --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/constants/workflow-status.constants.ts @@ -0,0 +1,19 @@ +import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; + +export const ACTIVE_AND_DRAFT_STATUSES = [ + WorkflowStatus.ACTIVE, + WorkflowStatus.DRAFT, +]; + +export const DEACTIVATED_AND_DRAFT_STATUSES = [ + WorkflowStatus.DEACTIVATED, + WorkflowStatus.DRAFT, +]; + +export const ACTIVE_STATUSES = [WorkflowStatus.ACTIVE]; + +export const DEACTIVATED_STATUSES = [WorkflowStatus.DEACTIVATED]; + +export const DRAFT_STATUSES = [WorkflowStatus.DRAFT]; + +export const NO_STATUSES = []; diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/enums/workflow-status.enum.ts b/packages/twenty-server/src/modules/workflow/workflow-status/enums/workflow-status.enum.ts new file mode 100644 index 000000000000..58e9d8e99b61 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/enums/workflow-status.enum.ts @@ -0,0 +1,8 @@ +export enum WorkflowStatusCombination { + ACTIVE = 'ACTIVE', + DRAFT = 'DRAFT', + DEACTIVATED = 'DEACTIVATED', + ACTIVE_AND_DRAFT = 'ACTIVE_AND_DRAFT', + DEACTIVATED_AND_DRAFT = 'DEACTIVATED_AND_DRAFT', + NO_STATUSES = 'NO_STATUSES', +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/jobs/__tests__/workflow-statuses-update.job.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-status/jobs/__tests__/workflow-statuses-update.job.spec.ts new file mode 100644 index 000000000000..bb370fa853d5 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/jobs/__tests__/workflow-statuses-update.job.spec.ts @@ -0,0 +1,268 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; +import { + WorkflowStatusesUpdateJob, + WorkflowVersionBatchEvent, + WorkflowVersionEventType, +} from 'src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job'; + +describe('WorkflowStatusesUpdate', () => { + let job: WorkflowStatusesUpdateJob; + + const mockWorkflowRepository = { + findOneOrFail: jest.fn(), + update: jest.fn(), + }; + + const mockTwentyORMManager = { + getRepository: jest.fn().mockResolvedValue(mockWorkflowRepository), + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + WorkflowStatusesUpdateJob, + { + provide: TwentyORMManager, + useValue: mockTwentyORMManager, + }, + ], + }).compile(); + + job = await module.resolve<WorkflowStatusesUpdateJob>( + WorkflowStatusesUpdateJob, + ); + }); + + it('should be defined', () => { + expect(job).toBeDefined(); + }); + + describe('handle', () => { + describe('when event type is CREATE', () => { + it('when already a draft, do not change anything', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.CREATE, + workflowIds: ['1'], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.DRAFT], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledTimes(0); + }); + + it('when no draft yet, update statuses', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.CREATE, + workflowIds: ['1'], + }; + + const mockWorkflow = { + id: '1', + statuses: [WorkflowStatus.ACTIVE], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledWith( + { id: '1' }, + { statuses: [WorkflowStatus.ACTIVE, WorkflowStatus.DRAFT] }, + ); + }); + }); + + describe('when event type is STATUS_UPDATE', () => { + test('when status is the same, should not do anything', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.STATUS_UPDATE, + statusUpdates: [ + { + workflowId: '1', + previousStatus: WorkflowVersionStatus.ACTIVE, + newStatus: WorkflowVersionStatus.ACTIVE, + }, + ], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.ACTIVE], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledTimes(0); + }); + + test('when update that should be impossible, do not do anything', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.STATUS_UPDATE, + statusUpdates: [ + { + workflowId: '1', + previousStatus: WorkflowVersionStatus.ACTIVE, + newStatus: WorkflowVersionStatus.DRAFT, + }, + ], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.ACTIVE], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledTimes(0); + }); + + test('when WorkflowVersionStatus.DEACTIVATED to WorkflowVersionStatus.ACTIVE, should activate', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.STATUS_UPDATE, + statusUpdates: [ + { + workflowId: '1', + previousStatus: WorkflowVersionStatus.DEACTIVATED, + newStatus: WorkflowVersionStatus.ACTIVE, + }, + ], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.DEACTIVATED], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledWith( + { id: '1' }, + { statuses: [WorkflowStatus.ACTIVE] }, + ); + }); + + test('when WorkflowVersionStatus.ACTIVE to WorkflowVersionStatus.DEACTIVATED, should deactivate', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.STATUS_UPDATE, + statusUpdates: [ + { + workflowId: '1', + previousStatus: WorkflowVersionStatus.ACTIVE, + newStatus: WorkflowVersionStatus.DEACTIVATED, + }, + ], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.ACTIVE], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledWith( + { id: '1' }, + { statuses: [WorkflowStatus.DEACTIVATED] }, + ); + }); + + test('when WorkflowVersionStatus.DRAFT to WorkflowVersionStatus.ACTIVE, should activate', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.STATUS_UPDATE, + statusUpdates: [ + { + workflowId: '1', + previousStatus: WorkflowVersionStatus.DRAFT, + newStatus: WorkflowVersionStatus.ACTIVE, + }, + ], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.DRAFT], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledWith( + { id: '1' }, + { statuses: [WorkflowStatus.ACTIVE] }, + ); + }); + }); + + describe('when event type is DELETE', () => { + test('when status is not draft, should not do anything', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.DELETE, + workflowIds: ['1'], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.ACTIVE], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledTimes(0); + }); + + test('when status is draft, should delete', async () => { + const event: WorkflowVersionBatchEvent = { + workspaceId: '1', + type: WorkflowVersionEventType.DELETE, + workflowIds: ['1'], + }; + + const mockWorkflow = { + statuses: [WorkflowStatus.DRAFT], + }; + + mockWorkflowRepository.findOneOrFail.mockResolvedValue(mockWorkflow); + + await job.handle(event); + + expect(mockWorkflowRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockWorkflowRepository.update).toHaveBeenCalledWith( + { id: '1' }, + { statuses: [] }, + ); + }); + }); + }); +}); diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts b/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts new file mode 100644 index 000000000000..4f4ce5886d1e --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job.ts @@ -0,0 +1,201 @@ +import { Scope } from '@nestjs/common'; + +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; +import { getStatusCombinationFromArray } from 'src/modules/workflow/workflow-status/utils/get-status-combination-from-array.util'; +import { getStatusCombinationFromUpdate } from 'src/modules/workflow/workflow-status/utils/get-status-combination-from-update.util'; +import { getWorkflowStatusesFromCombination } from 'src/modules/workflow/workflow-status/utils/get-statuses-from-combination.util'; + +export enum WorkflowVersionEventType { + CREATE = 'CREATE', + STATUS_UPDATE = 'STATUS_UPDATE', + DELETE = 'DELETE', +} + +export type WorkflowVersionBatchEvent = { + workspaceId: string; +} & ( + | WorkflowVersionBatchCreateEvent + | WorkflowVersionBatchStatusUpdate + | WorkflowVersionBatchDelete +); + +export type WorkflowVersionBatchCreateEvent = { + type: WorkflowVersionEventType.CREATE; +} & { + workflowIds: string[]; +}; + +export type WorkflowVersionStatusUpdate = { + workflowId: string; + previousStatus: WorkflowVersionStatus; + newStatus: WorkflowVersionStatus; +}; + +export type WorkflowVersionBatchStatusUpdate = { + type: WorkflowVersionEventType.STATUS_UPDATE; +} & { + statusUpdates: WorkflowVersionStatusUpdate[]; +}; + +export type WorkflowVersionBatchDelete = { + type: WorkflowVersionEventType.DELETE; +} & { workflowIds: string[] }; + +@Processor({ queueName: MessageQueue.workflowQueue, scope: Scope.REQUEST }) +export class WorkflowStatusesUpdateJob { + constructor(private readonly twentyORMManager: TwentyORMManager) {} + + @Process(WorkflowStatusesUpdateJob.name) + async handle(event: WorkflowVersionBatchEvent): Promise<void> { + switch (event.type) { + case WorkflowVersionEventType.CREATE: + await Promise.all( + event.workflowIds.map((workflowId) => + this.handleWorkflowVersionCreated(workflowId), + ), + ); + break; + case WorkflowVersionEventType.STATUS_UPDATE: + await Promise.all( + event.statusUpdates.map((statusUpdate) => + this.handleWorkflowVersionStatusUpdated(statusUpdate), + ), + ); + break; + case WorkflowVersionEventType.DELETE: + await Promise.all( + event.workflowIds.map((workflowId) => + this.handleWorkflowVersionDeleted(workflowId), + ), + ); + break; + default: + break; + } + } + + private async handleWorkflowVersionCreated( + workflowId: string, + ): Promise<void> { + const workflowRepository = + await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>( + 'workflow', + ); + + const workflow = await workflowRepository.findOneOrFail({ + where: { + id: workflowId, + }, + }); + + const currentWorkflowStatusCombination = getStatusCombinationFromArray( + workflow.statuses || [], + ); + + const newWorkflowStatusCombination = getStatusCombinationFromUpdate( + currentWorkflowStatusCombination, + undefined, + WorkflowVersionStatus.DRAFT, + ); + + if (newWorkflowStatusCombination === currentWorkflowStatusCombination) { + return; + } + + await workflowRepository.update( + { + id: workflow.id, + }, + { + statuses: getWorkflowStatusesFromCombination( + newWorkflowStatusCombination, + ), + }, + ); + } + + private async handleWorkflowVersionStatusUpdated( + statusUpdate: WorkflowVersionStatusUpdate, + ): Promise<void> { + const workflowRepository = + await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>( + 'workflow', + ); + + const workflow = await workflowRepository.findOneOrFail({ + where: { + id: statusUpdate.workflowId, + }, + }); + + const currentWorkflowStatusCombination = getStatusCombinationFromArray( + workflow.statuses || [], + ); + + const newWorkflowStatusCombination = getStatusCombinationFromUpdate( + currentWorkflowStatusCombination, + statusUpdate.previousStatus, + statusUpdate.newStatus, + ); + + if (newWorkflowStatusCombination === currentWorkflowStatusCombination) { + return; + } + + await workflowRepository.update( + { + id: statusUpdate.workflowId, + }, + { + statuses: getWorkflowStatusesFromCombination( + newWorkflowStatusCombination, + ), + }, + ); + } + + private async handleWorkflowVersionDeleted( + workflowId: string, + ): Promise<void> { + const workflowRepository = + await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>( + 'workflow', + ); + + const workflow = await workflowRepository.findOneOrFail({ + where: { + id: workflowId, + }, + }); + + const currentWorkflowStatusCombination = getStatusCombinationFromArray( + workflow.statuses || [], + ); + + const newWorkflowStatusCombination = getStatusCombinationFromUpdate( + currentWorkflowStatusCombination, + WorkflowVersionStatus.DRAFT, + undefined, + ); + + if (newWorkflowStatusCombination === currentWorkflowStatusCombination) { + return; + } + + await workflowRepository.update( + { + id: workflowId, + }, + { + statuses: getWorkflowStatusesFromCombination( + newWorkflowStatusCombination, + ), + }, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/listeners/workflow-version-status.listener.ts b/packages/twenty-server/src/modules/workflow/workflow-status/listeners/workflow-version-status.listener.ts new file mode 100644 index 000000000000..b8e3c9619556 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/listeners/workflow-version-status.listener.ts @@ -0,0 +1,96 @@ +import { Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; + +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; +import { + WorkflowVersionStatus, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { + WorkflowStatusesUpdateJob, + WorkflowVersionBatchEvent, + WorkflowVersionEventType, + WorkflowVersionStatusUpdate, +} from 'src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job'; + +@Injectable() +export class WorkflowVersionStatusListener { + constructor( + @InjectMessageQueue(MessageQueue.workflowQueue) + private readonly messageQueueService: MessageQueueService, + ) {} + + @OnEvent('workflowVersion.created') + async handleWorkflowVersionCreated( + payload: WorkspaceEventBatch< + ObjectRecordCreateEvent<WorkflowVersionWorkspaceEntity> + >, + ): Promise<void> { + const workflowIds = payload.events + .filter( + (event) => + !event.properties.after.status || + event.properties.after.status === WorkflowVersionStatus.DRAFT, + ) + .map((event) => event.properties.after.workflowId); + + if (workflowIds.length === 0) { + return; + } + + await this.messageQueueService.add<WorkflowVersionBatchEvent>( + WorkflowStatusesUpdateJob.name, + { + type: WorkflowVersionEventType.CREATE, + workspaceId: payload.workspaceId, + workflowIds, + }, + ); + } + + @OnEvent('workflowVersion.statusUpdated') + async handleWorkflowVersionUpdated( + payload: WorkspaceEventBatch<WorkflowVersionStatusUpdate>, + ): Promise<void> { + await this.messageQueueService.add<WorkflowVersionBatchEvent>( + WorkflowStatusesUpdateJob.name, + { + type: WorkflowVersionEventType.STATUS_UPDATE, + workspaceId: payload.workspaceId, + statusUpdates: payload.events, + }, + ); + } + + @OnEvent('workflowVersion.deleted') + async handleWorkflowVersionDeleted( + payload: WorkspaceEventBatch< + ObjectRecordDeleteEvent<WorkflowVersionWorkspaceEntity> + >, + ): Promise<void> { + const workflowIds = payload.events + .filter( + (event) => + event.properties.before.status === WorkflowVersionStatus.DRAFT, + ) + .map((event) => event.properties.before.workflowId); + + if (workflowIds.length === 0) { + return; + } + + await this.messageQueueService.add<WorkflowVersionBatchEvent>( + WorkflowStatusesUpdateJob.name, + { + type: WorkflowVersionEventType.DELETE, + workspaceId: payload.workspaceId, + workflowIds, + }, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-array.util.ts b/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-array.util.ts new file mode 100644 index 000000000000..267b4a68114e --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-array.util.ts @@ -0,0 +1,37 @@ +import isEqual from 'lodash.isequal'; + +import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; +import { + ACTIVE_AND_DRAFT_STATUSES, + ACTIVE_STATUSES, + DEACTIVATED_AND_DRAFT_STATUSES, + DEACTIVATED_STATUSES, + DRAFT_STATUSES, +} from 'src/modules/workflow/workflow-status/constants/workflow-status.constants'; +import { WorkflowStatusCombination } from 'src/modules/workflow/workflow-status/enums/workflow-status.enum'; + +export const getStatusCombinationFromArray = ( + statuses: WorkflowStatus[], +): WorkflowStatusCombination => { + if (isEqual(statuses, ACTIVE_AND_DRAFT_STATUSES)) { + return WorkflowStatusCombination.ACTIVE_AND_DRAFT; + } + + if (isEqual(statuses, ACTIVE_STATUSES)) { + return WorkflowStatusCombination.ACTIVE; + } + + if (isEqual(statuses, DEACTIVATED_AND_DRAFT_STATUSES)) { + return WorkflowStatusCombination.DEACTIVATED_AND_DRAFT; + } + + if (isEqual(statuses, DEACTIVATED_STATUSES)) { + return WorkflowStatusCombination.DEACTIVATED; + } + + if (isEqual(statuses, DRAFT_STATUSES)) { + return WorkflowStatusCombination.DRAFT; + } + + return WorkflowStatusCombination.NO_STATUSES; +}; diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-update.util.ts b/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-update.util.ts new file mode 100644 index 000000000000..634133990a87 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-status-combination-from-update.util.ts @@ -0,0 +1,75 @@ +import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowStatusCombination } from 'src/modules/workflow/workflow-status/enums/workflow-status.enum'; + +export const getStatusCombinationFromUpdate = ( + previousCombination: WorkflowStatusCombination, + statusToRemove?: WorkflowVersionStatus, + statusToAdd?: WorkflowVersionStatus, +): WorkflowStatusCombination => { + switch (previousCombination) { + case WorkflowStatusCombination.ACTIVE_AND_DRAFT: + if ( + statusToAdd === WorkflowVersionStatus.ACTIVE && + statusToRemove === WorkflowVersionStatus.DRAFT + ) { + return WorkflowStatusCombination.ACTIVE; + } + if (statusToRemove === WorkflowVersionStatus.DRAFT) { + return WorkflowStatusCombination.ACTIVE; + } + break; + case WorkflowStatusCombination.DEACTIVATED_AND_DRAFT: + if ( + statusToRemove === WorkflowVersionStatus.DRAFT && + statusToAdd === WorkflowVersionStatus.ACTIVE + ) { + return WorkflowStatusCombination.ACTIVE; + } + if (statusToRemove === WorkflowVersionStatus.DRAFT) { + return WorkflowStatusCombination.DEACTIVATED; + } + break; + case WorkflowStatusCombination.ACTIVE: + if ( + statusToRemove === WorkflowVersionStatus.ACTIVE && + statusToAdd === WorkflowVersionStatus.DEACTIVATED + ) { + return WorkflowStatusCombination.DEACTIVATED; + } + if (!statusToRemove && statusToAdd === WorkflowVersionStatus.DRAFT) { + return WorkflowStatusCombination.ACTIVE_AND_DRAFT; + } + break; + case WorkflowStatusCombination.DEACTIVATED: + if ( + statusToRemove === WorkflowVersionStatus.DEACTIVATED && + statusToAdd === WorkflowVersionStatus.ACTIVE + ) { + return WorkflowStatusCombination.ACTIVE; + } + if (!statusToRemove && statusToAdd === WorkflowVersionStatus.DRAFT) { + return WorkflowStatusCombination.DEACTIVATED_AND_DRAFT; + } + break; + case WorkflowStatusCombination.DRAFT: + if ( + statusToRemove === WorkflowVersionStatus.DRAFT && + statusToAdd === WorkflowVersionStatus.ACTIVE + ) { + return WorkflowStatusCombination.ACTIVE; + } + if (statusToRemove === WorkflowVersionStatus.DRAFT) { + return WorkflowStatusCombination.NO_STATUSES; + } + break; + case WorkflowStatusCombination.NO_STATUSES: + if (statusToAdd === WorkflowVersionStatus.DRAFT) { + return WorkflowStatusCombination.DRAFT; + } + break; + default: + break; + } + + return previousCombination; +}; diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-statuses-from-combination.util.ts b/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-statuses-from-combination.util.ts new file mode 100644 index 000000000000..72c53862e533 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/utils/get-statuses-from-combination.util.ts @@ -0,0 +1,29 @@ +import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; +import { + ACTIVE_AND_DRAFT_STATUSES, + ACTIVE_STATUSES, + DEACTIVATED_AND_DRAFT_STATUSES, + DEACTIVATED_STATUSES, + DRAFT_STATUSES, + NO_STATUSES, +} from 'src/modules/workflow/workflow-status/constants/workflow-status.constants'; +import { WorkflowStatusCombination } from 'src/modules/workflow/workflow-status/enums/workflow-status.enum'; + +export const getWorkflowStatusesFromCombination = ( + combination: WorkflowStatusCombination, +): WorkflowStatus[] => { + switch (combination) { + case WorkflowStatusCombination.ACTIVE: + return ACTIVE_STATUSES; + case WorkflowStatusCombination.DRAFT: + return DRAFT_STATUSES; + case WorkflowStatusCombination.DEACTIVATED: + return DEACTIVATED_STATUSES; + case WorkflowStatusCombination.ACTIVE_AND_DRAFT: + return ACTIVE_AND_DRAFT_STATUSES; + case WorkflowStatusCombination.DEACTIVATED_AND_DRAFT: + return DEACTIVATED_AND_DRAFT_STATUSES; + case WorkflowStatusCombination.NO_STATUSES: + return NO_STATUSES; + } +}; diff --git a/packages/twenty-server/src/modules/workflow/workflow-status/workflow-status.module.ts b/packages/twenty-server/src/modules/workflow/workflow-status/workflow-status.module.ts new file mode 100644 index 000000000000..57c69f530e84 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-status/workflow-status.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { WorkflowStatusesUpdateJob } from 'src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job'; +import { WorkflowVersionStatusListener } from 'src/modules/workflow/workflow-status/listeners/workflow-version-status.listener'; + +@Module({ + providers: [WorkflowStatusesUpdateJob, WorkflowVersionStatusListener], +}) +export class WorkflowStatusModule {} diff --git a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.factory.ts b/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.factory.ts deleted file mode 100644 index 72f46451e669..000000000000 --- a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.factory.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { WorkflowStepType } from 'src/modules/workflow/common/types/workflow-step.type'; -import { - WorkflowStepExecutorException, - WorkflowStepExecutorExceptionCode, -} from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.exception'; -import { WorkflowStepExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.interface'; -import { CodeActionExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor'; - -@Injectable() -export class WorkflowStepExecutorFactory { - constructor(private readonly codeActionExecutor: CodeActionExecutor) {} - - get(stepType: WorkflowStepType): WorkflowStepExecutor { - switch (stepType) { - case WorkflowStepType.CODE_ACTION: - return this.codeActionExecutor; - default: - throw new WorkflowStepExecutorException( - `Workflow step executor not found for step type '${stepType}'`, - WorkflowStepExecutorExceptionCode.INVALID_STEP_TYPE, - ); - } - } -} diff --git a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.interface.ts b/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.interface.ts deleted file mode 100644 index 169ebc2ca92c..000000000000 --- a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { WorkflowResult } from 'src/modules/workflow/common/types/workflow-result.type'; -import { WorkflowStep } from 'src/modules/workflow/common/types/workflow-step.type'; - -export interface WorkflowStepExecutor { - execute({ - step, - payload, - }: { - step: WorkflowStep; - payload?: object; - }): Promise<WorkflowResult>; -} diff --git a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.module.ts b/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.module.ts deleted file mode 100644 index 293a3614bba9..000000000000 --- a/packages/twenty-server/src/modules/workflow/workflow-step-executor/workflow-step-executor.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module'; -import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; -import { WorkflowStepExecutorFactory } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.factory'; -import { CodeActionExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor'; - -@Module({ - imports: [ServerlessFunctionModule], - providers: [ - WorkflowStepExecutorFactory, - CodeActionExecutor, - ScopedWorkspaceContextFactory, - ], - exports: [WorkflowStepExecutorFactory], -}) -export class WorkflowStepExecutorModule {} diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.service.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.service.ts index 4db20d091aae..da8affbb6df5 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.service.ts @@ -4,7 +4,7 @@ import { EntityManager } from 'typeorm'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity'; -import { WorkflowDatabaseEventTrigger } from 'src/modules/workflow/common/types/workflow-trigger.type'; +import { WorkflowDatabaseEventTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type'; @Injectable() export class DatabaseEventTriggerService { diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/listeners/database-event-trigger.listener.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/listeners/database-event-trigger.listener.ts index a19a990980b1..5ea3f82d4781 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/listeners/database-event-trigger.listener.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/database-event-trigger/listeners/database-event-trigger.listener.ts @@ -1,14 +1,15 @@ import { Injectable, Logger } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; +import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; +import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event'; +import { ObjectRecordDestroyEvent } from 'src/engine/core-modules/event-emitter/types/object-record-destroy.event'; +import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; -import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/workspace-event.type'; import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity'; @@ -49,11 +50,19 @@ export class DatabaseEventTriggerListener { await this.handleEvent(payload); } + @OnEvent('*.destroyed') + async handleObjectRecordDestroyEvent( + payload: WorkspaceEventBatch<ObjectRecordDestroyEvent<any>>, + ) { + await this.handleEvent(payload); + } + private async handleEvent( payload: WorkspaceEventBatch< | ObjectRecordCreateEvent<any> | ObjectRecordUpdateEvent<any> | ObjectRecordDeleteEvent<any> + | ObjectRecordDestroyEvent<any> >, ) { const workspaceId = payload.workspaceId; diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.exception.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception.ts similarity index 100% rename from packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.exception.ts rename to packages/twenty-server/src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception.ts diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/jobs/workflow-event-trigger.job.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/jobs/workflow-event-trigger.job.ts index 465204bd4bc0..12391290f877 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/jobs/workflow-event-trigger.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/jobs/workflow-event-trigger.job.ts @@ -1,8 +1,8 @@ import { Scope } from '@nestjs/common'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; +import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; +import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { @@ -10,11 +10,11 @@ import { WorkflowVersionWorkspaceEntity, } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; -import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-runner.workspace-service'; +import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service'; import { WorkflowTriggerException, WorkflowTriggerExceptionCode, -} from 'src/modules/workflow/workflow-trigger/workflow-trigger.exception'; +} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception'; export type WorkflowEventTriggerJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/modules/workflow/common/types/workflow-trigger.type.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/types/workflow-trigger.type.ts similarity index 100% rename from packages/twenty-server/src/modules/workflow/common/types/workflow-trigger.type.ts rename to packages/twenty-server/src/modules/workflow/workflow-trigger/types/workflow-trigger.type.ts diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/assert-version-can-be-activated.util.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/assert-version-can-be-activated.util.ts index a75e7732361b..e6fac6a9d722 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/assert-version-can-be-activated.util.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/utils/assert-version-can-be-activated.util.ts @@ -3,19 +3,14 @@ import { WorkflowVersionWorkspaceEntity, } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; -import { - WorkflowTrigger, - WorkflowTriggerType, -} from 'src/modules/workflow/common/types/workflow-trigger.type'; import { WorkflowTriggerException, WorkflowTriggerExceptionCode, -} from 'src/modules/workflow/workflow-trigger/workflow-trigger.exception'; +} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception'; +import { WorkflowTriggerType } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type'; export function assertVersionCanBeActivated( - workflowVersion: Omit<WorkflowVersionWorkspaceEntity, 'trigger'> & { - trigger: WorkflowTrigger; - }, + workflowVersion: WorkflowVersionWorkspaceEntity, workflow: WorkflowWorkspaceEntity, ) { assertVersionIsValid(workflowVersion); @@ -37,11 +32,7 @@ export function assertVersionCanBeActivated( } } -function assertVersionIsValid( - workflowVersion: Omit<WorkflowVersionWorkspaceEntity, 'trigger'> & { - trigger: WorkflowTrigger; - }, -) { +function assertVersionIsValid(workflowVersion: WorkflowVersionWorkspaceEntity) { if (!workflowVersion.trigger) { throw new WorkflowTriggerException( 'Workflow version does not contain trigger', diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.module.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.module.ts index dbf7e6feb393..ecd72856dd5a 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.module.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.module.ts @@ -5,7 +5,7 @@ import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-commo import { WorkflowRunnerModule } from 'src/modules/workflow/workflow-runner/workflow-runner.module'; import { DatabaseEventTriggerModule } from 'src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.module'; import { WorkflowEventTriggerJob } from 'src/modules/workflow/workflow-trigger/jobs/workflow-event-trigger.job'; -import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workflow-trigger.workspace-service'; +import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service'; @Module({ imports: [ diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.workspace-service.ts deleted file mode 100644 index 6e225bdcde5e..000000000000 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/workflow-trigger.workspace-service.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { EntityManager } from 'typeorm'; - -import { buildCreatedByFromWorkspaceMember } from 'src/engine/core-modules/actor/utils/build-created-by-from-workspace-member.util'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; -import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { - WorkflowVersionStatus, - WorkflowVersionWorkspaceEntity, -} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; -import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; -import { WorkflowTriggerType } from 'src/modules/workflow/common/types/workflow-trigger.type'; -import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workflow-common.workspace-service'; -import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-runner.workspace-service'; -import { DatabaseEventTriggerService } from 'src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.service'; -import { assertVersionCanBeActivated } from 'src/modules/workflow/workflow-trigger/utils/assert-version-can-be-activated.util'; -import { - WorkflowTriggerException, - WorkflowTriggerExceptionCode, -} from 'src/modules/workflow/workflow-trigger/workflow-trigger.exception'; - -@Injectable() -export class WorkflowTriggerWorkspaceService { - constructor( - private readonly twentyORMManager: TwentyORMManager, - private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService, - private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory, - private readonly workflowRunnerWorkspaceService: WorkflowRunnerWorkspaceService, - private readonly databaseEventTriggerService: DatabaseEventTriggerService, - ) {} - - async runWorkflowVersion( - workflowVersionId: string, - payload: object, - workspaceMemberId: string, - user: User, - ) { - const workspaceId = this.scopedWorkspaceContextFactory.create().workspaceId; - - if (!workspaceId) { - throw new WorkflowTriggerException( - 'No workspace id found', - WorkflowTriggerExceptionCode.INTERNAL_ERROR, - ); - } - - await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail( - workflowVersionId, - ); - - return await this.workflowRunnerWorkspaceService.run( - workspaceId, - workflowVersionId, - payload, - buildCreatedByFromWorkspaceMember(workspaceMemberId, user), - ); - } - - async enableWorkflowTrigger(workflowVersionId: string) { - const workflowVersion = - await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail( - workflowVersionId, - ); - - const workflowRepository = - await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>( - 'workflow', - ); - - const workflow = await workflowRepository.findOne({ - where: { id: workflowVersion.workflowId }, - }); - - if (!workflow) { - throw new WorkflowTriggerException( - 'No workflow found', - WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION, - ); - } - - assertVersionCanBeActivated(workflowVersion, workflow); - - const workspaceDataSource = await this.twentyORMManager.getDatasource(); - const queryRunner = workspaceDataSource.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - const manager = queryRunner.manager; - - try { - if ( - workflow.lastPublishedVersionId && - workflowVersionId !== workflow.lastPublishedVersionId - ) { - await this.disableWorkflowTriggerWithManager( - workflow.lastPublishedVersionId, - manager, - ); - } - - await this.activateWorkflowVersion( - workflowVersion.workflowId, - workflowVersionId, - manager, - ); - await workflowRepository.update( - { id: workflow.id }, - { lastPublishedVersionId: workflowVersionId }, - manager, - ); - - switch (workflowVersion.trigger.type) { - case WorkflowTriggerType.DATABASE_EVENT: - await this.databaseEventTriggerService.createEventListener( - workflowVersion.workflowId, - workflowVersion.trigger, - manager, - ); - break; - default: - break; - } - - await queryRunner.commitTransaction(); - - return true; - } catch (error) { - await queryRunner.rollbackTransaction(); - throw error; - } finally { - await queryRunner.release(); - } - } - - async disableWorkflowTrigger(workflowVersionId: string) { - const workspaceDataSource = await this.twentyORMManager.getDatasource(); - const queryRunner = workspaceDataSource.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - try { - await this.disableWorkflowTriggerWithManager( - workflowVersionId, - queryRunner.manager, - ); - - await queryRunner.commitTransaction(); - - return true; - } catch (error) { - await queryRunner.rollbackTransaction(); - throw error; - } finally { - await queryRunner.release(); - } - } - - private async disableWorkflowTriggerWithManager( - workflowVersionId: string, - manager: EntityManager, - ) { - const workflowVersionRepository = - await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( - 'workflowVersion', - ); - - const workflowVersion = await workflowVersionRepository.findOne({ - where: { id: workflowVersionId }, - }); - - if (!workflowVersion) { - throw new WorkflowTriggerException( - 'No workflow version found', - WorkflowTriggerExceptionCode.INVALID_INPUT, - ); - } - - if (workflowVersion.status !== WorkflowVersionStatus.ACTIVE) { - throw new WorkflowTriggerException( - 'Cannot disable non-active workflow version', - WorkflowTriggerExceptionCode.INVALID_INPUT, - ); - } - - await workflowVersionRepository.update( - { id: workflowVersionId }, - { status: WorkflowVersionStatus.DEACTIVATED }, - manager, - ); - - switch (workflowVersion?.trigger?.type) { - case WorkflowTriggerType.DATABASE_EVENT: - await this.databaseEventTriggerService.deleteEventListener( - workflowVersion.workflowId, - manager, - ); - break; - default: - break; - } - } - - private async activateWorkflowVersion( - workflowId: string, - workflowVersionId: string, - manager: EntityManager, - ) { - const workflowVersionRepository = - await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( - 'workflowVersion', - ); - - const activeWorkflowVersions = await workflowVersionRepository.find( - { - where: { workflowId, status: WorkflowVersionStatus.ACTIVE }, - }, - manager, - ); - - if (activeWorkflowVersions.length > 0) { - throw new WorkflowTriggerException( - 'Cannot have more than one active workflow version', - WorkflowTriggerExceptionCode.FORBIDDEN, - ); - } - - await workflowVersionRepository.update( - { id: workflowVersionId }, - { status: WorkflowVersionStatus.ACTIVE }, - manager, - ); - } -} diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts new file mode 100644 index 000000000000..309f3d158772 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts @@ -0,0 +1,368 @@ +import { Injectable } from '@nestjs/common'; + +import { EntityManager } from 'typeorm'; + +import { buildCreatedByFromWorkspaceMember } from 'src/engine/core-modules/actor/utils/build-created-by-from-workspace-member.util'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory'; +import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; +import { + WorkflowVersionStatus, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; +import { assertWorkflowVersionTriggerIsDefined } from 'src/modules/workflow/common/utils/assert-workflow-version-trigger-is-defined.util'; +import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; +import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service'; +import { WorkflowVersionStatusUpdate } from 'src/modules/workflow/workflow-status/jobs/workflow-statuses-update.job'; +import { DatabaseEventTriggerService } from 'src/modules/workflow/workflow-trigger/database-event-trigger/database-event-trigger.service'; +import { + WorkflowTriggerException, + WorkflowTriggerExceptionCode, +} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception'; +import { WorkflowTriggerType } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type'; +import { assertVersionCanBeActivated } from 'src/modules/workflow/workflow-trigger/utils/assert-version-can-be-activated.util'; + +@Injectable() +export class WorkflowTriggerWorkspaceService { + constructor( + private readonly twentyORMManager: TwentyORMManager, + private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService, + private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory, + private readonly workflowRunnerWorkspaceService: WorkflowRunnerWorkspaceService, + private readonly databaseEventTriggerService: DatabaseEventTriggerService, + private readonly workspaceEventEmitter: WorkspaceEventEmitter, + ) {} + + async runWorkflowVersion( + workflowVersionId: string, + payload: object, + workspaceMemberId: string, + user: User, + ) { + const workspaceId = this.scopedWorkspaceContextFactory.create().workspaceId; + + if (!workspaceId) { + throw new WorkflowTriggerException( + 'No workspace id found', + WorkflowTriggerExceptionCode.INTERNAL_ERROR, + ); + } + + await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail( + workflowVersionId, + ); + + return await this.workflowRunnerWorkspaceService.run( + workspaceId, + workflowVersionId, + payload, + buildCreatedByFromWorkspaceMember(workspaceMemberId, user), + ); + } + + async activateWorkflowVersion(workflowVersionId: string) { + const workflowVersionRepository = + await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( + 'workflowVersion', + ); + + const workflowVersionNullable = await workflowVersionRepository.findOne({ + where: { id: workflowVersionId }, + }); + + const workflowVersion = + await this.workflowCommonWorkspaceService.getValidWorkflowVersionOrFail( + workflowVersionNullable, + ); + + const workflowRepository = + await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>( + 'workflow', + ); + + const workflow = await workflowRepository.findOne({ + where: { id: workflowVersion.workflowId }, + }); + + if (!workflow) { + throw new WorkflowTriggerException( + 'No workflow found', + WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION, + ); + } + + assertVersionCanBeActivated(workflowVersion, workflow); + + const workspaceDataSource = await this.twentyORMManager.getDatasource(); + const queryRunner = workspaceDataSource.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + const manager = queryRunner.manager; + + try { + await this.performActivationSteps( + workflow, + workflowVersion, + workflowRepository, + workflowVersionRepository, + manager, + ); + + await queryRunner.commitTransaction(); + + return true; + } catch (error) { + await queryRunner.rollbackTransaction(); + throw error; + } finally { + await queryRunner.release(); + } + } + + async deactivateWorkflowVersion(workflowVersionId: string) { + const workspaceDataSource = await this.twentyORMManager.getDatasource(); + const queryRunner = workspaceDataSource.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + const workflowVersionRepository = + await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>( + 'workflowVersion', + ); + + await this.performDeactivationSteps( + workflowVersionId, + workflowVersionRepository, + queryRunner.manager, + ); + + await queryRunner.commitTransaction(); + + return true; + } catch (error) { + await queryRunner.rollbackTransaction(); + throw error; + } finally { + await queryRunner.release(); + } + } + + private async performActivationSteps( + workflow: WorkflowWorkspaceEntity, + workflowVersion: WorkflowVersionWorkspaceEntity, + workflowRepository: WorkspaceRepository<WorkflowWorkspaceEntity>, + workflowVersionRepository: WorkspaceRepository<WorkflowVersionWorkspaceEntity>, + manager: EntityManager, + ) { + if ( + workflow.lastPublishedVersionId && + workflowVersion.id !== workflow.lastPublishedVersionId + ) { + await this.performDeactivationSteps( + workflow.lastPublishedVersionId, + workflowVersionRepository, + manager, + ); + } + + await this.upgradeWorkflowVersion( + workflow, + workflowVersion.id, + workflowRepository, + workflowVersionRepository, + manager, + ); + + await this.setActiveVersionStatus( + workflowVersion, + workflowVersionRepository, + manager, + ); + + await this.enableTrigger(workflowVersion, manager); + } + + private async performDeactivationSteps( + workflowVersionId: string, + workflowVersionRepository: WorkspaceRepository<WorkflowVersionWorkspaceEntity>, + manager: EntityManager, + ) { + const workflowVersionNullable = await workflowVersionRepository.findOne({ + where: { id: workflowVersionId }, + }); + + const workflowVersion = + await this.workflowCommonWorkspaceService.getValidWorkflowVersionOrFail( + workflowVersionNullable, + ); + + if (workflowVersion.status !== WorkflowVersionStatus.ACTIVE) { + return; + } + + await this.setDeactivatedVersionStatus( + workflowVersion, + workflowVersionRepository, + manager, + ); + + await this.disableTrigger(workflowVersion, manager); + } + + private async setActiveVersionStatus( + workflowVersion: WorkflowVersionWorkspaceEntity, + workflowVersionRepository: WorkspaceRepository<WorkflowVersionWorkspaceEntity>, + manager: EntityManager, + ) { + const activeWorkflowVersions = await workflowVersionRepository.find( + { + where: { + workflowId: workflowVersion.workflowId, + status: WorkflowVersionStatus.ACTIVE, + }, + }, + manager, + ); + + if (activeWorkflowVersions.length > 0) { + throw new WorkflowTriggerException( + 'Cannot have more than one active workflow version', + WorkflowTriggerExceptionCode.FORBIDDEN, + ); + } + + await workflowVersionRepository.update( + { id: workflowVersion.id }, + { status: WorkflowVersionStatus.ACTIVE }, + manager, + ); + + this.emitStatusUpdateEventOrThrow( + workflowVersion.workflowId, + workflowVersion.status, + WorkflowVersionStatus.ACTIVE, + ); + } + + private async setDeactivatedVersionStatus( + workflowVersion: WorkflowVersionWorkspaceEntity, + workflowVersionRepository: WorkspaceRepository<WorkflowVersionWorkspaceEntity>, + manager: EntityManager, + ) { + if (workflowVersion.status !== WorkflowVersionStatus.ACTIVE) { + throw new WorkflowTriggerException( + 'Cannot disable non-active workflow version', + WorkflowTriggerExceptionCode.FORBIDDEN, + ); + } + + await workflowVersionRepository.update( + { id: workflowVersion.id }, + { status: WorkflowVersionStatus.DEACTIVATED }, + manager, + ); + + this.emitStatusUpdateEventOrThrow( + workflowVersion.workflowId, + workflowVersion.status, + WorkflowVersionStatus.DEACTIVATED, + ); + } + + private async upgradeWorkflowVersion( + workflow: WorkflowWorkspaceEntity, + newPublishedVersionId: string, + workflowRepository: WorkspaceRepository<WorkflowWorkspaceEntity>, + workflowVersionRepository: WorkspaceRepository<WorkflowVersionWorkspaceEntity>, + manager: EntityManager, + ) { + if (workflow.lastPublishedVersionId === newPublishedVersionId) { + return; + } + + if (workflow.lastPublishedVersionId) { + await workflowVersionRepository.update( + { id: workflow.lastPublishedVersionId }, + { status: WorkflowVersionStatus.ARCHIVED }, + manager, + ); + } + + await workflowRepository.update( + { id: workflow.id }, + { lastPublishedVersionId: newPublishedVersionId }, + manager, + ); + } + + private async enableTrigger( + workflowVersion: WorkflowVersionWorkspaceEntity, + manager: EntityManager, + ) { + assertWorkflowVersionTriggerIsDefined(workflowVersion); + + switch (workflowVersion.trigger.type) { + case WorkflowTriggerType.DATABASE_EVENT: + await this.databaseEventTriggerService.createEventListener( + workflowVersion.workflowId, + workflowVersion.trigger, + manager, + ); + break; + default: + break; + } + } + + private async disableTrigger( + workflowVersion: WorkflowVersionWorkspaceEntity, + manager: EntityManager, + ) { + assertWorkflowVersionTriggerIsDefined(workflowVersion); + + switch (workflowVersion.trigger.type) { + case WorkflowTriggerType.DATABASE_EVENT: + await this.databaseEventTriggerService.deleteEventListener( + workflowVersion.workflowId, + manager, + ); + break; + default: + break; + } + } + + private emitStatusUpdateEventOrThrow( + workflowId: string, + previousStatus: WorkflowVersionStatus, + newStatus: WorkflowVersionStatus, + ) { + const workspaceId = this.scopedWorkspaceContextFactory.create().workspaceId; + + if (!workspaceId) { + throw new WorkflowTriggerException( + 'No workspace id found', + WorkflowTriggerExceptionCode.INTERNAL_ERROR, + ); + } + + this.workspaceEventEmitter.emit( + 'workflowVersion.statusUpdated', + [ + { + workflowId, + previousStatus, + newStatus, + } satisfies WorkflowVersionStatusUpdate, + ], + workspaceId, + ); + } +} diff --git a/packages/twenty-server/src/modules/workflow/workflow.module.ts b/packages/twenty-server/src/modules/workflow/workflow.module.ts index 5f794b972a4d..08456972b3b5 100644 --- a/packages/twenty-server/src/modules/workflow/workflow.module.ts +++ b/packages/twenty-server/src/modules/workflow/workflow.module.ts @@ -1,8 +1,9 @@ import { Module } from '@nestjs/common'; +import { WorkflowStatusModule } from 'src/modules/workflow/workflow-status/workflow-status.module'; import { WorkflowTriggerModule } from 'src/modules/workflow/workflow-trigger/workflow-trigger.module'; @Module({ - imports: [WorkflowTriggerModule], + imports: [WorkflowTriggerModule, WorkflowStatusModule], }) export class WorkflowModule {} diff --git a/packages/twenty-server/src/queue-worker/queue-worker.module.ts b/packages/twenty-server/src/queue-worker/queue-worker.module.ts index bef26e3a94f4..3b8589080a12 100644 --- a/packages/twenty-server/src/queue-worker/queue-worker.module.ts +++ b/packages/twenty-server/src/queue-worker/queue-worker.module.ts @@ -1,14 +1,14 @@ import { Module } from '@nestjs/common'; -import { IntegrationsModule } from 'src/engine/integrations/integrations.module'; -import { JobsModule } from 'src/engine/integrations/message-queue/jobs.module'; -import { MessageQueueModule } from 'src/engine/integrations/message-queue/message-queue.module'; +import { JobsModule } from 'src/engine/core-modules/message-queue/jobs.module'; +import { MessageQueueModule } from 'src/engine/core-modules/message-queue/message-queue.module'; import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module'; import { WorkspaceEventEmitterModule } from 'src/engine/workspace-event-emitter/workspace-event-emitter.module'; +import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module'; @Module({ imports: [ - IntegrationsModule, + CoreEngineModule, MessageQueueModule.registerExplorer(), WorkspaceEventEmitterModule, JobsModule, diff --git a/packages/twenty-server/src/queue-worker/queue-worker.ts b/packages/twenty-server/src/queue-worker/queue-worker.ts index d38f49d306d5..157e098a2900 100644 --- a/packages/twenty-server/src/queue-worker/queue-worker.ts +++ b/packages/twenty-server/src/queue-worker/queue-worker.ts @@ -1,9 +1,10 @@ import { NestFactory } from '@nestjs/core'; -import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service'; -import { LoggerService } from 'src/engine/integrations/logger/logger.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; import { shouldFilterException } from 'src/engine/utils/global-exception-handler.util'; import { QueueWorkerModule } from 'src/queue-worker/queue-worker.module'; +import 'src/instrument'; async function bootstrap() { let exceptionHandlerService: ExceptionHandlerService | undefined; diff --git a/packages/twenty-server/src/utils/generate-front-config.ts b/packages/twenty-server/src/utils/generate-front-config.ts index f6f0f663be14..5bc490639257 100644 --- a/packages/twenty-server/src/utils/generate-front-config.ts +++ b/packages/twenty-server/src/utils/generate-front-config.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { config } from 'dotenv'; -config(); +config({ path: process.env.NODE_ENV === 'test' ? '.env.test' : '.env' }); export function generateFrontConfig(): void { const configObject = { diff --git a/packages/twenty-server/test/activities.integration-spec.ts b/packages/twenty-server/test/activities.integration-spec.ts new file mode 100644 index 000000000000..01f262c8f295 --- /dev/null +++ b/packages/twenty-server/test/activities.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('activitiesResolver (integration)', () => { + it('should find many activities', () => { + const queryData = { + query: ` + query activities { + activities { + edges { + node { + title + body + type + reminderAt + dueAt + completedAt + id + createdAt + updatedAt + deletedAt + authorId + assigneeId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.activities; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const activities = edges[0].node; + + expect(activities).toHaveProperty('title'); + expect(activities).toHaveProperty('body'); + expect(activities).toHaveProperty('type'); + expect(activities).toHaveProperty('reminderAt'); + expect(activities).toHaveProperty('dueAt'); + expect(activities).toHaveProperty('completedAt'); + expect(activities).toHaveProperty('id'); + expect(activities).toHaveProperty('createdAt'); + expect(activities).toHaveProperty('updatedAt'); + expect(activities).toHaveProperty('deletedAt'); + expect(activities).toHaveProperty('authorId'); + expect(activities).toHaveProperty('assigneeId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/activity-targets.integration-spec.ts b/packages/twenty-server/test/activity-targets.integration-spec.ts new file mode 100644 index 000000000000..cbbeb216f0aa --- /dev/null +++ b/packages/twenty-server/test/activity-targets.integration-spec.ts @@ -0,0 +1,59 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('activityTargetsResolver (integration)', () => { + it('should find many activityTargets', () => { + const queryData = { + query: ` + query activityTargets { + activityTargets { + edges { + node { + id + createdAt + updatedAt + deletedAt + activityId + personId + companyId + opportunityId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.activityTargets; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const activityTargets = edges[0].node; + + expect(activityTargets).toHaveProperty('id'); + expect(activityTargets).toHaveProperty('createdAt'); + expect(activityTargets).toHaveProperty('updatedAt'); + expect(activityTargets).toHaveProperty('deletedAt'); + expect(activityTargets).toHaveProperty('activityId'); + expect(activityTargets).toHaveProperty('personId'); + expect(activityTargets).toHaveProperty('companyId'); + expect(activityTargets).toHaveProperty('opportunityId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/api-keys.integration-spec.ts b/packages/twenty-server/test/api-keys.integration-spec.ts new file mode 100644 index 000000000000..a196db0861c4 --- /dev/null +++ b/packages/twenty-server/test/api-keys.integration-spec.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('apiKeysResolver (integration)', () => { + it('should find many apiKeys', () => { + const queryData = { + query: ` + query apiKeys { + apiKeys { + edges { + node { + name + expiresAt + revokedAt + id + createdAt + updatedAt + deletedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.apiKeys; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const apiKeys = edges[0].node; + + expect(apiKeys).toHaveProperty('name'); + expect(apiKeys).toHaveProperty('expiresAt'); + expect(apiKeys).toHaveProperty('revokedAt'); + expect(apiKeys).toHaveProperty('id'); + expect(apiKeys).toHaveProperty('createdAt'); + expect(apiKeys).toHaveProperty('updatedAt'); + expect(apiKeys).toHaveProperty('deletedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/app.e2e-spec.ts b/packages/twenty-server/test/app.e2e-spec.ts deleted file mode 100644 index a8a18c8bcbf1..000000000000 --- a/packages/twenty-server/test/app.e2e-spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { INestApplication } from '@nestjs/common'; - -import request from 'supertest'; - -import { createApp } from './utils/create-app'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - [app] = await createApp(); - }); - - afterEach(async () => { - await app.close(); - }); - - it('/healthz (GET)', () => { - return request(app.getHttpServer()) - .get('/healthz') - .expect(200) - .expect((response) => { - expect(response.body).toEqual({ - status: 'ok', - info: { database: { status: 'up' } }, - error: {}, - details: { database: { status: 'up' } }, - }); - }); - }); -}); diff --git a/packages/twenty-server/test/attachments.integration-spec.ts b/packages/twenty-server/test/attachments.integration-spec.ts new file mode 100644 index 000000000000..440a6484e6b1 --- /dev/null +++ b/packages/twenty-server/test/attachments.integration-spec.ts @@ -0,0 +1,71 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('attachmentsResolver (integration)', () => { + it('should find many attachments', () => { + const queryData = { + query: ` + query attachments { + attachments { + edges { + node { + name + fullPath + type + id + createdAt + updatedAt + deletedAt + authorId + activityId + taskId + noteId + personId + companyId + opportunityId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.attachments; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const attachments = edges[0].node; + + expect(attachments).toHaveProperty('name'); + expect(attachments).toHaveProperty('fullPath'); + expect(attachments).toHaveProperty('type'); + expect(attachments).toHaveProperty('id'); + expect(attachments).toHaveProperty('createdAt'); + expect(attachments).toHaveProperty('updatedAt'); + expect(attachments).toHaveProperty('deletedAt'); + expect(attachments).toHaveProperty('authorId'); + expect(attachments).toHaveProperty('activityId'); + expect(attachments).toHaveProperty('taskId'); + expect(attachments).toHaveProperty('noteId'); + expect(attachments).toHaveProperty('personId'); + expect(attachments).toHaveProperty('companyId'); + expect(attachments).toHaveProperty('opportunityId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/audit-logs.integration-spec.ts b/packages/twenty-server/test/audit-logs.integration-spec.ts new file mode 100644 index 000000000000..99a573235cda --- /dev/null +++ b/packages/twenty-server/test/audit-logs.integration-spec.ts @@ -0,0 +1,65 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('auditLogsResolver (integration)', () => { + it('should find many auditLogs', () => { + const queryData = { + query: ` + query auditLogs { + auditLogs { + edges { + node { + name + properties + context + objectName + objectMetadataId + recordId + id + createdAt + updatedAt + deletedAt + workspaceMemberId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.auditLogs; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const auditLogs = edges[0].node; + + expect(auditLogs).toHaveProperty('name'); + expect(auditLogs).toHaveProperty('properties'); + expect(auditLogs).toHaveProperty('context'); + expect(auditLogs).toHaveProperty('objectName'); + expect(auditLogs).toHaveProperty('objectMetadataId'); + expect(auditLogs).toHaveProperty('recordId'); + expect(auditLogs).toHaveProperty('id'); + expect(auditLogs).toHaveProperty('createdAt'); + expect(auditLogs).toHaveProperty('updatedAt'); + expect(auditLogs).toHaveProperty('deletedAt'); + expect(auditLogs).toHaveProperty('workspaceMemberId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/auth.integration-spec.ts b/packages/twenty-server/test/auth.integration-spec.ts new file mode 100644 index 000000000000..64cdde13cd6b --- /dev/null +++ b/packages/twenty-server/test/auth.integration-spec.ts @@ -0,0 +1,80 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +const auth = { + email: 'tim@apple.dev', + password: 'Applecar2025', +}; + +describe('AuthResolve (integration)', () => { + let loginToken: string; + + it('should challenge with email and password', () => { + const queryData = { + query: ` + mutation Challenge { + challenge(email: "${auth.email}", password: "${auth.password}") { + loginToken { + token + expiresAt + } + } + } + `, + }; + + return client + .post('/graphql') + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.challenge; + + expect(data).toBeDefined(); + expect(data.loginToken).toBeDefined(); + + loginToken = data.loginToken.token; + }); + }); + + it('should verify with login token', () => { + const queryData = { + query: ` + mutation Verify { + verify(loginToken: "${loginToken}") { + tokens { + accessToken { + token + } + } + } + } + `, + }; + + return client + .post('/graphql') + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.verify; + + expect(data).toBeDefined(); + expect(data.tokens).toBeDefined(); + + const accessToken = data.tokens.accessToken; + + expect(accessToken).toBeDefined(); + expect(accessToken.token).toBeDefined(); + }); + }); +}); diff --git a/packages/twenty-server/test/blocklists.integration-spec.ts b/packages/twenty-server/test/blocklists.integration-spec.ts new file mode 100644 index 000000000000..d8080b3cd570 --- /dev/null +++ b/packages/twenty-server/test/blocklists.integration-spec.ts @@ -0,0 +1,55 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('blocklistsResolver (integration)', () => { + it('should find many blocklists', () => { + const queryData = { + query: ` + query blocklists { + blocklists { + edges { + node { + handle + id + createdAt + updatedAt + deletedAt + workspaceMemberId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.blocklists; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const blocklists = edges[0].node; + + expect(blocklists).toHaveProperty('handle'); + expect(blocklists).toHaveProperty('id'); + expect(blocklists).toHaveProperty('createdAt'); + expect(blocklists).toHaveProperty('updatedAt'); + expect(blocklists).toHaveProperty('deletedAt'); + expect(blocklists).toHaveProperty('workspaceMemberId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/calendar-channel-event-associations.integration-spec.ts b/packages/twenty-server/test/calendar-channel-event-associations.integration-spec.ts new file mode 100644 index 000000000000..5d03268b840d --- /dev/null +++ b/packages/twenty-server/test/calendar-channel-event-associations.integration-spec.ts @@ -0,0 +1,63 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('calendarChannelEventAssociationsResolver (integration)', () => { + it('should find many calendarChannelEventAssociations', () => { + const queryData = { + query: ` + query calendarChannelEventAssociations { + calendarChannelEventAssociations { + edges { + node { + eventExternalId + id + createdAt + updatedAt + deletedAt + calendarChannelId + calendarEventId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.calendarChannelEventAssociations; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const calendarChannelEventAssociations = edges[0].node; + + expect(calendarChannelEventAssociations).toHaveProperty( + 'eventExternalId', + ); + expect(calendarChannelEventAssociations).toHaveProperty('id'); + expect(calendarChannelEventAssociations).toHaveProperty('createdAt'); + expect(calendarChannelEventAssociations).toHaveProperty('updatedAt'); + expect(calendarChannelEventAssociations).toHaveProperty('deletedAt'); + expect(calendarChannelEventAssociations).toHaveProperty( + 'calendarChannelId', + ); + expect(calendarChannelEventAssociations).toHaveProperty( + 'calendarEventId', + ); + } + }); + }); +}); diff --git a/packages/twenty-server/test/calendar-channels.integration-spec.ts b/packages/twenty-server/test/calendar-channels.integration-spec.ts new file mode 100644 index 000000000000..6056af6ac616 --- /dev/null +++ b/packages/twenty-server/test/calendar-channels.integration-spec.ts @@ -0,0 +1,75 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('calendarChannelsResolver (integration)', () => { + it('should find many calendarChannels', () => { + const queryData = { + query: ` + query calendarChannels { + calendarChannels { + edges { + node { + handle + syncStatus + syncStage + visibility + isContactAutoCreationEnabled + contactAutoCreationPolicy + isSyncEnabled + syncCursor + syncStageStartedAt + throttleFailureCount + id + createdAt + updatedAt + deletedAt + connectedAccountId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.calendarChannels; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const calendarChannels = edges[0].node; + + expect(calendarChannels).toHaveProperty('handle'); + expect(calendarChannels).toHaveProperty('syncStatus'); + expect(calendarChannels).toHaveProperty('syncStage'); + expect(calendarChannels).toHaveProperty('visibility'); + expect(calendarChannels).toHaveProperty( + 'isContactAutoCreationEnabled', + ); + expect(calendarChannels).toHaveProperty('contactAutoCreationPolicy'); + expect(calendarChannels).toHaveProperty('isSyncEnabled'); + expect(calendarChannels).toHaveProperty('syncCursor'); + expect(calendarChannels).toHaveProperty('syncStageStartedAt'); + expect(calendarChannels).toHaveProperty('throttleFailureCount'); + expect(calendarChannels).toHaveProperty('id'); + expect(calendarChannels).toHaveProperty('createdAt'); + expect(calendarChannels).toHaveProperty('updatedAt'); + expect(calendarChannels).toHaveProperty('deletedAt'); + expect(calendarChannels).toHaveProperty('connectedAccountId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/calendar-event-participants.integration-spec.ts b/packages/twenty-server/test/calendar-event-participants.integration-spec.ts new file mode 100644 index 000000000000..50e65547e406 --- /dev/null +++ b/packages/twenty-server/test/calendar-event-participants.integration-spec.ts @@ -0,0 +1,65 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('calendarEventParticipantsResolver (integration)', () => { + it('should find many calendarEventParticipants', () => { + const queryData = { + query: ` + query calendarEventParticipants { + calendarEventParticipants { + edges { + node { + handle + displayName + isOrganizer + responseStatus + id + createdAt + updatedAt + deletedAt + calendarEventId + personId + workspaceMemberId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.calendarEventParticipants; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const calendarEventParticipants = edges[0].node; + + expect(calendarEventParticipants).toHaveProperty('handle'); + expect(calendarEventParticipants).toHaveProperty('displayName'); + expect(calendarEventParticipants).toHaveProperty('isOrganizer'); + expect(calendarEventParticipants).toHaveProperty('responseStatus'); + expect(calendarEventParticipants).toHaveProperty('id'); + expect(calendarEventParticipants).toHaveProperty('createdAt'); + expect(calendarEventParticipants).toHaveProperty('updatedAt'); + expect(calendarEventParticipants).toHaveProperty('deletedAt'); + expect(calendarEventParticipants).toHaveProperty('calendarEventId'); + expect(calendarEventParticipants).toHaveProperty('personId'); + expect(calendarEventParticipants).toHaveProperty('workspaceMemberId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/comments.integration-spec.ts b/packages/twenty-server/test/comments.integration-spec.ts new file mode 100644 index 000000000000..0f89ba5491e6 --- /dev/null +++ b/packages/twenty-server/test/comments.integration-spec.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('commentsResolver (integration)', () => { + it('should find many comments', () => { + const queryData = { + query: ` + query comments { + comments { + edges { + node { + body + id + createdAt + updatedAt + deletedAt + authorId + activityId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.comments; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const comments = edges[0].node; + + expect(comments).toHaveProperty('body'); + expect(comments).toHaveProperty('id'); + expect(comments).toHaveProperty('createdAt'); + expect(comments).toHaveProperty('updatedAt'); + expect(comments).toHaveProperty('deletedAt'); + expect(comments).toHaveProperty('authorId'); + expect(comments).toHaveProperty('activityId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/companies.integration-spec.ts b/packages/twenty-server/test/companies.integration-spec.ts new file mode 100644 index 000000000000..63c7f9eec481 --- /dev/null +++ b/packages/twenty-server/test/companies.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('companiesResolver (integration)', () => { + it('should find many companies', () => { + const queryData = { + query: ` + query companies { + companies { + edges { + node { + name + employees + idealCustomerProfile + position + id + createdAt + updatedAt + deletedAt + accountOwnerId + tagline + workPolicy + visaSponsorship + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.companies; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const companies = edges[0].node; + + expect(companies).toHaveProperty('name'); + expect(companies).toHaveProperty('employees'); + expect(companies).toHaveProperty('idealCustomerProfile'); + expect(companies).toHaveProperty('position'); + expect(companies).toHaveProperty('id'); + expect(companies).toHaveProperty('createdAt'); + expect(companies).toHaveProperty('updatedAt'); + expect(companies).toHaveProperty('deletedAt'); + expect(companies).toHaveProperty('accountOwnerId'); + expect(companies).toHaveProperty('tagline'); + expect(companies).toHaveProperty('workPolicy'); + expect(companies).toHaveProperty('visaSponsorship'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/company.e2e-spec.ts b/packages/twenty-server/test/company.e2e-spec.ts deleted file mode 100644 index 1a52998601d8..000000000000 --- a/packages/twenty-server/test/company.e2e-spec.ts +++ /dev/null @@ -1,310 +0,0 @@ -import { INestApplication } from '@nestjs/common'; - -import request from 'supertest'; - -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; - -import { createApp } from './utils/create-app'; - -describe('CompanyResolver (e2e)', () => { - let app: INestApplication; - let companyId: string | undefined; - - const authGuardMock = { canActivate: (): any => true }; - - beforeEach(async () => { - [app] = await createApp({ - moduleBuilderHook: (moduleBuilder) => - moduleBuilder.overrideGuard(JwtAuthGuard).useValue(authGuardMock), - }); - }); - - afterEach(async () => { - await app.close(); - }); - - it('should create a company', () => { - const queryData = { - query: ` - mutation CreateOneCompany($data: CompanyCreateInput!) { - createOneCompany(data: $data) { - id - name - domainName - address { - addressCity - } - } - } - `, - variables: { - data: { - name: 'New Company', - domainName: 'new-company.com', - address: { addressCity: 'Paris' }, - }, - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const data = res.body.data.createOneCompany; - - companyId = data.id; - - expect(data).toBeDefined(); - expect(data).toHaveProperty('id'); - expect(data).toHaveProperty('name', 'New Company'); - expect(data).toHaveProperty('domainName', 'new-company.com'); - expect(data).toHaveProperty('address', { addressCity: 'Paris' }); - }); - }); - - it('should find many companies', () => { - const queryData = { - query: ` - query FindManyCompany { - findManyCompany { - id - name - domainName - address { - addressCity - } - } - } - `, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const data = res.body.data.findManyCompany; - - expect(data).toBeDefined(); - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBeGreaterThan(0); - - const company = data.find((c) => c.id === companyId); - - expect(company).toBeDefined(); - expect(company).toHaveProperty('id'); - expect(company).toHaveProperty('name', 'New Company'); - expect(company).toHaveProperty('domainName', 'new-company.com'); - expect(company).toHaveProperty('address', { addressCity: 'Paris' }); - - // Check if we have access to ressources outside of our workspace - const instagramCompany = data.find((c) => c.name === 'Instagram'); - - expect(instagramCompany).toBeUndefined(); - }); - }); - - it('should find unique company', () => { - const queryData = { - query: ` - query FindUniqueCompany($where: CompanyWhereUniqueInput!) { - findUniqueCompany(where: $where) { - id - name - domainName - address { - addressCity - } - } - } - `, - variables: { - where: { - id: companyId, - }, - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const data = res.body.data.findUniqueCompany; - - expect(data).toBeDefined(); - expect(data).toHaveProperty('id'); - expect(data).toHaveProperty('name', 'New Company'); - expect(data).toHaveProperty('domainName', 'new-company.com'); - expect(data).toHaveProperty('address', { addressCity: 'Paris' }); - }); - }); - - it('should not find unique company (forbidden because outside workspace)', () => { - const queryData = { - query: ` - query FindUniqueCompany($where: CompanyWhereUniqueInput!) { - findUniqueCompany(where: $where) { - id - name - domainName - address { - addressCity - } - } - } - `, - variables: { - where: { - id: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e', - }, - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const errors = res.body.errors; - const error = errors?.[0]; - - expect(error).toBeDefined(); - expect(error.message).toBe('Forbidden resource'); - }); - }); - - it('should update a company', () => { - const queryData = { - query: ` - mutation UpdateOneCompany($where: CompanyWhereUniqueInput!, $data: CompanyUpdateInput!) { - updateOneCompany(data: $data, where: $where) { - id - name - domainName - address { - addressCity - } - } - } - `, - variables: { - where: { - id: companyId, - }, - data: { - name: 'Updated Company', - domainName: 'updated-company.com', - address: { addressCity: 'Updated City' }, - }, - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const data = res.body.data.updateOneCompany; - - expect(data).toBeDefined(); - expect(data).toHaveProperty('id'); - expect(data).toHaveProperty('name', 'Updated Company'); - expect(data).toHaveProperty('domainName', 'updated-company.com'); - expect(data).toHaveProperty('address', { addressCity: 'Updated City' }); - }); - }); - - it('should not update a company (forbidden because outside workspace)', () => { - const queryData = { - query: ` - mutation UpdateOneCompany($where: CompanyWhereUniqueInput!, $data: CompanyUpdateInput!) { - updateOneCompany(data: $data, where: $where) { - id - name - domainName - address { - addressCity - } - } - } - `, - variables: { - where: { - id: 'twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e', - }, - data: { - name: 'Updated Instagram', - }, - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const errors = res.body.errors; - const error = errors?.[0]; - - expect(error).toBeDefined(); - expect(error.message).toBe('Forbidden resource'); - }); - }); - - it('should delete a company', () => { - const queryData = { - query: ` - mutation DeleteManyCompany($ids: [String!]) { - deleteManyCompany(where: {id: {in: $ids}}) { - count - } - } - `, - variables: { - ids: [companyId], - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const data = res.body.data.deleteManyCompany; - - companyId = undefined; - - expect(data).toBeDefined(); - expect(data).toHaveProperty('count', 1); - }); - }); - - it('should not delete a company (forbidden because outside workspace)', () => { - const queryData = { - query: ` - mutation DeleteManyCompany($ids: [String!]) { - deleteManyCompany(where: {id: {in: $ids}}) { - count - } - } - `, - variables: { - ids: ['twenty-dev-a674fa6c-1455-4c57-afaf-dd5dc086361e'], - }, - }; - - return request(app.getHttpServer()) - .post('/graphql') - .send(queryData) - .expect(200) - .expect((res) => { - const errors = res.body.errors; - const error = errors?.[0]; - - expect(error).toBeDefined(); - expect(error.message).toBe('Forbidden resource'); - }); - }); -}); diff --git a/packages/twenty-server/test/company.integration-spec.ts b/packages/twenty-server/test/company.integration-spec.ts new file mode 100644 index 000000000000..bd25d66eb4dc --- /dev/null +++ b/packages/twenty-server/test/company.integration-spec.ts @@ -0,0 +1,48 @@ +import request from 'supertest'; + +const graphqlClient = request(`http://localhost:${APP_PORT}`); + +describe('CompanyResolver (integration)', () => { + it('should find many companies', () => { + const queryData = { + query: ` + query Companies { + companies { + edges { + node { + id + name + } + } + } + } + `, + }; + + return graphqlClient + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.companies; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const company = edges[0].node; + + expect(company).toBeDefined(); + expect(company).toHaveProperty('id'); + expect(company).toHaveProperty('name'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/connected-accounts.integration-spec.ts b/packages/twenty-server/test/connected-accounts.integration-spec.ts new file mode 100644 index 000000000000..e17fd5b28504 --- /dev/null +++ b/packages/twenty-server/test/connected-accounts.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('connectedAccountsResolver (integration)', () => { + it('should find many connectedAccounts', () => { + const queryData = { + query: ` + query connectedAccounts { + connectedAccounts { + edges { + node { + handle + provider + accessToken + refreshToken + lastSyncHistoryId + authFailedAt + handleAliases + id + createdAt + updatedAt + deletedAt + accountOwnerId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.connectedAccounts; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const connectedAccounts = edges[0].node; + + expect(connectedAccounts).toHaveProperty('handle'); + expect(connectedAccounts).toHaveProperty('provider'); + expect(connectedAccounts).toHaveProperty('accessToken'); + expect(connectedAccounts).toHaveProperty('refreshToken'); + expect(connectedAccounts).toHaveProperty('lastSyncHistoryId'); + expect(connectedAccounts).toHaveProperty('authFailedAt'); + expect(connectedAccounts).toHaveProperty('handleAliases'); + expect(connectedAccounts).toHaveProperty('id'); + expect(connectedAccounts).toHaveProperty('createdAt'); + expect(connectedAccounts).toHaveProperty('updatedAt'); + expect(connectedAccounts).toHaveProperty('deletedAt'); + expect(connectedAccounts).toHaveProperty('accountOwnerId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/favorites.integration-spec.ts b/packages/twenty-server/test/favorites.integration-spec.ts new file mode 100644 index 000000000000..f58e702e5517 --- /dev/null +++ b/packages/twenty-server/test/favorites.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('favoritesResolver (integration)', () => { + it('should find many favorites', () => { + const queryData = { + query: ` + query favorites { + favorites { + edges { + node { + position + id + createdAt + updatedAt + deletedAt + workspaceMemberId + personId + companyId + opportunityId + taskId + noteId + viewId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.favorites; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const favorites = edges[0].node; + + expect(favorites).toHaveProperty('position'); + expect(favorites).toHaveProperty('id'); + expect(favorites).toHaveProperty('createdAt'); + expect(favorites).toHaveProperty('updatedAt'); + expect(favorites).toHaveProperty('deletedAt'); + expect(favorites).toHaveProperty('workspaceMemberId'); + expect(favorites).toHaveProperty('personId'); + expect(favorites).toHaveProperty('companyId'); + expect(favorites).toHaveProperty('opportunityId'); + expect(favorites).toHaveProperty('taskId'); + expect(favorites).toHaveProperty('noteId'); + expect(favorites).toHaveProperty('viewId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/jest-e2e.json b/packages/twenty-server/test/jest-e2e.json deleted file mode 100644 index 0456e6d75219..000000000000 --- a/packages/twenty-server/test/jest-e2e.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "setupFilesAfterEnv": ["<rootDir>/utils/setup-tests.ts"], - "moduleNameMapper": { - "^src/(.*)": "<rootDir>/../src/$1", - "^test/(.*)": "<rootDir>/$1" - }, - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} diff --git a/packages/twenty-server/test/message-channel-message-associations.integration-spec.ts b/packages/twenty-server/test/message-channel-message-associations.integration-spec.ts new file mode 100644 index 000000000000..a250550f4b88 --- /dev/null +++ b/packages/twenty-server/test/message-channel-message-associations.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('messageChannelMessageAssociationsResolver (integration)', () => { + it('should find many messageChannelMessageAssociations', () => { + const queryData = { + query: ` + query messageChannelMessageAssociations { + messageChannelMessageAssociations { + edges { + node { + createdAt + messageExternalId + messageThreadExternalId + direction + id + updatedAt + deletedAt + messageChannelId + messageId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.messageChannelMessageAssociations; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageChannelMessageAssociations = edges[0].node; + + expect(messageChannelMessageAssociations).toHaveProperty('createdAt'); + expect(messageChannelMessageAssociations).toHaveProperty( + 'messageExternalId', + ); + expect(messageChannelMessageAssociations).toHaveProperty( + 'messageThreadExternalId', + ); + expect(messageChannelMessageAssociations).toHaveProperty('direction'); + expect(messageChannelMessageAssociations).toHaveProperty('id'); + expect(messageChannelMessageAssociations).toHaveProperty('updatedAt'); + expect(messageChannelMessageAssociations).toHaveProperty('deletedAt'); + expect(messageChannelMessageAssociations).toHaveProperty( + 'messageChannelId', + ); + expect(messageChannelMessageAssociations).toHaveProperty('messageId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/message-channels.integration-spec.ts b/packages/twenty-server/test/message-channels.integration-spec.ts new file mode 100644 index 000000000000..8100a885d89c --- /dev/null +++ b/packages/twenty-server/test/message-channels.integration-spec.ts @@ -0,0 +1,85 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('messageChannelsResolver (integration)', () => { + it('should find many messageChannels', () => { + const queryData = { + query: ` + query messageChannels { + messageChannels { + edges { + node { + visibility + handle + type + isContactAutoCreationEnabled + contactAutoCreationPolicy + excludeNonProfessionalEmails + excludeGroupEmails + isSyncEnabled + syncCursor + syncedAt + syncStatus + syncStage + syncStageStartedAt + throttleFailureCount + id + createdAt + updatedAt + deletedAt + connectedAccountId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.messageChannels; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageChannels = edges[0].node; + + expect(messageChannels).toHaveProperty('visibility'); + expect(messageChannels).toHaveProperty('handle'); + expect(messageChannels).toHaveProperty('type'); + expect(messageChannels).toHaveProperty( + 'isContactAutoCreationEnabled', + ); + expect(messageChannels).toHaveProperty('contactAutoCreationPolicy'); + expect(messageChannels).toHaveProperty( + 'excludeNonProfessionalEmails', + ); + expect(messageChannels).toHaveProperty('excludeGroupEmails'); + expect(messageChannels).toHaveProperty('isSyncEnabled'); + expect(messageChannels).toHaveProperty('syncCursor'); + expect(messageChannels).toHaveProperty('syncedAt'); + expect(messageChannels).toHaveProperty('syncStatus'); + expect(messageChannels).toHaveProperty('syncStage'); + expect(messageChannels).toHaveProperty('syncStageStartedAt'); + expect(messageChannels).toHaveProperty('throttleFailureCount'); + expect(messageChannels).toHaveProperty('id'); + expect(messageChannels).toHaveProperty('createdAt'); + expect(messageChannels).toHaveProperty('updatedAt'); + expect(messageChannels).toHaveProperty('deletedAt'); + expect(messageChannels).toHaveProperty('connectedAccountId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/message-participants.integration-spec.ts b/packages/twenty-server/test/message-participants.integration-spec.ts new file mode 100644 index 000000000000..45c190c536ec --- /dev/null +++ b/packages/twenty-server/test/message-participants.integration-spec.ts @@ -0,0 +1,63 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('messageParticipantsResolver (integration)', () => { + it('should find many messageParticipants', () => { + const queryData = { + query: ` + query messageParticipants { + messageParticipants { + edges { + node { + role + handle + displayName + id + createdAt + updatedAt + deletedAt + messageId + personId + workspaceMemberId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.messageParticipants; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageParticipants = edges[0].node; + + expect(messageParticipants).toHaveProperty('role'); + expect(messageParticipants).toHaveProperty('handle'); + expect(messageParticipants).toHaveProperty('displayName'); + expect(messageParticipants).toHaveProperty('id'); + expect(messageParticipants).toHaveProperty('createdAt'); + expect(messageParticipants).toHaveProperty('updatedAt'); + expect(messageParticipants).toHaveProperty('deletedAt'); + expect(messageParticipants).toHaveProperty('messageId'); + expect(messageParticipants).toHaveProperty('personId'); + expect(messageParticipants).toHaveProperty('workspaceMemberId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/message-threads.integration-spec.ts b/packages/twenty-server/test/message-threads.integration-spec.ts new file mode 100644 index 000000000000..714bf06bb65a --- /dev/null +++ b/packages/twenty-server/test/message-threads.integration-spec.ts @@ -0,0 +1,51 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('messageThreadsResolver (integration)', () => { + it('should find many messageThreads', () => { + const queryData = { + query: ` + query messageThreads { + messageThreads { + edges { + node { + id + createdAt + updatedAt + deletedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.messageThreads; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageThreads = edges[0].node; + + expect(messageThreads).toHaveProperty('id'); + expect(messageThreads).toHaveProperty('createdAt'); + expect(messageThreads).toHaveProperty('updatedAt'); + expect(messageThreads).toHaveProperty('deletedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/mock-data/user.json b/packages/twenty-server/test/mock-data/user.json deleted file mode 100644 index f6fbc0d03709..000000000000 --- a/packages/twenty-server/test/mock-data/user.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "20202020-a838-4fa9-b59b-96409b9a1c30", - "firstName": "Tim", - "lastName": "Apple", - "email": "tim@apple.dev", - "locale": "en", - "passwordHash": "$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6", - "avatarUrl": null -} diff --git a/packages/twenty-server/test/mock-data/workspace.json b/packages/twenty-server/test/mock-data/workspace.json deleted file mode 100644 index 37d7f52a3d2a..000000000000 --- a/packages/twenty-server/test/mock-data/workspace.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "20202020-1c25-4d02-bf25-6aeccf7ea419", - "displayName": "Apple", - "domainName": "apple.dev", - "inviteHash": "apple.dev-invite-hash", - "logo": "data:image/png;base64,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" -} diff --git a/packages/twenty-server/test/note-targets.integration-spec.ts b/packages/twenty-server/test/note-targets.integration-spec.ts new file mode 100644 index 000000000000..30d309dc32f5 --- /dev/null +++ b/packages/twenty-server/test/note-targets.integration-spec.ts @@ -0,0 +1,59 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('noteTargetsResolver (integration)', () => { + it('should find many noteTargets', () => { + const queryData = { + query: ` + query noteTargets { + noteTargets { + edges { + node { + id + createdAt + updatedAt + deletedAt + noteId + personId + companyId + opportunityId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.noteTargets; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const noteTargets = edges[0].node; + + expect(noteTargets).toHaveProperty('id'); + expect(noteTargets).toHaveProperty('createdAt'); + expect(noteTargets).toHaveProperty('updatedAt'); + expect(noteTargets).toHaveProperty('deletedAt'); + expect(noteTargets).toHaveProperty('noteId'); + expect(noteTargets).toHaveProperty('personId'); + expect(noteTargets).toHaveProperty('companyId'); + expect(noteTargets).toHaveProperty('opportunityId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/notes.integration-spec.ts b/packages/twenty-server/test/notes.integration-spec.ts new file mode 100644 index 000000000000..eb13fedbac42 --- /dev/null +++ b/packages/twenty-server/test/notes.integration-spec.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('notesResolver (integration)', () => { + it('should find many notes', () => { + const queryData = { + query: ` + query notes { + notes { + edges { + node { + position + title + body + id + createdAt + updatedAt + deletedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.notes; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const notes = edges[0].node; + + expect(notes).toHaveProperty('position'); + expect(notes).toHaveProperty('title'); + expect(notes).toHaveProperty('body'); + expect(notes).toHaveProperty('id'); + expect(notes).toHaveProperty('createdAt'); + expect(notes).toHaveProperty('updatedAt'); + expect(notes).toHaveProperty('deletedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/objects.integration-spec.ts b/packages/twenty-server/test/objects.integration-spec.ts new file mode 100644 index 000000000000..80d1458ab668 --- /dev/null +++ b/packages/twenty-server/test/objects.integration-spec.ts @@ -0,0 +1,75 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('objectsResolver (integration)', () => { + it('should find many objects', () => { + const queryData = { + query: ` + query objects { + objects { + edges { + node { + id + dataSourceId + nameSingular + namePlural + labelSingular + labelPlural + description + icon + isCustom + isRemote + isActive + isSystem + createdAt + updatedAt + labelIdentifierFieldMetadataId + imageIdentifierFieldMetadataId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.objects; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const objects = edges[0].node; + + expect(objects).toHaveProperty('id'); + expect(objects).toHaveProperty('dataSourceId'); + expect(objects).toHaveProperty('nameSingular'); + expect(objects).toHaveProperty('namePlural'); + expect(objects).toHaveProperty('labelSingular'); + expect(objects).toHaveProperty('labelPlural'); + expect(objects).toHaveProperty('description'); + expect(objects).toHaveProperty('icon'); + expect(objects).toHaveProperty('isCustom'); + expect(objects).toHaveProperty('isRemote'); + expect(objects).toHaveProperty('isActive'); + expect(objects).toHaveProperty('isSystem'); + expect(objects).toHaveProperty('createdAt'); + expect(objects).toHaveProperty('updatedAt'); + expect(objects).toHaveProperty('labelIdentifierFieldMetadataId'); + expect(objects).toHaveProperty('imageIdentifierFieldMetadataId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/opportunities.integration-spec.ts b/packages/twenty-server/test/opportunities.integration-spec.ts new file mode 100644 index 000000000000..9eebe96a0da7 --- /dev/null +++ b/packages/twenty-server/test/opportunities.integration-spec.ts @@ -0,0 +1,63 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('opportunitiesResolver (integration)', () => { + it('should find many opportunities', () => { + const queryData = { + query: ` + query opportunities { + opportunities { + edges { + node { + name + closeDate + stage + position + id + createdAt + updatedAt + deletedAt + pointOfContactId + companyId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.opportunities; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const opportunities = edges[0].node; + + expect(opportunities).toHaveProperty('name'); + expect(opportunities).toHaveProperty('closeDate'); + expect(opportunities).toHaveProperty('stage'); + expect(opportunities).toHaveProperty('position'); + expect(opportunities).toHaveProperty('id'); + expect(opportunities).toHaveProperty('createdAt'); + expect(opportunities).toHaveProperty('updatedAt'); + expect(opportunities).toHaveProperty('deletedAt'); + expect(opportunities).toHaveProperty('pointOfContactId'); + expect(opportunities).toHaveProperty('companyId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/people.integration-spec.ts b/packages/twenty-server/test/people.integration-spec.ts new file mode 100644 index 000000000000..fd568bd5ba40 --- /dev/null +++ b/packages/twenty-server/test/people.integration-spec.ts @@ -0,0 +1,77 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('peopleResolver (integration)', () => { + it('should find many people', () => { + const queryData = { + query: ` + query people { + people { + edges { + node { + jobTitle + phones { + primaryPhoneNumber + primaryPhoneCountryCode + } + city + avatarUrl + position + id + createdAt + updatedAt + deletedAt + companyId + intro + whatsapp { + primaryPhoneNumber + } + workPrefereance + performanceRating + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + console.log(res.body); + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.people; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const people = edges[0].node; + + expect(people).toHaveProperty('jobTitle'); + expect(people).toHaveProperty('phones'); + expect(people).toHaveProperty('city'); + expect(people).toHaveProperty('avatarUrl'); + expect(people).toHaveProperty('position'); + expect(people).toHaveProperty('id'); + expect(people).toHaveProperty('createdAt'); + expect(people).toHaveProperty('updatedAt'); + expect(people).toHaveProperty('deletedAt'); + expect(people).toHaveProperty('companyId'); + expect(people).toHaveProperty('intro'); + expect(people).toHaveProperty('whatsapp'); + expect(people).toHaveProperty('workPrefereance'); + expect(people).toHaveProperty('performanceRating'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/serverless-functions.integration-spec.ts b/packages/twenty-server/test/serverless-functions.integration-spec.ts new file mode 100644 index 000000000000..b4b87ff7caed --- /dev/null +++ b/packages/twenty-server/test/serverless-functions.integration-spec.ts @@ -0,0 +1,61 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('serverlessFunctionsResolver (integration)', () => { + it('should find many serverlessFunctions', () => { + const queryData = { + query: ` + query serverlessFunctions { + serverlessFunctions { + edges { + node { + id + name + description + sourceCodeHash + runtime + latestVersion + syncStatus + createdAt + updatedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.serverlessFunctions; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const serverlessFunctions = edges[0].node; + + expect(serverlessFunctions).toHaveProperty('id'); + expect(serverlessFunctions).toHaveProperty('name'); + expect(serverlessFunctions).toHaveProperty('description'); + expect(serverlessFunctions).toHaveProperty('sourceCodeHash'); + expect(serverlessFunctions).toHaveProperty('runtime'); + expect(serverlessFunctions).toHaveProperty('latestVersion'); + expect(serverlessFunctions).toHaveProperty('syncStatus'); + expect(serverlessFunctions).toHaveProperty('createdAt'); + expect(serverlessFunctions).toHaveProperty('updatedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/task-targets.integration-spec.ts b/packages/twenty-server/test/task-targets.integration-spec.ts new file mode 100644 index 000000000000..e54e855d31e5 --- /dev/null +++ b/packages/twenty-server/test/task-targets.integration-spec.ts @@ -0,0 +1,59 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('taskTargetsResolver (integration)', () => { + it('should find many taskTargets', () => { + const queryData = { + query: ` + query taskTargets { + taskTargets { + edges { + node { + id + createdAt + updatedAt + deletedAt + taskId + personId + companyId + opportunityId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.taskTargets; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const taskTargets = edges[0].node; + + expect(taskTargets).toHaveProperty('id'); + expect(taskTargets).toHaveProperty('createdAt'); + expect(taskTargets).toHaveProperty('updatedAt'); + expect(taskTargets).toHaveProperty('deletedAt'); + expect(taskTargets).toHaveProperty('taskId'); + expect(taskTargets).toHaveProperty('personId'); + expect(taskTargets).toHaveProperty('companyId'); + expect(taskTargets).toHaveProperty('opportunityId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/tasks.integration-spec.ts b/packages/twenty-server/test/tasks.integration-spec.ts new file mode 100644 index 000000000000..900fd3de5ce1 --- /dev/null +++ b/packages/twenty-server/test/tasks.integration-spec.ts @@ -0,0 +1,63 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('tasksResolver (integration)', () => { + it('should find many tasks', () => { + const queryData = { + query: ` + query tasks { + tasks { + edges { + node { + position + title + body + dueAt + status + id + createdAt + updatedAt + deletedAt + assigneeId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.tasks; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const tasks = edges[0].node; + + expect(tasks).toHaveProperty('position'); + expect(tasks).toHaveProperty('title'); + expect(tasks).toHaveProperty('body'); + expect(tasks).toHaveProperty('dueAt'); + expect(tasks).toHaveProperty('status'); + expect(tasks).toHaveProperty('id'); + expect(tasks).toHaveProperty('createdAt'); + expect(tasks).toHaveProperty('updatedAt'); + expect(tasks).toHaveProperty('deletedAt'); + expect(tasks).toHaveProperty('assigneeId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/timeline-activities.integration-spec.ts b/packages/twenty-server/test/timeline-activities.integration-spec.ts new file mode 100644 index 000000000000..a5ef6a5f9662 --- /dev/null +++ b/packages/twenty-server/test/timeline-activities.integration-spec.ts @@ -0,0 +1,75 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('timelineActivitiesResolver (integration)', () => { + it('should find many timelineActivities', () => { + const queryData = { + query: ` + query timelineActivities { + timelineActivities { + edges { + node { + happensAt + name + properties + linkedRecordCachedName + linkedRecordId + linkedObjectMetadataId + id + createdAt + updatedAt + deletedAt + workspaceMemberId + personId + companyId + opportunityId + noteId + taskId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.timelineActivities; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const timelineActivities = edges[0].node; + + expect(timelineActivities).toHaveProperty('happensAt'); + expect(timelineActivities).toHaveProperty('name'); + expect(timelineActivities).toHaveProperty('properties'); + expect(timelineActivities).toHaveProperty('linkedRecordCachedName'); + expect(timelineActivities).toHaveProperty('linkedRecordId'); + expect(timelineActivities).toHaveProperty('linkedObjectMetadataId'); + expect(timelineActivities).toHaveProperty('id'); + expect(timelineActivities).toHaveProperty('createdAt'); + expect(timelineActivities).toHaveProperty('updatedAt'); + expect(timelineActivities).toHaveProperty('deletedAt'); + expect(timelineActivities).toHaveProperty('workspaceMemberId'); + expect(timelineActivities).toHaveProperty('personId'); + expect(timelineActivities).toHaveProperty('companyId'); + expect(timelineActivities).toHaveProperty('opportunityId'); + expect(timelineActivities).toHaveProperty('noteId'); + expect(timelineActivities).toHaveProperty('taskId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/utils/create-app.ts b/packages/twenty-server/test/utils/create-app.ts index 9011599ea6f4..dfa136e4d4b7 100644 --- a/packages/twenty-server/test/utils/create-app.ts +++ b/packages/twenty-server/test/utils/create-app.ts @@ -1,10 +1,6 @@ import { NestExpressApplication } from '@nestjs/platform-express'; import { Test, TestingModule, TestingModuleBuilder } from '@nestjs/testing'; -import mockUser from 'test/mock-data/user.json'; -import mockWorkspace from 'test/mock-data/workspace.json'; -import { RequestHandler } from 'express'; - import { AppModule } from 'src/app.module'; interface TestingModuleCreatePreHook { @@ -19,14 +15,14 @@ export type TestingAppCreatePreHook = ( ) => Promise<void>; /** - * Sets basic e2e testing module of app + * Sets basic integration testing module of app */ export const createApp = async ( config: { moduleBuilderHook?: TestingModuleCreatePreHook; appInitHook?: TestingAppCreatePreHook; } = {}, -): Promise<[NestExpressApplication, TestingModule]> => { +): Promise<NestExpressApplication> => { let moduleBuilder: TestingModuleBuilder = Test.createTestingModule({ imports: [AppModule], }); @@ -36,21 +32,14 @@ export const createApp = async ( } const moduleFixture: TestingModule = await moduleBuilder.compile(); + const app = moduleFixture.createNestApplication<NestExpressApplication>(); if (config.appInitHook) { await config.appInitHook(app); } - const mockAuthHandler: RequestHandler = (req, _res, next) => { - req.user = { - user: mockUser, - workspace: mockWorkspace, - }; - next(); - }; - - app.use(mockAuthHandler); + await app.init(); - return [await app.init(), moduleFixture]; + return app; }; diff --git a/packages/twenty-server/test/utils/setup-test.ts b/packages/twenty-server/test/utils/setup-test.ts new file mode 100644 index 000000000000..aac860fc79ee --- /dev/null +++ b/packages/twenty-server/test/utils/setup-test.ts @@ -0,0 +1,16 @@ +import 'tsconfig-paths/register'; +import { JestConfigWithTsJest } from 'ts-jest'; + +import { createApp } from './create-app'; + +export default async (_, projectConfig: JestConfigWithTsJest) => { + const app = await createApp({}); + + if (!projectConfig.globals) { + throw new Error('No globals found in project config'); + } + + await app.listen(projectConfig.globals.APP_PORT); + + global.app = app; +}; diff --git a/packages/twenty-server/test/utils/setup-tests.ts b/packages/twenty-server/test/utils/setup-tests.ts deleted file mode 100644 index 9e48ba513fa7..000000000000 --- a/packages/twenty-server/test/utils/setup-tests.ts +++ /dev/null @@ -1,3 +0,0 @@ -global.beforeEach(() => { - // resetDb(); -}); diff --git a/packages/twenty-server/test/utils/teardown-test.ts b/packages/twenty-server/test/utils/teardown-test.ts new file mode 100644 index 000000000000..8cc1946d5053 --- /dev/null +++ b/packages/twenty-server/test/utils/teardown-test.ts @@ -0,0 +1,5 @@ +import 'tsconfig-paths/register'; + +export default async () => { + global.app.close(); +}; diff --git a/packages/twenty-server/test/view-fields.integration-spec.ts b/packages/twenty-server/test/view-fields.integration-spec.ts new file mode 100644 index 000000000000..058568763900 --- /dev/null +++ b/packages/twenty-server/test/view-fields.integration-spec.ts @@ -0,0 +1,61 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('viewFieldsResolver (integration)', () => { + it('should find many viewFields', () => { + const queryData = { + query: ` + query viewFields { + viewFields { + edges { + node { + fieldMetadataId + isVisible + size + position + id + createdAt + updatedAt + deletedAt + viewId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.viewFields; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const viewFields = edges[0].node; + + expect(viewFields).toHaveProperty('fieldMetadataId'); + expect(viewFields).toHaveProperty('isVisible'); + expect(viewFields).toHaveProperty('size'); + expect(viewFields).toHaveProperty('position'); + expect(viewFields).toHaveProperty('id'); + expect(viewFields).toHaveProperty('createdAt'); + expect(viewFields).toHaveProperty('updatedAt'); + expect(viewFields).toHaveProperty('deletedAt'); + expect(viewFields).toHaveProperty('viewId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/view-filters.integration-spec.ts b/packages/twenty-server/test/view-filters.integration-spec.ts new file mode 100644 index 000000000000..8caa942b2b61 --- /dev/null +++ b/packages/twenty-server/test/view-filters.integration-spec.ts @@ -0,0 +1,61 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('viewFiltersResolver (integration)', () => { + it('should find many viewFilters', () => { + const queryData = { + query: ` + query viewFilters { + viewFilters { + edges { + node { + fieldMetadataId + operand + value + displayValue + id + createdAt + updatedAt + deletedAt + viewId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.viewFilters; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const viewFilters = edges[0].node; + + expect(viewFilters).toHaveProperty('fieldMetadataId'); + expect(viewFilters).toHaveProperty('operand'); + expect(viewFilters).toHaveProperty('value'); + expect(viewFilters).toHaveProperty('displayValue'); + expect(viewFilters).toHaveProperty('id'); + expect(viewFilters).toHaveProperty('createdAt'); + expect(viewFilters).toHaveProperty('updatedAt'); + expect(viewFilters).toHaveProperty('deletedAt'); + expect(viewFilters).toHaveProperty('viewId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/view-sorts.integration-spec.ts b/packages/twenty-server/test/view-sorts.integration-spec.ts new file mode 100644 index 000000000000..fc29b1d4c293 --- /dev/null +++ b/packages/twenty-server/test/view-sorts.integration-spec.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('viewSortsResolver (integration)', () => { + it('should find many viewSorts', () => { + const queryData = { + query: ` + query viewSorts { + viewSorts { + edges { + node { + fieldMetadataId + direction + id + createdAt + updatedAt + deletedAt + viewId + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.viewSorts; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const viewSorts = edges[0].node; + + expect(viewSorts).toHaveProperty('fieldMetadataId'); + expect(viewSorts).toHaveProperty('direction'); + expect(viewSorts).toHaveProperty('id'); + expect(viewSorts).toHaveProperty('createdAt'); + expect(viewSorts).toHaveProperty('updatedAt'); + expect(viewSorts).toHaveProperty('deletedAt'); + expect(viewSorts).toHaveProperty('viewId'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/views.integration-spec.ts b/packages/twenty-server/test/views.integration-spec.ts new file mode 100644 index 000000000000..122a8c398fcc --- /dev/null +++ b/packages/twenty-server/test/views.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('viewsResolver (integration)', () => { + it('should find many views', () => { + const queryData = { + query: ` + query views { + views { + edges { + node { + position + name + objectMetadataId + type + key + icon + kanbanFieldMetadataId + isCompact + id + createdAt + updatedAt + deletedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.views; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const views = edges[0].node; + + expect(views).toHaveProperty('position'); + expect(views).toHaveProperty('name'); + expect(views).toHaveProperty('objectMetadataId'); + expect(views).toHaveProperty('type'); + expect(views).toHaveProperty('key'); + expect(views).toHaveProperty('icon'); + expect(views).toHaveProperty('kanbanFieldMetadataId'); + expect(views).toHaveProperty('isCompact'); + expect(views).toHaveProperty('id'); + expect(views).toHaveProperty('createdAt'); + expect(views).toHaveProperty('updatedAt'); + expect(views).toHaveProperty('deletedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/webhooks.integration-spec.ts b/packages/twenty-server/test/webhooks.integration-spec.ts new file mode 100644 index 000000000000..7c4224b69aa6 --- /dev/null +++ b/packages/twenty-server/test/webhooks.integration-spec.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('webhooksResolver (integration)', () => { + it('should find many webhooks', () => { + const queryData = { + query: ` + query webhooks { + webhooks { + edges { + node { + targetUrl + operation + description + id + createdAt + updatedAt + deletedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.webhooks; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const webhooks = edges[0].node; + + expect(webhooks).toHaveProperty('targetUrl'); + expect(webhooks).toHaveProperty('operation'); + expect(webhooks).toHaveProperty('description'); + expect(webhooks).toHaveProperty('id'); + expect(webhooks).toHaveProperty('createdAt'); + expect(webhooks).toHaveProperty('updatedAt'); + expect(webhooks).toHaveProperty('deletedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/test/workspace-members.integration-spec.ts b/packages/twenty-server/test/workspace-members.integration-spec.ts new file mode 100644 index 000000000000..5ef7a415d886 --- /dev/null +++ b/packages/twenty-server/test/workspace-members.integration-spec.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; + +const client = request(`http://localhost:${APP_PORT}`); + +describe('workspaceMembersResolver (integration)', () => { + it('should find many workspaceMembers', () => { + const queryData = { + query: ` + query workspaceMembers { + workspaceMembers { + edges { + node { + id + colorScheme + avatarUrl + locale + timeZone + dateFormat + timeFormat + userEmail + userId + createdAt + updatedAt + deletedAt + } + } + } + } + `, + }; + + return client + .post('/graphql') + .set('Authorization', `Bearer ${ACCESS_TOKEN}`) + .send(queryData) + .expect(200) + .expect((res) => { + expect(res.body.data).toBeDefined(); + expect(res.body.errors).toBeUndefined(); + }) + .expect((res) => { + const data = res.body.data.workspaceMembers; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const workspaceMembers = edges[0].node; + + expect(workspaceMembers).toHaveProperty('id'); + expect(workspaceMembers).toHaveProperty('colorScheme'); + expect(workspaceMembers).toHaveProperty('avatarUrl'); + expect(workspaceMembers).toHaveProperty('locale'); + expect(workspaceMembers).toHaveProperty('timeZone'); + expect(workspaceMembers).toHaveProperty('dateFormat'); + expect(workspaceMembers).toHaveProperty('timeFormat'); + expect(workspaceMembers).toHaveProperty('userEmail'); + expect(workspaceMembers).toHaveProperty('userId'); + expect(workspaceMembers).toHaveProperty('createdAt'); + expect(workspaceMembers).toHaveProperty('updatedAt'); + expect(workspaceMembers).toHaveProperty('deletedAt'); + } + }); + }); +}); diff --git a/packages/twenty-server/tsconfig.json b/packages/twenty-server/tsconfig.json index 7b2af2c49a5b..272cbdde673c 100644 --- a/packages/twenty-server/tsconfig.json +++ b/packages/twenty-server/tsconfig.json @@ -27,7 +27,7 @@ "paths": { "src/*": ["packages/twenty-server/src/*"], "test/*": ["packages/twenty-server/test/*"], - "twenty-emails": ["packages/twenty-emails/src/index.ts"] + "twenty-emails": ["packages/twenty-emails/dist"] } }, "ts-node": { diff --git a/packages/twenty-server/tsconfig.scripts.json b/packages/twenty-server/tsconfig.scripts.json new file mode 100644 index 000000000000..ae5b155f1f9b --- /dev/null +++ b/packages/twenty-server/tsconfig.scripts.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["scripts/**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/twenty-ui/package.json b/packages/twenty-ui/package.json index b22ff8b7ca2a..b004cba081fc 100644 --- a/packages/twenty-ui/package.json +++ b/packages/twenty-ui/package.json @@ -1,6 +1,6 @@ { "name": "twenty-ui", - "version": "0.24.0", + "version": "0.30.0", "type": "module", "main": "./src/index.ts", "exports": { diff --git a/packages/twenty-ui/src/display/avatar/components/Avatar.tsx b/packages/twenty-ui/src/display/avatar/components/Avatar.tsx index 81c3a80219ae..5230e67ce07b 100644 --- a/packages/twenty-ui/src/display/avatar/components/Avatar.tsx +++ b/packages/twenty-ui/src/display/avatar/components/Avatar.tsx @@ -7,6 +7,7 @@ import { invalidAvatarUrlsState } from '@ui/display/avatar/components/states/isI import { AVATAR_PROPERTIES_BY_SIZE } from '@ui/display/avatar/constants/AvatarPropertiesBySize'; import { AvatarSize } from '@ui/display/avatar/types/AvatarSize'; import { AvatarType } from '@ui/display/avatar/types/AvatarType'; +import { IconComponent } from '@ui/display/icon/types/IconComponent'; import { ThemeContext } from '@ui/theme'; import { Nullable, getImageAbsoluteURI, stringToHslColor } from '@ui/utilities'; @@ -17,13 +18,16 @@ const StyledAvatar = styled.div<{ color: string; backgroundColor: string; backgroundTransparentLight: string; + type?: Nullable<AvatarType>; }>` align-items: center; flex-shrink: 0; overflow: hidden; user-select: none; - border-radius: ${({ rounded }) => (rounded ? '50%' : '2px')}; + border-radius: ${({ rounded, type }) => { + return rounded ? '50%' : type === 'icon' ? '4px' : '2px'; + }}; display: flex; font-size: ${({ size }) => AVATAR_PROPERTIES_BY_SIZE[size].fontSize}; height: ${({ size }) => AVATAR_PROPERTIES_BY_SIZE[size].width}; @@ -51,6 +55,8 @@ export type AvatarProps = { size?: AvatarSize; placeholder: string | undefined; placeholderColorSeed?: string; + Icon?: IconComponent; + iconColor?: string; type?: Nullable<AvatarType>; color?: string; backgroundColor?: string; @@ -63,6 +69,8 @@ export const Avatar = ({ size = 'md', placeholder, placeholderColorSeed = placeholder, + Icon, + iconColor, onClick, type = 'squared', color, @@ -101,14 +109,26 @@ export const Avatar = ({ return ( <StyledAvatar size={size} - backgroundColor={showBackgroundColor ? fixedBackgroundColor : 'none'} + backgroundColor={ + Icon + ? theme.background.tertiary + : showBackgroundColor + ? fixedBackgroundColor + : 'none' + } color={fixedColor} clickable={!isUndefined(onClick)} rounded={type === 'rounded'} + type={type} onClick={onClick} backgroundTransparentLight={theme.background.transparent.light} > - {showPlaceholder ? ( + {Icon ? ( + <Icon + color={iconColor ? iconColor : 'currentColor'} + size={theme.icon.size.xl} + /> + ) : showPlaceholder ? ( placeholderChar ) : ( <StyledImage src={avatarImageURI} onError={handleImageError} alt="" /> diff --git a/packages/twenty-ui/src/display/avatar/types/AvatarType.ts b/packages/twenty-ui/src/display/avatar/types/AvatarType.ts index 9e9b7dc9589e..e267555111db 100644 --- a/packages/twenty-ui/src/display/avatar/types/AvatarType.ts +++ b/packages/twenty-ui/src/display/avatar/types/AvatarType.ts @@ -1 +1 @@ -export type AvatarType = 'squared' | 'rounded'; +export type AvatarType = 'squared' | 'rounded' | 'icon'; diff --git a/packages/twenty-ui/src/display/banner/components/Banner.tsx b/packages/twenty-ui/src/display/banner/components/Banner.tsx index 8a89a8b209ea..ae1b8d780881 100644 --- a/packages/twenty-ui/src/display/banner/components/Banner.tsx +++ b/packages/twenty-ui/src/display/banner/components/Banner.tsx @@ -22,12 +22,18 @@ const StyledBanner = styled.div<{ variant?: BannerVariant }>` export type BannerVariant = 'danger' | 'default'; +type BannerProps = { + variant?: BannerVariant; + className?: string; + children: React.ReactNode; +} & React.HTMLAttributes<HTMLDivElement>; + export const Banner = ({ variant = 'default', + className, children, -}: { - variant?: BannerVariant; - children: React.ReactNode; -} & React.HTMLAttributes<HTMLDivElement>) => ( - <StyledBanner variant={variant}>{children}</StyledBanner> +}: BannerProps) => ( + <StyledBanner variant={variant} className={className}> + {children} + </StyledBanner> ); diff --git a/packages/twenty-ui/src/display/chip/components/AvatarChip.tsx b/packages/twenty-ui/src/display/chip/components/AvatarChip.tsx index 2c993ba652d1..72b0253eed81 100644 --- a/packages/twenty-ui/src/display/chip/components/AvatarChip.tsx +++ b/packages/twenty-ui/src/display/chip/components/AvatarChip.tsx @@ -14,6 +14,7 @@ export type AvatarChipProps = { avatarType?: Nullable<AvatarType>; variant?: AvatarChipVariant; LeftIcon?: IconComponent; + LeftIconColor?: string; isIconInverted?: boolean; className?: string; placeholderColorSeed?: string; @@ -41,6 +42,7 @@ export const AvatarChip = ({ avatarType = 'rounded', variant = AvatarChipVariant.Regular, LeftIcon, + LeftIconColor, isIconInverted, className, placeholderColorSeed, @@ -71,7 +73,11 @@ export const AvatarChip = ({ /> </StyledInvertedIconContainer> ) : ( - <LeftIcon size={theme.icon.size.md} stroke={theme.icon.stroke.sm} /> + <LeftIcon + size={theme.icon.size.md} + stroke={theme.icon.stroke.sm} + color={LeftIconColor || 'currentColor'} + /> ) ) : ( <Avatar diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-array.svg b/packages/twenty-ui/src/display/icon/assets/illustration-array.svg new file mode 100644 index 000000000000..56b2864ff05e --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-array.svg @@ -0,0 +1,8 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M7.84682 4.19127L4.10596 3.92969L3.05961 18.8931L6.80048 19.1547" fill="currentFill"/> +<path d="M17.199 4.84524L20.9399 5.10683L19.8935 20.0703L16.1526 19.8087" fill="currentFill"/> +<path d="M7.99728 15.4793L8.00663 15.4799L7.99728 15.4793Z" fill="#E8EFFD"/> +<path d="M11.7381 15.7409L11.7475 15.7415L11.7381 15.7409Z" fill="#E8EFFD"/> +<path d="M15.479 16.0024L15.4884 16.0031L15.479 16.0024Z" fill="#E8EFFD"/> +<path d="M7.84682 4.19127L4.10596 3.92969L3.05961 18.8931L6.80048 19.1547M17.199 4.84524L20.9399 5.10683L19.8935 20.0703L16.1526 19.8087M7.99728 15.4793L8.00663 15.4799M11.7381 15.7409L11.7475 15.7415M15.479 16.0024L15.4884 16.0031" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-calendar-event.svg b/packages/twenty-ui/src/display/icon/assets/illustration-calendar-event.svg new file mode 100644 index 000000000000..705ca57ac710 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-calendar-event.svg @@ -0,0 +1,8 @@ +<svg width="26" height="26" viewBox="-1 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M5.66433 7.43347C5.72493 6.9399 5.97912 6.49062 6.37099 6.18446C6.76285 5.8783 7.26028 5.74035 7.75386 5.80095L18.92 7.17199C19.4136 7.23259 19.8629 7.48678 20.169 7.87864C20.4752 8.27051 20.6131 8.76794 20.5525 9.26151L19.1815 20.4277C19.1209 20.9212 18.8667 21.3705 18.4748 21.6767C18.083 21.9828 17.5855 22.1208 17.092 22.0602L5.92582 20.6891C5.43224 20.6285 4.98296 20.3744 4.6768 19.9825C4.37064 19.5906 4.23269 19.0932 4.2933 18.5996L5.66433 7.43347Z" fill="#E8EFFD"/> +<path d="M17.2875 5.08246L16.8305 8.8045L17.2875 5.08246Z" fill="#E8EFFD"/> +<path d="M9.84339 4.16844L9.38638 7.89048L9.84339 4.16844Z" fill="#E8EFFD"/> +<path d="M5.20732 11.1555L20.0955 12.9836L5.20732 11.1555Z" fill="#E8EFFD"/> +<path d="M8.47236 15.3346L10.3334 15.5631L10.1049 17.4241L8.24385 17.1956L8.47236 15.3346Z" fill="#E8EFFD"/> +<path d="M17.2875 5.08246L16.8305 8.8045M9.84339 4.16844L9.38638 7.89048M5.20732 11.1555L20.0955 12.9836M5.66433 7.43347C5.72493 6.9399 5.97912 6.49062 6.37099 6.18446C6.76285 5.8783 7.26028 5.74035 7.75386 5.80095L18.92 7.17199C19.4136 7.23259 19.8629 7.48678 20.169 7.87864C20.4752 8.27051 20.6131 8.76794 20.5525 9.26151L19.1815 20.4277C19.1209 20.9212 18.8667 21.3705 18.4748 21.6767C18.083 21.9828 17.5855 22.1208 17.092 22.0602L5.92582 20.6891C5.43224 20.6285 4.98296 20.3744 4.6768 19.9825C4.37064 19.5906 4.23269 19.0932 4.2933 18.5996L5.66433 7.43347ZM8.47236 15.3346L10.3334 15.5631L10.1049 17.4241L8.24385 17.1956L8.47236 15.3346Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-calendar-time.svg b/packages/twenty-ui/src/display/icon/assets/illustration-calendar-time.svg new file mode 100644 index 000000000000..6a5b335d293a --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-calendar-time.svg @@ -0,0 +1,9 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M12.8968 20.4301L6.54196 20.8745C6.04589 20.9092 5.55636 20.7454 5.18105 20.4191C4.80575 20.0929 4.57542 19.6309 4.54073 19.1348L3.75597 7.91225C3.72128 7.41618 3.88508 6.92665 4.21132 6.55135C4.53757 6.17605 4.99954 5.94571 5.49561 5.91103L16.7182 5.12627C17.2143 5.09158 17.7038 5.25537 18.0791 5.58162C18.4544 5.90786 18.6847 6.36984 18.7194 6.8659L18.981 10.6068" fill="currentFill"/> +<path d="M14.7627 17.4803C14.8321 18.4724 15.2928 19.3964 16.0434 20.0488C16.794 20.7013 17.773 21.0289 18.7652 20.9595C19.7573 20.8902 20.6812 20.4295 21.3337 19.6789C21.9862 18.9283 22.3138 17.9492 22.2444 16.9571C22.1751 15.965 21.7144 15.041 20.9638 14.3885C20.2132 13.736 19.2341 13.4084 18.242 13.4778C17.2499 13.5472 16.3259 14.0079 15.6734 14.7585C15.0209 15.5091 14.6933 16.4881 14.7627 17.4803Z" fill="#E8EFFD"/> +<path d="M14.717 3.38663L14.9786 7.12749L14.717 3.38663Z" fill="#E8EFFD"/> +<path d="M7.23525 3.9098L7.49684 7.65067L7.23525 3.9098Z" fill="#E8EFFD"/> +<path d="M4.01756 11.6531L18.981 10.6068L4.01756 11.6531Z" fill="#E8EFFD"/> +<path d="M18.4052 15.8122L18.5036 17.2188L19.5042 18.0886" fill="#E8EFFD"/> +<path d="M12.8968 20.4301L6.54196 20.8745C6.04589 20.9092 5.55636 20.7454 5.18105 20.4191C4.80575 20.0929 4.57542 19.6309 4.54073 19.1348L3.75597 7.91225C3.72128 7.41618 3.88508 6.92665 4.21132 6.55135C4.53757 6.17605 4.99954 5.94571 5.49561 5.91103L16.7182 5.12627C17.2143 5.09158 17.7038 5.25537 18.0791 5.58162C18.4544 5.90786 18.6847 6.36984 18.7194 6.8659L18.981 10.6068L4.01756 11.6531M14.717 3.38663L14.9786 7.12749M7.23525 3.9098L7.49684 7.65067M18.4052 15.8122L18.5036 17.2188L19.5042 18.0886M14.7627 17.4803C14.8321 18.4724 15.2928 19.3964 16.0434 20.0488C16.794 20.7013 17.773 21.0289 18.7652 20.9595C19.7573 20.8902 20.6812 20.4295 21.3337 19.6789C21.9862 18.9283 22.3138 17.9492 22.2444 16.9571C22.1751 15.965 21.7144 15.041 20.9638 14.3885C20.2132 13.736 19.2341 13.4084 18.242 13.4778C17.2499 13.5472 16.3259 14.0079 15.6734 14.7585C15.0209 15.5091 14.6933 16.4881 14.7627 17.4803Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-currency.svg b/packages/twenty-ui/src/display/icon/assets/illustration-currency.svg new file mode 100644 index 000000000000..6f801b59dcad --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-currency.svg @@ -0,0 +1,13 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_39321_100611)"> +<path d="M10.2501 3.41974L14.9262 3.74672C15.2983 3.77274 15.6447 3.94549 15.8894 4.22697C16.1341 4.50844 16.257 4.87559 16.2309 5.24764C16.1702 6.11577 15.7672 6.92422 15.1104 7.49515C14.4536 8.06608 13.5969 8.35272 12.7288 8.29201L11.7936 8.22662C10.9255 8.16591 10.117 7.76283 9.54608 7.10605C8.97515 6.44927 8.68851 5.59259 8.74922 4.72447C8.77523 4.35242 8.94798 4.00594 9.22946 3.76125C9.51093 3.51657 9.87808 3.39372 10.2501 3.41974Z" fill="#E8EFFD"/> +<path d="M4.19089 16.1531L4.25629 15.2179C4.39504 13.2336 5.31637 11.3857 6.81758 10.0807C8.31879 8.77574 10.2769 8.12056 12.2612 8.25931C14.2455 8.39807 16.0934 9.31939 17.3983 10.8206C18.7033 12.3218 19.3585 14.2799 19.2197 16.2642L19.1544 17.1994C19.085 18.1916 18.6243 19.1155 17.8737 19.768C17.1231 20.4205 16.144 20.7481 15.1519 20.6787L7.67017 20.1555C6.67803 20.0862 5.75409 19.6255 5.1016 18.8749C4.4491 18.1243 4.12151 17.1452 4.19089 16.1531Z" fill="#E8EFFD"/> +<path d="M10.2501 3.41974L14.9262 3.74672C15.2983 3.77274 15.6447 3.94549 15.8894 4.22697C16.1341 4.50844 16.257 4.87559 16.2309 5.24764C16.1702 6.11577 15.7672 6.92422 15.1104 7.49515C14.4536 8.06608 13.5969 8.35272 12.7288 8.29201L11.7936 8.22662C10.9255 8.16591 10.117 7.76283 9.54608 7.10605C8.97515 6.44927 8.68851 5.59259 8.74922 4.72447C8.77523 4.35242 8.94798 4.00594 9.22946 3.76125C9.51093 3.51657 9.87808 3.39372 10.2501 3.41974Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M4.19089 16.1531L4.25629 15.2179C4.39504 13.2336 5.31637 11.3857 6.81758 10.0807C8.31879 8.77574 10.2769 8.12056 12.2612 8.25931C14.2455 8.39807 16.0934 9.31939 17.3983 10.8206C18.7033 12.3218 19.3585 14.2799 19.2197 16.2642L19.1544 17.1994C19.085 18.1916 18.6243 19.1155 17.8737 19.768C17.1231 20.4205 16.144 20.7481 15.1519 20.6787L7.67017 20.1555C6.67803 20.0862 5.75409 19.6255 5.1016 18.8749C4.4491 18.1243 4.12151 17.1452 4.19089 16.1531Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_39321_100611"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-json.svg b/packages/twenty-ui/src/display/icon/assets/illustration-json.svg new file mode 100644 index 000000000000..eb2a6a747c6f --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-json.svg @@ -0,0 +1,5 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M6.80092 4.84535C6.30485 4.88004 5.84288 5.11037 5.51664 5.48567C5.19039 5.86097 5.0266 6.3505 5.06128 6.84657L5.25747 9.65222C5.30951 10.3963 5.16235 11.1237 4.84837 11.6744C4.53438 12.2251 4.0793 12.554 3.58323 12.5887C4.0793 12.554 4.57572 12.8163 4.96329 13.3179C5.35086 13.8196 5.59782 14.5194 5.64985 15.2635L5.84605 18.0692C5.88073 18.5652 6.11106 19.0272 6.48637 19.3535C6.86167 19.6797 7.3512 19.8435 7.84727 19.8088" fill="currentFill"/> +<path d="M16.1531 4.19138C16.6492 4.15669 17.1387 4.32049 17.514 4.64673C17.8893 4.97298 18.1196 5.43495 18.1543 5.93102L18.3505 8.73667C18.4025 9.48077 18.6495 10.1806 19.0371 10.6823C19.4246 11.1839 19.9211 11.4462 20.4171 11.4115C19.9211 11.4462 19.466 11.7751 19.152 12.3258C18.838 12.8765 18.6909 13.6039 18.7429 14.348L18.9391 17.1536C18.9738 17.6497 18.81 18.1392 18.4837 18.5145C18.1575 18.8898 17.6955 19.1202 17.1994 19.1548" fill="currentFill"/> +<path d="M6.80092 4.84535C6.30485 4.88004 5.84288 5.11037 5.51664 5.48567C5.19039 5.86097 5.0266 6.3505 5.06128 6.84657L5.25747 9.65222C5.30951 10.3963 5.16235 11.1237 4.84837 11.6744C4.53438 12.2251 4.0793 12.554 3.58323 12.5887C4.0793 12.554 4.57572 12.8163 4.96329 13.3179C5.35086 13.8196 5.59782 14.5194 5.64985 15.2635L5.84605 18.0692C5.88073 18.5652 6.11106 19.0272 6.48637 19.3535C6.86167 19.6797 7.3512 19.8435 7.84727 19.8088M16.1531 4.19138C16.6492 4.15669 17.1387 4.32049 17.514 4.64673C17.8893 4.97298 18.1196 5.43495 18.1543 5.93102L18.3505 8.73667C18.4025 9.48077 18.6495 10.1806 19.0371 10.6823C19.4246 11.1839 19.9211 11.4462 20.4171 11.4115C19.9211 11.4462 19.466 11.7751 19.152 12.3258C18.838 12.8765 18.6909 13.6039 18.7429 14.348L18.9391 17.1536C18.9738 17.6497 18.81 18.1392 18.4837 18.5145C18.1575 18.8898 17.6955 19.1202 17.1994 19.1548" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-link.svg b/packages/twenty-ui/src/display/icon/assets/illustration-link.svg new file mode 100644 index 000000000000..6852612db912 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-link.svg @@ -0,0 +1,17 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="24" height="24" rx="3" fill="none"/> +<g clip-path="url(#clip0_36855_127168)"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/> +<path d="M3.60925 11.1178C3.49343 12.2198 3.59579 13.3338 3.91049 14.3962C4.22519 15.4586 4.74606 16.4486 5.44336 17.3097C6.14067 18.1708 7.00075 18.8861 7.9745 19.4148C8.94826 19.9435 10.0166 20.2753 11.1186 20.3911C12.2205 20.5069 13.3345 20.4045 14.3969 20.0898C15.4593 19.7751 16.4493 19.2543 17.3104 18.557C18.1715 17.8597 18.8868 16.9996 19.4156 16.0258C19.9443 15.0521 20.276 13.9837 20.3918 12.8818C20.6257 10.6563 19.966 8.42898 18.5577 6.68991C17.1494 4.95084 15.108 3.84243 12.8825 3.60852C10.657 3.37461 8.42971 4.03436 6.69064 5.44263C4.95157 6.8509 3.84316 8.89234 3.60925 11.1178Z" fill="currentFill"/> +<path d="M4.46411 8.3797L20.1278 10.026L4.46411 8.3797Z" fill="#E8EFFD"/> +<path d="M3.87614 13.9739L19.5399 15.6202L3.87614 13.9739Z" fill="#E8EFFD"/> +<path d="M12.416 3.55949C10.5807 5.91142 9.44243 8.73125 9.1306 11.6982C8.81876 14.6651 9.34592 17.6599 10.6521 20.342" fill="#E8EFFD"/> +<path d="M13.3487 3.65752C14.6548 6.33963 15.182 9.3345 14.8702 12.3014C14.5583 15.2683 13.42 18.0881 11.5848 20.4401" fill="currentFill"/> +<path d="M4.46411 8.3797L20.1278 10.026M3.87614 13.9739L19.5399 15.6202M12.416 3.55949C10.5807 5.91142 9.44243 8.73125 9.1306 11.6982C8.81876 14.6651 9.34592 17.6599 10.6521 20.342M13.3487 3.65752C14.6548 6.33963 15.182 9.3345 14.8702 12.3014C14.5583 15.2683 13.42 18.0881 11.5848 20.4401M3.60925 11.1178C3.49343 12.2198 3.59579 13.3338 3.91049 14.3962C4.22519 15.4586 4.74606 16.4486 5.44336 17.3097C6.14067 18.1708 7.00075 18.8861 7.9745 19.4148C8.94826 19.9435 10.0166 20.2753 11.1186 20.3911C12.2205 20.5069 13.3345 20.4045 14.3969 20.0898C15.4593 19.7751 16.4493 19.2543 17.3104 18.557C18.1715 17.8597 18.8868 16.9996 19.4156 16.0258C19.9443 15.0521 20.276 13.9837 20.3918 12.8818C20.6257 10.6563 19.966 8.42898 18.5577 6.68991C17.1494 4.95084 15.108 3.84243 12.8825 3.60852C10.657 3.37461 8.42971 4.03436 6.69064 5.44263C4.95157 6.8509 3.84316 8.89234 3.60925 11.1178Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_36855_127168"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-mail.svg b/packages/twenty-ui/src/display/icon/assets/illustration-mail.svg new file mode 100644 index 000000000000..67787031c947 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-mail.svg @@ -0,0 +1,14 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="24" height="24" rx="3" fill="none"/> +<g clip-path="url(#clip0_36855_127259)"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/> +<path d="M3.25579 7.91194C3.2211 7.41587 3.3849 6.92633 3.71115 6.55103C4.03739 6.17573 4.49936 5.9454 4.99543 5.91071L18.0885 4.99516C18.5845 4.96047 19.0741 5.12426 19.4494 5.45051C19.8247 5.77675 20.055 6.23873 20.0897 6.7348L20.7437 16.087C20.7783 16.583 20.6145 17.0726 20.2883 17.4479C19.9621 17.8232 19.5001 18.0535 19.004 18.0882L5.91099 19.0037C5.41492 19.0384 4.92538 18.8746 4.55008 18.5484C4.17478 18.2221 3.94445 17.7602 3.90976 17.2641L3.25579 7.91194Z" fill="#E8EFFD"/> +<path d="M3.25579 7.91194L12.0651 12.9347L20.0897 6.7348" fill="#E8EFFD"/> +<path d="M3.25579 7.91194C3.2211 7.41587 3.3849 6.92633 3.71115 6.55103C4.03739 6.17573 4.49936 5.9454 4.99543 5.91071L18.0885 4.99516C18.5845 4.96047 19.0741 5.12426 19.4494 5.45051C19.8247 5.77675 20.055 6.23873 20.0897 6.7348M3.25579 7.91194L3.90976 17.2641C3.94445 17.7602 4.17478 18.2221 4.55008 18.5484C4.92538 18.8746 5.41492 19.0384 5.91099 19.0037L19.004 18.0882C19.5001 18.0535 19.9621 17.8232 20.2883 17.4479C20.6145 17.0726 20.7783 16.583 20.7437 16.087L20.0897 6.7348M3.25579 7.91194L12.0651 12.9347L20.0897 6.7348" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_36855_127259"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-many-to-many.svg b/packages/twenty-ui/src/display/icon/assets/illustration-many-to-many.svg new file mode 100644 index 000000000000..06f6a5539ed5 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-many-to-many.svg @@ -0,0 +1,8 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M3.25628 7.91194C3.22159 7.41587 3.38539 6.92633 3.71163 6.55103C4.03788 6.17573 4.49985 5.9454 4.99592 5.91071L18.0889 4.99516C18.585 4.96047 19.0746 5.12426 19.4499 5.45051C19.8252 5.77675 20.0555 6.23873 20.0902 6.7348L20.7441 16.087C20.7788 16.583 20.615 17.0726 20.2888 17.4479C19.9625 17.8232 19.5006 18.0535 19.0045 18.0882L5.91147 19.0037C5.4154 19.0384 4.92587 18.8746 4.55057 18.5484C4.17527 18.2221 3.94494 17.7602 3.91025 17.2641L3.25628 7.91194Z" fill="#E8EFFD"/> +<path d="M14.9367 13.6737L14.6751 9.93282L17.7423 13.4775L17.4807 9.73663" fill="currentFill"/> +<path d="M6.51971 14.2623L6.25812 10.5214L9.32536 14.0661L9.06377 10.3252" fill="currentFill"/> +<path d="M11.9021 10.5966L11.9028 10.606L11.9021 10.5966Z" fill="#E8EFFD"/> +<path d="M12.0983 13.4023L12.099 13.4116L12.0983 13.4023Z" fill="#E8EFFD"/> +<path d="M14.9367 13.6737L14.6751 9.93282L17.7423 13.4775L17.4807 9.73663M6.51971 14.2623L6.25812 10.5214L9.32536 14.0661L9.06377 10.3252M11.9021 10.5966L11.9028 10.606M12.0983 13.4023L12.099 13.4116M3.25628 7.91194C3.22159 7.41587 3.38539 6.92633 3.71163 6.55103C4.03788 6.17573 4.49985 5.9454 4.99592 5.91071L18.0889 4.99516C18.585 4.96047 19.0746 5.12426 19.4499 5.45051C19.8252 5.77675 20.0555 6.23873 20.0902 6.7348L20.7441 16.087C20.7788 16.583 20.615 17.0726 20.2888 17.4479C19.9625 17.8232 19.5006 18.0535 19.0045 18.0882L5.91147 19.0037C5.4154 19.0384 4.92587 18.8746 4.55057 18.5484C4.17527 18.2221 3.94494 17.7602 3.91025 17.2641L3.25628 7.91194Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-map.svg b/packages/twenty-ui/src/display/icon/assets/illustration-map.svg new file mode 100644 index 000000000000..a78cae3ae27e --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-map.svg @@ -0,0 +1,14 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_39400_7686)"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/> +<path d="M3.25625 7.91258L8.67136 4.71455L14.4788 7.12782L19.894 3.92979L20.7441 16.0876L15.329 19.2856L9.52151 16.8724L4.10641 20.0704L3.25625 7.91258Z" /> +<path d="M8.67136 4.71455L9.52151 16.8724L8.67136 4.71455Z" fill="#E8EFFD"/> +<path d="M14.4788 7.12782L15.329 19.2856L14.4788 7.12782Z" fill="#E8EFFD"/> +<path d="M8.67136 4.71455L3.25625 7.91258L4.10641 20.0704L9.52151 16.8724M8.67136 4.71455L14.4788 7.12782M8.67136 4.71455L9.52151 16.8724M14.4788 7.12782L19.894 3.92979L20.7441 16.0876L15.329 19.2856M14.4788 7.12782L15.329 19.2856M15.329 19.2856L9.52151 16.8724" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_39400_7686"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-numbers.svg b/packages/twenty-ui/src/display/icon/assets/illustration-numbers.svg new file mode 100644 index 000000000000..238a1c474b7f --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-numbers.svg @@ -0,0 +1,14 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="currentFill" xmlns="http://www.w3.org/2000/svg"> +<rect width="24" height="24" rx="3" fill="none"/> +<g clip-path="url(#clip0_36855_127138)"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/> +<path d="M15.4792 7.99748C15.4098 7.00534 14.9491 6.08139 14.1985 5.4289C13.4479 4.77641 12.4688 4.44882 11.4767 4.5182C10.4846 4.58758 9.56062 5.04824 8.90813 5.79884C8.25564 6.54945 7.92805 7.52851 7.99743 8.52065L8.06282 9.45587C8.1322 10.448 8.59286 11.3719 9.34347 12.0244C10.0941 12.6769 11.0731 13.0045 12.0653 12.9351C13.0574 12.8658 13.9814 12.4051 14.6338 11.6545C15.2863 10.9039 15.6139 9.92483 15.5446 8.93269" fill="#E8EFFD"/> +<path d="M8.5206 16.0024C8.58998 16.9945 9.05064 17.9185 9.80124 18.571C10.5518 19.2234 11.5309 19.551 12.5231 19.4817C13.5152 19.4123 14.4391 18.9516 15.0916 18.201C15.7441 17.4504 16.0717 16.4713 16.0023 15.4792L15.4792 7.99748" fill="none"/> +<path d="M15.5446 8.93269C15.6139 9.92483 15.2863 10.9039 14.6338 11.6545C13.9814 12.4051 13.0574 12.8658 12.0653 12.9351C11.0731 13.0045 10.0941 12.6769 9.34347 12.0244C8.59286 11.3719 8.1322 10.448 8.06282 9.45587L7.99743 8.52065C7.92805 7.52851 8.25564 6.54945 8.90813 5.79884C9.56062 5.04824 10.4846 4.58758 11.4767 4.5182C12.4688 4.44882 13.4479 4.77641 14.1985 5.4289C14.9491 6.08139 15.4098 7.00534 15.4792 7.99748L16.0023 15.4792C16.0717 16.4713 15.7441 17.4504 15.0916 18.201C14.4391 18.9516 13.5152 19.4123 12.5231 19.4817C11.5309 19.551 10.5518 19.2234 9.80124 18.571C9.05064 17.9185 8.58998 16.9945 8.5206 16.0024" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_36855_127138"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-one-to-many.svg b/packages/twenty-ui/src/display/icon/assets/illustration-one-to-many.svg new file mode 100644 index 000000000000..bc0c08aa5171 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-one-to-many.svg @@ -0,0 +1,8 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" fill="currentFill"/> +<path d="M7.69334 10.456L8.62855 10.3906L8.89014 14.1315" fill="#E8EFFD"/> +<path d="M14.5014 13.7391L14.2399 9.99822L17.3071 13.5429L17.0455 9.80203" fill="currentFill"/> +<path d="M11.4669 10.662L11.4676 10.6714L11.4669 10.662Z" fill="#E8EFFD"/> +<path d="M11.6631 13.4677L11.6637 13.477L11.6631 13.4677Z" fill="#E8EFFD"/> +<path d="M7.69334 10.456L8.62855 10.3906L8.89014 14.1315M14.5014 13.7391L14.2399 9.99822L17.3071 13.5429L17.0455 9.80203M11.4669 10.662L11.4676 10.6714M11.6631 13.4677L11.6637 13.477M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-one-to-one.svg b/packages/twenty-ui/src/display/icon/assets/illustration-one-to-one.svg new file mode 100644 index 000000000000..1dcdff806d78 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-one-to-one.svg @@ -0,0 +1,8 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" fill="#E8EFFD"/> +<path d="M8.62855 10.3906L9.56377 10.3252L9.82536 14.0661" fill="#E8EFFD"/> +<path d="M15.1751 9.93282L16.1103 9.86743L16.3719 13.6083" fill="#E8EFFD"/> +<path d="M12.4021 10.5966L12.4028 10.606L12.4021 10.5966Z" fill="#E8EFFD"/> +<path d="M12.5983 13.4023L12.599 13.4116L12.5983 13.4023Z" fill="#E8EFFD"/> +<path d="M8.62855 10.3906L9.56377 10.3252L9.82536 14.0661M15.1751 9.93282L16.1103 9.86743L16.3719 13.6083M12.4021 10.5966L12.4028 10.606M12.5983 13.4023L12.599 13.4116M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-phone.svg b/packages/twenty-ui/src/display/icon/assets/illustration-phone.svg new file mode 100644 index 000000000000..e286b05178e3 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-phone.svg @@ -0,0 +1,12 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="24" height="24" rx="3" fill="none"/> +<g clip-path="url(#clip0_36855_127302)"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/> +<path d="M4.93049 4.97614L8.67136 4.71455L10.8688 9.25984L8.62883 10.8262C9.77242 12.787 11.531 14.3157 13.6319 15.1753L14.8712 12.7391L19.6781 14.2826L19.9397 18.0234C19.9744 18.5195 19.8106 19.009 19.4843 19.3843C19.1581 19.7596 18.6961 19.99 18.2 20.0247C14.5365 20.0581 10.9874 18.7495 8.2224 16.3459C5.45738 13.9423 3.66764 10.6099 3.19085 6.97737C3.15616 6.4813 3.31996 5.99176 3.6462 5.61646C3.97245 5.24116 4.43442 5.01083 4.93049 4.97614Z" fill="currentFill" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_36855_127302"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-setting.svg b/packages/twenty-ui/src/display/icon/assets/illustration-setting.svg new file mode 100644 index 000000000000..007c16e28b9c --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-setting.svg @@ -0,0 +1,6 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M5.38754 12.4777C5.42223 11.9816 5.65256 11.5196 6.02786 11.1934C6.40316 10.8671 6.89269 10.7033 7.38876 10.738L16.7409 11.392C17.237 11.4267 17.699 11.657 18.0252 12.0323C18.3515 12.4076 18.5153 12.8971 18.4806 13.3932L18.0882 19.0045C18.0535 19.5006 17.8232 19.9625 17.4479 20.2888C17.0726 20.615 16.583 20.7788 16.087 20.7441L6.7348 20.0902C6.23873 20.0555 5.77675 19.8252 5.45051 19.4499C5.12426 19.0746 4.96047 18.585 4.99516 18.0889L5.38754 12.4777Z" fill="#E8EFFD"/> +<path d="M10.8026 15.6757C10.7853 15.9237 10.8672 16.1685 11.0303 16.3561C11.1934 16.5438 11.4244 16.6589 11.6725 16.6763C11.9205 16.6936 12.1653 16.6117 12.3529 16.4486C12.5406 16.2855 12.6557 16.0545 12.6731 15.8065C12.6904 15.5584 12.6085 15.3137 12.4454 15.126C12.2823 14.9384 12.0513 14.8232 11.8033 14.8059C11.5552 14.7885 11.3105 14.8704 11.1228 15.0335C10.9352 15.1967 10.82 15.4276 10.8026 15.6757Z" fill="currentFill"/> +<path d="M8.32398 10.8034L8.58557 7.06254C8.65494 6.0704 9.1156 5.14646 9.86621 4.49397C10.6168 3.84148 11.5959 3.51389 12.588 3.58327C13.5802 3.65264 14.5041 4.1133 15.1566 4.86391C15.8091 5.61451 16.1367 6.59358 16.0673 7.58572L15.8057 11.3266" fill="#E8EFFD"/> +<path d="M8.32398 10.8034L8.58557 7.06254C8.65494 6.0704 9.1156 5.14646 9.86621 4.49397C10.6168 3.84148 11.5959 3.51389 12.588 3.58327C13.5802 3.65264 14.5041 4.1133 15.1566 4.86391C15.8091 5.61451 16.1367 6.59358 16.0673 7.58572L15.8057 11.3266M5.38754 12.4777C5.42223 11.9816 5.65256 11.5196 6.02786 11.1934C6.40316 10.8671 6.89269 10.7033 7.38876 10.738L16.7409 11.392C17.237 11.4267 17.699 11.657 18.0252 12.0323C18.3515 12.4076 18.5153 12.8971 18.4806 13.3932L18.0882 19.0045C18.0535 19.5006 17.8232 19.9625 17.4479 20.2888C17.0726 20.615 16.583 20.7788 16.087 20.7441L6.7348 20.0902C6.23873 20.0555 5.77675 19.8252 5.45051 19.4499C5.12426 19.0746 4.96047 18.585 4.99516 18.0889L5.38754 12.4777ZM10.8026 15.6757C10.7853 15.9237 10.8672 16.1685 11.0303 16.3561C11.1934 16.5438 11.4244 16.6589 11.6725 16.6763C11.9205 16.6936 12.1653 16.6117 12.3529 16.4486C12.5406 16.2855 12.6557 16.0545 12.6731 15.8065C12.6904 15.5584 12.6085 15.3137 12.4454 15.126C12.2823 14.9384 12.0513 14.8232 11.8033 14.8059C11.5552 14.7885 11.3105 14.8704 11.1228 15.0335C10.9352 15.1967 10.82 15.4276 10.8026 15.6757Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-star.svg b/packages/twenty-ui/src/display/icon/assets/illustration-star.svg new file mode 100644 index 000000000000..9a0c714b5d7b --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-star.svg @@ -0,0 +1,10 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_39321_100605)"> +<path d="M10.6518 4.4387C11.0177 3.18817 12.7418 3.06761 13.2782 4.25504L15.0487 8.17475C15.2173 8.54805 15.5406 8.82907 15.9337 8.9441L20.0617 10.1519C21.3122 10.5177 21.4328 12.2418 20.2453 12.7782L16.3256 14.5487C15.9523 14.7173 15.6713 15.0406 15.5563 15.4337L14.3485 19.5617C13.9826 20.8122 12.2585 20.9328 11.7222 19.7454L9.95166 15.8257C9.78304 15.4524 9.45976 15.1713 9.06662 15.0563L4.93866 13.8485C3.68814 13.4827 3.56757 11.7586 4.75501 11.2222L8.67471 9.4517C9.04801 9.28308 9.32903 8.9598 9.44406 8.56666L10.6518 4.4387Z" fill="currentFill" stroke="currentColor" stroke-width="1.5"/> +</g> +<defs> +<clipPath id="clip0_39321_100605"> +<rect width="20.6124" height="20.6124" fill="white" transform="translate(1.5 2.43799) rotate(-4)"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-tag.svg b/packages/twenty-ui/src/display/icon/assets/illustration-tag.svg new file mode 100644 index 000000000000..9ca0212269e7 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-tag.svg @@ -0,0 +1,6 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M9.06327 9.89091C9.57978 9.85479 9.96921 9.4068 9.93309 8.8903C9.89697 8.37379 9.44898 7.98436 8.93248 8.02048C8.41597 8.05659 8.02654 8.50458 8.06266 9.02109C8.09878 9.53759 8.54677 9.92703 9.06327 9.89091Z" fill="currentFill"/> +<path d="M4.69131 7.84715L4.94367 11.4562C4.97879 11.9584 5.21167 12.4261 5.5919 12.7566L13.7129 19.8161C13.901 19.9796 14.1196 20.1046 14.356 20.1837C14.5925 20.2628 14.8422 20.2946 15.0909 20.2772C15.3396 20.2598 15.5825 20.1936 15.8056 20.0823C16.0287 19.9711 16.2278 19.8169 16.3913 19.6288L20.596 14.7918C20.7596 14.6036 20.8846 14.3851 20.9637 14.1487C21.0428 13.9122 21.0746 13.6625 21.0572 13.4138C21.0398 13.1651 20.9736 12.9222 20.8623 12.6991C20.7511 12.4759 20.5969 12.2769 20.4088 12.1133L12.2868 5.05395C11.9071 4.72385 11.4117 4.55804 10.9098 4.59295L7.30077 4.84531C6.55666 4.89735 5.8637 5.24284 5.37434 5.8058C4.88497 6.36875 4.63927 7.10305 4.69131 7.84715Z" fill="currentFill"/> +<path d="M9.06327 9.89091C9.57978 9.85479 9.96921 9.4068 9.93309 8.8903C9.89697 8.37379 9.44898 7.98436 8.93248 8.02048C8.41597 8.05659 8.02654 8.50458 8.06266 9.02109C8.09878 9.53759 8.54677 9.92703 9.06327 9.89091Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M4.69131 7.84715L4.94367 11.4562C4.97879 11.9584 5.21167 12.4261 5.5919 12.7566L13.7129 19.8161C13.901 19.9796 14.1196 20.1046 14.356 20.1837C14.5925 20.2628 14.8422 20.2946 15.0909 20.2772C15.3396 20.2598 15.5825 20.1936 15.8056 20.0823C16.0287 19.9711 16.2278 19.8169 16.3913 19.6288L20.596 14.7918C20.7596 14.6036 20.8846 14.3851 20.9637 14.1487C21.0428 13.9122 21.0746 13.6625 21.0572 13.4138C21.0398 13.1651 20.9736 12.9222 20.8623 12.6991C20.7511 12.4759 20.5969 12.2769 20.4088 12.1133L12.2868 5.05395C11.9071 4.72385 11.4117 4.55804 10.9098 4.59295L7.30077 4.84531C6.55666 4.89735 5.8637 5.24284 5.37434 5.8058C4.88497 6.36875 4.63927 7.10305 4.69131 7.84715Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round" fill="none"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-tags.svg b/packages/twenty-ui/src/display/icon/assets/illustration-tags.svg new file mode 100644 index 000000000000..0174ac4fe9cf --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-tags.svg @@ -0,0 +1,6 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M8.23485 6.65934L5.58444 6.84467C5.08217 6.87979 4.61443 7.113 4.2841 7.493C3.95378 7.87299 3.78794 8.36864 3.82306 8.87091L4.00839 11.5213C4.04351 12.0235 4.27639 12.4912 4.65662 12.8218L10.7764 18.1416C10.9645 18.3052 11.1831 18.4301 11.4195 18.5092C11.656 18.5883 11.9057 18.6201 12.1544 18.6027C12.4031 18.5853 12.646 18.5191 12.8691 18.4079C13.0922 18.2966 13.2913 18.1425 13.4548 17.9543L15.9199 15.1185C16.0835 14.9304 16.2084 14.7118 16.2875 14.4754C16.3667 14.239 16.3984 13.9892 16.381 13.7405C16.3636 13.4918 16.2974 13.2489 16.1862 13.0258C16.0749 12.8027 15.9208 12.6037 15.7326 12.4401L9.61192 7.12034C9.23213 6.79024 8.73683 6.62443 8.23485 6.65934Z" fill="#E8EFFD"/> +<path d="M18.1301 17.6281L20.5952 14.7923C20.7587 14.6042 20.8837 14.3856 20.9628 14.1492C21.0419 13.9127 21.0737 13.663 21.0563 13.4143C21.0389 13.1656 20.9727 12.9227 20.8614 12.6996C20.7502 12.4765 20.596 12.2774 20.4079 12.1139L13.2866 5.9243" fill="none"/> +<path d="M6.69086 9.58667L6.68151 9.58732L6.69086 9.58667Z" fill="#E8EFFD"/> +<path d="M18.1301 17.6281L20.5952 14.7923C20.7587 14.6042 20.8837 14.3856 20.9628 14.1492C21.0419 13.9127 21.0737 13.663 21.0563 13.4143C21.0389 13.1656 20.9727 12.9227 20.8614 12.6996C20.7502 12.4765 20.596 12.2774 20.4079 12.1139L13.2866 5.9243M6.69086 9.58667L6.68151 9.58732M8.23485 6.65934L5.58444 6.84467C5.08217 6.87979 4.61443 7.113 4.2841 7.493C3.95378 7.87299 3.78794 8.36864 3.82306 8.87091L4.00839 11.5213C4.04351 12.0235 4.27639 12.4912 4.65662 12.8218L10.7764 18.1416C10.9645 18.3052 11.1831 18.4301 11.4195 18.5092C11.656 18.5883 11.9057 18.6201 12.1544 18.6027C12.4031 18.5853 12.646 18.5191 12.8691 18.4079C13.0922 18.2966 13.2913 18.1425 13.4548 17.9543L15.9199 15.1185C16.0835 14.9304 16.2084 14.7118 16.2875 14.4754C16.3667 14.239 16.3984 13.9892 16.381 13.7405C16.3636 13.4918 16.2974 13.2489 16.1862 13.0258C16.0749 12.8027 15.9208 12.6037 15.7326 12.4401L9.61192 7.12034C9.23213 6.79024 8.73683 6.62443 8.23485 6.65934Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-text.svg b/packages/twenty-ui/src/display/icon/assets/illustration-text.svg new file mode 100644 index 000000000000..3e35ec3c7e60 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-text.svg @@ -0,0 +1,17 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="24" height="24" rx="3" fill="none"/> +<g clip-path="url(#clip0_36855_127272)"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/> +<path d="M3.75727 18.6752L6.55436 18.9691L3.75727 18.6752Z" fill="#E8EFFD"/> +<path d="M13.0809 19.6551L19.6075 20.3411L13.0809 19.6551Z" fill="#E8EFFD"/> +<path d="M6.94965 14.2974L13.383 14.9735L6.94965 14.2974Z" fill="#E8EFFD"/> +<path d="M10.8797 6.50999L14.9448 19.8518L10.8797 6.50999Z" fill="#E8EFFD"/> +<path d="M4.68963 18.7731L11.8517 4.44329L13.7165 4.63928L18.6751 20.2431" fill="none"/> +<path d="M3.75727 18.6752L6.55436 18.9691M13.0809 19.6551L19.6075 20.3411M6.94965 14.2974L13.383 14.9735M10.8797 6.50999L14.9448 19.8518M4.68963 18.7731L11.8517 4.44329L13.7165 4.63928L18.6751 20.2431" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_36855_127272"> +<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-toggle.svg b/packages/twenty-ui/src/display/icon/assets/illustration-toggle.svg new file mode 100644 index 000000000000..ad2d65267334 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-toggle.svg @@ -0,0 +1,13 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_39321_100602)"> +<path d="M14.3703 11.869C14.405 12.3651 14.6354 12.8271 15.0107 13.1533C15.386 13.4796 15.8755 13.6433 16.3716 13.6087C16.8676 13.574 17.3296 13.3436 17.6559 12.9683C17.9821 12.593 18.1459 12.1035 18.1112 11.6074C18.0765 11.1114 17.8462 10.6494 17.4709 10.3231C17.0956 9.9969 16.6061 9.8331 16.11 9.86779C15.6139 9.90248 15.1519 10.1328 14.8257 10.5081C14.4995 10.8834 14.3357 11.3729 14.3703 11.869Z" fill="currentFill"/> +<path d="M3.14775 12.6538C3.04369 11.1656 3.53507 9.69697 4.51381 8.57107C5.49255 7.44516 6.87846 6.75417 8.36667 6.6501L15.8484 6.12693C17.3366 6.02286 18.8052 6.51425 19.9311 7.49298C21.057 8.47172 21.748 9.85764 21.8521 11.3458C21.9561 12.8341 21.4648 14.3026 20.486 15.4286C19.5073 16.5545 18.1214 17.2455 16.6332 17.3495L9.15143 17.8727C7.66322 17.9768 6.19463 17.4854 5.06872 16.5066C3.94281 15.5279 3.25182 14.142 3.14775 12.6538Z" fill="currentFill"/> +<path d="M14.3703 11.869C14.405 12.3651 14.6354 12.8271 15.0107 13.1533C15.386 13.4796 15.8755 13.6433 16.3716 13.6087C16.8676 13.574 17.3296 13.3436 17.6559 12.9683C17.9821 12.593 18.1459 12.1035 18.1112 11.6074C18.0765 11.1114 17.8462 10.6494 17.4709 10.3231C17.0956 9.9969 16.6061 9.8331 16.11 9.86779C15.6139 9.90248 15.1519 10.1328 14.8257 10.5081C14.4995 10.8834 14.3357 11.3729 14.3703 11.869Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M3.14775 12.6538C3.04369 11.1656 3.53507 9.69697 4.51381 8.57107C5.49255 7.44516 6.87846 6.75417 8.36667 6.6501L15.8484 6.12693C17.3366 6.02286 18.8052 6.51425 19.9311 7.49298C21.057 8.47172 21.748 9.85764 21.8521 11.3458C21.9561 12.8341 21.4648 14.3026 20.486 15.4286C19.5073 16.5545 18.1214 17.2455 16.6332 17.3495L9.15143 17.8727C7.66322 17.9768 6.19463 17.4854 5.06872 16.5066C3.94281 15.5279 3.25182 14.142 3.14775 12.6538Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round" fill="none"/> +</g> +<defs> +<clipPath id="clip0_39321_100602"> +<rect x="1.25" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-uid.svg b/packages/twenty-ui/src/display/icon/assets/illustration-uid.svg new file mode 100644 index 000000000000..4affb07a32f2 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-uid.svg @@ -0,0 +1,8 @@ +<svg width="25" height="26" viewBox="0 0 25 26" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M4.50317 7.59525C4.56818 6.85217 4.92571 6.16535 5.49712 5.68588C6.06853 5.20641 6.80701 4.97357 7.55009 5.03858L18.7573 6.01908C19.5004 6.0841 20.1872 6.44163 20.6667 7.01304C21.1461 7.58445 21.379 8.32292 21.314 9.06601L20.4969 18.4053C20.4319 19.1484 20.0743 19.8352 19.5029 20.3147C18.9315 20.7942 18.193 21.027 17.4499 20.962L6.24275 19.9815C5.49967 19.9165 4.81285 19.559 4.33338 18.9875C3.85391 18.4161 3.62107 17.6777 3.68608 16.9346L4.50317 7.59525Z" fill="currentFill"/> +<path d="M7.99377 10.7239C7.95043 11.2193 8.10566 11.7116 8.4253 12.0925C8.74495 12.4735 9.20283 12.7118 9.69822 12.7552C10.1936 12.7985 10.6859 12.6433 11.0669 12.3236C11.4478 12.004 11.6862 11.5461 11.7295 11.0507C11.7728 10.5553 11.6176 10.063 11.298 9.68208C10.9783 9.30114 10.5204 9.06278 10.0251 9.01944C9.52966 8.9761 9.03735 9.13132 8.65641 9.45097C8.27547 9.77062 8.03711 10.2285 7.99377 10.7239Z" fill="currentFill"/> +<path d="M15.6286 9.50969L17.4965 9.67311L15.6286 9.50969Z" fill="#E8EFFD"/> +<path d="M15.3018 13.2454L17.1697 13.4088L15.3018 13.2454Z" fill="#E8EFFD"/> +<path d="M7.50352 16.3275L16.8428 17.1446L7.50352 16.3275Z" fill="#E8EFFD"/> +<path d="M15.6286 9.50969L17.4965 9.67311M15.3018 13.2454L17.1697 13.4088M7.50352 16.3275L16.8428 17.1446M4.50317 7.59525C4.56818 6.85217 4.92571 6.16535 5.49712 5.68588C6.06853 5.20641 6.80701 4.97357 7.55009 5.03858L18.7573 6.01908C19.5004 6.0841 20.1872 6.44163 20.6667 7.01304C21.1461 7.58445 21.379 8.32292 21.314 9.06601L20.4969 18.4053C20.4319 19.1484 20.0743 19.8352 19.5029 20.3147C18.9315 20.7942 18.193 21.027 17.4499 20.962L6.24275 19.9815C5.49967 19.9165 4.81285 19.559 4.33338 18.9875C3.85391 18.4161 3.62107 17.6777 3.68608 16.9346L4.50317 7.59525ZM7.99377 10.7239C7.95043 11.2193 8.10566 11.7116 8.4253 12.0925C8.74495 12.4735 9.20283 12.7118 9.69822 12.7552C10.1936 12.7985 10.6859 12.6433 11.0669 12.3236C11.4478 12.004 11.6862 11.5461 11.7295 11.0507C11.7728 10.5553 11.6176 10.063 11.298 9.68208C10.9783 9.30114 10.5204 9.06278 10.0251 9.01944C9.52966 8.9761 9.03735 9.13132 8.65641 9.45097C8.27547 9.77062 8.03711 10.2285 7.99377 10.7239Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/assets/illustration-user.svg b/packages/twenty-ui/src/display/icon/assets/illustration-user.svg new file mode 100644 index 000000000000..05c928e0fdd2 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/assets/illustration-user.svg @@ -0,0 +1,6 @@ +<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M4.08295 12.5883C4.16025 13.6937 4.45449 14.7729 4.94889 15.7646C5.44329 16.7562 6.12816 17.6407 6.9644 18.3676C7.80064 19.0946 8.77187 19.6497 9.82264 20.0012C10.8734 20.3528 11.9831 20.494 13.0885 20.4167C14.1938 20.3394 15.2731 20.0452 16.2647 19.5508C17.2563 19.0564 18.1408 18.3715 18.8678 17.5353C19.5947 16.699 20.1498 15.7278 20.5014 14.677C20.853 13.6263 20.9941 12.5165 20.9168 11.4112C20.8396 10.3059 20.5453 9.22658 20.0509 8.23497C19.5565 7.24336 18.8716 6.35883 18.0354 5.6319C17.1992 4.90497 16.2279 4.34987 15.1772 3.99828C14.1264 3.6467 13.0167 3.50552 11.9113 3.58282C10.806 3.66011 9.72672 3.95435 8.73511 4.44875C7.74349 4.94315 6.85897 5.62803 6.13204 6.46427C5.40511 7.3005 4.85 8.27174 4.49842 9.32251C4.14684 10.3733 4.00566 11.483 4.08295 12.5883Z" fill="none"/> +<path d="M9.56346 10.3255C9.61549 11.0696 9.96099 11.7626 10.5239 12.252C11.0869 12.7413 11.8212 12.987 12.5653 12.935C13.3094 12.8829 14.0024 12.5375 14.4917 11.9745C14.9811 11.4115 15.2268 10.6772 15.1748 9.93314C15.1227 9.18904 14.7772 8.49608 14.2143 8.00671C13.6513 7.51734 12.917 7.27165 12.1729 7.32368C11.4288 7.37571 10.7359 7.72121 10.2465 8.28416C9.75712 8.84712 9.51143 9.58142 9.56346 10.3255Z" fill="#E8EFFD"/> +<path d="M7.49359 18.7865C7.6712 17.9999 8.09763 17.2915 8.70962 16.7664C9.32162 16.2413 10.0866 15.9274 10.891 15.8714L14.6319 15.6098C15.4373 15.5532 16.2395 15.7581 16.9192 16.194C17.5989 16.6299 18.1197 17.2735 18.4042 18.0291" fill="currentFill"/> +<path d="M7.49359 18.7865C7.6712 17.9999 8.09763 17.2915 8.70962 16.7664C9.32162 16.2413 10.0866 15.9274 10.891 15.8714L14.6319 15.6098C15.4373 15.5532 16.2395 15.7581 16.9192 16.194C17.5989 16.6299 18.1197 17.2735 18.4042 18.0291M4.08295 12.5883C4.16025 13.6937 4.45449 14.7729 4.94889 15.7646C5.44329 16.7562 6.12816 17.6407 6.9644 18.3676C7.80064 19.0946 8.77187 19.6497 9.82264 20.0012C10.8734 20.3528 11.9831 20.494 13.0885 20.4167C14.1938 20.3394 15.2731 20.0452 16.2647 19.5508C17.2563 19.0564 18.1408 18.3715 18.8678 17.5353C19.5947 16.699 20.1498 15.7278 20.5014 14.677C20.853 13.6263 20.9941 12.5165 20.9168 11.4112C20.8396 10.3059 20.5453 9.22658 20.0509 8.23497C19.5565 7.24336 18.8716 6.35883 18.0354 5.6319C17.1992 4.90497 16.2279 4.34987 15.1772 3.99828C14.1264 3.6467 13.0167 3.50552 11.9113 3.58282C10.806 3.66011 9.72672 3.95435 8.73511 4.44875C7.7435 4.94315 6.85897 5.62803 6.13204 6.46427C5.40511 7.3005 4.85 8.27174 4.49842 9.32251C4.14684 10.3733 4.00566 11.483 4.08295 12.5883ZM9.56346 10.3255C9.61549 11.0696 9.96099 11.7626 10.5239 12.252C11.0869 12.7413 11.8212 12.987 12.5653 12.935C13.3094 12.8829 14.0024 12.5375 14.4917 11.9745C14.9811 11.4115 15.2268 10.6772 15.1748 9.93314C15.1227 9.18904 14.7772 8.49608 14.2143 8.00671C13.6513 7.51734 12.917 7.27165 12.1729 7.32368C11.4288 7.37571 10.7359 7.72121 10.2465 8.28416C9.75712 8.84712 9.51143 9.58142 9.56346 10.3255Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconArray.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconArray.tsx new file mode 100644 index 000000000000..b53d1186748d --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconArray.tsx @@ -0,0 +1,21 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconArrayRaw from '@ui/display/icon/assets/illustration-array.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; +type IllustrationIconArrayProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconArray = (props: IllustrationIconArrayProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconArrayRaw + fill={fill} + color={color} + height={size} + width={size} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarEvent.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarEvent.tsx new file mode 100644 index 000000000000..32c4b6e4b29d --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarEvent.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconCalendarEventRaw from '@ui/display/icon/assets/illustration-calendar-event.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; +type IllustrationIconCalendarEventProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconCalendarEvent = ( + props: IllustrationIconCalendarEventProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconCalendarEventRaw + fill={fill} + color={color} + height={size} + width={size} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarTime.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarTime.tsx new file mode 100644 index 000000000000..701415963d3b --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconCalendarTime.tsx @@ -0,0 +1,24 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconCalendarTimeRaw from '@ui/display/icon/assets/illustration-calendar-time.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconCalendarTimeProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconCalendarTime = ( + props: IllustrationIconCalendarTimeProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconCalendarTimeRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconCurrency.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconCurrency.tsx new file mode 100644 index 000000000000..cd493e2e6b8c --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconCurrency.tsx @@ -0,0 +1,25 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconCurrencyRaw from '@ui/display/icon/assets/illustration-currency.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconCurrencyProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconCurrency = ( + props: IllustrationIconCurrencyProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconCurrencyRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconJson.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconJson.tsx new file mode 100644 index 000000000000..c95136c9fb98 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconJson.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconJsonRaw from '@ui/display/icon/assets/illustration-json.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconJsonProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconJson = (props: IllustrationIconJsonProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconJsonRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconMail.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconMail.tsx new file mode 100644 index 000000000000..bb5b631868aa --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconMail.tsx @@ -0,0 +1,22 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconMailRaw from '@ui/display/icon/assets/illustration-mail.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconMailProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconMail = (props: IllustrationIconMailProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconMailRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconManyToMany.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconManyToMany.tsx new file mode 100644 index 000000000000..d00f479c2b10 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconManyToMany.tsx @@ -0,0 +1,24 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconManyToManyRaw from '@ui/display/icon/assets/illustration-many-to-many.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconManyToManyProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconManyToMany = ( + props: IllustrationIconManyToManyProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconManyToManyRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconMap.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconMap.tsx new file mode 100644 index 000000000000..2fac17d9d7d7 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconMap.tsx @@ -0,0 +1,22 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconMapRaw from '@ui/display/icon/assets/illustration-map.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconMapProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconMap = (props: IllustrationIconMapProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconMapRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconNumbers.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconNumbers.tsx new file mode 100644 index 000000000000..74cbe38c763b --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconNumbers.tsx @@ -0,0 +1,24 @@ +import { useTheme } from '@emotion/react'; +import IllustrationIconNumbersRaw from '@ui/display/icon/assets/illustration-numbers.svg?react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconNumbersProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconNumbers = ( + props: IllustrationIconNumbersProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconNumbersRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconOneToMany.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconOneToMany.tsx new file mode 100644 index 000000000000..9bad7f1325bc --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconOneToMany.tsx @@ -0,0 +1,25 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconOneToManyRaw from '@ui/display/icon/assets/illustration-one-to-many.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconOneToManyProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconOneToMany = ( + props: IllustrationIconOneToManyProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconOneToManyRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconOneToOne.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconOneToOne.tsx new file mode 100644 index 000000000000..0fd6a902a4ab --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconOneToOne.tsx @@ -0,0 +1,25 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconOneToOneRaw from '@ui/display/icon/assets/illustration-one-to-one.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconOneToOneProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconOneToOne = ( + props: IllustrationIconOneToOneProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconOneToOneRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconPhone.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconPhone.tsx new file mode 100644 index 000000000000..d1f0f67a358c --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconPhone.tsx @@ -0,0 +1,24 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconPhoneRaw from '@ui/display/icon/assets/illustration-phone.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconPhoneProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconPhone = (props: IllustrationIconPhoneProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + + return ( + <IllustrationIconWrapper> + <IllustrationIconPhoneRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconSetting.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconSetting.tsx new file mode 100644 index 000000000000..348f7bb1e8b1 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconSetting.tsx @@ -0,0 +1,26 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconSettingRaw from '@ui/display/icon/assets/illustration-setting.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconSettingProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconSetting = ( + props: IllustrationIconSettingProps, +) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + + return ( + <IllustrationIconWrapper> + <IllustrationIconSettingRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconStar.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconStar.tsx new file mode 100644 index 000000000000..b57ce132f6f4 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconStar.tsx @@ -0,0 +1,24 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconStarRaw from '@ui/display/icon/assets/illustration-star.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconStarProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconStar = (props: IllustrationIconStarProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + + return ( + <IllustrationIconWrapper> + <IllustrationIconStarRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconTag.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconTag.tsx new file mode 100644 index 000000000000..fdfa375911ec --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconTag.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconTagRaw from '@ui/display/icon/assets/illustration-tag.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconTagProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconTag = (props: IllustrationIconTagProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconTagRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconTags.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconTags.tsx new file mode 100644 index 000000000000..97fd173bb02a --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconTags.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconTagsRaw from '@ui/display/icon/assets/illustration-tags.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconTagsProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconTags = (props: IllustrationIconTagsProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconTagsRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconText.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconText.tsx new file mode 100644 index 000000000000..93ef4d8d3a3c --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconText.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconTextRaw from '@ui/display/icon/assets/illustration-text.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconTextProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconText = (props: IllustrationIconTextProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconTextRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconToggle.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconToggle.tsx new file mode 100644 index 000000000000..2ee16a190d64 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconToggle.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconToggleRaw from '@ui/display/icon/assets/illustration-toggle.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconToggleProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconToggle = (props: IllustrationIconToggleProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconToggleRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconUid.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconUid.tsx new file mode 100644 index 000000000000..6c1fa241e2aa --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconUid.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconUidRaw from '@ui/display/icon/assets/illustration-uid.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconUidProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconUid = (props: IllustrationIconUidProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconUidRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconUser.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconUser.tsx new file mode 100644 index 000000000000..4993dbb84cc8 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconUser.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconUserRaw from '@ui/display/icon/assets/illustration-user.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconUserProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconUser = (props: IllustrationIconUserProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconUserRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/icon/components/IllustrationIconWrapper.tsx b/packages/twenty-ui/src/display/icon/components/IllustrationIconWrapper.tsx new file mode 100644 index 000000000000..4e583a312008 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/IllustrationIconWrapper.tsx @@ -0,0 +1,11 @@ +import styled from '@emotion/styled'; + +const StyledRectangleIllustrationIcon = styled('div')` + background-color: ${({ theme }) => theme.background.primary}; + border: 0.75px solid ${({ theme }) => theme.border.color.medium}; + border-radius: ${({ theme }) => theme.border.radius.sm}; + display: flex; + justify-content: center; +`; + +export const IllustrationIconWrapper = StyledRectangleIllustrationIcon; diff --git a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts index aa95be3a50c6..2daafb4ec61f 100644 --- a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts +++ b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts @@ -22,6 +22,7 @@ export { IconBookmark, IconBookmarkPlus, IconBox, + IconBracketsContain, IconBrandGithub, IconBrandGoogle, IconBrandLinkedin, @@ -47,6 +48,7 @@ export { IconCircleX, IconClick, IconClockHour8, + IconClockShare, IconCode, IconCoins, IconColorSwatch, @@ -133,8 +135,12 @@ export { IconPencil, IconPhone, IconPhoto, + IconPhotoUp, IconPilcrow, IconPlayerPlay, + IconPlayerStop, + IconPower, + IconPlaystationSquare, IconPlug, IconPlus, IconPresentation, @@ -150,6 +156,7 @@ export { IconRestore, IconRocket, IconRotate, + IconRotate2, IconSearch, IconSend, IconSettings, @@ -176,6 +183,7 @@ export { IconWand, IconWorld, IconX, + IconPlaylistAdd, } from '@tabler/icons-react'; export type { TablerIconsProps } from '@tabler/icons-react'; diff --git a/packages/twenty-ui/src/display/icon/components/llustrationIconLink.tsx b/packages/twenty-ui/src/display/icon/components/llustrationIconLink.tsx new file mode 100644 index 000000000000..70a480068608 --- /dev/null +++ b/packages/twenty-ui/src/display/icon/components/llustrationIconLink.tsx @@ -0,0 +1,23 @@ +import { useTheme } from '@emotion/react'; +import { IllustrationIconWrapper } from '@ui/display/icon/components/IllustrationIconWrapper'; + +import IllustrationIconLinkRaw from '@ui/display/icon/assets/illustration-link.svg?react'; +import { IconComponentProps } from '@ui/display/icon/types/IconComponent'; + +type IllustrationIconLinkProps = Pick<IconComponentProps, 'size'>; + +export const IllustrationIconLink = (props: IllustrationIconLinkProps) => { + const theme = useTheme(); + const size = props.size ?? theme.icon.size.lg; + const { color, fill } = theme.IllustrationIcon; + return ( + <IllustrationIconWrapper> + <IllustrationIconLinkRaw + height={size} + width={size} + fill={fill} + color={color} + /> + </IllustrationIconWrapper> + ); +}; diff --git a/packages/twenty-ui/src/display/index.ts b/packages/twenty-ui/src/display/index.ts index fd659f04f7f6..bdccc2a098dc 100644 --- a/packages/twenty-ui/src/display/index.ts +++ b/packages/twenty-ui/src/display/index.ts @@ -18,6 +18,28 @@ export * from './icon/components/IconMicrosoft'; export * from './icon/components/IconRelationManyToOne'; export * from './icon/components/IconTwentyStar'; export * from './icon/components/IconTwentyStarFilled'; +export * from './icon/components/IllustrationIconArray'; +export * from './icon/components/IllustrationIconCalendarEvent'; +export * from './icon/components/IllustrationIconCalendarTime'; +export * from './icon/components/IllustrationIconCurrency'; +export * from './icon/components/IllustrationIconJson'; +export * from './icon/components/IllustrationIconMail'; +export * from './icon/components/IllustrationIconManyToMany'; +export * from './icon/components/IllustrationIconMap'; +export * from './icon/components/IllustrationIconNumbers'; +export * from './icon/components/IllustrationIconOneToMany'; +export * from './icon/components/IllustrationIconOneToOne'; +export * from './icon/components/IllustrationIconPhone'; +export * from './icon/components/IllustrationIconSetting'; +export * from './icon/components/IllustrationIconStar'; +export * from './icon/components/IllustrationIconTag'; +export * from './icon/components/IllustrationIconTags'; +export * from './icon/components/IllustrationIconText'; +export * from './icon/components/IllustrationIconToggle'; +export * from './icon/components/IllustrationIconUid'; +export * from './icon/components/IllustrationIconUser'; +export * from './icon/components/IllustrationIconWrapper'; +export * from './icon/components/llustrationIconLink'; export * from './icon/components/TablerIcons'; export * from './icon/hooks/useIcons'; export * from './icon/providers/IconsProvider'; @@ -29,3 +51,4 @@ export * from './tooltip/OverflowingTextWithTooltip'; export * from './typography/components/H1Title'; export * from './typography/components/H2Title'; export * from './typography/components/H3Title'; +export * from './typography/components/StyledText'; diff --git a/packages/twenty-ui/src/display/typography/components/StyledText.tsx b/packages/twenty-ui/src/display/typography/components/StyledText.tsx new file mode 100644 index 000000000000..76bbdf562c8a --- /dev/null +++ b/packages/twenty-ui/src/display/typography/components/StyledText.tsx @@ -0,0 +1,52 @@ +import { ReactElement, ReactNode } from 'react'; +import styled from '@emotion/styled'; + +type StyledTextProps = { + PrefixComponent?: ReactElement; + text: ReactNode; + color?: string; +}; + +export const StyledTextContent = styled.div` + font-size: ${({ theme }) => theme.font.size.sm}; + font-weight: ${({ theme }) => theme.font.weight.regular}; + + overflow: hidden; + padding-left: 0; + + white-space: nowrap; +`; + +export const StyledTextWrapper = styled.div<{ + color?: string; +}>` + --horizontal-padding: ${({ theme }) => theme.spacing(1)}; + --vertical-padding: ${({ theme }) => theme.spacing(2)}; + + cursor: initial; + + display: flex; + + flex-direction: row; + + font-size: ${({ theme }) => theme.font.size.sm}; + + gap: ${({ theme }) => theme.spacing(2)}; + + padding: var(--vertical-padding) 0; + + color: ${({ theme, color }) => color ?? theme.font.color.primary}; +`; + +export const StyledText = ({ + PrefixComponent, + text, + color, +}: StyledTextProps) => { + return ( + <StyledTextWrapper color={color}> + {PrefixComponent ? PrefixComponent : null} + <StyledTextContent>{text}</StyledTextContent> + </StyledTextWrapper> + ); +}; diff --git a/packages/twenty-ui/src/index.ts b/packages/twenty-ui/src/index.ts index 09b018c3f5b6..bc26e1a7c694 100644 --- a/packages/twenty-ui/src/index.ts +++ b/packages/twenty-ui/src/index.ts @@ -1,5 +1,6 @@ export * from './components'; export * from './display'; +export * from './layout'; export * from './testing'; export * from './theme'; export * from './utilities'; diff --git a/packages/twenty-ui/src/layout/expandableContainer/components/ExpandableContainer.tsx b/packages/twenty-ui/src/layout/expandableContainer/components/ExpandableContainer.tsx new file mode 100644 index 000000000000..aff789f57556 --- /dev/null +++ b/packages/twenty-ui/src/layout/expandableContainer/components/ExpandableContainer.tsx @@ -0,0 +1,42 @@ +import styled from '@emotion/styled'; +import { isDefined } from '@ui/utilities'; +import React, { useLayoutEffect, useRef, useState } from 'react'; + +const StyledTransitionContainer = styled.div<{ + isExpanded: boolean; + height: number; +}>` + max-height: ${({ isExpanded, height }) => (isExpanded ? `${height}px` : '0')}; + overflow: hidden; + position: relative; + transition: max-height + ${({ theme, isExpanded }) => + `${theme.animation.duration.normal}s ${isExpanded ? 'ease-in' : 'ease-out'}`}; +`; + +type ExpandableContainerProps = { + isExpanded: boolean; + children: React.ReactNode; +}; + +export const ExpandableContainer = ({ + isExpanded, + children, +}: ExpandableContainerProps) => { + const [contentHeight, setContentHeight] = useState(0); + const contentRef = useRef<HTMLDivElement>(null); + + useLayoutEffect(() => { + if (isDefined(contentRef.current)) { + setContentHeight(contentRef.current.scrollHeight); + } + }, [isExpanded]); + + return ( + <StyledTransitionContainer isExpanded={isExpanded} height={contentHeight}> + <div ref={contentRef}>{children}</div> + </StyledTransitionContainer> + ); +}; + +export default ExpandableContainer; diff --git a/packages/twenty-ui/src/layout/expandableContainer/components/__stories__/ExpandableContainer.stories.tsx b/packages/twenty-ui/src/layout/expandableContainer/components/__stories__/ExpandableContainer.stories.tsx new file mode 100644 index 000000000000..66c0915b43c4 --- /dev/null +++ b/packages/twenty-ui/src/layout/expandableContainer/components/__stories__/ExpandableContainer.stories.tsx @@ -0,0 +1,81 @@ +import styled from '@emotion/styled'; +import { Meta, StoryObj } from '@storybook/react'; +import { ComponentDecorator } from '@ui/testing'; +import { useState } from 'react'; +import ExpandableContainer from '../ExpandableContainer'; + +const StyledButton = styled.button` + padding: ${({ theme }) => theme.spacing(2)} ${({ theme }) => theme.spacing(4)}; + background-color: ${({ theme }) => theme.color.blue50}; + color: ${({ theme }) => theme.font.color.primary}; + border: none; + border-radius: ${({ theme }) => theme.spacing(1)}; + cursor: pointer; + margin-bottom: ${({ theme }) => theme.spacing(3)}; + + &:hover { + background-color: ${({ theme }) => theme.color.blue40}; + } +`; + +const StyledContent = styled.div` + background-color: ${({ theme }) => theme.background.primary}; + height: 200px; + padding: ${({ theme }) => theme.spacing(3)}; + + p { + color: ${({ theme }) => theme.font.color.primary}; + margin-bottom: ${({ theme }) => theme.spacing(2)}; + font-size: ${({ theme }) => theme.font.size.md}; + } +`; + +const ExpandableContainerWithButton = (args: any) => { + const [isExpanded, setIsExpanded] = useState(args.isExpanded); + + return ( + <div> + <StyledButton onClick={() => setIsExpanded(!isExpanded)}> + {isExpanded ? 'Collapse' : 'Expand'} + </StyledButton> + <ExpandableContainer isExpanded={isExpanded}> + <StyledContent> + <p> + This is some content inside the ExpandableContainer. It will grow + and shrink depending on the expand/collapse state. + </p> + <p> + Add more text or even other components here to test how the + container handles more content. + </p> + <p> + Feel free to adjust the height and content to see how it affects the + expand/collapse behavior. + </p> + </StyledContent> + </ExpandableContainer> + </div> + ); +}; + +const meta: Meta<typeof ExpandableContainer> = { + title: 'UI/Layout/ExpandableContainer', + component: ExpandableContainerWithButton, + decorators: [ComponentDecorator], + argTypes: { + isExpanded: { + control: 'boolean', + description: 'Controls whether the container is expanded or collapsed', + defaultValue: false, + }, + }, +}; + +export default meta; +type Story = StoryObj<typeof ExpandableContainerWithButton>; + +export const Default: Story = { + args: { + isExpanded: false, + }, +}; diff --git a/packages/twenty-ui/src/layout/index.ts b/packages/twenty-ui/src/layout/index.ts new file mode 100644 index 000000000000..8b8c34526885 --- /dev/null +++ b/packages/twenty-ui/src/layout/index.ts @@ -0,0 +1 @@ +export * from './expandableContainer/components/ExpandableContainer'; diff --git a/packages/twenty-ui/src/theme/constants/Icon.ts b/packages/twenty-ui/src/theme/constants/Icon.ts index e103c0b8ec3f..cfe9cbc79423 100644 --- a/packages/twenty-ui/src/theme/constants/Icon.ts +++ b/packages/twenty-ui/src/theme/constants/Icon.ts @@ -3,7 +3,7 @@ export const ICON = { sm: 14, md: 16, lg: 20, - xl: 40, + xl: 24, }, stroke: { sm: 1.6, diff --git a/packages/twenty-ui/src/theme/constants/IllustrationIconDark.ts b/packages/twenty-ui/src/theme/constants/IllustrationIconDark.ts new file mode 100644 index 000000000000..9c9715b4d1ae --- /dev/null +++ b/packages/twenty-ui/src/theme/constants/IllustrationIconDark.ts @@ -0,0 +1,6 @@ +import { COLOR } from './Colors'; + +export const ILLUSTRATION_ICON_DARK = { + color: COLOR.blue50, + fill: COLOR.blue70, +}; diff --git a/packages/twenty-ui/src/theme/constants/IllustrationIconLight.ts b/packages/twenty-ui/src/theme/constants/IllustrationIconLight.ts new file mode 100644 index 000000000000..a292d9bfa68f --- /dev/null +++ b/packages/twenty-ui/src/theme/constants/IllustrationIconLight.ts @@ -0,0 +1,6 @@ +import { COLOR } from './Colors'; + +export const ILLUSTRATION_ICON_LIGHT = { + color: COLOR.blue40, + fill: COLOR.blue20, +}; diff --git a/packages/twenty-ui/src/theme/constants/ThemeDark.ts b/packages/twenty-ui/src/theme/constants/ThemeDark.ts index 6cbcf7787233..10a1e54cc9d7 100644 --- a/packages/twenty-ui/src/theme/constants/ThemeDark.ts +++ b/packages/twenty-ui/src/theme/constants/ThemeDark.ts @@ -1,15 +1,14 @@ import { BLUR_DARK } from '@ui/theme/constants/BlurDark'; - +import { ILLUSTRATION_ICON_DARK } from '@ui/theme/constants/IllustrationIconDark'; import { SNACK_BAR_DARK, ThemeType } from '..'; - import { ACCENT_DARK } from './AccentDark'; import { BACKGROUND_DARK } from './BackgroundDark'; import { BORDER_DARK } from './BorderDark'; import { BOX_SHADOW_DARK } from './BoxShadowDark'; +import { CODE_DARK } from './CodeDark'; import { FONT_DARK } from './FontDark'; import { TAG_DARK } from './TagDark'; import { THEME_COMMON } from './ThemeCommon'; -import { CODE_DARK } from './CodeDark'; export const THEME_DARK: ThemeType = { ...THEME_COMMON, @@ -24,5 +23,6 @@ export const THEME_DARK: ThemeType = { snackBar: SNACK_BAR_DARK, tag: TAG_DARK, code: CODE_DARK, + IllustrationIcon: ILLUSTRATION_ICON_DARK, }, }; diff --git a/packages/twenty-ui/src/theme/constants/ThemeLight.ts b/packages/twenty-ui/src/theme/constants/ThemeLight.ts index 259552e3ca51..781bfc63531b 100644 --- a/packages/twenty-ui/src/theme/constants/ThemeLight.ts +++ b/packages/twenty-ui/src/theme/constants/ThemeLight.ts @@ -1,14 +1,14 @@ import { BLUR_LIGHT } from '@ui/theme/constants/BlurLight'; +import { ILLUSTRATION_ICON_LIGHT } from '@ui/theme/constants/IllustrationIconLight'; import { SNACK_BAR_LIGHT } from '@ui/theme/constants/SnackBarLight'; - import { ACCENT_LIGHT } from './AccentLight'; import { BACKGROUND_LIGHT } from './BackgroundLight'; import { BORDER_LIGHT } from './BorderLight'; import { BOX_SHADOW_LIGHT } from './BoxShadowLight'; +import { CODE_LIGHT } from './CodeLight'; import { FONT_LIGHT } from './FontLight'; import { TAG_LIGHT } from './TagLight'; import { THEME_COMMON } from './ThemeCommon'; -import { CODE_LIGHT } from './CodeLight'; export const THEME_LIGHT = { ...THEME_COMMON, @@ -23,5 +23,6 @@ export const THEME_LIGHT = { snackBar: SNACK_BAR_LIGHT, tag: TAG_LIGHT, code: CODE_LIGHT, + IllustrationIcon: ILLUSTRATION_ICON_LIGHT, }, }; diff --git a/packages/twenty-ui/src/theme/index.ts b/packages/twenty-ui/src/theme/index.ts index f1faaf6fcf01..17eae52e1c2b 100644 --- a/packages/twenty-ui/src/theme/index.ts +++ b/packages/twenty-ui/src/theme/index.ts @@ -19,6 +19,8 @@ export * from './constants/FontLight'; export * from './constants/GrayScale'; export * from './constants/HoverBackground'; export * from './constants/Icon'; +export * from './constants/IllustrationIconDark'; +export * from './constants/IllustrationIconLight'; export * from './constants/MainColorNames'; export * from './constants/MainColors'; export * from './constants/MobileViewport'; diff --git a/packages/twenty-ui/tsconfig.dev.json b/packages/twenty-ui/tsconfig.dev.json index 7cf734bdd02d..82ab7669eb27 100644 --- a/packages/twenty-ui/tsconfig.dev.json +++ b/packages/twenty-ui/tsconfig.dev.json @@ -15,5 +15,5 @@ "src/**/*.tsx", "src/**/*.ts", "vite.config.ts" - ] +] } diff --git a/packages/twenty-website/package.json b/packages/twenty-website/package.json index 0eb6260beb6a..c235f812a142 100644 --- a/packages/twenty-website/package.json +++ b/packages/twenty-website/package.json @@ -1,6 +1,6 @@ { "name": "twenty-website", - "version": "0.24.0", + "version": "0.30.0", "private": true, "scripts": { "nx": "NX_DEFAULT_PROJECT=twenty-website node ../../node_modules/nx/bin/nx.js", diff --git a/packages/twenty-website/public/images/releases/0.30/0.30-array-field.png b/packages/twenty-website/public/images/releases/0.30/0.30-array-field.png new file mode 100644 index 0000000000000000000000000000000000000000..84736fe547e42d1e23bc189cdef5e146fdd74e5b GIT binary patch literal 168345 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 literal 0 HcmV?d00001 diff --git a/packages/twenty-website/public/images/releases/0.30/0.30-emails.png b/packages/twenty-website/public/images/releases/0.30/0.30-emails.png new file mode 100644 index 0000000000000000000000000000000000000000..d22595abb56a57f59a5c50ee8876ebc0084f732a GIT binary patch literal 147906 zcmX_mbySq!_w@h+3^_wLGjt;$jlc{!bO_Ro3W~HyNjCyRhafGTBHayAgQO@W(jC(H zo6q-M>zzODnkUwJ?mhdQefBx`M(b*;k`U4p0ssIKHKdY00DuPv0C2WJIG8(i#l3Zy z3xKYsfimWj;(tGKa&ia+g87RXDJd!c-_8F&-re2Z+}zyW-d<l{W1gO#o?cyDU0hr| ze*F0S{QUCrGBY#t<mBY&=;+|!U~g}4Zf<UCYioUdePd%|etv#+b@j!I7mJIF%gf6@ zfBxLr+1cIQotl~&9UYyRnCS2C@9ys2+}vz$Z*OgFZEkL!o}L~X8|&@u9UdNDT3TXa zk?QR1oSmJWnVA_H8p_Sheg6D891broE^cgWWMyUT>gr;EN!HZV)YsP!4i0K+YBEAa zeSCZZ0s=%uMVVmYDJdz;Y|<4Km0DU_^e}NI78z#NCvtLfk&%&UX=(l6rnR-Tg@lCC z)6?mhMCh0v6%`c~78Z8&55>g9)Ya9&*yZS<kE^Py3knK)N2g+AV@p1NZtWR-_3D*~ zhzJ8rYG8bZiCJj$`!W;?{WiDS(%s)ZIBafiPQ$=YL(kPSJkG+x@@@7f0~5cCi%WB7 z-}u6M$H3^&<gBZ!Yjkw<2zm}<|IwL66B83RH@C*N&g$AP#zw|DIXNAJ<MDBE&7ED{ zL!;i_-XXyuUt8LdNaWD;&(8in3?%)dW7YMI5D0jDVOd2*1<EQ?T3R~!^Uv$ouj`xI z{QUgb*w_xxqr@aQTce#rQ;V#e3R7Q8>rz7In<~C$MIX>_?KRHZ(1FHuP0|($~|g z``Th_W3$*<d$KgMJKp~($c=)EvHXMo&;+_T^6mM`VuFhq4>!+vO+Ga(YtQF&XJ==A zKK_=xl!d{j<+0BG<j6nM{Rs&Pq4v6a^CN${TgGydhngD(zkHtRtZgYN_VDn?_I|NG z&{Y%QG4?s*rL#X5zlyM!Vs~zQS#nfEq;FSU^<q_VRZfPKlyu^|*UMk4qkP|*+PZyq zwrA%Q%gC!p4hy{6TAmr`4RCtyYpl}pA^7{}?9k|RQ7N6}sfnD}7+wKsPw()t&UU?L z_ODEys%lxd`X!huNifn=$|;*9TR&A4<rU^&*xf&j{+5sbUyyj}Yd;12v~Yn)!@6n` z4s(w(qpiCD*mCx2N(ck*ANx6enr4QKL&_2>4e3iC(^yXg<lJ6;HW@Q8_Xkpl{G*-7 zY<659i^x>b<sxIDFL)~951&&0-7uFj{X<*h^>d8@Pri8S($}vy^c3o1JPlY_wI3ID zd1xPXJns;gVx^SLt$tLk?aY6Fe1AW2eUZ{qXZy$TWlm<Yhck1yLcZ?9m+X%ogPAXL z8r=tYhz4SwPL7Ne>T*+#{)@==(3X9VweR+W&WDmPT;Y1fO(lZVMC|~Pugm?<Y~qR7 z{V|zQ%MV?>#_Qbzg~cb_f?X1i5^s;%_|rusHcri3G(YRQ62?DwF>dqPn;ZWqvC>F# z_G#F+mu>GGA8TRZ-?^YZTai~)77>j&_yOdSu6b2^sKuTA1A)axuLIMg#@|B;Rw7a} zb|T7!X>Y|?{doEKnv9Y@9`Ka5e=v0CO~rmN`nD!hth=d3=c9^JD+rqJAn)O!)a=!x zs<0Q{h9V_LyZ7{?gS(W|WQDG>SKGARwV&v373sP>vNHmerPCO`Mj9_s`Z(KOJ^d z7`j_NUGKdPp!mq=JgKqzcUorhTk#m(F}@GlP5qe#_Ko*(<5HBolF#v9z}!(aEgh31 ze(<({F>Do#W`1LlL+$ap;w;$cD0}zdU}wiNu-)JN-0;hC5jf)Wt5>{yCtu0oUT}7r zVQSB_@T@<Q;W7Ex`9%ZIeKOcx1c?jRQ3?k7N9nF`p(x&y@ickv`$vyIIPF+dx|;Ix z1iOyTVC$W#N~NZ_(52cUWcAHkS#ZKD$JP$?#N~YeM(Jv*349(rXId~3yslN_Ki6gw zq4JGnO7Ei{0H<AabaZuJ&uxM|S%Vo@FKo7_vpksu{*D-x47OK!`2|*dzunVS4eWeu zEfTKzRIEU_pJAO4*t%pH%RE0f*okdE+?DZX29|QowvrObt#KdlO^Dp(!}d#T1&|tD zv}&qrlzB?F0jVy}h~L$84^j#~aI*51cR&gelt}Ef4Hyz8Djh1QV!#-A=jCZ)zIW$x z>z5Rj1YCvqZfw1J+yVa!-p{1X?W#Xn>i;rBhF$%v;3Z8CJ+L>reZ7l)d3E$}gXNZn z=aUof8N@YJS^K<RPR=X7co`Td=^)%v^1`6<m|~e3`z!EdF^z^u7Yk7g2;I;R*4>P4 z7X_cBIDLx36?`^=0Huv`Ribp*aeD~|>h=*Vl+6ab(f+K|&Bl&A4}7@Q6?~_lt+B$K z0NygoUzV20!Xa|j$pJUB;DANmpLn>H-oa5LIKTEo<lDSDn*4yZU-3d9hz~gy7I=9T z8bq`L@tq^!Q`M4^%Rup6ru`FN{I`l=N$G6uF0Ku)1jCpr67$@U*X=TmE;UrEhS*jz z3GEAX^a$=9-R#IKp$>^9N-a`B!C-dgXQc+&A~LuNgdWpd{e&g`<wfLls`Ls(%Pc(Q z881O5ZqJxMH=tA!IFtp`|A_D&<G;#R#M<j=K26<Dkb$%bz1v8Lk5`INBiVE13YxKL z*uKcOp1Pi@Q9MwM;EHVjWk>P!*V9Pfj?10#7aHAvgs%s)ltP`NRYmcR>EX;XA-bzJ zdRQPOEWCURh&p|?>as}8_fmi`@el`9)D%q3bhQ^rXs?!vErqSkmkHl=*H$l68ia`$ z4V&<78g!1bbR?{g6{=qEnybIS3szyJMvjC6juPnN5@fsvfTw?}Ex?D&aZ0Rz<subb zp7>wY4v>K)u|LV_z-t7g0`5BVA4VQnriS`~j8E+Ma~dS2NgYE!<+(V$ScO2wu#A|` zv(1}kg5lk;8E8raYDFi&aNOFEg6;Z+hBSM#YA^dYu8qsLBesyHqS&UQwma0vFc-7L z^K6J(tk<?`s+tbVM<ggyk?!@M7D=g;@j|mlbh67`aViO8X4@hy>cMH&7DP92qS_Z> z2{N^Ez~zA31JzFEI8D|4DyH}#?Glg1hJ>Yi)r22ExXuFQ9uAsb*JSPfCG~oj5ErNA zNhke2R8ghF<fRy1=%H|}iYBum!CxdE<1GVKrW6M3O#Y1y!^S+6pcH^ku`FduW7J<E z?FV)_zkq9*q&9DEo??I2^cE2RG0%@wiqOjJulI?O3kIS?+(rgoM+c(5{F3XemUNE! zD`QRa{a09ZiW_hGxpMuJ{;3R{C;pv_CvE$+_^N3!g3YSqVY+E0;NN}Jo2#Yzva%i? zlq!1Q&6_uPS}y}6JXJiOSqa(GzwX8h*2SXHRD7eT*hlQM|Fb2zOVMad%V7=wMgT<^ zmV{PV4yQp*M+8klv1rRAcAfT7{SyTIsEzEXCsWX9Y?_i$O_(hxvzW}?l)0b)l`>9A z*sMk+D~{eyj2Xl2<#r|NSoNipe?eVCesHo=lDph^Td{-m)3DO;^V9g}fDuxQ+uQcn zmn%?4SD;FK4VIr~Ua^TWY}r2-UF2b`rIP!+QmxWbZ1si`-q5pz<DK#oyIsSYiCP?_ z*tVUbNqs8FPwew0HK5BNiiv#3zjv)~F%3T4Nh=r)M@dB~>c0?-Pc~i=8+t&pm^^;> zWB-9W;l7Fx`$+-Xu8!pa^;o1KR`-3?)V+7Y(fctJ{x%Llk^KtO^ObgyH(#0-4wBg( zIdulybKI6BEVTbw0Yi6prxWgo<KB{7;Sku{?&%KOi|#O~#G+raWA~ik@D)BoGUXB4 z#;cOKMk1_wE^%Mo+3~(CmFLbB+^{&dTI68rJ|-b=S5s=ms$oBHP}y~{u&qP>?W0R2 z%r%JdP@oA@Xq6lsXUR^X2pxOY<%?SBW+Mz!Nf=NS#1H0n-TTnt^WrSD@&~S8e>m9l z*Sq&>5BN3v(8jL`?N+-7biV)k?kBb4<9(X~R%#A*>%CIaJWWa7IM}WAGd-U`jch&M zIr*%3U`*9qNXS!!<<HU@x*d|P!YcFV>6feGp^a%`1(Txi_RL8NmNeAzF$t*an+8oY z%FIAhe1M{^dqC|i(ztkmCGiQD<dgJj9g|(&IrVk$nhO=KLgA3DB9Qgz>P)#M+tqI} z;lOsS?&6B~x2rdsoe~<2oe!f`-`S{g;~E>8?|xSqjh=OMPu27}R}5Oe?G%1~AbtEj zn8EoY<GU+S`ncJm$9uK#>P3CrbOA#W83H6JyJNO}LL9@0#lGWL(`fO+$EW7I;L!qs zjd61r0N+Nz-4<j8PFg<hxQlS&@%91e;|iw6{J~|_7@vF6KT5gxt_KQKX2b-LbU%!+ zeIZA{J7XT-r0I5eY;H)d_hZzXL_cWTZPR6B<P!Kn_{q*egtAd+sG^I~ISdk76X<C+ zlJn6j$5Z*&8~i*HTjg)H)-_R71VCc!2h=E?HHrT(TJR0FIpOiB$9esDvF^0xaGST# z7j4IWLNzh8&>m3XF9TmPK^U#DVK7l&F(V@<{f5)XY&)MjQbt1ohMAXm5q>Y+k)nfF zFk=V&VL?)LF|?$J!+-y9B`{RXNHu|R|I+JSUp&INt?f1`Xo)adk)eKR(Be}m^`L#Q zT*DNOuuOw#?h*ZVu&Ch)HrAs&v!E`T#X7slZAi0aJoV|i)gK4!eEV+-%jaD5<w)$z zw*@Te_62L?zTw2A$>hk<>I4NI?L~F{1~w9MG)zighH#Sg-h(H2YP)V5MM&MZifA_? zJOBqw!a|zx?ZKbY<-bNIbe`TG!BC-n2NMVgXrDe?L`S<#fjh)OROS6t5pKG%*t30b z&LXkdY{@eTLou;nd3vu9%FVt)n!<s<*)h(*e0vPTXmZilf6*2-;N)@bVG%_ORY<e< zq6CUl{!&&(ol6m9YHSzfrWOTT(r<|be{?uE_KbpOWWZy>@5rEX-Oy%tDvIH6kNPgg zAMA!cU;cYY>iG5IXh>1RIV<B>ij%E6@0lH-(z(g(H6fm&5P)d#I0P>3>x(xp$`S>y zMd*$qKQIISA-(I3s#M67v}sQD>m68Jenc(74S09_L)7Fp)5kkWqhXMdG39B37FYef zwinut_Pnla7WG*5Wykix=5>c}>1ES^B2hF%MXNW-X@>y{LDQ)Y;9lmVXbLXYTv@T7 z%j=?-d1V|C)f0WoQR5VEUlZ5f_T|0(*kGFcvim4Tg~_+0y2Q?PHp{jLDuZh>hEipH z`?jCu0+;{6q|l6jhYpiCtkO8f-mBY{M@KAjK<;9>sga{BX4~0GhgoEoxs=XHuR^nv z@hQizT&B0{JW+sxZV$}`g?+Hw608n?0%{C<M6|#7rCf}WIo|)Tp@tQHWeuj5!LB?x z9!6~Yg^3PBr><RJSDC(>q9VPuKnO)Gwh`h&I&ngN<DcN0N2`+m)Wes!`+}V|py;(N z!mo};<U^D`q}11<<roHy!u{ybjCv29$yc*X(+JRhe9NUgO!!irvUc=2YdFTg1@2fa z(+sT`Y2-k8V4F3=Y}r+v@je_IT5I=j4v~uUdon*Ag+Bbzx#`0Zr16}v`IU<JP1=gJ z{V5@`PcOE(Y3OH1HSIaNpC}BeAT*?6Nf#!KMXtD8ZJ3-(6R{hb)T6NcZ&*pu)2T5! z!ekakMr5A7A*JSt93`JWUB{;WwU;Qn`X=ny*DwU`oRJS^l=t?_Ym9UN=e<bvuwLCh zKIXWWjvaaD?Q}nX=@W#NK14CyJzXJ4q3QCj?Y(n{;uh_(G5-zo8H^gF4I4LxDS^3o z6us|+gO1+q!@+{qBRb*cD)I&~Ne>Fk&qdJ?q!b!*n4}{**2rRZ0#z(XqOa%p;7EDi zo42?pMSxYrJ!_dza#)DA(?ejhylx}PqM$xJJ&j6W78Be4T>qlhr8{uuMXbN;%Hgj^ z9~yo0Zf(STo{;KH`Q~ZaxwnLHvav&Q`u4YD=>>HA=*@9)EAiM-FBqkFEh{Vh$f^M# zY{gGx??uJM13m-~!4st$DZ&Cor8(}y+Y<x|qa#M7+1*IUcQBsB4cRtCO`A=7*iuY5 z=15K}5yPm4nUm1J=k)1isp<54dO7&T+9GK{bweXx`BG#cey@1R{KkIcto`-s>L{+6 z{Nuj!6_49YxiBA4**ATKUClk#dD^1284oaM`AMBK@zcZNyO`lP3CZ~QxRujStj1MD zQn%o>WV}k))xMo^MED&`2~-0)V$b4&KFxH<P=XP!xM;sDSWCK8l@x5DBs(dL&D5V! zwQ|!3@Cg2b7pkVgeYXioxlrlhyQ$4P<}<1!-9zB>vQ4c}f!{V=9q+CE0fa^@e7pX% zg@WKG;=8gBZXlRx#fX=adCfaxe_xB5#V5w?H(BKjA6=ZBm#+rmy#oOoSow9GdO=U{ zf(>X;P=fGmXO1HNDFsW8t{iZjm#H%aNh(i?C~va1DDd?QBS|t58r2EjYUP0251^z_ zO+=w8HP+J9h@7W(nIPnjr9a`Sm+BPHd<`5VXH+}A6H?s*r3Hss<4DsRlV3#Ygbi8X ztkr59eSdY4*mY-3mNQa1zayPTP=Axv28W{HuIuo*(wcv?3<aGJ12=<Q^aMJnC9Y4U z)zuM0Vc1{Eds{yIH@_JLOY@W=Lad~(@6&%NDZ=U666Ltk##^hwg%Cn>-dVL!ACG<j zYtO;u_wBl{;p>L6a-u}}u+%me*7ZWwV$c;%DN`7I+RDly)KyuLQ(#|mUIzQOHHw0( zH$Z2&M0n@37nB$w`^{c-7Y<_zeH~+DL>BBHj14lzL4>HtlH)xo<(&3bC`vqT${Og? zq?Mk|NxD|BWQDAK7f8cQs95A0UT!R>CW{s#nj|0!%TA_6^oJY2<Xo_Oy7TH)LUAZ@ zuR<nm)p`fUW)1RDvh29^IseSh46AS;@OT9>J_vD765o3m?L{-*-P*DD%p0MM)<+#v z3}N;KV)R<1ITJgK<~U@)MLRZfq-;TJCp|!|TMX|XvWTAPO}j#zkxkjQf~C6Y@O5}Q zff>a@5eCIY8MF{a8$zc)IW%vOkawQR7ZSOvI8pd2oHz5Q*Y^h@bSaozaL6vO9v}=` zVRV0CqCWS(^N1MEF*Qd%ii`H#J1<vmx#Wz_KlqS{^CwEtnl=p_akBfiO3~qwH2JU! z1VmXA^r`?%hGZr;C}i8JNNpzQog$~^VA{}03~!H?IZY|!qUTLtR8lM$FyW$iFXN;a zWFqd&se`=6Ewjc*=QyDc#5yY6-0H{p=tyo%cVUT4tKw#8=)SwVnGZsOXO2i9ItDU+ zMh!jos(Z9C2gorMFsRjRrCxeSpR1{O6$A|7Gd70Cxnjw({~qBQ7@DttWpMu7fg<cb zc-#tDNa=XE=+&v4Y4ul4J1Iz#DG%zMVxD-^OsU9+swC_yeqva{E#PmaBvLYOZNn$C zYW=}l-$9Pv7<h1KDtv3Km(CYNV~_jfH_n7}MwLT&nXxf!%A$#u$?Nt@VCThK5)d#H zsDLbw=UT&V+9vpE9@V-{NR{&$sg`_pDx`dt=}@YPkwpwL?CTLnCY<#3(-b6MG-353 zoe^)P<CqsC8G#{|;!}!7R{btdXmFDju1h&2YGD=R@iiwm`M<F&Aj2?bNYuanL_5{^ z9}(?O?c_-OQz&ovdEkWyUunk$ssi7qT=q5Hda;Ji%-RG$QDa0<vd964(^nM^8FGQa zpj@aHu7VoQb(KBKQ9EV=u3s=CuOulEdnhJ<cxs3Hlk6E3f$3%IiKTGFRI`5*IYT5q z#m@58c_{<2zf|f1g70AfkzoL+{{?=q63%<9B{aoQe7MCY*i1Ds-knXDoB(LU^(bF) zVlJKy+Hv-$t?OSDFofnfL>|QM0%(^9{!QxJ_6?@jNeFex7%A4Jwr6>C_V1$u@^q+@ zf}}Xs>!<CbWmd7ur*<CR8Xi0*xY{tn24MoA!nEq$G~Y6_?N&Qs5cab%sFqemTZf`z z<KMKjpn>%%KkQPHb+qCIA@MX`5XNOyVn?QT_iO)MqqlUrZiz&qxKUfV?A;W>Te%6p z_J73^D>MVRAh<veX_DBa6NTk5F8Ub0<{~b71#?R;3KAb4&X3d0+mH2!pP@W#+dw-3 zJx(~5)b4m%9!5hz)?K!I4@)z%@L<_6Zyn#~6t%v;$`Nf<#l<=<GxQfi?<Hs(uB2_u zq`84W+n@uMXAT8so>fen@m+E^cbP*g_lNW8c3S5hlQ;`hes%CqGzVDkx-EgeQMd)0 z##EY5Q@&%u=685|8Clx~j9{4iY@AEei*!+47OlIF0>rTUL1^x?=Mp=@_)Y;o9<Cxg zJQChG$M-cWDMfvK=~6Ky?G}A|PyaSnUbG;(aGJEQEHAF*&2wYDrv9kmj3p7f!;e)J z%EFDArZm6SsTnAoV#fqNhQT-w=eKU}FB+(2nU+Hz2Tb}dNxLv+zF*$*^9c}7P6nqG ze1`*2B3ImBCmyv#FvDyR-3i$6zfzw62G-C9ul$d9mRT4rZyx|6n!4Qu)Hh$E41tJc z+Fp8_SFFj`%_U-F^C9n{f>w9|-N682VnR+}S0~C=V>>k%@*u*_7!{LA(}K_Xd=_@} zgJ@-QC$N}KAX!QA7E4Kw*NTDyJ(f$`WAkrcj7|$Re(Y_VnlcXbmo&$QMN-HGNHl8< zDoTQThr}@3B|y~KwwW~259)u6#$UBwLZ1T$-$p{(WR4f?YR>gZ_Dr_R(xCyZ>8w7g zYw$tUz{6481_#lb>n0-$4M0zb)S;I5`bK|a#o^6<6<FT?b<3JU!QiW&;3?)P-jCb* zX(XrBIS$)`D;!4RcRfmqvk}n|FCz1-`SXy<0~=YcT>NQbPJu+mDTUs2@1H)gH05~y zNNRvp8pr<S@o!$1Q087=^Iltj6o8VlE{`-6hW`jNaNCls{{&-$LbR;qVcA-spjG(! zxdU^4`*m(Bxv&6X$9>;R@K5jgQ%9@L3+gDW7yj2Ami}jbKlOF@EKRT1zWq5nwBOU4 zCKUrj?It<4>(7y#n&vt*H_DR@<OROBnVj*+L?kYggM?)x!p^h>1`FNgTtb|Jhmy;S zoH$Dgy<uxC#dAJo9+pL_Z9%GL49p1BneGy{>~>Cv%-`js*u^?@-L)Ic-rCy10fHBH zjj%KB=uph`mrfl`D2%^&`&Qv{b~YIH-X-wi`ltH4rnz5CN1Tot2!HY@{04Z_XXUMc ztHw8Ch+6#KZ+hCw;)o)C+KsQ9!=&#PmHI{>`kzmFR0ce4cseUG-%k$G8}%}J_(V#u zI4B?q+RNbO`8dKdk$gJEd1Ki1CvxH1SUKUFAZACVZNL5-5HSG(*o5t${qQq^u#3q* zEZDiiIzl@{Lk9ppH+4O3t88MU0H32<rEVG^9FB4jO4A(d0qZA0FW`&-bgLV_jhz3w zHtX<v2$sE-3yI%L<-|Kwy*27xp+Sqr;kwnA&pdJE<?C^8lO2rBZEGkkGzU7nxHd1H z<mlgfNQFIDr5d7o-QGrd3+<x&F)*HoUy&c23x|}3uDSPfq%*dTM_YA?W@{I3-9j1Y zX?NfMp~8ZEI4LN{4S-Yp#=*(F4Cn*_2&e%C%1OlFXYAF#*_gK@;EC1^hX*ccM?g8) z;IQ*g9Jdi=1s)<ipDL--5lWc%?*w-GaxV>0gR5b#Ss;vk(sX`<$FE^j1sHjtY-jvr zfNvi3hN}dJS?Ldd<$ISFGys{%eBM9^g>*P{;khJ9yLGN|FkLdwf4}&}_2tZELg!pw zd`kXm)UG2Tg!vI$bW@<UEx+>UnDtZptF5rZ1o{wMn}FK&)(I8hKqVZ0mZ;-%dp3F4 zJ~=hpHRBpS%W=)}{2o?w5goC~;8VTc`N^js|5b@npT6-Sp2K*`APMOg?0G9f(xp_a z`qb?8ulZB)oBs$vuq7Ly2B65ewLp6ARlv;rJW*6b?9ujqf2<j^)4|R)9Si5#8IP#K z4L+W5<OMgUk01UJ*YqmBqrZcDY2aE(5i_BR+FL-B%JT|u_FhtU>V&>T05j?lC`31R zV~L24`LZWuUz>w}KX~{zyy&43Vaa!SVGIwBmS>5m?6O1lTW5Y7%dM@{a@>$w7LX{5 zC@<RQd`V?G?VPIJP}PGD^|wFpsqls3dajbre#wB%A4_;9Vfm~tRDb&P=_p`qB0fH@ zm~;8g(;pIQ4DLD})a4YD&Q>8Hnyq>m85zk8_gnWRwm6q&MGBSTdU7+{4E$~$!p_5A zB_qDsEqJelk|Dv@H|rZ%<c(ydK^OBgY<#s$ZQFQVB3fQ9@RXh;D1%vXUHIsRdmDB4 zJcxT11&opnXKt0;2~gB}GbB)1q1($lUAQ4j97GGs4@Y@np^~AjL3ii+;<094l47|N zc^AUx3s-mh{3muP01=#^^G81uXY3wo9SU*CH6fBH5aoB4W5tx3DB<^0ODp0uAO(P1 z1!+1fSUJ5u05!k+EJRXNS0LBH*cG<NiAHe*=tWiQ{7D&<_iKp3Rtu`skjj}M*&uLs z*@{B}Kz)VmD4eDhLb&52Nz~ui8chQn*h*kh&UgTJFpFKGqr>0g%2F#VRtm+ZKvbb_ zFX44)1TG6$VH4+Fw_*Zrvo{rKEHBM5dj9hIr9)owtM+!)QppX<ni;FKGs<Ly<z8_H zCw=R$efXTFsOLv^`iGD9!eCMgKjF{w_M*s9D~du~5)J~?TMjM>w1vG;$5+2!0o@N0 z?gV>ThKfeGTWBTlT|t==YC=|K2`VWr(JNNDzrU}MTWe|i{N+&Int^oggpLm4p6H14 zcRqv>j~&p97dC3-3y5*NqQ@yp$YKYgngWeqgdEd@B7;YT_{+MglmBBf7>ZCti<n2t zHIsw>hag*V$~2NFDfLdxCnzPJB@tj^<sN0|NkwWubkCw>PK7mXjkFGhlFZ@=lv*Rw z1!~ycXASyBCrBr;86E{g4aTr_>Zgo-ZEaZ}KNh>_-8iQi8u(4G;;EO9ty~&WtZHhS zM8*^ojvb6rxleG-SPf>t**I`vh6U~K73XRzzXibR30N<Vz^Bfl@F#yLNJ#M4m#veg z9i9e(jx)oZ=%|a#)!DLY3s~5(>X$b>4WdKdkWeFH08*g<+wMYxwpSt5RM=X>*+TG6 zO-}a~!K}WJ-_{{;lW7g>VPoI+Kwn?qBtX)&b@*VVH5>p2^s54*8<c?X<9PXv%iH$| z0Pp~;{$x#jIP%RUnm#I>F{*r6^c@ca$>~G!^s{0?sW0Ihb$SJB&|k5_IG|<YTL-EM z1W%|Y0pvEuZ(FcQy<&R_8>)=2f683(0pE7P1O`fNl6GqtqO;;apvV9lGL?mo5%ns# zv8>*=!tcc%KbE@aozdL<T?~jb30EelhzBUhLK@^<OD+;n(8tDaoe-r7%R>O0kh^s% z)q-y@in6%GvjE}Y+Zs$?(D{p!;$(yvIf>h29Z`dSTD9El$<;aouSGylKRcAD2Q3)G zKx{>#5#eGGER^9~pDT3!J`F|!L{V%eMFV4uSN@&<;u<z!%()Lcz@OmB&dvCg8Nx}x z0z}<uYXkwqZG@q{a$2$Z5d&=PLa_Wiux(HfjNK}Op5@7y86P#;VuClbnENZ4v<2~L z^@@@rS#tfeg8UrP`t?G?52VpMQkcDE;Bafwmr*^#V!|^MKV1S?SV9slvw~+z9t>$C zRB_gL$WF0QklPuGt5&S~MF`qgxO1&3e;uE0<&6al#zhdZ-+N1po1BCR;`G-HusVd) z5}*N)Vf^s-SJVrXx}4_tLDn4ia+{H6Zc<F{F-D^y2unXMdS6X)64_$7qRzFFB7+yQ zU+j&LOoWnoTyw3vY6TKw7;XF_YV2PwQmr^cGx|h8C+;$2f+{nXoN*9n(pL6q;Ih$( zl7<MD>^~-cB;nF_-y^*(#)_?{t3%%&bpgN%VwEFfy?SoC3idqYjP&;bTKMv?AF!gP z-6;UUZ-O|8Z}}Pi0QX#+rQTJl8mImo@#zm~bgja0S}^!bNpT60xK!!<IEdR{d2_x2 zf!#moE-e|K{tVr*1Z~y9Zy<zev9CSJfC8c*RCT4v59{jKSJo8u7tt%v^_sGD5}v>O zp81epM$-+(8y@rgw=pyJ+KO>V;GCNXFN`vl-G?ytwHXYrlQazY{y}Kh=$JcS`Y<$G z^=Z39fefWoD97^wSWSu0f&ILaB1I4_=>}9yv>`k0%80w^v!$?)K6d|vf<~)1EAq{d z+^uI2OL~I@Wusic_p9c{{&+s5CMx1AzKbo>J_x`@lXLT(>kAL@!RLsVL!2N?(=td? z`{gR!ay+oMfQ+j*58oM)^@rq@LGL<~LJ*DwE0LC?9tY8fo;f6xF6}^>;2TG%W>F>G z#;>LZ=eh?BXrH4a1{BA?Sy42xIL*SYwSp_|(7fcZM(O}2KEd$clpQ%t5Uh>*8-=Cp zt?Dp9JW&scKgi-A^1IK{lNRzvfUr-3frm0htvdFcgS9d7<j=5R$&a55$#l3Ts{pV# znmdAZSoh6MOG6JYCB$PSdTr2lE>7pyciSIU`Or15dcc;?Qn$#|O+<#<a)(6QN47Z^ z#89JOUKHdHJwZ=l*qXZjPZFT+Yc^yHG6g%D2!Rr#6uvP^*y11JI?>)WAOC3l)3iAS z$4Ar>8Be)cbxCAR*iYLP@`$4G5eYPwpR)FIvEZB~^3v+x!>~+DW4Khy&DvU9O;x+W zvSI$oDmL;3h>hbU04fihTBX}iQ|HX!#>kSx!J%QS|BU!_*>ohBoA<tIp}Nb70QQ0> zZcr8D<1*O&`39PfDS)~rM#Jrp=AS>6S0;pD>9g}zeoR*g-q|X3K+El+jLY4A1x0!* z0<3s<+9D&ztnugUTJM9+AFi7c%b?FMUVvbaYu+C_OT;G=Zm5{H`6BaFNgr_Vl+Lb4 zf~`+N=e~!wM=?j>5LhcJ5wUu?=^W-4hV7y-s?#2IIa7ecll!pM=vI)wRQNy=9r4e7 zWoUzuZxN@iX*if07k^zATfmbRB8vV<cy1kF?u|<U<lujXIR<opDxu-&3A>OZK51c| zlz&)OU|usSw1b1vKv)nFSmsV<=6tP6>Dz>J&|AYkzgpG>_~jaoM%bF%54{q4qZ9x+ zF>uP_Qn@g9el9A7iLRLYziKQ#HN8-|B6u3SpW#rN!A>tiK96(^)5I=oMmkmC5$rm< zgZr1=T}d>?Y!0GsQUM@FQ2#MZSS|(wVtLah983-f!S4af#?RB_MWyBrmkdTk215+0 zBR)UQ^yhqh|LQ>vP}B|9Yl#5`Ts5FJx9mU+XmPHfFrQ(XM>wLnRB@e#!@^i_dm^RL z0)!=aL=;_1n^BR~@cvDca~;N^^6+I-@uQfC%*kQm>0e?3y_B*>{)Rwva!4l4iF{ER zOz$Y<;qh%p&UkXnQdoc4EFm{gY?yx|%xlyr3YK|?4LDsEdQpG6BYJi6qoO82h~`M! z^THFs7LDwNV#CP=q?^~kxKn!IE1`whYl|x|^Y$AhUh3kGp#n5R$3C1=Ie%Q0hvzk( z4+|!d*kzCKV;meHtRpH)Xzs7|szpiB?6W8)_QcbZ(+Q-&Up{-)^h$+ZtPbsN;^+T% z#zQW>ly|)*jJX>OiSo!l9w@Gfq&fYbi3?!=_#RBru`_lqbJXs8Hkw3T=KO|<j&9^@ zKOh!G8lcnwYgge028G>q;}^GtG8sQa-Pi?SgCJ)u=@H(B^iRr?@RUYd5tbOLWLr7v zN_N;5Cp11BjgBZU&oCIPOnj1fEYHD9K*c5c3d|Bf3*hNdoKjr1yY5SM)`vk7_M~yb zd|Aknsvjem|2bfNX6t}IudKs8{yl4CC42kn@Nff^@~!TmJ3cQS`x%V3ifv_0k%`E{ zgVzp?C;dFfLAWb{W)>%R)>mp(H5@BZ0K!v2?!(7U9|C*LPQR{&vDNm9wkW@cmgfeA zfmCrKPeIzHd7!AICiX@k2QQ%%rCeqGXD>6iQP@{_%y}NBOsjTw?mVfI((5Edt(%A2 z@)bOm_YC0kp1~)It@-nvh=?d-AS-~%w4LkI7@3^+QK-VZdwaO85KL|uEXMjn2@uv- zzw2qOQYfyr?~2COqf`U)5K;I@u%f3NP#HAMP8bJ&NK{hP3CGA=<JBa<bs#~UqjE9S zx2DM}L0ez(J8uwxSt+5S#@X~CW*;AcO$xl=*bidINU|>u4(fT&4@VNHt<2a1+6V8v zw=TR3R^<Q?+0{$2U2m#<hXL3X%b+*UPavFtT;XQdmJG;G4(}|x@cqRsfoEkOUyza- z-5#OYw!s-4Q4ll$)EjN8KbY4N0_bCQRiMu)NDNaS)CeFv7#VB~iT7Ly#?t?17KF;e zv_<zEJy3V5Nh~%1b|U~15EH$HT+g?YH)ZemJ0Wuv1Rd)7h$9yT6=;wE8DFs}k*`PQ zPSm|&-y{1gCa(X1;8BsP7!FLeAY|aLNun7{{~71$!>p2GUvOoYk|HL*_Jf~Yza}4} z{1)&UH&QL=ZW0)x`z!6cX5;(M6uuEyy{kdA(3v~<Mfs{c;W}foc?edBj4%hD?}vuQ zfWYg~=y&EfH#D(F@RvCrw)y_Ey?$E&WE2Uq8{b-Y*N`@x4{AvcFKAA@JI5b1HQjWj z1Zgq5r?qAGB-J~knog}2#wkd`amunChArAIQXIIm_BZF*<uvs-jP6VR2hv-X0UlQJ z_GJq?*rX5~X^lVgv-XavCSY}9fRD+K!TU2$B@hef92U5;muQ~8a6W9<=gu$NGTss! z`?7jNWx@Y=1X^dzPig1xT1!A^+~b<>tISyTo6}d4_F^X`Q5mmDr2(EDlf9N&?~Z!+ zo1BCW_ToV)1Cor<jnW#T{5KR&K7JNWOFH3zKe!a=zMDN*6PHe}rG+V>DonI`-}kc^ zLwF4ah`|ba#%?$Ky^8J8bIfy>CCg_J4vPUa$@MlKT;+q~Kpvd`GlfPF_<Wj2IPpVd zLO(;;Tgp)erJ(3|tV-{1KWz+pPD{(z%abC5ktR~ZZ3imMi@`na6oIzX8GK%1`&rY? zJ$7jhAgWs9&8+S?5^~r-D=D7uza%M((gdO~9RTRcgxdjO6QJgf>N;PKu7U%5kIY3) zWj%WLQ%Gy)zlU4FY2@Lrr<>&7kIBEgarIOkV@rQa_y`4iq9{S+VNtMJ4un6=sjtqd zJBk$$0(Dx%PW+!q0Qx-Wss3Eovf&7T8+R(8fS$C!vilFUODjA4A>Dmd<&CE#WH%%) z<SRYwn}-u7EJz4zgCIGM*vSBKYZ6(y$+vV@+@-09vr=AAUziF2t=G5yhm=s45`=Dm zxCTEh0zlODi4{8stx;gUY?-OOKO>5UUhpD*=*Cw$w5}NGf*BuL_p4O_%W!EH9Bntv zV$#O7K^|BR91b+nK83}6G(uP-qA<iC0(}=?f)pg6yzWUDEV0JM>aT_N6SJI;@1*_a zNHpdy+5<vdmDss&&{{*G34rwyCeN(?URxH^T~DG{KveRSLXC~be$o}H-V1e^-}MNs z+plh@ZZ1JkblQB7;jqoiuakv9!=tW++4tXIR$t*REu7txdAMu}2%AiJB~CoNrD6K+ zCp_Y0SZ7^XX-IaS(0vt^kXYa@rTtnpnP~x@+YkLNCP0lYOC-hV1+aKtU6bv!ZRdU| z5JeLyo3eUD7UHn-8f!0NCDwbR-qm#Nr3(NdDfm&k11TyWi-*(o=`G6DV*G<yUKfd~ z2i-|r@cF&`{zIKk^+d;7L{wNYYn1`is@p%F7xfXQ#01R%Dy#jpr*<w_FR%bPE9tqd zEh#8@mb`XjbGEo9@NLsSE(nP=D>cBC_~h~M_=MMov-87p=3l8d)0@Q|z}JDY|I*J~ zN%?k#W^w>6hIktsv?#Ep_gW~}QvSB_m`N(LCssrMq)#b`(LW-;qK{)vA&8_f@~THU zvDoyWma)?BPx*`DGQ(O<gWhlS>vz?ky<bKjs?yxc(W7MVwWudpiOT~~O<soYMsB-g zP|rB%sd?h+B<zV!uag7N5JG^|(5}}ASjOnp`T7<IJa4PoTz&CQXwpV~dZoAnA@tid zGasrDi1@A-^Ktk3c0Ta_m?tXnk>=AuPJPETIu*$gBDWBlf`6`bzHAFvYar^E-ubnW z%;#1lr*qj3NNsN{R+1m74huV1p?#pJoFUZex{N8up)wXsfQHS-PftE#F$}kbf`k7c z7y_&Lx4*oS*O$nwR`6vU7i>uxb@60RU;oqh=Ztsp7=rs)B6sZ*KI4^AzkqLZ_EYMw zyvUlO+4dd*s8{Ehr-mzeM&M|vi3xJI5s?fJdBwDm>P37ym+KJ4Qn{O=(s@l}KF^7+ z^?kItyIT7RoH>gtxD-nOaQxCrhEsRLIy^qMK0poPA0}GK`Fym6jbsgy9OiV9AO#vd zAr4~*`A%>+?CwkQC%cv?DL3Ha{#%XIG3!>Njkw$MfPxQEfDm?NiNY{2@|H#Q7^;j_ zL179*T!2sIrmn3x@KTtPy0&!A2jci$?*oWO#8=q=*%-;_)8oK@R0y(B$;c9YTZH}^ zEOZ)3057+EAc2SqFs2p>y6Lk9A%Q)fSkD2Vj_4QuZ@)^eK3qRO3Ow!8x%|SL8p_XY zcEU$M8URhHKvHU2R8<B~i1ku+hYV>SqDhgAXOqc$3b=fw!lCW|M9{h<!7=@)gMqx} zM5ZJrp193Yf1bF?Ec~EsqPO4P6x^>lcz(l!)iBCj#Xi5O^YFm#uab1xOB!29)SZKk zJRa60P*$-w|FbH0O{3Ectc#W^Wz8*M;qQFCtbXrd{o76i$c?3F9wJmZG<bW<3;Gg7 zbwxJQj93oLZ~*xzG-hQvG%Lz}ZZjCXJG_p?pm^Ab8>y@ZKr-|vXI1Jn4vF7v%cj=q z_Oz~pP|AePl0=nRXRGd2Z$MC(Is&4ofGyK&=HvpA)s@!K7sz1);%1CIUN-+d!U|dj zK$N-Z<vdAp;wo{b6ZCvYgpCpNU+qwr@;ajDpNA!C5#$%u(nF(LI_xgNe1Ia{-TF9Y z#~`I|FbMz*!fPxT?3nj_l_vz{ru0O}Qj(REilu=#<BwBOEX*-0f2R&9X&n9>?1gTD zXK=139GYnK<DrD{HI7lIlzQDsSaicdO7r1;PN6?AU6CUq^Cb$BYg8C`Nrp^ZZK;$h zY2_)sUhvYcj`$D40R#XkGc(Y3Ki_D4`LQzk;ig8A1E=9$_}ynER%ZS8o@H{{wX)j0 z_CfgmDx{mMZ2RAUPXO!-QZ{e+`aCkt3h4M>lCrbN!c@7X1SkU}8X^4s%^o2VlBm2r z%-1z$q4l#%Oa0MT<Rl*nAgN_{JaG(fFfm68aE$e=HW(sJvt`(LmRh?k>-Ch0d>|mQ z=%K~F8Yd#;-S!tTR1X&f#``)LDz*LC3~f3UQQDrmc-8~n0zq)I#wr6iq_H>;hwe|= z&zrxKJZ?wmR^a*k3ogL;QXmJq){!S}!14nWMpYC2ND@#aV9T8Lw(qZGv=}v9sQ=qV z_m)T6$C=;UHa4WTtePo66CBQRyTzyOGnJm+!%h>~71uvF++lbSxXPdMMQKI({wzL7 zhC)d8hmi!?*s*wpd){G#e=wIbauPe80-GK9U35gVHw8(}+d$wCX2xee4e9`7Y`@wv z5=iHsmM&Jww^EQB92ftba7Z{<R7h+D6fF9YnpaV6!D0x1w)BbsOMyrv7l+E7dOywn zg)FEjtbbLY@!5;H+}sm)_eaDaiiLIV_yT9iQSqo7dCcCytCdzI#X4os2^YQi8|;PF z4V)$R4^7v}t8i1chop#tjAY}`_ku-Tm&;#N;{hhjPjWe(lj<k)MUqp>Og`y+aa1pu zN_F6rAR{>*2@6|0#MjVoO*r`b0U+F>#iL2$2>|}<bs{l49YvCOGW6_P(zw@#Xkr+o zQ4lS3IIyI@!NbzucKoZ|4(Xf9l!P&`;jRdo24KgGZ13}>T<aJ$$U|+0JeR!y_$#c} zv*d>~7gFTs`fmvI#q$_W_JLKw6c2fngB!);M=`GNR0`B=LybIPnnJ;BnO1ahGl+TM zGlyW{8;psMn9RsY@IzG|zFKBF7)zsKl==n{bq*+RfUQ=J4FG8d3|M6n<4-fYjD!t; ze`)#$UP(3W`CaXLZ`sk6mkptB>8M`uVIfD+mGYEw0l0QJWZP+r^?}XkC$`(2K6L|< zRYP>`mVPX=%58~GUi@W51okuCvKxFK=mi)3-z<y_h`ttJ96nU)`^1Gl&ieb_zsII0 zxB>Z#9Cixp>sa%?JD=n!SfGpbuBAj&DhdW=;MzPHp`3o377gCblyMj|gaGVET$9u` z^N4#(j-gqLsr?)R&6AE+FI4TYisV;;E)tCP3>XC*+J0YPa-bvXwBGxPWYvhBK1(*( z)+#tQIwJ1XZEZKzptl)2bxcYlB=+7I3B3meO$EWwud?W=y=7m9vi%;7{5ry;r-akx zR4k*;7b&G~-C|ZY6kJXX!P%ijiPf0UXymmNf=a#>o;VCc9lWN36Cee&8+x*#?VbG) zodT9a7jxJw6w`5fPy(F@_)F9cIM?t1iey>gu%gq`NjmZAq4W|-;&NBmNSGln4oJ1q zl_!Cxh<1+jr156sHOU|Cg)l3jE%jgTe)3->E`(1Skf-^=f+i=Mwjq$$L16@yu!L6( z8}CnbzTu<f-DKl`b7I@87O+4|wMCs+;j581ETctldZ(2i*&deUxcGhh^YT+2`7>wq z0ezk67j@-`qIUd`q3*1CkrNE&-BA$O1lnyI(mOlk2{mT%<cTpiky|ru4RbMMWE;@v z0h_Vx4~XvBVDk+Z`r`S>R|=zRJxGezv$)Wxa&6I>!ux|QV~eG{K>&(6IzJ}yVwZMb zE(~9)o_YA}shWW2p;O8sBFp|WBanwX#Q2?T)(b|QPkmpCej;A7Kl((vTN{zOeGYae zJ6%#3S&S<r`|;?bd}J>V3_*p_IPcyStZnLHh~Z~5UbMiwYYGw;Inz{!;m*mfEu`f1 z-|W~6)<3OFi~5SbD0Bh<1nPBe*)<f8z;z3FCDs&9S{+j9<4`rH5`{Ub%&C8v$jHbJ zl?h?j*;I4>-u*#*Z6a#@3*$h{Ji7E4I;Q(!VFrxHK3s!w+HYbg*}#Ie?mZo+n*8Ws z1And5=m=beM)=85t{oM?-K|)!vNV>L8hnKh|2y<s6&LmLH2mUQ^14!)7!u|Wf{`}8 zNPGWP^rWR70^1qld*|!#FP-^?Ams10>7vmbfsH0%N$uPj^v%O4r?(HG&9D%`X~hF# zSu5RtGTDLK+xwoNS=fOS&Pzce!N>lfq}cfx)3@siLv6Pr1K;)EMHk@vJO!BO9#iv# zf^%l8#<W~DWXH*WR>-MYK0%xAHWO&no938z-ffrcd>}LRd=%ZOm}Fm8#UXvXL3kzH zV2$(44vp>-yh?!O?m{<y<v0vmeOW&KT-p*HK`-|gP~-`FD9EvQWNTxq#)b<vw4wqk zW4<6nW8co7tgY2IP(L;M!Hr$(^e9Xe&BRWS5(1kJ`N#^0y8U|)DR=+CMe2qH%j(wO zS2K;bAKy&36#FO49}=a2BfBj>ckoHcGO)m=>*yU!T{O&f_NWO{r(7MkbC&jR&dr~1 zt=0liL{-(xCjGkvus)Vc#G#xD1(1OSJ4*Smnke8{vJ}YMBty=p;l=}8*QFLfCNTz{ z{{4Na(-J`n*zs}JI@Z0y-r%ag7iJ{IYb?bL2PI<yhI!*+cz)xUgWj2*y%YHpPa9ws zTp^9tr8g)RwLECSEVA*+OlDUli(4-u9&$Q(c1@XS4BE8NJm5A>hu~;-grt;Ykh6&A zf6Vv76-evH&w?%PW`5sGSjpASuv73Hn}RnvRgPr6t!1kUbO?AiWn^wH1Vj9*YX$#+ z9j)Mio<~PeY3#q(;cI&n9YMHw>RS!!7{!1pU#g)@)=~9m)RFqN=gP_Y>M8_e@`}p> zeIUpJ&)$8;Yn6%Rrftct@s*)K2=m$>o|I;(+{eFv<h95A9NM3@ll+HMuM}=sLPJg& z`hYK6E0#E4Q(CSe7=#Rc#z{Z8grz^a)xzFc`esE6uz?-Z)f|ly<m<T_p(l=HBewhX z{<AJccV5OHEfHEWfYM$F5E1jvU3qKTeawjDtrSYJNu8UHdTSW+y03)v*X5T2e-7vy z5|kk2i`tMU<vyrO7l|UjC9L|ACX48Z`-A8Ry_&M<h&Ib)?)4M%a#j2wbN0nU+=Mmm z5GwpR5S{$#L4H-3=C`L)0-otT2W7SSm{U$KPq1D(wkwkm^&{HC-0hLQkKB1c?mKmf zS3SHHqehA1aD^x}l<HUT>0G*l<S`fhZe4lGU<X2xf+Uu7<nO#eJFgDf`S*VyqV}64 zm>hnVEU3R^+FJ%Iqy9YJ=noUez6}zgdiJHBrE>j)2l6DAj?BGQDTCm;rx0QA)pq0? zrkDT4Z-{Z_*Q3pMetKY>_Nz-A`H%+>S=-R|i{gKJOP3cj@6&M{U#b^!*}wh`Uw?CE z(N!Xf7i125dodS1dcG?g^|lgy)oEvnTK9yw2899W#Dh7nDUFo-sYLve>0E7qCc-G1 zJL9TsdZ?G0jwP<#!aeslqdOBed2G3m_Wuexyo2o|Fd_c>3D?a^r4K-_zy=q7ycs7L zUlH1e4WFoMAjJkx?+iphJ|%01eCXQHM#_yZBDmm`FKyRZwp-kNGZ)$l#1f^}$_yf( zK6!)ZzZyzPHUi4iFiOecz7?jWl{>D%`$uL_j3Kx^P0@2tWM#5$sss1M#|#JB{91Ei zaiQZbPQNoBL1sD{+@Ng5x5cDGK5ylsAR$)gwM0!_(Z#)@IDmaP;;-lowFCug&@r_i ztkm}8uV;@`rNWt*fZ8XH-XU6J+sk&HfV@$9<x;C~-1EE~%;GNTx#&+>bb@1ZKn%K0 z2BAgA=9_To2Li!BbvE`%45Kd3biCsFHGxk@xfWA+a-doQLyE9GnzkRe0~Y&aqCX|F z(4U6?S~Y(bk5!$y*2joU(+&a~*8H`X_k75EV2s9=4|$~<7ux=ny7|Vf%gSOkrqPR) z-gve3hBm2+CoXjS<B`}}J^*#b6Nf&fX?+4BEAY3}Jdgi-6tDr@NA4(EBW7k$2i;;~ z9IOtyNXih7NigZAq(O`T#IUwr!^m0SnY{h3z=Jv#Crgk-Dc-EmuvtZU+eSwP6B46d z?;n*%Ax<Klt`nZ|g!ZiiP#(N*r^mz3^=c>)>NFw`hnj%8C&|PL8rky@9Lm&9LARH# zNrI4_2VqE(rpJ@LeX><Mr6A%+Pbf|n_<=V3!DmWP>^bT(mxJCHs~-RUw^HAPSn_al zDi#@th4)z(r;O=yKSmQu!1RlePzP$h-ScP&m75s4V!XF7neiC8C^O0VtkZPzWi-jz zrfx(Vlljn3EZEayyFsaC4f)RA9t;0;mJ^nzP`-!q?<9LrMBD5Frl?DHSg28V<X=K# z(%twg6y>LH_yfz91dyZG_0viKq~C0+w9{uc%P^o`Lv*}G$)F2Uj;15eDe+Wol!bek zn84f79o-Deq~kf@Q)6iE-RY=z*m`OeX<8dp*ZzB3egIX&Q!S>A`}A916c<`|1BH?M zaYT!)yR=EoTRg4@0a{qFH)(f(e)*50lV({EqG4>pL6`e0J}lb<Ftg1^Tg4m+_v*mA z!R40oF^H1Q6^*BkYHGQEHBq85BwC3*M2QucXuQzOK^_oN{B_~R!}d{K0~sH~mj3MH z?Wgy`ibfdE4D^-5L%aFpNSAyn;0^o8u`%F#okIHL-%Z5#P)V=66Eg3l$um?QyJ6^q zlq8S}b7X)D_J1T@bwHEf*O!tJgV7D6K|(+}M|XEhNq4t&NsJBw>27I|jtPQ<bV!Wu zkW_g0{k{L}pFMl-xu@^hIiFiT!*y5kFU6w7Vi$?WuLaYJ2GOkC<IO+^*-JQs*<oB> zk6It>wlc4fNV$Pcg8%%X2=w-6ek9`V`T8T$a+mD8->!iaX3F_{i7y#9(+fhf(Az1~ z^vQkHaa=b+8!p(BuiOx*xM(>4hh0bT@3DaL$l#Xv@K-rPkLLl4S9E#_GY{G7n-V_# z?rx&Gbhy1CPilOz)Ob?9X2X^R!GCZ5T>FzRiwzv>u}a`*1;3d`cNHl5+kelQ9g5`- z6`%mFO4tOH6q#7b4cRx2Scuz&VjF1CAzO1Zymfi`%|N5uy~&D(Q<*}0dSSIjT#?Z6 z_`JUV_PsdE`(Bf$pr=`(fKP#YUQJi=^(Yw)51W3cN`djv^Kg5?kgqiGQ=J%tsu?a) zxgpX8TXCQ<xnm3L`knpWh@in2FeFpTA+ja>xH!$Mi_?|5(zfaSBpnMEgUY@18^YkC zWRpO<pnLwuHszA;N{N0Mxa3BU!~5SM-`q<q-iLP-J=DKpH2$md#-h|#DwI7(hhjRP zoEG&%Y@~u&j@YJBWQtMbnUKH&Y&D(lp@qt{+oRt5CTgL9T;)7G4u){u6u<~PaBze* zR>>CX!5h6sDNPIjlo84kX?$oBc`z!qPKqxz1w}FYvMn;8S)4hXcrrcU!h}z?FTd(z z5>)v2Rhm0L@M>z=j%ATpZpa7!gtPAx9#S*=P2S)Q#gr}p*MQ4k-hOkQeS?0m!K-YS z<CzJFJ4OEXBKcG>wu?9rePFnjdS7y5nx@f~42be_SXU#-W5bJWv1VtGPha-F<<k;+ zGw7;ZiZw9*rq_y@>Q6sy@u;t?#LgykoF3RT;hSLpJLZJaqz*)5?y(Tj!zzZo(^Yf* zqe8P}t4o$gUYY(jj6IsDBp)R1Tx~2=_fcD2Y*Gi+Uo-qjc4VIOVw`AkOYK+>2M3Ox zoh=GGmb$7VNr<)xksH$BCm&yJ71LfJiFjp5$SS$QU{D&Ouqc!>;lZus-GCN%BYU7L zQQRZ9{FYQm=-|^|>>E!DKN1ynYWVIej2JHR(Km_F?n`#rZP4@r*7SsE0$1=MC9<_< zZ6rU3&E*tZ=Ln}<1AI{>LD*x2CjVH_$4Krg%8@A-pFh-h&5rcsF>=CvaNdCzd-UDm zXS5QFE8aHa@OLu<>UgPcY7<a}FP&4zv`1BoTX5Nhx`Ti9yR|b{(s#j|a9j;Ed#LX^ z{6ai4@mO!QU5i$ig&fEz6)!h*&-^p;6_OPm-FsennFY28Lm7rE=Aep+%RrTvFWE#9 zi4le5v*7bi%PdisA4514z+)h2)sB=`T%}|So+*b4qnlZgM2>V#$6GU2r|&g#oMt@O zCwxcu;nx70->Rf6LO=6KfmRuE((k#*qcuw`NRJ*3wz*INq>0HUF@R;c*%w*&fZb8L z-@GD(wWeX!2qi=q9fH?;FH^V_z;DU(<iLj_%kQ&xoNoU(ail{-rBiAEom%b#0{>>y z`ndO1Bi>0soDu8bf2P8>b-GuhiWqoRbXUVm9xY7@j3|4cGT4*~4IOG$vV+#{NS_5; z%wFuPuENh_6KM*00_YnQJCzGaI%*$>M+|nThZBLn7vAkUn$JvC;Ka#?hMr2xh|f8P z1(%q-zcGF6FTmAc{+5CehaDQ=#Wu)7PPz&*`h^u+*P1Hg71EBK1N?2UW29@2-1*WC z(i=t!|4->tc~={bXjce_bx=|>V`p&ic<;S9CLGOxx*<7B3xVY5cD<yM2G@fHA?w!k z=b2aKTnL5F#BZ0AACI1yrugKe!eT_;xrf+<bSg;|uW+Ff>NObQWvRd+({|YcO%$1< z!atjgD1eDp3QGG1vNR~jsIMAv5iH@zQ=K_W6?v5RS&)<7f6do-`!12DF8mb|*6vlB z6>#ZYg5(Aj8L&?EMCnRX*NOM!b%>#?`%>2)-P*-=_8q4W0My8kwBF^rbMWue|3AKt zS>;qxbOzz&NaQ&pteNFKLe9dmc+d*=D0Rb*Qz@f`^z(H5g+FR;$)en1TS0wekOmuP zrg@?-CL4KY1K*`N3Dv2xPc|esweuDuBYiUeb8ELJhjI%<JX%4dfROV7Gao51u`T&- z02^fU*N#Yn{XeNcT*B@4p1;37A=?9=*C$5rCH1(M6tyQrrxk5Cy4ZaVC_3J`PtkJ7 zm9LpjLlBYB5!ABpk8+#93wtW$yI(};)Yq8{S4QKN?xy3k*>{IGB*>^gqUIAza^97R zKkd!|4JhrQcivA8O&p0I?Rjh6!zPGC7=(L2pec}O$Dkr1?+qVq1OO+<;bQ;(J|@Nh z4Zy}YS1x^9tAtu;-=Y(uHHqHL+lRDDrsh(PXe112+b1B@N66ig3QU5ooJ`_-KWU8k z%>wxRj5`UdYRT^YE|}(Uda3W|YUT~CA1WXlIF^h*3O?t4BX+|<2%ca7UTrwHo8y<z zzGp0<y*sOMfI6|e0maiqlMxcUw(wpjhfhuzvp|RwaIVCwe=vIpmRJ-{@RBbuEgMP9 z6$&Q&hN(v}vUAa&NN&vCII}=9RT0GN&P%i*ER2vk@&j+}&smtVF*$he-G^2z1Uq6U zCCv!IPjb}ox?`GEZiJjI-y+n5z>)bp+0WHJgn-ry0OF$INB7qZJ)!W2F21;yShTm! zOmAE`FEX#hU1Sh3f3sGu4^50Tm&=amQP&7PL9&M~B5aW(A)3nc^A~u-rF{9^6Ha3E z@#{Ey``R<gnm_M4N%6quYJbho*L;kbi@E-yCMMbnmk6%MzlxKN(h1W!!$-oDiNxx7 zg+WK;T;GP;-Xq0EOB?3*#>Jn$XF<YIl;NG4a?zwkaNC#*rR({|$;XDFzh4D^z8UeV zLV{s{$o(6fs!pC@4*}k2NL8}J)w$|aULld+^_HRI-<3|KlcJyaq9VP3$d(R7pk1f} zxxYSnXdZb{%3b@*$P9=sC6ZPHpBNYN<?jTt;xc}gn+PQ^cwpvYxv~nfU5gp(VGgJ8 zX9GgiBBo&?a67xY-&=MDSwu2EEVAoZ=wA*Jo?h}xicrC29~9g^F3ns#RL-kt3bCik zZA^$al_A0G5fuKWcH{M`&)!s`1lAP3o(3j>untCE--ATbh-Ii<n{^T2a*MMHlAlF= z&qS;UVMy#bR(Vy-A1|*uld{PCDVKy2IENVrLnmZ#DJBdziT8q${U$ydQ@@|m`_3^O zF<M+wq>ZGRF3*3(iLa`elv7OKph^c#Eh&m9u`o?RzOlq3j8teK)yzqR$?zC`PyBdl zcQBq5tr%quo6$g%(R|jWZ+H!^ko%spc;@wDRcRLrMIsN4z+`~p+eNMo6aZeI>1cr! z{bayeBve2S2KOaIlZ|IicynbaONGh`tOf~IMVr)v>&sgj$a`-D`oP7z{L_$K-VW|* zVJ#!UwSBgi#qWnHFP#K|h}-M)ENdZYCKdPy2Xn74!@BW8gNl$~P4r1UBlh5pl~gN0 zD0QhY1UXzQf?40>L@XK?G-t@e2mh!8a_9B(mzSQnByQ_bE<vy=)uiD(oawJed-j<V z+>{}_m{P<J{*U$C&Y+s*tLQ6Rjh@i(=}{v57GeK$;FTfowB8OE6H$U-`LN>gOH)Y^ zTQ_f)$Ly5wgs(0neQx`au^OH-?^T$hj{?=E=e_F9$Zu@_c1BZ8l(?Du`U4JjM<cL* zkP?)ja0(p6PZPykX0OqwzmQ3aPHm}CRumZqFJs0Dv?2(zHlgo<DJb;*?@cAYU|0;q zu`9IKe`*1-yM%;Xq~u)X10}^S0kwZbJBI@aWs1#7{oj9?9~6m^N_p9k?X|n6&_88i z>R1x2)kE+q^81nK#8vgL|8W|R+`o_N6x_<lZ5el5`}JQ7#0pHWS`3yH=b9!_fE4cp zs5oBY;9qWjqXtMn3&;;~fU^XToV;aMauK_v-wN<Ivov*p&%c8I0wng34E1*D=2nD< zLQuBHpcr0kiDNCk9pYg`YQZ;_LRo|~88CVaohaNdOvp`1*ZPcUb<k}ORVMK!V&rYa z>#UHpG|Wxy;HpYT4O8g^VE!u{HidKXL35^}KTLKILI5$8g%)QvMM~hI_fIB~{A+qm zm8)vzR>8=UqPNR`&kUj?-T6JUzWTiZk6XBVio=9|!#;%rvh8t>QDFjC3nh`0;-(lv zJ>0#-2Iv4s3a#W!)M2LWt%s+~;fPICl7O$Fr~*@39*#rEyR22$t-ks#4}6?W_LLd; zCQg*)$i<YeHNxqtyy=Q@xGE%>i@)G6%bCHV^U7iij$*5<ZX_wx*a;TskTJY*g5FS| zmPSR!HV-q9U{?WlfPJ@dJJ2mul8_>kAY`9z-s(^m^a0+wk3Vb$^s}-ArZFrwm=b#! zU8d5lY*U@#iFGZ47<6<nQAweL1guOHby~nyEuUGWG^a@gb&F=`b`UyS)G%0!cFWk0 z3aLHK_E!oEc==7ID`i`4s79AMnv4*;o_$+2k#47$dIv?UUJJ-WSm#=W-W3?o?(MFE zTE0r)@K&N651@|Hl-F^^%ay)n2`qXG4ceqGXyDLS0Gtnfvf@S!xK%Mnj+?-Wb&hlj zuOTxrDm&9a(!Bj7gWnq<CStFVYA_4?Tx?&fZTU4t-zIh<g+-nYOuL(|2112m9w{H; zByj;IY<-p-jG`wFu>Wyy*;8O%M5+=xMy5Eh{OqQ5)*ISfmoi@HTH;ITQKq*sSwLuf zGxHB6Wat~%XGMC~oZa0Vk6$;5Jum_blH$TwLxD7I7vKtLCI0t*j1m(s-n>DF@X(8h zaH~@YdX}n~>V?Y=fpqmhB+f)jwVt@$m8U}G5{3>PNcuPPuHDAZGnkR!-K6(_;9_{y zOR!ILLz&+I?Tbm4EAb(fL%P7j3(}x|qZN^Rr`i#s{Cv;KFayUS&!E8}0Av*CEIQd3 z)9rMp2bqQ$^DM{nCx$#3vh}55#$LU(Yal+JclhHG?ENn^rruT0_v`YBOYr>OS)cIR zdV6t08!71b=*92l!Fqw^lyB#MvV;4|dXL=C&~aHZzk0={>CWb?S{(E<8Cl@@O!MKa zBz#?HEv0d`a(+*ql0t`jc=^YM-j!HCazy|MW7I+#xjE3D$TqkRxmYyPr^%>*`3Ldb zlPKe<&eilXaXX4*?t4aBh3<J6)=Um(E678tFy*dCA9sa}{);4p3z=p#yPU_YktNKJ zoD#M4us;7U9R5Z7!6S$_pF!&F0Y{*HBaqaGH;Dfz=|otsjRY!b8`OYUYWTpd;GJ+# zhuF4<Hsi{5-WOdtc9%9~dQkp%D$b~fZ51J<>e3W}DFJmZ!R>VS*l0WXH{eWuWfHve z+Oh9OW5#P?V{#&RU4FFSREFb;`+6iqOiiK!-m!`oz3J3ZxSD_hatF1}CUIl&saa^} z3~zG`zrVlp>5x92JpIXV+`1qIo6(MPM+7yBe7)Ag3M}#g<))qn6R;^`9NVankPx|` z?2a7=WGy^=Q!)H4wy6j{D80mL!0d=emEqV9fVA9>sdzq{t?E`JT8!Axf{hrEMQQDa z^3NVvcXq54;hOLM>8)+*pRQuwO!Ci^d_<&CavRx$gJdfM^2Ic(2A>EvJ*AcUXOX_! z3ERQ*Lu0vKCqvW`?G8i=!+G4V!M%7sh}fGEn&1~;tq3`S`+BU5)||YSJ(FA*Sq}R^ zyll4KeYH9hli>~jfH27*9rxPC8M8l$J$#^;)Q?6@fxQQgR2>K?#Lz+fB>uncMhb5q z)Z7@o#Kn#1<GBl_6lAvM-3_5E;AD5+AaMt2<q~*#RrkF}RVd4y#pA>Sju}w(Y^e@h zW1)O|tb%8q@({72@8IO21L1?G3hh`ClKV%v7@T*mtQ+g31Z*BOR{C-gW2PR(unc#Q zq+AN-89kE94{a%0X^ZwxXnm384;0W!;uI$5U&2g^29^JN106=yx2i*EJlE%Ho*J#c znl{hHFMDpNJUOm?wyD8)Mv1CPG1aRNm5*$cw)FOJs!Kv#N9V3Rf^n*Y86bGwx{#uO z=8RIsamWdWd?mBN$O#yj4KWqAOk$e>(<9^WVkMZ52p-r0e1yr*aCIJHLP$&A&1A?Q z%L{#K6<0UhsMDjs``(<0to5ci;;60f%i&~h#Xx*{QxX91S}-joic#<?+9c!8VXnFc zv{zfHdY2kKRj<-*iK!CZdB^Va()MPW(+#8OFE4e&P0_^Qs9xze+zdz?9bmAbyfim2 zyAb(VNhs7rqyoA4ukRxg=hw7}fuO|hxj#G<G_~(6p<fc8b>+Tjkg^g<ndPyf%Vy-& zIAb7@%);2Bb#{8wPs{e-Fx8RTkIN=f@_E)05%Hqzlzw1J!}v0Y4jiFtVhC4|!DRiW z^@pjisKa&B4zN>+Brp9%*)8hx2l*je<PSawLtBg4mD{%eGn7sjv)G_VA+R#*X)p2X zhM!qjf^a`9^!y#Nr)hkMnZ3lhq_(bL5o$A4ctTfQwKTme6?T=N9qHE+3kCBcsTrzS z?F<%$ok3dzIi+DM<aNKDe-bZU|8}~Q8nW8^K0a)eq8Ra<ZMsD%(I%pa5Ay@0@GI`T zRM&s-v^Q&Xvk8(bg;_7nxZz?lAR=n;Q-e(v!FMmydI1PQf3*QwPJY-#F%hxB4RV^} zS+FPAm%ndL=}}U1W+r7EU5%Y1Kd3Q0C_>K6>Ie)*rCcn#rIn2z<pYJ5W8{BrlA79{ zX>{^hm1U-;`S)kt@$=uyW7`|F5Tv-+2x?mF0TFha&%@-g119&d*xMK(a?JWoyAA;i zPDJ7za*R6V`g+bd%ilBgL#Kc;wLO*tJ^L)6bPdMVW1utwFB86|CN5IV!hJR@6hXxR zTq@eZ`KW*x0N0(SD8E9RsZ;&*irhxIgiD$b(t|djGR~|n$vS^d(8WFtO<(4I_iu?p zi7<e(VUiU(#pG8}D~ReC6RtOJ0&Ogr8?O!`{^jV<hQu9~1<5&NK2wNmQ0BNwG_!vg z?5C>>Bc$-3>mzP(sLYIyL4nihLNQ4OS!R-5YA@CQG3!Y0^V!D9K-hUpDOMB<pTeDG z926j<f452*AN+PoL?WqWZD@+#3^JxQp`uSA<CcEP{<%HL$eE1m&f9Y5$y<8J{J;kp zN2JQ?Be+!|EkY&3A871*e%SOD;;mj!NwWFZImw#bi)Yp4Vn=ZZWK~ngNM$p}9>?;Y zC4ni5sddqixFve!f~JsXWsvNv7%WO1rdmv0j*3^`DsZwaMg`9nH(ySTAiBVx*rbxF z{$6gB5|IxG-{-;z?=}XSY=#-LZ)1eXg;$i4qFeC9CG>}gfm(>z%1j4@WIjYMEq=he zwx?BZCCxMM*ubwAK*!={(CU;k+cmFx#rbUbY>p&Uqrg1~VZIO}_XpA?x>H=3t;tnd zZdiz{cYrqzb!2{_JaW@IKU`=>Qr}tLa*i{`O2(R1%E)7bi0}$&@1hF4yD5Q1TugTt zn>_z%<s4KGQa<wL>1y}(<K0jC9R8JwI!Zke8cfORp4F$jfA5Tr?mvI?Ty`#v9lRju zSa<jCQW#5911ZKp@HvsgB7q8IhNQBM<{$$eC1N`UJ$3_dlaw7@7!<;8IKX!C`ef-! z?pIZxn)jAY*}5R@p-Qle@0}lh%qO_S{_U6g+5K0MT>3o@&)FS~>6I1s@L;M{JG@Xg zO=P%RYk0`XaSVR4svWxZE|KfO<snJ(UQBoV(9qnS_%O-E`+o{Eh$45hf9*%C*wFAL zG(BQ=<vuxi=>R`88KoR~q_{QlImTQItQz)be1)Gw_gXlPUb+CS$L^rt33Xkj=sW`} zTZ0XrOIy(L$G;fl{$>2w7D!~Ihg{o|PH+BbY&Yqi>PyF>|FR+h>SOghjRbwg%_dQk zc+>|;edqeOV<6caz)5u-nMB*TBdA_+?7{nkN`B~K9H$|))SeIudl_0v>vtgQDnw@! zEe+Xz&1k;CC4Yd(O}%1!MXr%r&4F9Yx!#@DXX(+}J*nm8Df*VX+HGOK$1Un=>V*W3 zwQe+Z=NB?(K?*Tax?;U%-NP}-I8SCieU+_ybNia9GzJ*oHQn7snzY!!(Wv{kqqHIN zLzG0Rjmq@sEM_GB*eCz7fW4vf!;xMdI-0d6=M<;D@#t<U)*Q{XK*Dyde7oC8-LHX; zyR4z)fR7vn<te_(Hm^R5a(&@0WX}D{5>+;DRZ|^(R3Mf7N#g*|=K9@}*n0_Sdv=0I z()NuN#2m-j-bnS}u@~<TTGQ{0wV&N!Wq7ymwPIPoDW8XcggANxP&d2l$Ub^I^Hw2@ z$ts$X2R42aZ(zIi*#>g#YqdY~%cfYv=XUVP+R(;<jC`VBo*$KX+hQF)(iDw#KTns$ zt;;+9AQUq#C**+)NBFQKy(9WH{by@@!&{iVnKt8h8TZ%_{o7Pi@{&*)m&}*7J@~k! zwEIZ!HA5kIm%-p@NvBAjSNY_1aNs__VHm@Vt-Qn!AtX6*8O-drn=oT^@Y1<}`O=)y zyab`VZYv3nSn4zW$@2MgPC%Ci1{vYK;GR<K<)()d5s8PvVXH9tYZLMY6Y12gx3UQN zCh}Z%)V32to6)68z)`A>oj-oG6Mb#c*N0$>bxAq9&3ndEK~o}eYG_LlP(`?19Uts` zee1Xqd!{fYuh%Mry@*P|Z({x&?Lg*Hj9MxA0sb~$!a+K7=;UpD7HmYZF|3wr8q{oQ zW=P-t64tw;QD1VTuIO&M%QYc%HFL!itZPx;Yu9ck0F{2!OG_Uf35w2!o{wvvyzqSc zDShh)<}F(z>iM5Ty#&i6!*N-w`6h7^ej+6-CyH#BU$S8En*_JzfR_w&e+s_*X(Y!v zth}uvAGA93S3@3rKC7>@)Dl2U+c-5x@n+~l45a=dTZ)7t*sNFNMP8!!Z=tb2y`acP zx@G<w^OB2c@BnLAwx5kyOW`ZqY~wKReXZXbcV{tna4NSU-TFG5)^z|83qN=GSwle3 z&B1iKzCnNHPLz7$V-JM>WL~qiOo@#!8crFx<gNGG*Hz@qg;Y~t!5UV^{eHBJ8&hFe z`H5>A-Y4)XnH;s;tC~tv;tW`do!}UE!1|fF)$9QM;In=srCw=(AjNmufO0LRIhcqB zyerq4IKXYQ$nO9s)+<b9)a1YlZUbFuma(x_3ra8`NfJ9YPRF5XO}sRZ(YH#Un5A(f zL6994c&tKb&={KO8tTAcwX-TaVo(hju_93^k;z44h9{-VB_$0!R?w}<0XY&w;$k(J z33YTbc?Q<)%s-7kjT<|*v2z|=G!__xF<{Tbx%zgpz<=&j-RWt`DSa8;)33y+<_PZ5 zalzyfjP~Jl3AavvE!wYtF|$TRPiF0~7-k(C>14^#7(C{Xc|1J~Cew~4F?o{GsMjNS zhcrQ<Po?j>jb|j;Te@<;ZBOH#YAVcz0VBM=TPMkFWTl6?ok-g45BqY8V@6Z=b978M z@y0lAma?}iN~cF+3!r0~;SWY93D?NdHE+iK>DwY;b8aDRd6;Yo*d$bP)6C8&|Ic&H zr#quDIQbGSl)L{d%c~D08*y28nQj-r%rmXE5Bz<tI5vcDa>GSFs5}+*<Co^!N?pYH z$hG4bUphPeFDbSdag}l3<AkTf#>KLSv3uzec%JE2WmgoJ?j2epk0o;*9u$FH3i6C( z07;GiYLAYzce77G#<wptVf@J3>j7{lPS3iIlNT@6x3qO*qj5PEt*Q`r8)7_RIIZA+ zjU;v8X_;&Ou4Py$hm0Y53jG21g1Bifc58Y^TKxdY=sUVX?_jrh05N`XszHEp5%QI! z2CtMJGsTi9n}g!X@A3pFsnrHg%NQnHJWK9zF&-J;ka+QXDMxYxwxpasL&wyY+U|rM zy@907VbZfg@O%6`;)==R?|^!q)#!B@hRSSPt@519o^h`_@;;d?$6S2{QB1zGEnG42 z;B&WZzpZWb{8g?XlIELuJt)048tadf0vO;3FgM52`NIj5Z6IaS%NXzmis~Fvr))*8 z;AU~ah^bH-7w0HAD;`6HBRLLT6=B&YF_IZgI~1*!7ceK0xwYN@w37tzV<qGS;V?%r z9!NGE6w>S3vQsutt)N5nr<i|NCD)xl&o+&TNW5$V#coqy1yjDrN{SD4_qAi83023d zX6KsI<%gF6=d@HB#&tkyG!4)bJHNovu$922y~X@%5`<gfFsjmfK)_Xd@#Ne{5jLI7 zuo}E|s~3>w#-O@^e9D+l@uI!Zh#?~!PV`pVe+CEhb975Iq=c$OcmGW2bs-4gYD1|l z3upM^2GGhZQ?k%C=<K!NS4o*7B4;<VeW(<fC<SqurL_0Wt#wDsD3QghLlPi#s-iB= z<@YO2yp9{uBEB`(DfQBCEKpH@H6W!m4ld_kf+<hIek5rOU@Enfl-)+V#m6EOAN7S^ z?Vx3z8*>BU6?xjVIPb2fT4E?IY9#Y4Ms`*IRX+1<8sQBA>&T`HW^4`$Mi(znQ{vqr zeBiH>a91`J$th*sR6rsj^IX$YMjAAnGCBVh!|aDg!Rw%yh9jhh#+bC1G3PpJP!gfC z1NR9nn65I1;!;DNTjR*RbbN6)D}Bg;DuAoj(aXLJOd0<7u~x~FYJi1W7sP?(Gm=qN zSK$pnrj#ENVFcfNj12$QIN9Kh(D5rmE#Za8xn@<0g|zbNos&Rg*Sk)7HEM%={~l@- zXdrTWxa$QRd%?1a(w7~4YaJQEQD51vV_DTH{KH4`SeJ*3fM)2(&e;9R_|r6f-Zu}i z(A8+LYvzY4Un-m!jZeU@WT>qCwb<WBwgbEd&XOhNhgR#7@0s_a()|gcoSx$34Ih8c z4v30cb34v`TD_2#FNm)D<ei0u88E){wTUA8hK?%AdZ?WsKD4mW;{pvobw#}*9WRn$ zSHpHdk&V?roTqzL`ez{2FMSnP?FFDKW;DxeBm)LZ(l5BmTiZ0ZCjSGMXOZA(^P3}m z2ZN{lK2c`JzH#;7?LkSSFW_S^WGV^uO7ejJ<^NrfcKL`r$1gHtjHU2ZWSe2(yNJT? zrloH^7~}s+i0~Q@)am?qkRQWF8FCC^8^p&&{J)BhF+R_?6`Qc$ykd8V740BKHWKW9 z3FqIy#6*6-Au9isyQ`6fx`~!J4alx9M8464n&oz9Ad7TJN$@maT-#<g&Ew1-&fcwc z6sK<Q12&``75S!65o$L*LPpq=a9lC5_-n5=lq-gCaK%^=N8E#h#tuE)hlT&HT|tyO zsK?`ApyQB_$v$T&z?^V65^ST`Wu|GV1U7u_X_np0fQ5|j!8_c&#(~6*mdXNNhp!Rf z)Rxjr@}EZ87OeeTGF}i&esurI^-WI?;<jn;DJfX%_v^{z@O5^wwgr<|<PQbO4zqfR zQl57w+!~#1d<=F{$?u1X<O3h~!my|cWpR#gmbH?L&llM+Js)lN!4A^-7PL;n>83~z z4N1{n4DHc+&vxZYLIoX+r)?*--7Rd+p_&ob-THP@L)<WiBl)|=2~-lvnTUeORt4UV z@F*oO5K9(w*FlN`-B-9xJ~g~#8mMoqBr={+O>NPkG?xkg#<z{TJ{H)*w<b?z8fFL$ zkfe15%v>S;VhczM=%3+o_2DhO>m%4O(u8yk3LDfvwfZ^p=d1m6YImum<aR*ZN?^i% z7{>H*{ZmI$n`cK!*sInnv*6=4BRrPR71$H#dtwZ<2h#jw%$%mLyX?#$5;_NAx&9qT zO>eU0#>grd{bN7A=EIPR^3nqB?#9*<S?EV-yrLtn20JP6K||!F)0Ykj-FSaocWYZF zBYRY^Vou?=+Er5}9=oj9cq-zOKQ(4n^{61nM=mtjB`+DCXn^a<0dW*Q7pwyo3d=_h z?w>memsYbd!X$Cix}{cZP^k2eNO8Q|&(x$3nuLS%R=G{)f*>wTyqH=DsAZCJN%IM; zQcFz;gDe=B6g_ayFmWX^UqXZiKPzVHK6QOA`JhZ9a<60)eGYVM3p#{f^1S!nKBP{% znz7*AuMMcTrxQ3ZdN}BQ)~naXs8uA?G9Q<g6zDS7Fitn0GN~F1`4nA~anL@R&-hm{ z5nqd_w7Sg;AY~}f{add(W}UrE5vVUrzIOvad~^ccIbTlk%P%z{1vp&GrXPoCB3Iu_ z%hCQFcz?ls*TWtkaX8HJK_GMH^Vsuvw13LgiQ>O&&OL7bc}B|R{%>Sg5IMH39-^VU zs*okw%@bF~cTQz>BK3&r)=nxSUZB2wQT13iK&+kwzrQWdk~CNyBQ{A=hbkDBZ}3o< z1TmNYi9B8gW;xMKiuPZcfl_Z}P#Jw2CKAR+gKtO|jad#@*{o(6wHZ&E4J~a*;-;$y zl_l=AQ%GDKkCk?EcL)l8nY7s-bHCb|LSQ_HnHzK@B$a9S3HEk5{ZMO+=p+a%9nC}i zaJ{A@{yL|Is@hsj7gzm2GRW^y$^!));_w~IF?auNX)d@U`Om>?V|iv`4}<B&3`(G) zjMhtUrKENg112muS{k?f?_zUV)9;AVykw>UhcW9SCsRR89!E^cT*A`GIE;f#Nczvd z%Zsg{2$z4-zqy=Lx7$oF(-vpKjUWbmKZs&#=mM6cKQ|i(u2bs!NnMscG_I_0&ex9Z ze+-aDfWN{=?Oczh5_<x>yMK+>6oO=oFSMeNA&89G1j(NA9*10u7P&|%aJves0Ek6I z0G;q@dfwV5&qnQgqxvZ(08{<a8*x^0{;Ai3uB4RylmFu8%n-O)n`A?)O=U|10V&hL z<~q~)>uulkK)5L3IFIjGW5Sh@?b^nhxYq#ae~wd!GVqhH?pNQt^4<U_tXd-}{O@3? z?Q6yUH{;k5*dA(@ioz`cMzxWp`Zy;aI4FT)Y$BWdmhQ6Rm@qN4BKcLlRjXAGK52=% zFKNUz;!^M9>+9X3g4T+D@7A<`ardJqwuv?3x}j3*u$81G&ReE>5fcrYF6BwN31cyF z^<kt^m_4W#@=u@6_U{a)C_>+FT#1m|Xt-05Y)j@!cA;vzft1Qw1Ns?G=)_oS7ZBP4 zi_z>L!hezSs$Eho30->!3b-dF`BsxHqNH7m&MM^|rJFg5FO)4_N&jWWvi28Qb-T*N zWm~5lnkL-<=3q3VSr)$4xQoNjSIx9}E~bJej8fKatVk=2m}Yx6S{jnNxFeVJh;qRJ z*8>fp+k#KvN*Hqx53uER)y2y0cpQ?S6rJFP$zYKsw=PbJ27lhf5*zeByCC#)PjK`k z)oxJ`p)whdHvO@8y?paDacY)dH2rv~mh&fIIcWik+q^M{y(mg(g6_UWE{WUj(yi+- z1;rh!j;viqW3-}7!zb_sp`GB}v56hKBNDORd#CKbt~aZe6#h-iKE|Kl82y70qsd@O zudf6-BM6D~i8LX9hmkeP0=@%8Qd<<{o%&T%N4dtI!?~q0-|3QYCdupX4#+9<U(t<X z%xQZ1%qFx?P{TIBX#P!iE#b99^=C|;ChG|qe2OZkXpGmxoVTGqpi&AcDwdp8pBhTX zqUriT8NTZX`M!`~<0AB(`aa7{XLxWD9q89g%J5)-7mg$YF2VRO(%eSi<sTt(9x{0_ zQr2i5#c<@sH%~%n(hNdA6-@D+)d4?(KigK2l&@p{7_&giX*JXrF;<c|^TB5ceBL#p z^C3>vGm;e6>F+cvBt5IzZ#!M#TpXUYwUrUKkCfAjHdU$*Sc=;7w+Rv9$FgV3{j(Hu z4gaj}Dsb~kROR<;7dQg^js>P!h8h`-(aQSPu<M-`(&gr(5Q&tYFRxdM;p;e@F5YcC zp5^g(vt=yc{6e7{K|uYpC)yS`TR|9S#kTV|ujBsis;Xy=3hS`(3ns*8t*?xP`nG`1 zFLiAi*O=jUO{&wFFUH9LKV9rsN=|-wt13o!I&>1ffl!C01O4}Nv*kg`w!gCX4eH9> z;;|B>Ko)1BuEaKPC{>0kl<Vf*9NY*`ElTEohXDG7Hrxf1N9tT99OID2<)R3Db4)sa z@n(cqw20d$B5nSw!PgC{vLzwEUY$kUJkpZlSEc(};?9T?=p7i^Yw2JsW2^j2;>2{) z<ywX?IGjmO^a@llLaMZqtEGdaD;X9l6A6)`!Ga)H;b%a=3+zyXrdJqoXqMmO<sm&t z$^8TuZ+_(Oi1Z4+Q(Yep^0^qeRPPPBAd*!3`E9@86Rv>}hXKt^ql>9^S||^%z@$GF zNAt2a&f=smt5`ABTujiC6a3$!gZRf>`ld#M>RO8?yqW}^Uxm1wPhm1Xs^EinQBrMr zs59apNw~3zi*ZqBKM?vVC%4mziFRBP7nouBtbJ{iK3XqK5fF5t9$lqUZPyyf5<PHt z;rv@6O25PDLRRylO)~r)*!yR|TXg(gJp6uw$kGx;Z1#S@sKhiWk}U#*DvoZKdv`E{ zG5KV-t_&S?=_tToJL*R*x3R;9O&}Ex3QJ#gFeQ+2Cs}s~aIG*xj+LS?7~CJNw%@wp z{YAwGqRvtg`d*ElN`i6(&@P$sZk~-aY}cYY%KXWW|ELQa^$Ht{4ha5~Nr{KSYx#BU zWWT?l6k>Dp01_OE^m`iBBaZ@X#0o__?9B#FWpWGMWM?C=^>esQPCJhAP9agex-|W? z(KCHA6zd%AVsH)L3P`BI*NJ|PWd}5aU%O=5`_u|tWhv5>-)N0}=sdtsoX}5dlPDg) zZ@FcO3(#H|1XWYxZ%4!;BsNY-f+-2r0S26!x<CI`ZqRcd90@cV3nl?dZXXib9<mwG z_3KRP308(~wSYOy^ES8%0i{dFDc}BXxs=A3G~?K}pztz-_^+scGDiHU#Fdg7-m}Pw zsF?XsfB_(5Sm(FSqNKui#Z)?cQ5|GW%%hV4!K~yOBhefHJ6NvTJI*to01o+<So94g z(Dvh#OBeZ1`biQS*)=G9eQ2L39{{KZ%XhbAr2^JnL>pd>?eyxSL@Dx-fg0#vPWh87 zf5=%+GZTITXyelmx<^IUm@4Crx-3Z>_)7!-G^Q*nfJ9VcA?(uBu)Wq*45U*_|1tns zYn+>s6=jSTd6=8h4g{RvKN+wn?WW|@u${$wg^7%DJ1((43Om+V>$&~*nYrhXGmtdy z!x)P8%&l8uvZLW3{)alwk0Q>8I0fXCad?u;Msjs%w(avn1$^=3<G@^L-ww?IuR$Nv z2r6aVP)Ga9##3`pseAc0<?pdiV`X?)s8<YB3rTz_P4T%HrQ~ui$z+ij*4i+=ZMKgC zI4K8V5NZjY2kD;WStK=!H7E9vsKlNxuLE~M{9(U;VdqHhb0`nvD>HtkoPrtq3Ga;* z_{`AqE=VsQt8X*A`zO<+?HaLE4^K1l*g8)ctmd+?;CkXe#QOXY6>)H1h=_S};KS@5 zKdBedm_mY&T6I=Y;WJX#Ib}0<_{a|6X}XAU`4+j$A#3lNmDhm=KtNK|fY6csPyD)5 zsSn93dfJ-qiTJOcL1!5;i9Nq*ZfM@9E~3Q-9rt(~O(}l<_0_))vdo+?mMXiT6Vpv4 z@{jfbB}*anaHv4AU>%9bE2*QnYyJ?eN#1Y4%2-AuF$>L|*W0Qo<?cSd3+#49U9e*3 zD^1HFHEdR;6`qa$BV7KnQW_G*MtDu}oiw*7?s@4lDvdf-n}Ls)=PLS%?C@JckJvf& zXI4+gMbllsz1;cTuu!8yg%K*x)^p5ZB`lld07#rREqws0DObmq#m0_Hj1b6GHkN1x zu>X~L!2|6%o4oWj)7DY(WIeh_{Q6wI@IeRCXI}2BJ$)|AWx=#G#MN?h1j^tTdrJ*& z1*i2XavA0P*fU5i?TmY2KN_YcN|>k*A(T4o*{>-orCqS2J*7R1yX#nEKg0NLc4m+< zdJ-*u9M+u*#I-+Nr*U(}l-VX7%I~LO7jbK=4Ci-4L5{=7y}~<9kRO)b!|)aZi@<7> zZw6*d66?|F@hjH7X9p^RTx{Up&NpeyUu4*c`Pbf{^II_XAQw1<l}v$G(q|8(+Fm0c zGQ{VT`d<cqrtp8lLR1E%z4bj>Opb8&Qqf$<l5ZUe^K+!mF1c)9jYs-f1%DRmwnVsI z7z(wH=XO;1tpXwL7ok5EcLCP&U;MkN-}kjg-2j+g;y7RUL+{4x4xAm}-<nZ9EGmbt zn4PnDuEFn0AP$V|Xw7^YD_`vHmqNWygrTzlY}8rZSh>+-V^aT_pLS00Qw~fO|25)~ zKdEP!c)l60^SVr?@CBE@NJ`<by6=Q*g}|7ac7WW;AdKmVB&RLR@rVcdqCUIfyfp6$ z0*Xl&8!_ypp4puUUmx;%3dKD;#>sCvDFPC`0k_MxRnfBe@a<s}J34DUv^Nft;5m%K zQ7PFtnW4738U8!jF&PfVFoZb?V_3k&Rt908#fM?5#wd;!hdU~Um?5Z%cyu5&E(;6~ zIy6|p&9vzpihSMv09tMeDQ^}HEJ1MZQ&Q#5fRCw}qDa$RIHP}Qm1;+`cTL5{<L!B7 z8M*+(O|Xi0km3}l1YrszO%@1n5>OaOO(C3=f*1?bW?}!~U;z)nM2iv^ZF<zC&zfi? zj}qpEFT!)RA^HQhs$R-s{9R+c*fLVch3tA9RzpmAzzHbZ*F&}ghTs_lzcMKr$T3r) zoy9p0U!MFn`61a~gDd(LtileV(O$un9j6c6?WS4Hq{dGH69{t`IguP}^pCP7_DE2@ zH@&o!LK(K4WSVopiTtW^@Se=Kl<)bVRYsZ#io>T63jqsyQ{rketq&(9^fdhYlF+lb ziB!d%iI_0fkvZFg84OFe1z5f{I<UeJ^+1}Sybomvm4`Do)fyMs)}P`f65?X=gsFf$ zbv?$?2feFKFBiU?D&sEyff9g&mg{qH9!dE~WwPWp@&J()Gq}!g|NXN2Dgy%G6IB`V zvKG-t$i+n`<5pTSULxFY6bymU3;VpW3VV|Mo!Ha%wqUVfPGj5U4GAuB?4j7t>+5-f zr=}E8tz?6DEigwPhkcc8O!DmpTP#H#X{EWKIV}gazP#DtrMt*1N)YqeLz}~kgics2 zIgLv$!xgo5<<r;l#1MCf_VCg@E}gJYF7U$Z3kpbhD9Shg7zFrohZ7A=u^kwiBo$Q9 zcku<$Vt3G;B2d%XJEx>*eJoc)V0?Zh%W*3>YOV6tVrJJkrP>ipGM8jwfFEr-E$3~^ z7z6yUNEBF!;o2?D)15+X!=|GU(DSm<lTYjTT%w=Jowtj)^x^V?pX+Kb_FWNw7jRGs z$kN7D1(0F06KZ>>x{z;`R6Z0JUFzT!gK2_L5wzq97?#T+{j5^~7E<am=OZRA7OPr^ z6C*lce<EHy^PAVjl_)x58unF6hbf6xxXi1{$c2E$XYlQ2w10w-r0_{0IIn9j`-jS6 zgxk#qO~~QQhSUlyZDgXg_Eg2t>hC;Y7B-R6GYpQg<hGEd?Ye2QaEVT3;c$qHW`_*M zMXw)05r#~30)su>MkMs)*I87hv1_B>^;4FyEKu!Bxm-9|)Xk^--WKSYR(|BF#Mbjl z9>a|7NF`zq6`}Hqaq{7k@1#;<jf<@KLBN8`CRQ+Bd3?G079k{dfrC{D1DpO?+e$rN zYwr@j6C5pK8XMqXU{Yy`?0(8nDOf{S+!}Tcr;dw`Kqi|mP7&yCPq{0ngSv!7S8wC( zp<E}vH<%=_fztmVF7Ewf$MKtCqIpWI0(Y3u`!&)%qFX%(qowe0xPZ-b2e}^F#C9(o zCdzdj=DfG8-4Iz8qde~*=?MVLhmF;}G3f8${-i+vHhM;AY8V7#XT(uVPbEi16d7D8 z4Sx{;iy+}~(P^l0(Hl5%8!GH5VJ95Vp7iIM5A6@7pQ%D`9x-Bc18^S=@=Wzl-Pjb= zs{58_39D;U+J85CNMqtWy$a>Tc`g&_c%sb;aQlXdDYH5nqhhmPra@qKnzFJ&)HG%~ zyCd-_6HPx7nTST5VB2X*wO`JxWo81O7>GCJM8ZHD+p4w45;kjW{vjqAvdvJneI;Ln zoTYTL{-Gxfa!Zsv1bceyZa4jhCrYp9W>B4Yqsh{l%WrC+wAHtqYGU}Q7d^8BLo#oe z0^Mo8?&yKo&&2ifnA0~Nmc?v(FkZwSfsQiQ5yJ0-OW`G<H`$3RNC#k02pTYa2r?_@ z$;v|<vJt~@mC09IG2W{6F2c+56(@0+0p0<<4bc+U3`mx9_sjey@zVhgHfnSG{m;Z6 zS%EV2&*j)IKd(=m6n(Rb8jQEGe(E^$of;bc8=v)W8hly|zB^6|Gm`0Uw?xBfa_vqw z(rl0CYbc+7-D04z<ZaO*wK`;8a^ohc#SsfVcwZVCfi5}Nw_mhdyQjvE$TSCHWbsi^ z!#QKabJOB_?ibBG{J$blqQmY97BdDLMo_~3s?TJmw9DJnoczsIRvV<!h4uh0#s+8Q znUEW%!qwK-d={QQ2|Gd`p?puNg2Vf#2BjZ2E6h;3j{Hh_weT~TmXQqBi^{n$Q;v@= zrc>pg%`^fwuiIMNIt4nZ^c7iV)Vjb{AyJ5|ms2rJR29`jQqIgFe0utUke~e(2k1Z? z#uV7=T3lpoM9t#X8Kq$sjGxiN1A=W7bI`lu{?MZ{()Z`bEI@nS+{_tS6MH`d!-6*h zeDoNvZn3QL+;rBqatMdX-1yke1gwNXmnXUXWU2}*1O7Z)gG8#BmY*NA)z@eKxS0~K zolu+P;D3)}hgcg|q#E$(bdVXy@uh(gM<_O5ccyYIo*|{xmKL3Pd?If{DVa;>Rm5c{ z*Vx;pXq;s*5m6AV;6IAqYY|{sw3rqWw_^Bnj2z__%o|aJxEI97){0AV;=p5$A_e4M z>t09XMD%|tovOpapTRuT^YSLsC-@Nn@&yI|P~q*CGzhqmXw;qKWJ^@AevdI9Cc<se zp)2}UkQ9BoANF*oiGz_U7UvCai%W`=6as{ccX^s`^~e?%F}nvB_YiaFZ;}J7-~T7J zV}kuRA}?C*-w#to!0qUtX?>-+rD5Woxg`7hwmJBJJ-nuwLq$(8Y(?V~B^ANN3szxl z)aKy%S_!|YwIqyOl*WkgUw^=dcxM5Sn~pv?4$oMXqd}Ac2+I}FCM`x=;o4t{|7vf{ zrHMnRi9KRzDYdkX%+&Z9LQ+Z=#?XskP#l@ex97kNt!XKQ!E?*d@1&Vh_;)*XG|$Aa z25gc35bU&Vx5Vf*FQxFP)B6Vo`FZaaqW@MptDId%v5(Mmjtw=P>@G^5#dxX%^;zSD z<55S8I*D&<8U&EW%Dk6k5Qzj4T1wLyNX4?fdVhe!4-^$lyOWITk)T;7C(Z?{Hz$+O z9AgrOKZIaAKYt<|yL)d^pZ;EkK`r#&vZdv-hR%3eiWDiJ^hLp#=gP--0R^V$N4ofn z?umq;^o}0dX-zlC^LJP5;_@mFy<M~v-fv9bg=f%^>sia`aJpAbFPq^zvULKxNAZ8v zXrkHSA~(CU*mz^m9@zToa6R!}jr99))@6fSq8+{eZbl9BKj#}8bNci1F$2siFCirb zEDY|10+=8>@?CK@e!Cj448AB~Y!*bYET!<<u*@&1kBwoF$At4$?kgX?fLPM?5zOx= z#l#~&E&8+BKC_IN{z$tkj5}MQkaGJ)4n7eWQLZPbjrvO9JN+(Wo$pBhAb<gb!e^^p zX(C9*vEyngphs~Q#Z8u)n1<ue&$7dDs+-Ln9I}aSGWEU$($BkW-p}SA=3hC%Cq28D z7p97}3$|&MLD~KTU}D{E_o{-nXm&T&T@E*AC41gRT4R*38`9#GOFb)u+6U~SW>g#5 ze+R#JtduY^eP6Ga-22zVJ15YPmY^F=`>}gz&JcFBnl=()7ZmHfcUvBGW!=1^y(XLf zYU-`S*LRkQyat&xqSoRgX32-N#mh5)DtG?f6;Ql8GGuiAGfm5zmp7;@g;S!8AIGnh zOcE(_zWebL?u;@nZ5|AZLho=$SgeeWH~@@VB`Nrg$7bp`IjQ9r(nw4bb_hOhnB9ku zt~?-x-?Zdp=luLvw;zVgjcQNi`W>6_p=|0};lCPLq-3i`yfX{(>ZYGreq<)k#aHSb z_Nfj|oW(bdR~u*4qJ9*dAQG5F>Lqcu_T0t02BbM=3T`($?T&A0ul{k1t||H1_eUvt zUZokGW`{UKp24-lMVHO=J0bgJ=#yRA%>@^Lz{;vI<&F%y#I_|1x~*dKfjpBGb;caj zv1Jf?Qi(|_`-=txq_8`ERl$2j%~nSLKE@hRMKafy+c={$_HT2uZru>j%UjgEX9S=G z-|^OEbYMP3(}f?F$N8RU)3knKGYFG(OH|q#z|qIJh*^lQ_nO(niI-=91cA5WyQtp= z-8pImD8yRd^S_e2Xs8+y7*`prSOEZjZw|ag{KrVL(YUy5gj*W-Dn)KXv_fX2lf#m# zAa80ZIs?WJSoLd)L|eLqm&Ks8=pjHrn2M$GpH7G3hrc88&N19#ocSf#YDAc%_gO_` zlpoanxZfkpk(iPisXpV5gvQh?#IQP>(`UL!)H)}g0{pk1#&MgyqNVdZtP2n})n<5H z?435;YY?oW?bs<SJ2=1p(Iu0*b^fUCcAEaVpcLC8WYaTJ1f-ZKf60&{co+tFp?{>z zPYDUG>ii_&1n0x{_)sB<=vC(gyo=Q%MPuDs`*13Sz<Dh@`^CJ)$8hjp66Sn@@SguF z)}6yD<#%8DWG|yjBQ=zC9SSvWw?Am&=cNJG>c65Kj2G3|gg0Fq`%m4FBh`vCe4LKM zBWNi{%uQ#c$HobPMe*5nRGXlgF#5o)A?VEor0wS_%5^j$-L|2Mo3cd1n%5`hu!^kh zzHqvo_EWV9aw2|8`gBABUp|wZT!rUx$-n^MZdG`<H60Y{twTXL3$|w4!^01+=r8jQ zPaj1bvXVIxdm3Kc=4O5>Y-$BfS13zjP?k{0g^_vEG=IG&iC=qi^#3!^)Nxw;7do`} zin_xH4fgXmmcHJvpHhE=nKaqU8X=|>bSlIVSj#${Qd}`2ytD84avoSJ50#YTpid2X zlVdWtHlSX7isXZF!Wh)WBu0v%xSC@QGRX~3?C}pt*RB--L<Sr1F~3y?u@S6R;4XtP z2mo%2<oJ!rWB>R-3Kflsh*YwBHo{&CGf_nW)argFO}kdgy|<W5tj<o8zrWsmo^)w> zw3*fsDjj4`+lq8;r}Nq*hr~Tr$nS+esu__o%|?v=ur1rFzVH<j4+^1-CZ%%19mEV3 z2?3#1KMEG*QKyUHnYX3SN{1gA{k)V$L2*T-(MkpT`eX3j;CRwuAi*0hg+Wu$a98*F zo&+-8-(agF0&oXHt`#4P(UA`c&urnUPum?v?JB02Vsr-#C%qZYscI87<<%&*ok^MJ z!?t|+xNx&%J4!r<;N&I9WqK#w0S~n%t*NhYQ8cHo*j0P)zmA+6^Mq#tBz#4l&D@NL zCrr`tpu4URq=K&!9WZr?2e$Ur)0Pam4Slo8I#mCa1OhYjCTC&RA(aCKe5agQBigCb zbtZ*5C`T?M_5lF|QPA{Wn}a<C-%;tm5n+peP+aHEz;p*6=|%O8XezS`Es=z>$XrX4 z`pAAC-$1!x`sg%^wZDXeVYy@??GJ{>n>lQAsVWBMk@wAyXuth<e=ML{h7Q+wg5$|P zW3#Var$s(73K43hfnOSZIXauPHQmtG_)kBniqOmj%_;)Gpu$&^`Z53pR1`=kDjhw@ zioYMqDlJzVM%6F3gn74i)ycWGXfN_lk;0_opCa|eJuE}GLXGOM$26BTskAmD1rgfN zEa=aZ-+p^uQRGuIC^#}(J;Zj8AEZedjnb^WyINp?#k;&HoS#6KL@*ed=))+90}x|* z0oPm~-{88ex9{@_NrlQ_lqIwZvL~10S_2xbghjHd`ze`Dh;=Y$67V~>zKqT>ypm-T zGJJ^OYBhB3^bj<<H%z{J>G^WQwPho}$rQcCLv&7I{e7UH<o^I(L7~1C;V+<oTQ>?H zZbQ%gO;~K?ed(o_qzfVnq<q3J1#y_^B;nNE%CiuN#a1c(tv@J|q#J=`Sxldd1aesD zW90qdyUW9*519uCcy{l+oL`hp`_u(hsLJMgkf2HIdyfygf(4Gip=v`x54>C>bjlmA zMHD{3B)R;7;pVz(Wl_1pS`TzRuu|}qpL<9TgAcPuJtnamBn<|@IRdltqzx1D_X>zW zOdKz>k=L_!U;V*G-m8n3UK1;pH}XoFi4?IydqLQvqLitnHafARc_1M0Cc1M9{@>P= z#*sh{4C{@&5GrrI`OSg4ijWx+VGxGBtOf;d+KjwbNa&M-)}9}_M_>&?EIaWAJ<=e; zL~jxvn&XHo_jPZ&vetj(4r>J^`W2o`&__{h(Dh*1(M<l`a?y&12xBUP20R!hd~k|y zlUlYb5U+d<p+A4Hk@xiz*F~?4ybI)EX`-UdJbwVQjOIWDjYPu(f)uz=zZwZ-2<T|! zEf4so@nVT&_C-<7-;Od!dF6k}Qa-lL$a@2VxxRK(GjRS0f$X^G1NT47>U`dWDmI4b zBX_6N-`JG)dSqyOWXMO98EDz-0qOB;udWBDG~ymlz_v56xceQz9MJ(hQK*ghh}Vk1 zM&482Na%2HBkymo&tH>i!e?Z!)G-oyk7oMwI}?bOu*egTr&UxynjR8^gp@`{aApPB zNFav>GV&fUNvy&KqinU#9KZx%v_JC6`P+9Hd98dmV0rP#&_Ed_G**rea|h3Q@I+fE z&L~n%DA9P5T!{nOx*SrX;kvK&?|PtA#U-p=xp(P}PkRTOw9)>=kBta;Iig;xb|Wu^ zDfR&ydEa>bb+15NAlAYy1@T7SSqA>djvPQALLd(8h(My@0TM`(=1L&xNFW2i*KFh+ z3@#lh6xFS24jTR_SNkKkb4-f28+nUsN>V(mF^<kwE4^q$yFV%zZhL6`guq2B4`k~a z;SJ9qXnLUSA*w?^B0Vtc@m+tz6?g&{-0Y@zPBFUt1zfm7)lG<~1B+s@;$EwEBX6%L z-nfzX?UQ+>K%S7TQq^MH88}2tSppG<m?fltGD<YeTM`ZT4ki(6M*<lJ{$=DH3cP+G z0a7&bL~d$6SyJvuxyHy_O8IK}$<^5a=>rNxDTJp5^#RO58#SmApe23i4iER3C$Q*p zG&}MUky7HD=2%Gk{Jpv!AuPq{jXQRi+75=Gu6KJ6B*GZcFYt6>(`yws@;WfNkbR&d zlW-!hV-JmVR|Vqu0urRM!}%_Hu6ev6xhtbc!?r}j0~060EaM!=!GVpuLxD_bEbHlx z>y;UDs%SZAlDlmhc?U@p4NORY06~Okc4Bbq;-KrqG|fe69n3CM9#zjHwaOmBt2>i` ztK(yl9#8b>dc+loAyGt8j*4AacS(Dgb?&S9_c%W*iF>W$M&2{ZQZy<H`vFGYzp55` zS;|h3#W@&c8kPnZ0^yS?4~s@4LkZH|B=J^uc5nr*kw6X*9}Q_URD}hkgbI#wWwpnZ z5)JwzinrOwJAi$&oiK?cB(B=8sO6C~^CkqembS{@(-HGLs}in&%CIZ!aVqR_(o=dc zlsG0TM0URPBhiDR5^)!WS^qUwG#r|^&d58VME83q^1dJ@USW_Yp6~>Mwg)7Lu)JXE zBe8<6ghwKsX8K1g(J-e(LvuJ73FH8A%SPS@f-TB&aW`eGtmU|^dl{DI(XW1>ZBaLJ zYdPGcY2^J+pg|ULu*HcM!*cQlD)?&7kt=jZYEys4h`BDLMa|q5*yV5`C4Sc9iOW8- z9t^76G*a5P>E2CRo~ieNYfq?A4QGz@^~ly6c{z)>Z~cmmyck6HH7rEB>uPjR!>l5Z zv}%H=nK#KhCK^TwWQz@waVPrVQPd@@?;qJauzU$F+v}puaCN<eaEK7dCv{t+sQyBA zp$ZLkZk;rZyaPsPb?B@hAIu>9lRXcaCzHS&?wlLBIO0f<jF_Tkl~1cNb8VOxGu`Xa z-Eb9$;rHl{z;waSyy#;S2GI(b%9>tAUe#Vb&Ae>nl{vzoKu#+H!D2$PTj#kZnCb65 zwHEp#o@huNk}N)}(X~M`63BlZZ$9LhIaa?au56S*{36++k+XZPq5?Dk>7gmwb4!6% z{HKwTci6+`6s@Z<SBk(b+=>oFLLns;(iBIYD|67hN4J?5qCRG_73z7}>+#Cxv98Bw zAGS-66~8LC%5k%8>u$4I9xid=!RaLgZj$JQZ>c)g)yR9%a~(*#k=JdN@+B-;OL%&Y zL|!3!WEBEP;{}7@AF_L*VK%i<0zr|Col<d(1oGd<*N;8mn7QQ?60SEf7CPL)OmIae ztcw?yyugPP2i3Q*5`>Jr%NGtTbiK3k(95Lak%r^S@LO6t4B<ToNVZ;Gyz>3>6w(98 zJbNe*uUlZ&ql`<BpFZxAaAlf35VLax_bx7a3eoJFqPapn>1pKcO(AUL)h@b7kW=ZR zi;tI<f}nmSK%{#}HM=vAO4Ug`(J)VQ{0&9|8R6c>4<kKzdhhm1cLv_XRZ3$t{1T4{ zX(uoxD7%!rpYYP#w}3&ak4b&!z}BmkAgPA(pw$(E)aa({)cC$fm9LAYhxR<eZV%t} zkk{1w^Iv*M55UlcCm#%<p+vT7-K8fU9q*Wb#gCD%a+V_QI~jRdbP>6BhWQDJyeG(W zFQ0$@c_%?M(wzw;NB*Thc-ChPfdDqk+gEnjkw8W~EUw|Qr9r;<1o#bVPfQ>uv__Vt z2jhx{3`^;jc#rSmk)Z;d!Je!5R9>)$%C))mTUCdLBM%sMt+0q(G3kNI7533$%)E4t ztM~u>`##dcn8wPgaAIs(j?kN34pkg@#%VjC9ftjkyc}rKONOwK_arny#L0_Ubg{`{ zs}yW>9&Ex2|2EP%2jtoUi6<InSXv%$z$YSQL+^bgkP$mX31y+Uf<9ny_33TPzwnIv z8ZFhR5()2%qP*}FG<QsNd!UiRT^B>~pn2?F%}29suJP=t1AIAoqUng5uA5<sKu~}^ zFzXSQ9$!IvtN~>sQg(^iEx;UP*43*%t)YdkfR^EGll4a4E5qF%Cf3e4RwM8HY4u?( z)P_ZiZB>KdKRExRbz0d00*UJrxkL#h_uquJ83|;>?r_8W!83qyD!3xyLcMU131Q(f zN*4`%Qc>0U0J|PEDkx_HXI*iK6cCyAz*XoY$+3+V^22IM3Em4eeVn_(m1}#%rN^fq zKhudkxLBiA|J@P@2VU`89@>NGbYuDe>Tt!*MqajI1##8`=B<Ajd7(hi1PMi~x{2<M zSg2VN?cF!ga7sh$5dyKGuaQ7T><n=u6o*wYlnTyhJMAJuLiFtmrJ5SU%SU81w$L^e zh@lOz+VlW)nV>r~BhgCNTwrTtQ;kQ`(v{45xVFdq<3Hlkqmx~idm2n5JEsq-U{$E4 zSSV_3vxWr`($UCU8m`(=o2VPu$osVSVQClr=omGusdXAak!u%3*Ai<j@1BW<8lyF} zu>zOPMg=lr58!bQ&LxTC6Y}!j5b<1Kwxg|gE(z~~<vZt(3=Wv*z};%RmEKTCVZz2E z<qopyCb_#*0VRPyAU#6Eyr{x;ec|f;-+%2ZJ)*1zBEciD`(5W;!@>a=J#P!#Pw!~t zeT7O`AXOYdFC#DKVVxt*1Omi?2?WcCNrT)w(J-5a4oRc|@0kY;l88Qm9c(0!5j|i_ zdWes601Gfm``VA2nn1Yj#j*vI@;0&3<qI!dmIEwZ(JFJ01)k}GHxD6XOYv(ht*pB8 zk)`ImjyCr_^UQ{j5*V&d#jU%k^uR~C0;fHYM^k*^5_;<Tussq{b^>YjP2`>Er!NeQ zyg$$|I?}Lav&JL{me+$n{0X>so`~ubcQ#Q10fpRA;IcMPl4K;15$j=H^!l<Rfs|Nd z9>*MIC{-h^9^Z1{>!4z7a~>5m_(J#rpVS8jl_+`Onxk=^r>JH?cDOS}1wkI@dmNvO z@+jZ`{kILI2br$;_lKuFfX4e2%orP#uMFQXsFl9P$eXE=cVYnT6Wz<m`_$YSd7qJ; zgr^Rgr<l!b=Am)Q!XJRL>LvsN{z&skhh!=Mg~U@DK|MB2M*<nq1(D7;RjfW~d?D5Y zVUt$D<LAH)GlsqN&Z{8`j@Ecx4k+Q3eIdz~-kCJ%p(!N@Mnt-mPzY^>684yR-QkBl zjur?h=`TInrv^zH;di`85|K~rO}`<`T}q^bkyn2Hc@4K5%i9ZV<UKnJH7xA4MW(wK zmkLM_2cEmXCxPe?dyE58blBkokLVL?@y&cBkP+SRVyhr1mhW8H=2*zt-BX93fRnh= zRbY|rl~i4>m;QdZPF>F%ICvW^00J@YhW)T|OzL{SoIOJF5iD0JHkwl`JBrypanF&* z(W&&zw;(;(P!uDJohy+9rxosCIkJ5ilk`aBeZesLma*8#`<$eiIQ~#0uLkmFT*E>W zy+Zvv-av%dxQIwQrZi^OCNZ;MnvMiA;$N7fchLn{4%Lc<wmZ-&VFn2pI)8-5IZF@a z5haYs#&GqfqL2di2t9Mi4*6hGkoJ0@X)e-ZQ^OTtNF)(a><#L$A_j@WY*&V;Js3x4 zBQHk~_X8Vw&(H)ptwsqEXOhV*p#^A^&>f-VwkeW$?>!>|i4L&?ar-d1B}qmC8NrEE zU8#nNAs%T`dIGs_ZlfLcKHA2xIY;VN7GBD{Fgzp(P>Da4n>4A216u`CErknxpopM7 zk3v=o3br6UII#rBJ^|w38|Bm}jM*Z6un1uzZyYf425gwf``TR6OrG(9isu*wnHKEB zf&@Vr7EKeHt%D0(LRu~Q1RN4iX$1ASn~^|9P><rI>o1(IEr-2ri`7<1dHXo<$-wBt z(*!-qr%}QJbbvyxl-0q#;#3V+!X7#&Xypt7@jn%+^pI&Ygp@d(e6g|gV1#&%eO9ly z4TSrqV;A?kMO$d%(aSHt76ggpzFitZXcct@8+l(j36mgV<UN-X7L5{89F~d@`9EjZ z1QIQ9<;ouMltycPO5;c%BN&$u4Bhq&b_id*Dq>v~TV7nw2e{3AQlsLIm7V6QK8yg5 ziJ8>aR0xmMq}nw%()LKjds7RKkW(^qe?WQ&d2Fle!95Q)VC@kJvj(5*^4<;s*7B!_ zk@v_~SwDIC)huG<m80hz2pf67L7EAM(a#s&$m<CNshAGAhZ0CIG4BKzAj#TN8iBR~ zmwq>rF^}K#NFe`1_>ynOWW|dv=~?d$eyqHKNprmiM$JPwdt>nu&h_vbP_6VZvcA+E z81l$@&OGchFWli1uF7pn4}iu|@cZ5;DD_LbLc0gCR$FLdCJ(^vD^IGCmno!g8ZR4p zUy@Nm4OBcnKQ0_*elZBSu+nN4y>eDe<h(<~C60(<C6GLt(g?H{xJCl`AEMj(@glf% z*S0}?O>DrJG@Bm87r5#JRfSd!strir!;^?j6YDEi8AV))QCH3~X6|P_wkSOe&K#zq zkyrad0`lN_4BR9;hv6PbG?6zG<1T<ygk>=DvIyw|HuApYdLZ!eJ})IK@nN}6I@;-2 z8HMD5FpI9iVD7R<a7v>vTB|-0og7bT90}xq36U0;oqpAIw?>I4q(Q?Ig<d9#>Kmr& zAmGB;QT40={dBEsJuK!uESev1>rUkY-65Z1RxPA`V)I!K1{-!sgzOJZ-!5(+08y{i zJHCE(%Ouh?^7dT_!baX}zg4QlQjmos5QoAkkz-OJIXkg{{qqN>G^Qp>Ac{x>-sW~B zkpC6znQKcF9gVz2#}%{1^1nbJ>eii*Z<j#zpL!ZEkptBSK(i?@D~M*fyR!j^W~Zf4 z#|vM$qJ%3#f9V0HTjdb5FZGc$TIdf9@Yc%q^A|jSWF|X%fusn?h33)w!+Z%NZwOR8 zeSUH5aCD3d2qf@_)h0TX-1dwlkp@X?N+WQ`8j{&aApaYbl~%YeVC3CQfN&dR$lJ`R zRuyE2Khq~<Ts3~K53%F{se|!v1m7a1jpo&mAPl=RcZlJtY#lRy_rsgc(!<2>j9|YE zqO+59+I;9^^J&6HBJV4HHYuyR=_fB}KP1~^k`VY@6M4^Gtu~`CFpa)g$ORN)E1-{F zdGsuLArFJZA-2cL+B*oujs)_5LUB{i^_{`UyRiV_WcNpg3?&ZjmFt&Sei%j~U*gwP zn)+D}j2DN6P!<<0TdDMrwg(cfUikU9sPuSt(htqC1>Eo6smn<CRu$UA!Qf;XiM+}m zJX3gjal4eIQjGp{Ae_jnfr_Wk`$>?ab4MU5LZ+6yyb!H6$I1?25py^Q1ukoCw7@kI z$o~cy4p%IpE;jFz0L#G<h*E{p2Ls=7XIklj3w471z3zj;#US0tzZR4}5OX!fq@a@? z1<2!6$YcKPpPNVzhG8n<NXLC52}$h_MjfUlPLa2t6Mrzu(rnm7=S1EUKaBo_+OUpg zAY^fL?g^xxMo)pn-J-N<)BJ!4gi;#Y3S46k<bMM2$L&SoZs&5p&d6KzNFYI$;(#D5 zQJ-0H@Vp26bRGB&nV|21Zihds?vS%QdFlYD=P@mc%5e3<=Ub5;oYF3zm5IU0UL^?a za!L+?LbRYpM&8>fe*l|H5cA`sf*<GeS6{6n-F+U`^9#gcF@azhU1Te!fgIf90TGDb z(QaD_WI8I4p~H6Gs&UO50PTxtdv7E_7(P>RP@uu`FfGXLD}5hpy(*w#De`@Dya#f3 zGC_Hya>_WE-JvpEy%v`qKa%w5OCih<$|JblAJmAd3_`&3-l0m7jl6>8saXSfChmc6 zVdR~MrBYsl9J^Ds9Hb~L7=#81rwaF-==$Rar4?^Rj|45+EE^Tbka2di>^i<zfIk8} zgIsM(fLI@yb?}%ldqnD1xELXoMiIz;F{wSfsTOE3D(ET1orB*hL)ogv%x9DwEuIke zc;WM?;p+3}CijM!s79i6$A=ghBuBG+_Kmm%Aq7%);t$}S48lg<vnLT};t1s2bwU;k zuRsc23X<z2p`8+vI}!~KszHJR*GM44#Rbf`T?NQ(B#6DU0I}s78`kwBgMg!m=8!q% zvg4%mq266}g5si!%r)aG@u7HVmJ2dOu7-xW^gX=vC|%d%{kZh_=3df++aH>!qBr{w zEdgiHYN!J+@z#<k7<mO}UCLMYh~#A>??3Ea!EWPJ6#W8hD}J(xI~_ML(=?@YGz(CW zA_XM6V1dd4kYIs?1k!u}3nW%7kyx>0f%pdgfG^=!c=sLOmxJ@%)**@Qj!zxiX=b2> znVg<`&pr3_+54J@1tZo46i87_RDc+r12NO-y#wDGNYx*>U4|op3>XD1A19PouU3{F zmgm8x<h)JLJWzlX3#)a?yV+*;M&IEby84v13u3PzYCqINh4i4-hXBIEJ<$0u?n0v; za=>jRACo6@mvHso7r*_ucj-aR-iY7%jt>fvL=(Li3WV4LMqZ24ho}!-8Na)c_u2a( zkhu`Z{KB4OCVevXCM=_Iie{n=l7$luO&<xwGKd)!$e^LLz*wvTTR05$%*i;lcmO3B z%SUhCy_2>W#u!N403P?Sz=ht0Ir~q}7#GZ=9QOSjj@{H)xO}T>RIs9t6O5UE{L@$a zmLAkIX9l6mL6K}d?T_rJ5N$cJPLaC%FvL57jlAbR4$Bp<Y$dBGrhXFLFO@P<<pjbj zJ0?J$=M9C!&XD9IfeaT{Ta65J^CshxYE0j5C-T0$Q-G-S0Gf(r#rfrG2o)?)L=6!- z=lu4|r$l?0^wy}l!=#w?$YIr$2S=1t$?VsnJ>L6y-_j!ru8U$EXJ(MEXc6_Hb58$a z{`$ZmFHRrG9y_?O*vPv+^%CUTR<DFWriJ^HvDs_uMuyNi^J~lVC<zRF<D;>_CFxrG zm>?Nf+P+@kR9znSSigAjE#CMSL?D6s*PR^@kscnatA@?C)yusVAhEytSj3v;D#9VB zm=a`pt%n>bZX>BWVBiDsR_-LqL$-T>J_;EX#9j~E_1LrY;Ptf3AnLn19)aM%lg`Hm z8%Si++9xszWA`!iu#p%1VP^>~5U6Mg#JI(TStUVS1xpD;6AhE5K&r+>!&U{Zkw8W$ zjIhMKo@=;7RSVM|B@xKI^)DtD#<z?48%+RzT)fds#Iy~H6$q!ZqlrK%CE9qc(MO8T z2l7dhJb_==F-L}otEpzQYr@s#o}~w)&K*Y@_(=RT46eL@G3s7;1e@qB*&}Yh(>7@2 zogvcQje;P<#7YnW4H714ZecW1-9C$wZ36KMBnu}Rf?Gxc84-dpcL(7vYMt@Z|HzSb z<7TLr%|_lO&#b?=dnc5mtiI`wSZ}Dup$deFBxt+=aqvdkRDgJ^B-Pq=ZXB?YHiP&m zCVr*h?7N`!_+xkJ!K%Y^p7P(ZkZgz*&+LUaaP+2z1w{3BdP}sdVX=|-1=36`fgq4q z3|Ix4<=O;E5oRI>W-9D6$R>ulKhaPiF(?n&0WuQE>jYz)5H}At@~)LnC?<E-v<3aD z*~q){(&O^pjNKQPv;Hj|j5jCV2F12l+SZrwyx@j3+!YVUA4tCw>49W+Igx|E5S)ng zC=Vk&NNC{7iQ~uf?Luql6a7rmy8@QQhT7Vahu>D*8l1>$htaVVL~2+kg=G-%M@1k2 zti0Y9jxV{MXb1_?lxV0aoq2dx!x)}#9|`1j0y%XXYfXj)$g<ujziFyhT{ateUqX8H zkQpA7tqb^Nv^?uk?;f}lBS|>p%Ga)P1Qr>22y!70NDuTpriJYFxGwEB^Zj={7%Dq( z4+=cyvO!fGoOq>PpkCIn0P1W#1iQL;*~oi3L!`R|Dq@CE2?PwHUS8e_;?8Xo4FQQ{ z56@~qo+yWm1oB!T+^I0-VtI9L@bWoVp31ErNvSVg1qfsj7B*IT40OFm95Zov;X(0; z5qWj>eV2B3<1W>nhur2Sfm=5PZ=hk0Sr4Z?rsCFpYL&;?-VImb&|SbcZ;rHUki7-+ zpyZN1to~@uGQqVKf9x1#!baZruoFa<g3K=@i5Dd-(jcf}`L%?pe#L=-@2okH$~Q;? z1d`{u^LC8{^14Eux{Ts#1+&$qz6{*fJz0wtUWPbX)&I$jMqV>O=>gPYt#GFD6%g~8 zbq6>^g4rz)ubU?j9(V{UyVb;Gm@=Q(u7?bJ98`Lc;?RD72jFQKo;Z*CC^{4oWn#6d zVMYJf$SX@hKp;=6wS-owX44E3#MiMz-U2G>f{BLVE_s4Ki_kSuxWFX{5=fGa1oGHX z3Q;tU3f}yO7}RP-^MCrg4cZ}$8zk~R8bD)!FZ4ofbRgpW;QW@tZ#LLvUNtv!vAKBo zXk9sBA#G*2`r`M4N)I6FAm}P6L_Br$SbQ+MsaR@f!`f-9EgN~ypF1DcbrqyoOx+(G zBZ`3gAn39|g9utD8lpoIC~!fXK!gNCwv20#j0Ey%;okX+nsN}V)}BY^H3FgeKlzl= z-?cU@Paef4b6>TxV66eDfj6qUA2cEu`@}!>T%lj?;ATAR2@K-G5%UaotE%aNoU6)k z^}!*f2gA3}JBlhvh(8EXZ#y3wXxVK?4^}H8Q6ujMwvDbv-U~+{G72))IS?X{3ZCoQ zCK@&d`A!JoeNj%j<Y_t*$RmY!>T>I1<ysW;%5J-$P<2QTfE(c@;&<7qyFz1R=!pG; z>BHZFHtK^Ci95)m6Qf&Rg<QFI2jWRKbt~8TfL&K=SA{cNorMiopMSDP>A~+|9c=jk z)CJ3=3q-wUj*U`k2jz_algRrFMqbMxbBq$6pbJ86^wgjUqHT2i_idMG*j%GZi9Z4b zt~^aABY`|}s8g4P!>vk^`I<vUgfUopT$Xj=a>+cjEZ-d19;k<;l+ZKWG{4)b&l6X* zQtEIQ;!>-GD|g0}xy7`oLQ293S3i8ZSLwm#D}5XbiGOhYC#lezwIBCEzlV0}L!*t` zQ3)G)XCRR4GhGI9A_M~dP$+w(ss6`npJ>=bAo)ZQE^uWAFQy}bJX+L@yi1g#6!R6C zaUGkm^kA4Zjr^G_=iXWkA_TD!v0lPCSAN)oO|IKHv1#HV^MT0NR<mxVW?ghW5Y0Zv zLfS8WIga$;q4O@5ob%ARc0GDe86mXe51a*2Oa5RZ?`AC__Mun9=)@r2hLyBt5SAg> zWf+Xn5@gLOjadV|ppcu41Tt`tQ<s8oS)l04%aHV_am{);o1sIpw!dMJvmTi2s17_h zQ&-)t)GlYip(T9XM_YBx^P~z##8Rjn8CU2~B3l=3T_-)x%8&p4=Lph+%kLd*IOp*R z-1x@;%2ss^(z^XY+vVGV5_#W$|6F}o7cxtT=2<o&{;+UfUf~cbV(kIofD9e>PzuT< zyMGM{9Ka)i^bzLn4)%ODE9*wy*;c64jl4``LX;3>5YBoZ9(f38v^=!Q{0;o&SNfpY z3H{L-=hUG}Dv=3uh!0a?0_h<de=5h+ZG|dr-Rgs%k0w1BQ5RdHXi5-=H}MWmfwXO* zL-r|!v~u*Sk@uBVAa*MuB*;^@P0IDpG7FRWKrA^>#UcT+Hv)m>Jk8Va3?gt}O5;c% zy+e6<dsl{SxrAW2)W}`nYHRrK94|Komb`rR>eZaWu@vj!maf=k#kZ<JxL?i@wY9gs z6bdA*@^uYT5~*d5%9WI@EZnR|*(5zagY-BQys`AyP_3a)?9p@A?p_8#Vw_vjMmUjI z7(^o7=kqxNc?)iWV6iRsf>04_k4pnH?T|!w5J*s;WTu)y90{b45arOgRJM>;f!jGp z?#k!O#zfwm?Y&QURWVy@yzT(Shj0YWu^#@8t5@v0Qp8)G4?!-Zp&gGL)PZ9Hz;0DM zxi}M?2D=_#ee&*s*n_o)o{k7sAA0RyW_ueNX&vWIfj8~&4Qg0OGkI=HSQb?my(oN~ z36@H+l@|oE*Pj&<Noq{*CXl;R8Z#3N*^*7pBY|`UbiBhZT1W+jyI(MYG;S|H-`dPE zs~fF~^V#ftknG_}ga*wyAaN6b$2FLkou>i~xyp@8W>1iaYOql-lMmkNAzhE_v(mE1 z$AA77k{(|^j}MQi3nX%YLufu>U<xE^@8b=tk9HiQM&6s*Gc-Y58Eby=Umq_~2m%%P zi`_SpP=PB4M>M81X7?4ij4>mDbOKGhEyMhQS&yP9m$VKrOdvCQd5wGeCk<g);KL9w z>Oz#@UNZ#)H5m5l%7?q4Y~Xf!B&t0`dEmfa58L&SvQ>Hd>0cd453&OsmO_%+mCaVT zr=Q?^omz4?+BQM-4;9}4EseaELR=loiV#O3H5--#YFL~{d022tqXhN@hS(KNDUG0> zkwCh^9leO9Y7SB(W|Nb9TI-F|%caY=GXACYu)7@|w8w+4tUw}wMTnN~IlBpks}#Be zg)8|$+XJRXnfGwyA=}KI^!Pp4^*E&Th-%OFUcO?gXyy~8jzKlcL-1k2t=I#+fxDJa zBkxQC6)lBeApPn5<cTPdsiw0V=8z;MsdoehNt^=Vl*TZDWTBKsqaBh_fph|F9bW}k zjhD(F%pm8D*@}j@NL@KnLg<xMFZi89MjSJP$N}O|ixp33%L&ko*i;Vh-W9Jd8Xs_5 zxl;zWuA`2rYkEx4GnX;**_WM34}fwL_iw{Wl7IjK`X7<l0=v3nclYta$ZPSQ45JH) zSOro-fykdRVGoN9efU{IkLW0n!KVhB6*Wk*Bv{}AMgr*sbCC)}6@-^ucH$Hgu2->^ z;a{&MubbPI=9~-_u^f1SKlFrL_K3}`+9>DuLx5I$xS#Uu2|*<~=Yf27RITK&<Z&TW z=3RC@xO@e2+%J33qSuI5)B4X0a!xP=7En9bu;gf~LD<OqrjW-BvF>N$=0y`-00z-? zXJc|^5PYpiLy`o0?>c3eg@)KCBY|`Wu)-38VO}SMP<-MlutAD`{faV580(>iB|7R* z*Okvn#Ff@xR3;hRLwCfRS!p=yQwwMh3D(tV4}>EEjyj~aAYBiPnSb4}^dRcMd9O(D zNP?eEq9MdvwE@1Nov;IYu#xv|+XQ*;6v*?^xp`$4eadU4j3tk$>x)#WCQ2Y3BheOn zmgjj$pNs_3DbAg$Fl!`}Fv=}^uOXUQZ#i`hHRH*ui$44S{Z^E)8++8cAW>YaGw5CY zT|*Z`+2?tJh30}B{c<f`A)`bRu7o_w=B~#Z@sR*p#PuKql8{js&uQ#@uvXoDu}F-Q z9{6YlHS$^;)-(H%K8S0hKT#u=UkPIGpi1n0LIlz!hk!t;zaGJq#*sie#>^1`ro)$8 zue=N<@~XgC*QuyRD&_Kay;^^GHB|MX=_C*!U=JdXH!8}&p{IoQnR}qLoa=HA$=CG& zbI7D1?7EO1-5IU`d}|!zbr^7ENBKmfi62SRe49YpL1m!cw1OIWzZC`%3Bm+YOsR!# zpUG#YAP{fk?Ouc=iTgRrj0Dn0T!Ir2KeDL5a@FY6HDC+Evhw*39x*O#&Q&VGMOnil zG_s%s;u%D0Rze^~ZgN+>q9OAsW<3gfDylK_&buB;92(|zKmwsj!N}7H$YZ#}g7-?0 zs5N%VbY~;)v)SyKNDw5NoIKGkhzMXN5K$#5JC4<Ai+AwO5G<&rc|JDLJH@41r*7)Q ze+$+m+ZiQG{Cc)?xzv-P7ONCs4LK8W;6`5boeo@il{x<i4Xdv1_K^8NInkuK$tK=% zCDmw14~yBS-FH1`95Rj%M<LoGQpq7_et&%o#$EdIX@h$kc!9eUe|RIWr4K=+K<21m z34>@0y%0=M*P;SevXyAqxg-e{xW+-kP5>S__b%OA^Iy5KY)<4YRy5mz-(K7}HX0~Y zcyJ&IcRoNW+&JfC^O|2M)x93hsw?aP{z&u881h@Wx>YenNJ$Cl5$t+&1IVmHmao7P zgIg?kKcc1ykahxuM~al#TS1Mym$n6h#ZqsbU0+`~0fN=GC}K@cz#vY8q-jkrVc<Kf z5)J!<)DuWP5=aMtSGOdWZlH-ycuBuxp`#vx*-FxR7ekykkL!2at7y4%9%(EhgNrSd zRaed!6SPM)C76LeD(Wbta3y$h-G{D62r9D<f&hC^Nb#epVG$>`>Pi!Lx1f%&k#}ah zATwLS5(1G#-jf=E6cwf}^3X@R*Aor<MIcp!WF(NzAfjPT!++<YdKK#xPUID=uNDg= z_Rg&;`F1hHdGk2-1j6&>xK~7*gJu<cyf}cGl|6wzjQw!=RsiC&)o&#XLWZl(rAKJ& z{7~GXy`qrL7;;kLJw0@v1=$)q+OXKjYxT$Tw<OKv+65|#2640KV33LOhZ0DN|2>pw znB9?RnB-mZiu}DB38WL;ZiYR~E!rAfuR0Bco0QBT06OXeUF=a=b#bGI`gPGTr-rgt z67+{jA5Kzvb)i476$;aWIk*E`*~|p-h*j4^;t|8r<D*Y*x{@B?4gF^KO&k&TiNZgo zN5ijR)ezA~TVIm~JMRcJ@_yjv2+Oz5WUs9(wk<4lM9=+jQ%u!|1^q#b2~Fmm=9B!6 zM8p3-IWn%a9TwIkGYUkSD6a5~aZ_Jt?y(x^q<Jg{^*ZWXJ@9sl2mhrGy}wmK*hqxP zBTcu$te|BMq+B7IeR?v#KC}4FcRd)Nefmy(TyV>Sx2Nu3b<`_<L)c}$C+I2@96KnG zUBE`(bBV%o41zdC_^?pIQUbA5p<4-+<dL`z1=5^ohyvG0Ag>qRv>@XZ^FxVIbjGUY z)Gd~4)UgISDY)Sbxy6-<gohwdafxehfhitQ<Z4z)F6tkBk5t(MK_%G~OGKqjd2%s# zW9Hxg-5crQM?Q#1_PM~8LZEP^x2MO*8#RjD`u^Jxhhm4N=xpRg4a+jf(`ze1PCS92 zh9v}I;l@Cqq&ZGe3s?<_hQ?$gfxMp3rUogDlFM5!>%-~w#>l*!l|$@%kN_d}zyqYQ z>6+t6V*4O6ak1<O)|C_Dtq@d_qI2#HBGNT?&B|g@i1KjKqda@@#qa%*9vl{as2)fa z0)^|NB#pb9A^iRC+ynVPM&46wMwcLyrx&b1(3*q20|b)OUR(Ky!847Ch7%<iW42!n zN1}`b@+eTyK)ETeUcJeYCNp%^xdpPm9kNrGh=T{s0rg+ub7a5AiLAQR`KbI>au|bT zc8$1_y46It;ebJ;>v7#P>A^}1Cp`A5KOi~Cy8HOL91lw2-JL;zcn6S?S0u>uvh*da zlVa)#1mLZNFoZyDr#Uo6L!u#dNWuj!S0+oDM@9m96qu`5w^-aDHkVb$TJ*`BTOP|n zI(4@Z3s`mVYQatJESC?0wR;g9*y84NN2(E5_?b>4N+hGibv<M&)Qg{kU5_u`jXOg` zdF_7G05|)eBYs5g+_vio1ugg^-fpG01si#Pt<reiV%xd3VZpO&!K={?69~R|bjiUH zxiJlih8Z6JvUde5t`t%93+yh^MVFJwOpNHvIBLWPii)6u3NAz!Dkvzr5X7|$!Ic|9 zaOKjK-{2qk34VdUV%<7@D~C=sGj{4t(n+1}RCivU_@Zxea_XLYu1U^|lHbq^BPj%O z3|KxX{Tm`Z7|-#R)tf6ku~JmOo`*fJX(L*6<8%*tN*|mYLdyg36ip)!q+2=8w{n!r zE`8>h>*29__otNf`2Nei_Il_Z9o^-geSU0>9b@Q2tLJ!(zz7d78+m_Nb&crD_4@j9 z;VEQ(ex`$MH6wuuge=FQU#}fZGz>BuYqbSy9lXM>5XjLXOfOgIA!Ks<5vz_{l*m`h z<?4klZt<-*znQM#N*1b{W2Fz$C*-2m-S~C6){YN?^ixUAyrT|T0ZbGG5K}V8P^jfA zU;qB&fk}^4_*HK6E|-jeX^k__OCPuyRRI}05`+_Zudc!#)><S8%IJYVJS+<k2RFJP z3?{fwqG21Bgg%L>3)Z^iSBpX*)5VH($D1#$tVWdB^i+?ze|?&MD{2<3^&r`yYNHM( zrIc*anT(*3Q-De4NVpQ{)|I$*l{w_laNT!*`uxzO2cgm{@K}03PSCbX^q~T*8p9y` zcXI^P$ot(h-5%CbY*-6)qe~tZGl&p~({@<>)8CzFs1*{s{i=TrhsVG`bSuPU3V}=y zw;SoPWH0Xv(b=o=WZF~BNpsL0^?K+Ijscg{xM+)@GDss&@C8j^k#QA@<|vnII6KBd zEpDV_zI^591C|~Y4?Cw|`rUL05B`?hqnT<x4ip<XqKaPcP(f!S?>}9bB6<mLKp+qg zmd2tt{zRriquh7zL__Na^hx)xNfHRS$KMnJnH+9adi1*mSJ9{CyU!=u>rwalgF~%= zN-wEz-jq+$P55x~5R<M5deQo_&a436u>=UXI$vC)>hbp>OAkfVUKurriPqiYnrc3t zLq-g=?fZClOXPh<dkK|5&M}rS5{Pphg9u1H-I-`OYlo`jZWfUs5M!MSyJ&?#CW+V3 zImp0xLW(r8SGTvftEs7vn&;87-wNP%Ybqf}7_1$d?&451mxpU0JwlgxkmxeW9DU{z zuDkTO{q%sPM~^<p#+!jY3|8WiQ`)&waNUPoSYt6h&qR&9o<YzF685mP739peBtVcK z?Gei$_f0fR6Nrj(VTpu3Y4t^$A`oK=fgChmrnU~YW{J7?2%rWlP)LtPD(-yHT^yQc zBzL$r*uQd(oK_nJ1+5c{JM_7-M_2Wjg!HI-4fokf=1e80R5a(tL4K}vwDAlw-p9*E zUL_EbAU6w6GXb1H3w*}>pOTHxO@afQ6$-(z{jzI^^$G05D3BBaIZV74TLl>}pbRo? zfGT8_rC;>$E6w%58bGogccMAEwkpkKcTSd>omuQ#L3+&nc^)!Ko_gieKPDhObf_W( zNbbBuqf`?6uunyQ5Pk4-l4WB%(Z{0tK#jaw1d%*N_^_gnmkGqhK0*_aWn_o7O+ugC zMIdp5s}RTm;v+<tL~t(e)Hba&j-AGt6L08E6>n&}hV#V*T0Znp?m+QF=LzyqDC+gN zoQ(7U*mhRo+*ye*a~wNW{GUijstJwVz8X&<?{!9AFo=)C@&JRJ34^o&!XG3;OvJ7; zpYVf{<N$d^;ZpvtO-f@SkORb9L?DFu+uoElH9%}AiBK#eeu>kbRC7exAy178kXS#A z%wdgueFA$pL<e;nS2`7HadUa_hN~Vbu6yKf{5Z~##Q!He7#ia;%D}64I~sZ4TCJ|U zlNWnf;^Xz0>rg3(kS+-{fZx_GJ*2j6?<A16O>S`E^>lT`6av{hp7fZU(nx~41o4Ee zS3KxK*Pi$Yz-$`8G?grv?9r9XU2Bn10tkJ~e6PoP?f0#wBt3YvA}$#x*KWdRPpoSY zpk2`ToIdi#VtgA28+j#A@o9-Okt+JO1Oc1?af&q0eJ8+xQf&d;l1^#FtNL;>WGk4) z3W4kkm^wH$ckUp-7d?Pb`~$)xrUl~QxKM-Jrh_xiLwn4fHkm_u_+{?dLvVe$^z1Pe z!xgayaYvOgw_P^^Pu{#sGqb2Hv?J<~_z*_kH(n1$-lszq9b*a4JbHOp-4<5EqtWw% zIY57++G?;uGMv(=1};+wWFMG^aUjzNqzAxBi46U$<Zwh;`EyQmaw9-AyA?BvjgUS; zzn*!~5g@%D(kVERUXPAB0HRY|GFQ;?U-VS!AnDyIDxHt4Mc3PXAS3ZS{!+gGdKfE( zFcUu%#7hwLqN@fW1rlAnI3EKzrP1FcQW^=(KuTlV76REDmeY?$tZ{I=AXYiqrYa8w zS#%Xm0~;c$9{w=S*>2+sTUT)EqRkx9?2>SG`|}hGSKH7{tL&k>Oc|%<;EnH})7$Y> zpYK6_kdgQ6M?xT&Ds}BO$i{~in+aXq!BPsr8+tr2N+1IvTdnSI%~IQ67KKPx2xL!K zhH)ShM%<zTB6Z+WRn-&NuA&w>nnl51kTHcV5QqSo4xwajF&D}o0U|woKH_>gC_R4o z@BpO;z=T@mQXu+4sRVM0ErW!r7o8|D8OTFR=%Zwa8hM|S(df_WSVA<T(^M(8@<s|t zBw*zx5$lpwaw>rgrZi%vdm)fL09lG}KQUeK#+95jl9uNQVwxbRL^*>^GwAi`G8{Vk zpt^_c!m8&ULLb+`aP@k!*W;594p@57q;omzoT(+i3Fhr?(`2LzZUN~o<DlEG<84@K z<bCeZqt%rJ@;>DSh~{BQ9UVl{TI<3Q0^h(OBM2n>23Lwe44SZjQbgYiRxhn4T|y_# zfje?rVPzOudR9wR3LB^Sy5J4~(qrSfLa#^2M|}6Ef2Soq`pDflsQZGaQ1iH>BeI`) zg}Y3sM?#If-#+)o1tQ&5frKi^d?r^=h-SLOj<`Sm;FQM3HK`4*2wMoG;9jV^3-x;F ziVM4pQl-dPE^lz{;GjI5ZFC;(%%7I+x*_4pH=193`s>uB2Mu@EyDF3Zpxu2rPBw3s z-!tu5WvxGtR3L2R{pHc4i!fD6n$eNzE`$2ztC1}2EM~e33<dJm)q?{Ba(7B&+ZF;T zxCb~-x8G|H0@1A*YIE?Qk~v50`m>Tt*E<zXfe7Z1QxftKJ$$c~OfwhZKWXWq&CCg_ zPmbnuzn+M5x1x3rdZPDf&0%(@4>?9cjl6yf>s5>;^ggUhY+;>?p%?XZQXnQeOB(#o z-3Ks^-4y~U*abD+u<Bsl0XCtLtXRTTiDR><S2wI64u@Xz)&sk%XW@|VXE*B*&Hi&r zdVGHH(nFwuSF-4useB$g_)jP8ig&6~t^v+0!Tnfd^YN;Y_XSTN8mOpq3C|aSKu}QE zNM6)G1WpnSU9%q!8D`%`s6}Ib3xO2e%^(mUBtIZYs$R1P{hiZ%-8f6Ik|mG_a@mdZ zXjFPYf2i3?s^$pS73uMJN_u?!;j{IWpzNx0Bnu2qd7MNIq$3C}ci?98%p=Db^g2(T zI~#d__5>ml1iggt@t!XPkw9FR=^k_7T<q6ts>8u1rO`Q42&7;bHKmk9xq(v&1Zxa@ zh-NFUn>Scc@i4IKVy2*0%;iM5uK2Cc>)|)9Rv-SAmL8MXxDr%EuQg?uWWq_XMg++% zrH+BoA7Gk10DJ77$a~>^yrC0hy~b22Z%Pk<7@4V&R~n*VFtKR(My&ebK>7%^LQ<kk z3I+kap`rsT-EfdBmYT*G#Uif`>4fxf##&hrR1ymx0in@+?rY}jwS<(s`{(bImmd1@ z!@{G+nrCm})Qaa7lLxg>5@DDOyH^?KqDLd|BMb%cn^?Y;5I)`;f6*#Pt3`C3VqokH z7)mtUAFzwnHibY6hM_xF{z!wrp>a*OL$#@TgomS|hbFVn0(+q9F`EbJu@2JXi>XTw z(jOW}oTGeh*raOA6pH8h{&=iAD!u4cj?Dfmu7T`;1@^GM@&p1OmefE3fh<5Eayz#k zj(Q1+K%~GvkZ8Eyy)9!3ffU?jy;2&{UJs%VE}R1f5DgAgq1+)V1RK0o4ml}Y7d7+H zW-eo)jzM~;rCCpyu(E*6swdVs2xdsVf4PY#kcCIs{7{bpC-PoM8dm5f#8krbxtAU) zK;~O>rJD9WiH0qlQoEtdL@&r$Fjw}F6OZ_LNLpUEVhlw_)c9eJ1cJhcbzvf{Bk5tS zj)iJv-%93std}wsYVuVNMWv@8qkT6zjZ}k7F2AH2|6(|M@4v?!hRI{^ZG-|f@?J=! zJ32uwuho9F2&e2*kph8e53;<2Nme4@q%8zea44w55zb!U2S6M6{HeI*(r?f)SjiH8 zDrlnMEDjscY3AogCOtOtqoPYL^+DAozf6fa6uZ@J`27Ry#`1T}DLa8h_Aa=>-{f1# zQ@jc`taZmAb72pE6S7P|A+eRvkpM{~uIo3jqCg7vjasj$cz`y-qry`iW?s?G71Iap zK<i*A=V}*Vr0&t^u9eozg*h<T;~aL~i_eZldTbf6Kqr}C=;mkxOsc^rsTolTxsg|a zXp`(%R7n2(?IKjs#URoR1)0xfo<CxFbqgy{hyj7znP}K)5R<HsxFoR@0x5VbV6!fz zT>*(Qu-UefhCA)|fbk0YBWe$XBZkQybHU>Jsi%&_aMefl<V60=oK6EewL13t$jLzk z=(FKmmXxR<Lcy9B^^O)SHuApy%$3XpS+1oO<mN_af?z0!Rk+5*ft<qxVp`3_^+;Q7 z5z)9srG-EWvZ2-mvV$0d=h0GB34i(Juo8~Aa&mYyc2o5T*tm5eJ%U?zb#&5WYx*Fr z8DXZ=I2flp4ZqCnz)w<0@Wx{_xY8EnPIwVUUg-ou8665FFi7AJD@TB{sDPlywsY}1 zGmvNq3b9E7L748APpc3}K`wA#xq!5XuKLke$4AYZ?^xxDMu-|Aju?+9;DE#+Jy0|E zcHLu@9yL>L#@0br9+T+*&_5*KF-atdgVYMHQIyclLxcAuM?j6d-}xfQvj|iKgUmg^ z1HG~64g`YlT-GH6sanv-fIhJn1kw}&DR{i#Y(!l3mYb(_sbPMh-3WMf!60%Y%z>#M z>bFv*9p)cMfWwhiJ$mCmaw`wDvBq!phwkI85<w(H3QR6U4@@k0S#I^EhaiwTrwxmZ zyi!G10=c<{4NJ$Ox4eZF;has|tgI@KB!M)WiBLAFPfXJk0x8%X^)@!LWTQT6Dwpfe zcoPj*Rp1Vcg|g9Y1;|b;7^JJ2UrN>Es0>$W4iRM59$ff1ys78az=S~DF)eIdQ&{`# zfjj08;*<OCQ5{YrVI7UU(n^SC^h?hm*uwIVT_{1cVa2h8c;~~3hEO0bNg#3v1~<5@ zwZ@o2AO-hEjg>sR6sn7pzd}dTZq0QMLq!ixNOabjPJ6W4?a?)QgxPCn=P+C?Uq4#u z(eq!)ksYSH9CH0!{&aNl;1&)%1j;V-erT5pzZuVY{K<o$&MHCF$oq`;60W-<NZ^kd zxp-+0%fzW5cP1L9^$B2;7Ol9!RS2Zue*tw4Txj2lZu^<BoSZ=kB{<~9HI)<PEvE}L z4+~YUeqHSpT(b0FeEi|_^>Ls|<P+!2-i<YZ!z2&=)Mq6D9TLR@69Fr!_z&W@6MN7F z|Hy*^I&ypogpItLI4qfKD|=Wn^F|3I#wp_Th?F{<Xh>D^G=U`aiR~&Rwh&0cxPk{( z0pH3Edv)nb<xQ*<-6xWdn0G{(-88jS(eMH5cjOaq(?Rdc5<&d&eX_)OQ6A&IRtT zKDf=Rt#MDp12n3fO}LRSs5=tBTPcD_L~pot@PPpOkaINH$h(p<I^wVpXA+t~#EI3$ zHV_LFBkC07T~1AWvI8OlU)`|7wf!>YorAU#87YE7AO#z!%ZjbK4E~jL?1rYY>m~Tq z<#e(-jJ^STsPO2x18wFWFa3Pn(xX4WHY0n)ogV!dJ%IhID)mcxa+3$0edQ6K0LCOF zFVWEdopgRMQ6_cY$crj^D1!J+EbaAB#5fbGBn=}eP#Wj7g(N{B*!u!pdV{OAVUkrL zkb;O>kA66N_XARC0R+%p656uHD%EqTnY$)9Mywo-ZDYRfEC6=hMb~Ej)!)Z0JplDx z;U;qd-RP-1K8KZIQpKyP34nQn)J2~Kh#-df;lcDrz5Q%AAFmpD-x42|S0LEK3Jiii zbO?9<5c4|)Dn>;&a%6|IHod{s;uub8M95YlkpI}bn$>8EDEbCfWqRz!ndBQ2e<F$z zg@`{W2oX^cT&SR+WT6PIT?npRD7X`su6zXX4fI8P73<dNTXVdrwqs9^>CE&=Pjycw znJ@Xid^vOKo_p?$Tr~%2=mL=2)Mw4ko71=n(CHCUfB8a0Hh$Jsb_hfiOVOiVrfBwa zDVay<@yj7d55RHT<!Imy9ytVepMvH1T98ZKp}Tipz)VqAAdE1D5g2|eu#p!<5J}{X zKHfwiu;Y@Iw`ms2AAzN3FIYq%D64aWOHtV1S~T@cAO{am7c@nXox7wsJcxr$KAh91 zbD;pCjx@%cEW4Ox9uG8oV5H!q>(kG^ElH2BKHV?rp`gTKKeG0q?!k1PKoQ+|t=KqK zpoxA2mRk1vzdQI57=#jeMS{S{iz<4`!_qx0xrv~sJuJ34-yR`Ifuw^#C}gV+-5Xqz zgHqZ|oeAXNz>))33Qqb{2JxFREs+Sat(r8<9N~z$+XIarRP{Jd;kr*>7pop0KI``u zP8FRSn?tw>XBzE;>;-e&;V}f$8o1{?UuhK9R@+!=<YfX;4I*XqdO=l?)C-avj`a6C zIP=CLP{>wYPH9wBW&3a%vO5#VKEr#yBOo!N(gQ2td9#E=+4Uk~fr(H}TJQs(LZ#KN zE9`N6oH_+huD<>FkfcWoXDE66_!9k{Fo7W;Mg+C`V@lJzr!W%T8hM35&<XP3ffhla zK&Xtq&`kFLjM;yW4X(QN4wv;w-7|)yK1v&0GlA?Sd^(WF?rD`Xh($}iOdK0uOaMR{ zvZh2&seCL@GjGKQeg<XN3gPUMkC>_+Pk;CGH$BqB`7Y!XkaC4#(r~U_$E|>v^x7~D z6`~~%s*MM%`@$i4^NM152Z4>eXhwhZ(Til{T}6OD1X=`97cc(*1#An15eWpF2E`&r zr4fzgnBS&pYNRyI1hRK9y@5F>Q8|Q$4BC-738p+-1$fc5(;U>1C?x%?qt6^gkH{Zr zGe5ohV@v7bx_Lz(n+A_KEOtzz9OG$_z!GF){pb4iQM=$?u!naBBfNl7Bk#+Pzu5Y) zQk+Q?Agu(ck3`dRqGBeH0Y<F;0!cT4^p7Dq!Y9vLSo;Johd^nfBVHU4yZ=nt4KDb+ zZ58iTa>g{lkh(mo<k@XB-YWU6Qt3~^5g%DayKb86@$`qi(xYrzqNNi~4p}C`AH*K{ z>jHV~06~taxOb^59EXy}e(*;pg<u^9PULNUSQi%$o{}QSk|YRiVJQOO#s+q%OKs}^ zLLhJl1NBTG`vmVZjgSH<ftZ6rUU5}9ddY)Kg@xP%HI~hfQ2fcqNWpb1nxEWWdgR}< zWLfh3{u`9yCcJsYU;n5HCIJgI<^4bIU3cpWIu>e?zw_$%4!c17Hm_dT$ctw5i&#g0 zRAk7pIC%xkA9)XJ0DFwG!G&p5WqqO=WG0aPf%l$!Jpe30)4q^(#T-K8JovYq8a(u> zs?rhU1nxlDyxq3K_NOQh_;r_UKH}wvzw}9u@`e;M3C;}Wl?m-#Sxu+No8}`HKRAbs zvHMDh>xnE;?wF8y3fOg=qVt2GMqUY2j0!{~$fNOgejc~6<o^>3kZj|Xr6PCR?os_~ zg=DdbNSO&_ufWxE6K;jM9>$yqP<Rob)6n9&z+|X4;R?gdVb*;_g4rcqHziyRsCqc8 zSe&UNIJU!j&X$@KgP>HN8CkEfjw3^KXQ<eLzH=Lv<7>K0nVQ@Mc=rt(it(+yERF|) zjl7RPA$wS7>xf7qPpy^`%3H8usRa372_%Gm0)bv?W&*jt@N(cRP`P0;b@d*PcjlIl zoNt9Q99Kziv}n*}9;qYmjEY$|wV5aOc)CY=l%YW%9w*a($Kr%8<UA!GmNV&BPJL}- zS3b1A;(v8t@rw&r9y2(NKEGXqUd0UV1z{uam#3#MzWBtMAQ4F3!-6qI1&FM|Alys1 zdoYWLf2KQ!F`nll`h7-jFpuD>2NpbxpMB1^@|!LKGVCUq48I4gR#j$@x?S2`tEJr9 ze8gdfD@PR4Ni4V|I>GxVrb3*a9DSj38@>O7g3)o@MH$378aB%Yu|3<m+Ci2H8+m^_ zO+!J}qC%vUE@mtVb?2!d2nZ5YvRH_#WjfaAyulUMnLzF_NN>m``*gE!mq*b$y-VYL z;(``I?RjnDk$^ZJP1dcEtt%U~@kj|*kM<d^y5U^end=<q*m7Ng$z>uwUMk$^DHF-a z8H)T$pVYx_;b{J>p{os>?OoNQj2tWwZ`=5>)X3XLx<A<#LLOXPoJ%u$T}wAQ5s188 zOY@?V3Ymz*EvGbARWo;@-&c63jsocY90-fWXU7aj>qew-UAan49#}9=5b3%YXD*O7 z^B%(${SWJA59SUof0SD*sJVhZq941b8OK*Pf7g#Ue30kQ^BtT<Cy&C=D!gk?d{#Y# zVd2Mk-C`4YpL_ylUXdU|6@pC-y*{dCs~CY)!G)=akWe*BAk|DD_X=LmWVXTuklM?+ ze(o&%#uTbK(NzLWgF+!qj<=En<RJw<M6;)atIM7?bHMdB29mxYje#2%Lgb1?NZ(Vt z(b&axKfqtVQk>q#_wfc6Az*(jI|COw<e(9Q`(E;3P|oOf`j?HoU&SIwlpiUT7yNN9 ziHekFQZ)^Nfg+Bui3M<?;hh1KtY!kakI>S&jnoB~*gy@nUUAm8+!R%4TRnnWb%DAj z@{kuoZPjD_=xKk#Rfh&~hErTuGalC#@<&prgdQ1P4q!Qkh!JOrg709lALg)*4->;H zr+l?TINW%K2QkPbUJ36Q*0E^*{RaX@-oIWxjpXqp6o}ZcVhtn(@-EUI7O)hj3K-;( zrpjT*Hqmeb{}eNU+#4uSSOQV-CW;;IA;_;@;O)Rz!H7lD9|9<kx<<1HeuS4RF<h-< zug7&sdVKKqvnA4STr6PLD7&c~Z&zWl518Kd0!YsA)6qRak<e~b=v`@pO&3SCbNYMV z1#GEd*A)<evPmePB(8_5K%CF?v3(-%Wf}?+OCXwPa=xTiLSUI7^dSVI8wNxm=*XG? zhs*?Wf1nJ)13nnsIva4N7QvQCG#|04<ZS`RRnzcf4}sLoReD5}s~%s!x5}k&b|VpG z&@Xa&fDUd4Avn*Uns2h&&ovT+A8%Ls#BA*%4&bM@;>eLYD%AhU#5+FN#LEqz>6*^t z(+Br<>{rg!P;BWTXCv=V(n}}`L<nSk5fc?L5~Qy4CRVKkB4v;es!ZiJ(Qqb^8MhBf z<VJInAP#2|9C9duWWN>8ZF>@0%%xW_BQ<-ZM!^V#lwhvM$@PzA>0xT#0KH<f4tjY9 z8*&Q;klZkj4`te5IfJ__9#}0fO)#VA6@9q<)0yV@89SU~9JaC>9a4VvA9gmBusEB1 zFFVb<VPw2fqXPv98+lJtA}^W=(_E>g<dH&w5P_hKUPFLDdzwVUrqHX=%kwjV93r4R z<YX%z5uBuf6L+5>m!#zm*Ho?DN|r^u36PG6gv7Sj<0+LMe-)+2u`-q%p27s#)=DhG zJ|%jLIEFsgnMZL5m`|9v_)jX5fSyTjaQ9zHyExB%WUOU!g^4BBu0T6Uw3{@(_;5Vy zaPw!l{fcNG0*_^TAC?+<rIm0q8C?iO)P~3pr4X6Srh`I)%~P!EHcUiL<z9_{E0D|t za%iwUf^4;-VmXb$<BF?}^+<0nREX9^L?V#~v`6aoi0qNb<Mg}V3ew|aR6WcN4;iO$ zMLiMelDbi_@b7P2<`b@UAzg#zhB3=F9$M+Z1jk&!%)$x?&&1-!+Q3XX#CorGphW@} znrDl3SRSIY*L?3#Iy`O(Z^~iAp^3bY$260a=^p#gg+C(T!UBIF`{5A*B1P!mg+_KD zkg7-^craeL0%ig^Fl52OJ6K#x$dx`>Zt_QHy}I!NvFzzBo|Qe2&n`c$BAd}>zAj6T z_upHYJO{_c7rG=G@VH|Ap=Tun&M#p}L)8!BNka_OCt`TDP=v?gbOpEuVrwh3IKF3G zWQIV-gq<&L+WXvX$fGw!%eBkQ9XC<<_a6i`@}9i-c&dP;sZ!?{OSl9lWCnqUC0<eq zJ!l{mN8(yYbu&HFOdvBNm_1~X`-Dv>I~y+{Jg|a4<lMCJh>AKw6RyxIm<(4@dc600 zS$eE)6a%b<l_bPQp%9c4aGl?9mp{r<jlyH0PbCGxbOmrtq|>d-GKLyD3MR0^_m2yL zAD=w3_@HQaI;RK!16-hODu8T02h(GI8;lmg#ztOgMu!54dsxTkE5s>+J`@<2kg`lR ziHg7iTL$u0H{ByU7BhhyHau2F;tw;zNZ~g<#F;rlfcOZ)8gdmuMRSzPv2Ueq=Ig6p ze<@0jCwQxfx30?J4_@!kV&w^IlhXbVX)O9o(irrG+>iwJ#1o(N9&YB74Y$Z?b$R{6 zYp-3e?f1_+U;h(Ap!W3bT)k?v!gV-+F7r|16bFNiyzN-R2Wbxraf*-79#+%lVa0`~ zN^zng1WQ%OI|RFwCqf}`qN-*BIRwzg6`*Bw{8V##c*xfMTsL>Q(R|SaY+1#l#-R~c zfQ%HBUXPQHI;6+3c_GdP2hQ7~J94JGxG9(p3h(UZCYCWySAZ1(KE2!%XnTrTYjDq4 z#_E&T9|qo87ruYol=*hz#G-8XEHtydS0Cwz!-|D`7IHd}P{ctckkMu-vyt~q_ppRO z{@IHTXFVb!B7&kb(U8#`ZBQf-`2e(#%mlLE@Br^yweNN0+Ku3?Y&j|f>x%Tqk|Uj~ z1pxYZL_{*G9_u7MelAN7{>|#xG)%uaJNtP1tS$Dv{U5AUMH-;wtYYgfZ*>Vg6AjtJ z*kYWY{pGhF&UpXKeE+0!c8NfZgn>8(aQ`*h1Uq6l>nitW0x5vng>W7QHu9cGFQE`f zigOnQBFF@S7kdd+(`X+^1oaW-L_-UCKv5M34$cH}5CC&1sBw_yK~bw9h$F}y>|3R} zIYLUrvs)+mfw6+9ddRkw8m>;>>y#d*aA<5!hAvE;pdSz&QKTb=@&M}!Y6&d(wzw(8 zbv3nfv7R-}naGcf@9p=WsY<X*79r_iCOOGU=ocXRIaF9VycY95c*ow5?TuJ$<b65v zN7}=B5EaOSb77FkAwmjp@`6DC9&7765)B!3cKDVzxEATbnLzd&sx@dlt=rgyY+u*L zZ-tIQp^b_w<~440?lVs~K9_{6Zt20cCQ7q5W#---h@Oua^f<m2<Nd;sIfnYgZ9Z{1 z_DUa#>+0ppOYlR|AFo}1@&km(Cw2}m+sk$Y8>i@OZ()1cOCAa?mgmb^f0W_57Uu_p zjl7?pq(H^AhXor}s)9g*P#HvLqtghOVxl3VR*P>$VWc1)h6ZsK?KIMvK<+U}cgU4m zujn_Tp4fb&g%3m|E*cnitIagpI*~_P@mL<+QhIPlAI<`<Cj2k(-4Ut$br@Fxu}7&b zgo!}8P$}v1wIn;<IdlGtc)o`F>=Sw4>*`}R(?E8MT<*Xf90VeXZt|c{x6i%za|O3h zAb1mO$sugyef-52+dV8)(N}0CR41?Iy6a?Hex<+&#Ue+o3dD60Nd0dcT*#0QGlASw zcqS3tF~w?mQ!ge>_JI6oDm0k`B3ae08>4m8L|RCXh)%;5m7uw`k2?PJPCvXG7tCVD zYbl^FmD!I3iNf$tUj5l?4=X+s0dl2ea~<FF?xnZi|Nq0I0XKl<0xp;)O2O<@X{V=} zMnL$K;klH)%?1`5dH*~?nhBcGA0z@vbJ2x9<PAU(B=0K(+zh%1q^_Dmh2)4pPgO{1 zoC)Nfq7<`B22?o$=d)M2+Z=Td0VYB<Dm;#o_*lkUn(LA5x-WMcuFSp_*>1`4N^RtK z1)J~A9VE25r3YuFWO}iM`PJIFe-u65iAS!^ujCQAOBEBQtX+ajAAr4I6dWOtQ|o4v z`N5@JZINVxV>sBz`x1=2XQ>n9sbdsD9%=WMxC&AUz#l!M(OE=*K&k>m94R8nl=R60 z1k%g|a(}_Sf-FAt&~(%c%rkFtp9kopPNU4Z*+a6~k#N;*xT45fXOj^5#l0Q_1jop) z3t5zK4+_=U0pIl;`rV#<^4i1KE=0}2cz2zDbtDP$I<8Gb*RH>R5*(!hNq4xS<4L&C zATxd3S~G(=IPz_zMBdZKNrF6uBFHk=Kv;p$CKe8$M})*@=_8OuxqhP4*@Lr4Mb?=> zCXOsWu#nRyBScWyT!;hYp&O@*1Sk)QWoyHArBiUd{+Bj$r4L<;RH0mAzN-J3NI0~r z43;1_x0~`eL2~9J@#*?2shMA$`Slf;<a-M9y-a&p${+k}cR{2K;tB$pbamJ35T??O z2hMHVmOI$U`^%|Bx}Tw!@H{fevMr-8Y7{|KgFu1Aqs4&N9E>2;(n%l{2m~k(L<hHo zFcZiG;VC&07re`YOSS9+Epr6!F^{LDJ+$x<5y@lqRFCxF+zxIC#C=W>G4Srr&?zoR zg!F{0bNS>|p@*~YqtgoSjh7LRQM*Xm!}^4ujtVGu2c-u)xzKUD`K&btfg=oXJxU_) z(~&`BDB+_Qu@eMEkcgB^7h!E!f>EpvL3<G8*-QFFJ;2>5jR@JA31oT@{xDr1c?Tw5 z>x_?FG>=D$x2l4wj=HJa?W?xWJmu-2>am95syE?EU<Z8r0ZkjbhZRCSL_v@86)U?$ z58#h@c(j1LPwj@`HDMH{3y<3!@+n)i;)+XdRG&LM27zmTW+>rMa3XK4qRSpu8j21d zR$Bxi1=8BE5T~e{SR)aLJZEPUdokuWEEdg7AQOd${9x+fQGeF0kHUw%34v5iZZMBa zvT{6<`pnyXs~*D@Cw=JJ!grP(bc1U$@XnyWQe%lHyn}A@O<Gp6U9H?^kjQ6vhx1eW z{&O=3a|m$XExLCpaY^gaG|Zu3BX0^+L?_5o500N&9WR${e7h<TEuuHD$c&Q}fK9Br zOdtygklqch#iE%BWLiMCAZ~Jpnj38CqYAFAn5V%|RipXrb#h-IBN1-h)p?R0<*LUU zZ@;<XSXo?BL{x7}`Q85x^_>s&ew}Am*YCXZ&S$UiM|}?KZZ48zQ|mcuY(J9^xSGuO z4`ki|htO?q4;*hFYlJvOHuAo3a*8w)WV$CK@A45OTxI<cQ7I@!V0)CGr)rwqX4n){ z8uJF%Od!*Ow-Y~1m$z32@t8~N8hCcwc&i%uh~l~8fwUK~X8zoVTJ>PO|K2mcV-AzU z#YBEJj#nvRVp)BbTRq;o+B~vKuB(^xh6QRK*KE|4!umT#*7zyBSf&C8rzHNru)IB7 zNDT6b?^w+OTQ{RWl<@ouuS5|d45E8jB0-V_DC}W{JQHM>sMG>1v3VtZBA5weiujwo ztJ`g(2%}HXnZavzWv`PaCMDr7tqMjEln78zL=aLh+K5&n3K9s!H5W+S(2G{$4)Fjy z1aH72@J7rxXJ>Lc*^Og+ZLgg@w%6;Fx~*|?e7^5|=Yw+>;sZA#5F<DC`MZcKd%&Pz zH>HmTsS_W$oAtQ+@elu2N)P4_D)mx;x^BeJ#Cc#OG{6Cg1<avqqpQH9O1^MJGz%lI zJ!$I8LJMeDVmFkY;-kP~zyqs17&R-@(QAU!w+=pb8blPx<}Qr9ZYd~*nYbbrMe@#{ zKvLedUQHlv39C^6b5H|>=HYZ00&^`eoxrghmYJuZ55TSBx6)&4jPzj8h+Q~oL;-pN zH}7Qsz1VdbN1=}O%n=Crmw#}Qg#Hv5c^mrT7<+40EW6fYX+tYM(G6>ZXbxeRxrD_= zULg?c!;(NnksyvhdYwXp&>*3`fkBiiDiCUJFh)w@l_`xtYSA{)8wAfDyt<ZWKfI#` z3A=bhg{@E>pUp1w9<t3GU61o>>A_I`#&SdJ#(uu81!rK5)AReIqLTI4Gsq`sap+*1 z9=fIotww~Aw}}m3z`tD<4_!XkS>d<Pk;J`@JoGYOZcVArGe=>uk@tg#2OHMPJG3P% zN;Bzo3V0uHu@uA*)SO`~N(dzD78;}_kVXNF!FxaA;b~_C*T!Du4727Aw2>AeB{J(# zB|V<Jr>o#+xcM8uAwLak2Rh|PXE`1{JmD&qaXpXl@7EYhe}nr_F!IVTuIcMj2ehKD zGdcJwJ>j&*#Xn+tSx!$*^Ep_=A7+7qk@ts(4{Z%=2eX7eP%%^zoE#BzjG%}!xis1> z0T=^Giw;RUiQXV+4s9>4ijgSC8}RI6v0y5f)N@BK*mbwRE0rEUf6LONWMB9y6|H8& z;6(W2W95-!T9AyqM_f^Xk(WMR|KPrGYhJDi!2xN3I<8R2s}FFXSCjeV@{aahE)+CK zh`-IOP`|t;c;hWgAlo1iWV-h)3IfS<j1{5@65Ftr0ZwU5l9oW41AP@_`$1fyl8{~F z#sz&+V#g1fcPx3J>oI!%*RMB~9*WPEyWNh@)ZeoaSCF4jTjP7z^Pq7T7<p-^q%iX8 zmOo<Jh(gj>hQ!?}e4W(_iQsajqL=u3^Xhv&6WGZ6mN<DoyoWd}mxqN>5PO#sfmjH4 z&|ax!F^I91^Oisw2O2$x4~sS*8D$WKlZB|OM92eXJDD@@=eaXnZ6E*kbiDLX(E|!F zX>Lt_dgL<eaUruF0R}!?#wR2}a`Zd^t;on*_5|zgRl6y9(7-EiiwqB9+R*+Ypk?%e z@|7>Rqdv>RplLU9h*PY~$otm8h8THytCaN6a|aZ(IFr|4m{3mD@?d1J(X<58AW#bg z?BSqYFBHX3sa?UB0U(^cBR%si!RX0Y>A|2ygPgVn=(VAb<1p*-$ED(U=;a3C0$-yR zM<~MJ3rGBFI3w?xyhJtGtT^^K+E&Sn8_CMVH7;6|rYWtHOdgS9S=eVB%_6A=16FM0 zl_rQpx+4xtidY?sK_1ZeiM%G%u<Row8a8BwOG_Y21}E?0LD-dKAU{IiJaf_`MdPF2 zhh2B$`1kSB10ddz3k?o7ahhvJd~)(S;WSrNqf#CuJ1)q`n=22E@R9?5V$e+sfsR_t z0Pcw{=oqin59=TUSA@G*G*b&@QSe+Aee=u$Hu6ddYq;g&Oo}FmBM?xCG}43q0D+(z z+Oa?&RRhox$kI_z2aolM-CHI;+{_>dq?-tR*sIWov+G*CJwew4pl?=%V<T2W)eQ8y z887ln{qRB&yzF?S*vK2;jl2Pck++%IO$!5eFrsESiw?fybG9@2gMio7tC&4J(JcHm zk6CaQ24N%byG5Fb5Qtj}GLTWi{=lN(514t2F%XonQuHBO0%<`6f}0#e25y4&Etnci zFm7IGkHMZZTzxUF>k%U|zF4eTXvvjXkHho(_s<|jUIv>L`W=j844?-i?<xIQA|o%+ z&CA=!8dVV`(a-u4)`%Xfvj1A)NYud+g`a3)3CLs%u&Bp|#YSF?qDvEGe|OV2LGl4L zK{B>s34vs3hZ7BB+-OXsC6M(2_0O3-jCOAXum>Q8Ps<+8uDieW_Qk}~15p0J`_-G9 z%rONZ8w3|QsgbWn)dT`(6&ra8F!It1bbfL%%2f+;CCQObtA#I4#-WUos2oP^?fDal z|8r*VpT|btpKS%}LnlF`3F0R~T!eOB_^|vmVd$cV*{|xA9jRDtuH%uGK-L9J9XMC^ zddKA@Y9qBP7cGFa#7;*duJ*S!x4)ZAdc@z9Y}v(w2Ib1u0&Jx{=C;Mr%Lm|xk`fjo z63?hf!YvLMc~>BNd{NMJRph^#u{{urk};or{2eQ3J*OE$9P5cwWFzl}tR?g{tU-}x zVkxBPfOL9k<`A|LD%0&$69{HC#um6*0$CG~b@xi0*Cbds2>l^pS6B<RwLOjW;E8jR z9&77Cb+aDarno=i+SZYZ@#3;>mB+uAjJ&1LYx*KqgDtrW15dr;I{&=_tUzi+F!Fx1 zEd(NyAW$Gyc=RNZD0i?#khva6LKKo-Ni<~0m@&3_v;?yLfa@wmVWHyg%2ztUd!}&i z+P25u?&kjf{?5f;6G{&Tn_pA|cOumWG{vjA1?>*TAqa$wywS5A-Cn^#(25lZwYnFC zVEV<QIKFK@7A;NBA64w80ULS$+}M$=gtC^<H9?SvWv9Dx5g}>nD_A~G(INz=+Fwmn zj4b?WH!+nvKw1J>3xw=;e-})Hh`++vdDj)LHibUk|LxbQqz8lj`pxg2=TrW+*hy7w zs$v2O8U;pPHguglZ<`+EYL#oaEDTgZqJ)%a^Rk}Dzq!^pMK<zo$YNWvVY#hRt_0Oh z-7yOck~sw;ZW>B7jKLj}tUQdQE4v6=0$Bs-2pAsJca)p_aEk`P9zq|RTW|j}o%B$2 zU@hMC(8T=s^yqZT5fGw)2xO{?3FJam7<u#a;cb^51@x69-Nk}@T5_Sz1P>?Hk7#6` ze9F@y7<u288kR_qO$+2<Nvbv$+jfiLVGxMhZ0qI-Lt1b7$__6=k}?7b1uoMP$Vx-& zS0~VenO+kAEi#j3uI;hADcIjRjnv2E38V-6EJN$D;XeuChMIl`<b|rhMOh8&2%JGi z-o~yuS`s)#gl1j!;z2|1n(ZJK+~BLd1;TNPv+xHSd4B?d$XY_!uq>Pe>A1L5pim%~ zB(&!cAf+4t?x-S=tk_uF637~WcG!mR0TZ^~Ctd5;9qjGyTK<rrgYTZcB0YZjI@dQv z?5U@Ea-%<0lN%~Re(>PIXgFpF<c;g(Nz4x;o;HuEtMy++({xlyT0Da3oc=P5`t!+{ zGHYw7tDlj`yJKru*o-a`1V-LImV!hKA}}u2s7N%-O1k8r4ivalb%CptKuk*@tAmp7 z3T1TB=SngO*d18;vFEB+d-;FF9#6k~Zwm5Y<*nqt@hy-mZm4LR`N`>UDgrTw#7smP zkBGX6PAYL*;uN(*94EL$3h~@Q1ufP>b+bGEocP~Ab07V@F!DlzAW+dQ1;Ju;pc^rW z@!Ls@^B4vcfihKzK1tKSFQ#-Mx|<+r38eAx!h;}h3++})_H)M`7P}I$*3S=4UJLkp z684BWij7x|w_uSQittS8OCHav2?TslEkPdT)d}yp9bg~c;u4mQ9|X%qGr&=cG4Rzn z{rlN*R#PJHeY;W$3S?^^MqVpGJO#)l>_#tqyx<Ulsan}l*&zw?#NH|vq6>9pNzxKX z)1d($qNucz-iI{Jt%|ib`(eboGWwFb`|xQfT|LS56rd5{Ra#@=-B5(#ANFg6)9UKi z(RIvZ@nU$%C`S?Dw2mu!pH#o2mQN^G^G<jyN7rdQBY;e26d~#x7<ny$eCQMiwn`N# z?kPk_*CWiL8+)w^EJ2q%O{;2DN#_zJ1+FYfIxT^$2K@R#IRGL(dVQe|=ntzrdT!lE z|J}eJzuePPL0v{Bu2Q}(yP<&L2@<aUI6XbQjzK=Tz6O=Mr#ZP_JbLDWP9CTUq1Ub* zqAR`@k9stNJSzF5euKJJluTcjec*{V@>&9M!|0oE^7buyom3Qv7a&CmD^sQrAxbV~ zFk=a1e1R)XS^`-CXkH|xta!}(?jjiUi+#0y%O9Wl-p91XD~dhEcSF;=A60HBgCG3o zxg!(AC7w^vK2gJhjt)=<J3Ko+K0iDvuZG>~Cc0MKrfxoS1W=i_ra~jnn^3>SU#CVe z^13t=C=diHf<Od9Af!O3iscJgRWc+iBM?-#P{Zn$&`Ww9y(Czw-4aMspaYCdnu9xB z^{UeqU|Vf|;PuC&Tu%m;_)&P`ip00`<|e@zE%pEnkkA<0J{ew|ghe0+kTTp&x%Hr6 z8)lK_b4Db!D}s7;4FmY(AE4uuh>g5%7=2Gl5O86U1POtP86?P*BjpJSTqsjj>XYh} z#xO$C63FsVl&|h2ws0lL<(B8Y6yYUliq-m||M5gm4q^`){92ul%MV_)OAV=JMXP8l z+b5%vXA95ug6ZRAq$Y-5FC`LuMm+1$oWA)aQ1x5X`8jIn0kM(y=M76BB0*daBp7*N z<MsSeFh~XgGBbg6$pXwXh&N4XYzbuP&;r#>!5)Am50l871^m&Iedmu~1J3j$P&g1) zL2y_Y9HL4Td#i?(Ji*9`S}LXsk3&EH@K{ZYWN>$LZH&BHU7-)PLh|DhoS<7v(gLmO zt<6Ue8F|IWD@I<+AT$TUgCH4dSkwcV2q1yfcSzKA1X89??B50oq$Q9hK;JRlj$;kE z*n9UsHA@iQE{i|<f<IpazSTDd1;5FS10b6IA=xNH_i-i4yr7;s=j7gS*5f2z12sH; zetLR#oU19(+q}22vGJx>Gh_MYI8Ejy9-3P{5u%i?W#g1CXAxX#ppRhW{oFM{>|$Fl zK@jQQ>(CfTNW?+|L{FQGh$-bXxrRWXGRpfW1%+fSfh-w16Y0_GdFj#3v{8w1fdyTp zr3r)NpH87afFQPUw*q4ymoRdLXka66el>!`yhN9zYSv@O0;D`(aeC>oy#aJp1ihO5 z_n=ZiA}iJWAn<NnrR#W|`I+jnV6l-GKCHXaMn|Bc{AlP=4}`)@1l&V6Gf4divO410 zl*ZJ@Y;{`#Stg`sE}{SKAS=g|HnP7~B}U#TscWFSj>x^I)Ac`;T*Cp^<`=Q>En)b> z)kFTF|49^Zm5(k&fK<etTo8lMtVbPy^a$9SGcjm7n@PXuG4#=_5f8=;@Bg}4TH{&+ z#|9&>j1pQ2;%Zo%dxeqLNe~MkrwA1Ep_HeP8j<({SC(Z)#Yicou`OXO4LSpRKz{UW z-KrQum;ZgFKRP{Oke9{yhn@_f@PG$uMOq;F==|d1>_KjnLYpu$@_x_ttf8~t0vFfJ zdK^cy9y259??ZY3Z|?VM85z+F%1hDZ+`*maRjXN56|#VuIlN9AmgYp>H?0p#2xJ$- z=uUwMgRlazz*<{nY9|m3u~(0Qq?ZM*mOz#Slcha}zKd*5GmL?_1T1Z^KdRsl=g4}i znE#k?d{7lP+L+M9tPP|1#Eb$VoDM-A!N^Ml^0JT~<ib6AK2n5u=<wvC##xWf9!rny z;a)O};LukeYJM<H|5sPHHvr8iob}YSA@do*re3Y<5{J6R{e*1f-MNPv*1jVUC=d$} z2z*#%!vgTVQzKBts#u2GAp&V_yo-lUtn?6|aFuqG5Qe3UAj#}ClS*T+V=uit9~^=} zzL<nLv?>h_YW(b=Fh#&KQ-F-TAdnZ39s!5vA1k1WLHKDGD?O%FCc1=KxEjOIV@g<> z&vey%9ImS~EI1M9-(S->dM&f)oXG38N?8KAyT9pR15Mb+%YAg}f#5O^7*pDN4=wg~ zkZ_@Z^dNLIpW}{Aw(5@4rC5J1{2?8X!JrTze@`ww@F4!N(x@)F3CDbBj5>`Xu8hGO zc|bq-g-jm5B0cWs>N*S$qgjvnNRJ6hQ2ORfqJt4NFi45BC_d^^s~yQujw1*JvQ~ug zDoWn}xSy6maHxf5gOPW88*x~7u~uqJC}d9}v4lRjhz0%#3?hg5gHsx@rM)GPMS-OU z(CHdlBNZ0oBt~^JKR?*(i~jHeWa0vr3U}n^ofFJWf6bJC<>RwM+v6~2kQ2|(&V0mG z@g0&BMqYzC!m-k0bbdTkrL!LAc}>z|XTL}6q37PY(1AQSR6M2!hA&={84u?~FL;La zDOXj(zgn~Sv6zA4IK>$djJzLhZ-032O#~`#SpwPGwFDwntSHR{O?0A=1rkUYVows& z63Ai@OAl$8bBxIyxhT}Ir2hc|>A4QbVDFtNC(y}!wY0zz<8EfW?dn`qg>en<vs}Jl zh7cp?a&Ekl7f<+@rAKv)`@xl2kLT0RdUW^h5qoUk+w0EHe9J0@Ya}@16n>H>w4smJ zf^%>tmoX`BQ0w&;9}enf<S{|ViB}WO1UB;S_^nd=cVWib+>=5#NAg~-MJH&rFc_0b zgSOieNEPNTJ)#_w&;o%#bR&cvsbEP5eQ)sN1Og<;4dxJ*>+{PmF?<)pls^tOMB`M& z=-86N$QO1YN4`41V;FhCHirm699>crBWRRIswO18{he5P%o#y!;K&K(aj+T75qF`M z2Ga@0dkFl~uI7;WbfEYDjCnNla?k!6aw0D_qi=1=O$bEhK{_cyd9%<1aV0I6X}DMc z!aQPH0x7|QqzB-{2kx{szKNbmn+gFYvds4B1RW6Sfe?w{I%k;D2Aqj0gATYBZuS%D zaad*me-MMbfyc>FXo*0L4CR!bd~|qt_y!4(c-XLB=}`?GS)HZ|eP<=1Sy)`zMM26$ zvzSoD1)vYgt34e!3lxsE%oKXg7O0u!TQKsDc0Tlhig(>=DI~jN?%N{+fpnb1S4adO zqLz-9K!62E4*(&GkRjSFl5!&;aPVS+a4^{YU;+VB)(9mDG9QHZFWvcjIRjJB9sf?_ z@jrXlvfD}#1-~FYO~%;Vj0wqr<I5|6kr5;~2q|D;#12`2L=+?<5Gxiekl2s~NU%aI z`3ydRKi~`a75a2dcWOGF*kjK)Hn?&<9zS9b7rR{N)TwhxJr8$(iX0N$10%0If{ywW zuUH)1<G>XNBwLa6NEUPJ&N(v}d?$c9;YO}Izw_@O2jY;m@aXO&tA?ZZrEOULLe;~C z!A9P94uwI4K%Nm2vGXAN{Y<uklv^O?+I*y7*iUT<<Ufd*^oZ{Q0TdP-i$0YKmI1b* z_a{#XK2GKW>kfCdf`C7cuEN2~Toxnl{_JA%%lMa{FLJFsTMR)ULrp+o>t~!hBd;z3 zuFmq}A0-G9uCg;rMomkP>Qml0%)4^J5yY)HLwCbV6XqB~phs{=*dkjYb{>W}Y7P_S z5fB_}H1a<828_J9xg6NlQhixR+AjHcQ(K~d0!h>LppPwqtWJ7x2Lu-@Kvb#|w9tzI z^sd=vyZ`%QAz19cYFL5r(RDRgT;PU(d<cV;9~Hz?@tOazE+PF<m?G2K%MN+Ak8jsb z;uuWPBcU}PqkNTJk8u1ij<|m`iMyvF>VbFR&8S0#OcC#ttsXlM$|H58@$+^@B9di5 zMqYH$pRs0Ml(4!P^02@mXn}w~<o;GmTa=wrx|6DTuqBYS!z}5+@bs~hXz77;M1ml# z>=6oB`_G|*^<pv`+#==TY(xCPqJwCoxS!f=xYzYNrcW}iv;#Whx(qC{)dCoK@sjD! zmQ5f>ERB5WyXIP1<XNNAqdGXBaK^kiopM<UH^UP~C@E&~#OgT&O}_^!V<}t~m*ffm zJ=W`9>lVYpF4Enwhv4|w<nm&#t>X{rolE~iLXhOTrCoYlu(HEEd&YpsmO$1Fb4d?I z;zLZdxpXi?xZ5@qgbv8#{(DF<N#=y&)0Mb)!4uE|xZn?~5Aa8Rk!f|o^Z`u)T*L?@ z702!buj7rpV%j=`fGNaHcIgtX^n)3$k~u7&EHC&M;{$(@FS?3l1tET~;uH1oqvcQ@ zJ91btbuhiw6^G2;>gB*jUPB;umN1t#x+oA+$9}XYN`v#TBtNf+>fKE>zyxAzT-Iv4 zC6J9l1?j;yEcdyfRcePo+OS|*0(rc@{}sh3R^$-MQEGOCP&+7p0k}~vu~kES@}K>9 zJ{-O>DQl2CN+1&v7W9PkLfV{SsC+Wa^Za~r1}>tmzFrgQLE?|5z9T+eRvlcea;LYe zPMc??a-I>Qke$^D5$*~uwMjAweY|xr2pf5Oxg7<uHY}TF@<?pF6o(}Q0{#Gj1YLC4 zaLg}k31m}HS$Y7lVJQhQ(TO;CAwYydpg;Eaf0%!YFmPwCZfULe-LmfRx71CE>e5D) zTxSI%{7ijw7<tD!0AvTqM4m8llq5B)P|KLd)@IftqAL>m<B-J0bC^5g)v3+eP+q1G zCJ$V2wGz0=dm`=yxg>D4)nVinyzm@qSfV}z$H?SGo}xp?=IA~03M5!7RqVk=gXE5P ztHqW;)&i<5J=&dQe)cdZ{!i5AfDn^5^oQ`r@xkvEa}@ETnqObbljbZqxQC7_U~2hc zjG~plk4WRP+(akuRgUw*$Xhsr2f`;o!j*PEcLu36FFj)UhXGU2WH`XxtFYlg#w_mG zZrb>Gz!W>>W(fR<je~6^b0dlQ=-3Lkw3&^Kyq`%8OMF;j;l)})>7la%5w!7rRUW|m zjwwX+ih(_((J&G_m8iAe637Br59uNBf?in@mg;n1!9oW;GX<>U<A11!UJYJetNNko z6fEK4NQCe9KHW<U1L9e(b3Uafoa!=qm;|vn#koU{HBxSyIZfo^$V8&`%A`lkQRNuG zu>r4%W!2&MpY2v$CGlSjHg9}<2P6R^F_2Rn9>kr+vTtz>Qj`8*BkwnMtCV=K><l3Y z#76S+EJ$0jR_*5vG)7re;JG;H*uE%v3<a(&fmFnLNDnq)L4nu;mJFfW`jsURW53ux zIQYJLkfL%IlIpdC98e)(%gu+w)2=2IANRQ?WFL#{p!4ZH1kw$k(Eak~(RlpJ<O;7z z{NcWp1zKsfhAV)rxI9$Oi#}q+Pt__)Az1?-Zgt?hlECwbT;V7eJk)S8izS|%EMbhm zFO#LKzC_;dpFVu!IbXvP1!B7$v=jues~#{%7&g(<T?=TCh}>><Kp>qhfmFg8Nssb- z$@V}Jj1eM6aZmJz2#|wkP#H}sLE+eR|3k|K2z1EF^p`>zysACWH2<;8I8*9^j3Qn1 z_k}<PnvJ{!r2{ZgxZ5-o-<0$K5!}~BXJU`%T}Bc&SVrO|ueo2hg@MtJeij|c-R}ZC z3s*oR<A<I)=)YnJsyW_=Kq4-Uv~_^D`WL8Sxvf%}tVWlCk5=1D5IYHCz5bG9LiJ-N z5D1V~WTl|%keJtr_A|Ex(lkQpu?y)@4W+k>v_M3Hv}8mGTR^(95TH7ND9XBMf<SzB zh&wQFd&uiIF15qCGhHz<L|j>1L~2-HqKVEO^(c2RkKs@jA{v)KdU*66@7C4x2yb#@ zgE^r@^)YF|^W*DB7k6NX&m4Dn2|`4YgpqK9CM8J7-b)2x$-&Xb@>z<i)0V2k*co|^ z56jxHBuTN5AiDyDx^twv95hjgg}K*tLE5(oByH1H^E(!zx1_qYC6H#2=-Yce76KQ3 zl{SA2eIRSUs9-IkKsX*ru2ub-BYX9HYH&Wx%#8>x!<|qCvM{S8Y@O$Ldd$WP^kC$@ z2Q-x;S2)rIcyxTkTcM8k()xPl0hk?tkS|m~C@N+g3TFt{vw{Ud%_!u>EG3=<Es;hO zvlIsySIWF(IO<<EQ;aGZzZFJa>%#(p^!sL?l)%wPDG^Jj2IQ9yS9Y`ljY0YZXhjJG z|15K|C6L;I?+PS66z*S`K>Qq`PV5&7@P`nH;SVD~DiR1=6`Rl>*{c&WKaI|F9im$l zug-p+{5&pej!~>jeoCw|#yO$q1_{Z?tK;D86dqsXKDx-f$9W^tBVH#j2jB8sN6;Xj zF&Ic#>xHvBOdXy<2zTE~Sbyv^MIVaJBFr)Wm#$ivy!>(UT4ChHFgl{Jx{~HDlOVQ) zRpO5nkm<3qQ6zN)64enMsE<1cM4MOM5{SooN)LeFWlnjf)}MzQEGt0rUezW#ZTnYs zV~B}8#w4T=@W<rzro-`Z#{CZ86k%O*McQSY1^VQ}Q@T06#;rS{+)?>6{ApHt#B1nW zyeg%yo6APebHrU%EJWlIFa_U;!~3&nY`u0Z!iI*0=g^m5Y76PX790&D?^EK#l40~? zw+>{_6|ss6R>zmH07@+7l}~X3!A5gTCPwth%?L@1K(yWx$iqty5+J^yfdCr~8!vJc z_xFte>3v!y%pIVR);dkQ)Y>3?Jk<bCcAS=OUX_Eb0+6b}c=<1xc0j_F_Q-QR3*-*N zi7RAv8kZhPtQx`|Tvj6gtwl~~W4KyW*|}TISb|@pU#}e{@t0J#@ZwHVk=3&CS$c46 z1si#-1bHU6Y3`3R(?>T1VpV~;_+fNGszoP|35y}Ukq8HL?4UrQGE@jDf#4^qPek0< z2FaE{9!PrdTZIcwsZzFu-u9c&A4>@<@BL9}kdRVK=&Fu^kG!Cdv(d#Xd8TzfyeRG& z<w5@XI4{$~h>g6LI>3)&&GJTG{{1czt_FG$_||z$dOXujRil99pv_Rxk!AHCqLH#x z@D6oS7S#-j%}<4>g;hEiuqwNFBhmxE?2WwA1i@l-Q6N@=m^3Vdu!LnUB13%ZZ!V<N zAxY!<1ZYPI<fg#2C6LuhkNBH}ro}r3l4J4+n+P9E3ncITSs~4xR}0k(eQ^e|7-rON z$fx5nVZccBWvECpGV=bS15AiwoW_~FIvAW^7YSFDnL{olNYd^zCF!yMNHvRaSve;I zaOvZ}vKSC#fh)Q8GlL7lzhsmAp~|*JLNXtJ;7Ath#ia+piM-GC>{`NOj1o!_izh)u zfM7K`y6C9}<|Pmqd817Z^MIEi9Th^dmSFDM63Bx{4@TKes8yoHgCzq(dqN=lwt|)S zew$~ZEiVqL8Cnk6<fh?KvR>sAW)LvIIFiRsM&9fm0=cpz6(n2{s#D3{e(#p_Xncbk zttJnso%TR&lsor+&~krYeZs8@NSHqynqZJ{^_E%)#2<5}%0#6{JdqbZEW}}<iEh9W z#5;MtjaTXUgX>zY`v}Ajk;DsJf_Qf&-4aOS(t{CXOeff8TM!7Q2=m_2uXDz^`_^s! z{#~8@VtW&B=?Jb$jqhL1+($kukV)7uXYlx7Zl6FKL(Z<Mat0kcq4d~mbUQ+FD`wAJ zJe_cz1LvEUXLSd-&*9G(^|s?Bm`{L4yuGo=xP(rteod$@Js3Wb_YgHK<Y7G)4Pu?V zWgFIw5zA+pR`~j;(~gc22&!A)s#pVF9>v4ymOxf7Js71}w;k=H-1iLZDye--ATQ2Z ziOyeS**;pI0)eyY@{akvFN5igZkP1O2#t0oi(ev5^y_lV#P?gKc&$Y^<WWR=a6p!B zQiPDga2HkTpRcbGcLpNy>t1*Ga5vDv;wT#E?lg|&3S3O?5kv0`qXf@~&aOkwmL32n z@*cS~lYZYCd1ZZ6Oo5<;g|a{m!dm+RmthhWB@l-#fjortU{DQKCw4>uNs7f3$gxo% zy`!V&{+Znbai+rB!xPbmzC<aB`GfH#xpNua3rjpa{4vE1#-Q}umxb;3<m&qR>O@z= z-O}UHO}6|B;26Bb?PVFF)_9g<9tsKhgTt<HwG3FrG}uZfH&#_2FX_h`q(_*@`;{n= zqg?iZ*o9J=O>~D1%OGTs)Q3VW$sg#FV^H0ks9V@2L<(G60%=-$#C^QTQq--EUj>pq z?)OE2<c2`t?fYcr+khsaYJ--a^LQ&FzZg->`Zx<8E_&c&{_Rt$cX2{i?j;KtW?{so zhjw->xo%c@Pzg(}IWKALrvPVEsp16U?H~=I`2~ia@2grQxD1KY0JEh>JdyW1*^KVe zO!m9T!*ZGK?Q#vv{Baem8br0$Df%37o7JvIOrNy>?*!7k^kDe+B3kH4s%=g)l6bqW z1@gvoUq2yuH%n%~%j()t#Ok^|PUUfoOV`f8Gr$qtTz4MdQbgj%T<_xe5`Mz9UIg*3 z2ko|!v*4}Pgziw>DZf?0+JtfP7<TT`AE5xL9aOHWON^A$jw?E`IC`IK5z9#rz#Dnr zIy^L8bQ`EBJ}hLqKic)PgaCTz6oyrk#+Jp}(WG9D1__63F?RpY1hPWu0Z<N>WbrE9 zu~EDbAl*I)B=5a(`1-d`2wt8+9d%o<{Aca7Y}D;eg%QpsQ{shF?sH&(0~i@GaTOYQ znQZcLknsK^Y+Th5F<f=DqI@j(<5NwVMB+h<KsI~wqcqot6F2XH2O9$qDkk-9G34@Z z<#BYcIe0FeP*HjS-pKp;$>Gx?Lh|EdER_-;miy$sUBjZur$(Vur%$#7@?g><<Ph}G zl}fDwaY0zp1CcrO-qCYUW0dfNc?3x91uTOxkB?{5Gv|-ukdjfU@N_!HGmtux2S#3+ zJ?!Guu0vB-UWfD$D2~LU#JQ&4Yaoiyr0Wi9v$lAI2nobbd^8P5T|`?rsR@gWPI2GS zLM<abLL=|rZymm68Kf8mK@UW_=-fsZo#5eOsG9?)G^U+M5B>j1Ah)DPn(V9q^lntj z+z|T%6v!UN(ECCl(nLS}jf}ka#qZXwK<q)Evn0sT76*tluDA~MW#FJ12S#2{h{^LE zfsB5ML}M*0J!nh2-vvUajll1Tx)qu0@80C8k0N1&S`sua*eodAq?vq^sEuwGeDj0! z$imVC@J8OjTTcst9Ob5lbu&tcQIIfCQJbICm1Y}-zCWe$e@Gxn@LgdA(t}5&aIiKk zyAH%IlR^+yzbIinclh+1^B8$+V+^|KYf9Ipg45aPdU`!BE&Ir*hLzh#uDeu~3XHtt zpP7V4UCsDO?pjuQ0ObmnE-8?P01^p@3^rJIz?F-O`C%eih5TSIR&i+{@13^J--D!d zb`!~1i}V1zk@uy+$<w9}B7Jla$esaOAUAnfm_-LPkThM!!pGE>Km@Co9*o4ne_FS! z4QtN~5=xMXArQkKLLhJb6*KY%J-|8^Na^6FK#58?p$^8`G@}7R9n`RB%{dWBXynbN zu}MKT@-8Jk7@jhqMH<y0UIvyk_1)PTj|}eI{RoYj<H!E-?TFQ&;4u34s0l$Ta+Ec~ z^TZ!16>~}H5gK_fErFQDQb+l5-zM_Hhb2iPSbDwNb~{1*EV^7)gcwhy|0f%7(rG=6 z^k7i)LaQRkq;2QW;leT!<ml+|@U3U>H1aAwt+xZBffJGs=iE-`ZUuPZDrTz+8RZmX zA2~$Gh$jWv$h(a62;tbH>Gv3on6VSf`>-}8xnw6oB91i(3GP`5z*s~kbuKS-6fZxO zvasZU7to#7lF}nI@;*O!x(GCptx{-$*v+;W<wL@|$dD9pUfz}A|4bkcC_O@ZBF~Q( z+dy_*6a84`K%P51eEReIjl8v*ce6YzmevBVP(|sda!}$ZNNWEvP5?QmBJ}BYPft$* z_Mj&$Ej_q~Me$v=PoO8^F(e6l*BWjxpG_fmt}v(J!PO!07s#So6$nSn%q`<x0ZVu4 zkRE_H@;*N>R^G#-qaz`Z$B*4!+ed`}!InZI5bqb!YF=y!qz>uP(mN{$H$l*V!+(Fb zj}T4teawLv1#%KK@`fpWHI%Q0mtzqbll*4c`SeCl<Ux1h6t{g4`xy6<F!8UzMqZLM zguuu<zw|gd*wc4IISwH!7S3vB5#U~lxFJ1s#~yx0FqU^n$JGG5#pSG;<_mrFk3q#r z5LKu20KAd+?ZI0Z26@J$VSzvji)h>Ko4X+p3dE|{hqc{_eha#@4$^}?yxzwvpN!H( zcS$CFKS+4^*5H$vk(V{}47@dZa{QT^0VGfXpJ@OwCR3ch8v3I?4vf6^Jm+W<)WFVe z8F>dfz`RD@-F``W<o&4hU<0pbkcLDEgKWDv!^hJas}DDhMBr_JrFzvGz*9&g%Wh}1 zK!OLN(nBRnfQ`IAKYs!vukrD^QII{ju!KK^K!j3Sscofe1C=N_nj6;MtLDI#Kq??f z*F}1G&_|3pN*1rA-N42R0zngfFuB9X%ezwV0nAh9>R#ycvsj4w<mSdSY))Lt9dthM zC8$wpCgjWUtVCW$W~LO+yD{mJ9fZ<jUhoKd!->4C3<VqD!J^M%UM0IGq!Ew@c&#Qw zuj11R9+a5$puhj6@DYr>&r2KKBw|ULNgsP{MT4{rfn<U`i()Zhn))a#qe%S94z2FT zmO$p09__V}9uDOWhE}QFbu4orvJjmK<m9Eekyj=2O@Lr}?`L%{j8b3>Lju9+AnbQv zlWsT%l@I}S5tC(|Rgw7iI8K(59t=fIbf7u<;F#78N@|apVhi$EFa9W-dg}^V4E93F z591C^5_}ikZE1eFB~iq0zb`ecqn;fl^rIlwgOyo;LU<S*=-8c4?Ja@)m!$_a1zjad z;@s^*Tg-v<A0y4ZXG&NngXg1(yo&PR7bK8ucrm#=&y^~I)TghU3@2l5dQWerJtm<7 z$*5cLst^b_%`aX(FLvI3sZY%-pGI~R#!#p9P%J+@k&p|qZVK7Zl#(!7H(8sSRRBk7 zWGP-6pnNs2152mjtOtI*j=z64@?H-HLLdlKEUhJU{2{P$iaOP9FQGC9p%yYvI$Hwy zk4g_9F(3x8tMP?E3L9@<7TP|8Ci-9yGxCz-XO^?d7N>F*!sn7)W<oM&7d$RFyftG! z1xFC%iTRBhxgv%rRl~Bb2FS=8#cb)(gY=jSewHOL^{OT~g#R`+M1Z(T5Pz%p!-8w` zMqwm$n)ngNC7}E<Sm+u5UY2%t%b7>o&-~y}1JnmF@|sz6yH@Jp;J9ynSY3<~J|Y5n zl-kv{DMc#oQr@ACrdf47v1|!s6QxHmiLP9lyDAnEiVX{cga<ax{qX6N!P{))4ZS_H zk&nisp$ah+`T)k#KtG8k<i2{NGS1mw8ya~}iCr$4KdvhJbQzt!gXf4no;%p<=!#G{ zxMQ<}=-$t>?#s>{OW=(13jNP|5=dbGszZS&Rq{Mkk{+N9Ct&Jw+P&uzd9l~_83Za~ zlF)t~E;z(af^=G?I4qT7Py~oCMBlYDi1w|pC6Eo29wiEKX}sF6B$SPW-R!X}Bs?%B zEK4BIKVLTT2D=C<BYX8#W6gS!Fa~3A_z00n#(5?2ZM0Wh-!ffu;B1m>0vmZ}qTTNu zmZV2pFARkv$q##MK!B)+pBDU=y{lbqrHZ0YkTXXoHkfHm@7UW~i@l;o=q-r|fkH*_ zhZZc{QbEyo@Q?k`LdA#h&3qNlK5Nd&%E`&cWF~2ncBPq2rdJe`o0YZq+G{uF`aN}| zaRT00)6Pez-f1qRHh>L41z`(BH$&;c`O3Wa1&<ZrjJ)5-AmM9KAp57E9PPTjwt}{t zW*=H6NNpEHyFPjg>cifeQ3A2z<bCVYdLfWalpgHk<zkc-m+vFb9UE=;J7VKKFgC2? zsFByr&z8hl&k%-E7dFVS=e@hsyM9B%fIrG9=amrd{h!;t@H_+Ia@XrU+(pe)Y~)>< z^a!Dxv3H44CS<%?Yu}X<9mE_?cC4%Ln1rgMAYo=eG)PgWq2WsV+!~5Jt3`8iBCk;( zB0&s)6h5r1EfFRl5cAA9vYJI4mLm`a0-3zB!_+vC#-6?q$mU9qQ3YbRfxv**Y`G?g zD3H@4jrY|T$0uy$RXjWxXOQl7?_Nzp*LFl~K`PTq<weheyW{<#k*YU5{VniM<q$8X zpK<<(qStgpjl9d19$E!Y0bLVggl9pz(#pXaBikFi>Ee_TCXjFwWZj&*aWLIgXAss6 z<C_VSG>{&?ufS%zTC<kDk@uC<uyX05pGp@blciFoYGqfJ%icMZqI?eoZ+77aAf`al z;YO%tgkCHWJ!b;h4Cz7qL0MR-3=+!AZ);d?qtxNy*U|$y{)&yf3irvm3pcjzG-lLw zCqfV6kUB>}r&!W4r8d=b<L30qPu=o9LV9yOCwd%R1zVGC8-|giHb&PNDP7Vq7~LtI z5|V;|gp@M68Ql$nG)R|ph@!MgmlBeKh=kwset%%cvpcT)iZcYR9J^+fx^QHgt)BO( z64}*h9G0j0re?nK{_4t({Q{fv(WELE6S*B$!v^1l`Xc=enZDi)F&Ys>y<j`3A|Qxy zf+0`7^tG$W&8-TwlbUK)TI82oY7pbi##0aq0Y+TEjw}v;s3G#%kYg4IpAM}V%e1K7 zklw1oP>J}LA?Jk;&;JG-WZb&)l6tD%b$5j7ac3L$94yOY;qT*3Tdc9>Y|lR&OR>ci z9tdhN4KxPXSRvO61+9Zd#tBKYcD8o~Vuv>OQKcYx-@S+ahUsiy*^ddgbkgWcT%0S4 zDHDM*-yWU5`RkyuN8<c`yL(R&@iGhJA0B&)6)n#93zt{sLt`rub|^@+oSNTuBgh7~ z#bCA^1qws8c1eL}r$6I*n{x&S+lF}0I<N_HsZE+Q(rm7%WjoK5N(yB7H}_ckFGgG9 zx^4z?{-EjX59X*iTNGA5sc(qvyr^d0`0y>F=`^P<4quAma*za6*QM5R5sm5Qh%KH> z3P5f#fbV>KrEBq@?X-FK+7FA6u!`}`sjAU9I{VgU5c|>OJZQ2Lb6_06Yw!*&vyQ2_ z?j>}bt5Ex*5<sN9My!*c87;)ud`2CC7$0}sxm>VVacC-E$H2cfJ@tDNR%eE9ya(A2 zjGX>PO#kmx)rOoY{GBJhM0TiS&yRO<7eU$YcDq4<*YrzNfIexh?hE1v3*tqDA`?n~ zzF3`aMlj6%$ca#KBN;mvVRh=v!vsa+h{?N58c_kd_t$Vg#M?b43Gh~knU0{s&M|xJ zRG})TVFr%=Ksdzxc1h)o_<O^jmofEh|3!h@e&%T$3p`daO&6#PVYq>>Yj{D3Ic;EQ zl5+Cg&5m{E`o-UlPW!&M)8UT9jL*2*`e-;e4F9N8A2;w@w`pD~*J%cw3dLH$h9GGR zJgL8XrpDKX2PQ}_5%FH1J=ue^&v`<Z#NOHb3QN-z>2Ehmk5tsGJ`^U+_-+aKWCyz} z?^PL&3~>?q1AZ;M9$@`JABKVlQVS}@lEo*IDzx8njW^QTLu)Rxpy~*uzqm>eE<Y5- zuv$QEeW7gvgBQNnRg@uQ)qy_SVLE%IosWFgi>iEYkEMy-fI<u*26Q&IE9>D3FBX2t zpNkCA8Zv$#@acgM@KKoDDURg(m}nrbD;f6a*wfs83y_P_XPwG>KII6MWM4q{!O4dg zTE9FLd3MdG8g$3|e@sYd4@HGXhbCISI*IJw1+B0pjs8K%uSJ_G(x;TB`kxP`L@`R- zEJ%_)?B<Kct`0)Wqn`ATBKgtn5Om@lfQ!EW=4f&+fPqYzER9M~u9MG1iGRd#<|i>V zP1gRCeOzAiD*KQY`u<_MvIz@veqvGxOnmj%!;C9ZHY(*R(dOjPeG@`syi5U}6=0QL z6x%%Dp2X32uuiF-6aW`T9h4WHkOG`akC+*G5frJ`B5Ww8ZM(+I3P8l*r^LrHxu$CK zdQCFNQg`On*Rw#W)KeB!@7tPgDxyUcYqK&$$*Wud$8e|t0#^0n*4%EV^5~<%WB!cs zZR_M(6SYpxFv1MW``A80Rau10-t9Px_0O00%L^MJrfR9L^WH=hK}{AeV+GZ(l=d&x zF$)ZVT~=?ej#;#%FT$t(W->>!egD%CcD4KsKSNeHZoq37-Jpi6aa&*-H!rI9!i+X> zbNHKt9AAWWM7yQCR;aIA_-7a+Rn+1vA{T`ajp!_YK-0-iz_G~k6$<(a+8?CiTZeQ6 z=JD4G$zNE`$n+<?JbzLQ3#@9uIx{f3i^<oPLg1Q~eu_?>@Dfp6k5*k{=*F-W1;|xY zC`9TiYQ|}$>?$P%2VKG}5N^5DHg1ksHG=$PmyaJgG&JrSoHlG?U*QsRe3d5Bs0sKy z+@O|V^V!Fi&dX%#u<_+fz0;do9Ce_9`A|^7zeEAWycqXHxLZF-$W-2{bCg0|x%ek4 zUz^*jULO54=7M(eVz37y=r)JNkV1-9FX<^%Q6oK^BA^Yl4s~=RVA@kj?A<GXgcptb zvNiUHySuZ#ywRdC>_ST@{xvJTz|z3_z(7RsE91D$xapKUe3_`^csFW)qLhC=>^kK{ zjw4~V5|e;juG1L2#u&Z#HLWl7-cSAD2x)knitcD%k{3O<r^K}cKfFGn#DyvEDZOlc zgi|A`zYz|ul`=0TjN5Ywc=8eKs8ykc#qD56jpTl67Oe=aa&a>&Tv=+;C1N`{{&2}` z{%*aenV#(t7G0ph*yPWO(tnQ&?RW6tsZ;Rrz)x-JC^+_Qlzvd}w@(&9QCyw&QgOY| zs9Hoae(~2RYl+zlED6Ueph%D9!C#DN3oQR$S(liwhdJG@PzmIeoKCkLPHLpL{r4$^ z^@PO<+-zLqK^3bGB^Iy)tGf%TBDfx@<TLKy;ELh@DsEcDg{eax;>~>t>3pV_tk{(9 zMPNCz%4O%dMQK~uhvZ~C`OrG@fguoE<eb_)GpM<UKy9Zbb*Y~4ns<q%$roeEjv(nI z@=hLKG?=z5wPEgSG{xRcZiR%Zvx?C)zbHNOfjY_ikynPq9b|O*84L|kV6RXl)#Kt@ zYKo{^1wjKbGc}QfPYz06{K0F!;ZN*^RTF|z4HVhW<3V5#Gu>Ae0F9J1jSe?lJg9e| ztpPV}Pe17C)Kc}38F<p&6efOTs92{mZa8E`Igy)-D-{@-YWgwi!|%y`5UYQW3il75 zZ@)HTt;7L7`3h8e`*!*^SiQF*Z?PQPXKhVBL}b5oUfm!8x4+@*d#&e_Qwodw{%=Rh z(VVdcv`n(uO3eM%DHRWB#Mxf=g`{Z&j&#H02&8JilgV!*oK)J^h=3LlQXR?)H78(w zLbL=*?P+}MnxwtP<7Y0EN`xlIfvU?^dLzNg{k%^LFJgDN-6}bB$w}<{pX5mLk(B3i zsw*Jm2Pb5HNU+H;R1@Y3D!qB}iOq8dZvbH^z#_4DZQSV6ZdRrt#`GwlNG|mvC+&cY zsqEl&%C2-1{i-`RJ1g@{z+9%7@jB#YGHJc?$BZY5H!vvjFMA4M&wvA1v)m6y{hIc_ zA~UvZh3R=k&%bkGXvF#GI7H>42r_P3TnW?yiSJ~<XBOAdi%ELe#BWWAz~=kG%%;{z zDB@&YbS6djiUV`C;V!CBkSbyDYa@E`OIqp@_sV1b4N*2hjC{92+q>h2hK6GS=9}Z8 z#y5+%RD`#7#kjNO>0K)wMvauRv7XN^&(vVer;CjWzXukuRDN2>j3}|4Y1yooB#>cJ z1C}u)+2{{ds;@O61v-Vd>aRn+32pzqudVztk*}3E*`J9pb9DdM+K(ghv<woAsqwFP zB*V_%^E9BI(6P2s%`r<q0n{wVH{T=zyu2D1z!LmrBj`i+M6Ck1`I$x#-C<y4T<=}c zcVZ|DcF@E_jq#fw^{WQ^X9mmfMiqo=ae`YWqKvmCH`9_#&%coitg(apL!7hpcPNW% zI=!Y&glPji$Tmn1Dtgknwt(3M;Z4QUi?9_CpEkmACsPAzI^04ug2y9{WY-g381CD1 z<0ewpW5aw8BA@uJl`<nh7}7iIs!IRxoKgn@&;=SRiS4(V?t}DBBk~|7hMx}`*M=q% zSogy$8N+`ymn~XL^5xh@QO>Ff+{6}PX|>7+Az6|BmVXNW;qZoUJulwT{j_UCk+r1s zPT)RZ{RS^B!rtWb!TVsFR2G_-F3_h2wau$o`B_<T79$ZpwagE8y0kBBu%GTAeL3p% zxMmAOdL6e(gZH!^r@k<J=AIOU_@o%r1fF@K&I^>I{p+`<N`U8M4Cre*=ft|>PGQpW zz(lPzYa_K|sj!5Sfjj>63H*-w&D6R}8aoHQ>ybZbe{)Dj2+^X54+cAefAhBgWcR}< zj@w9qE0PnKt+$!FBp){Y@OJ1qxPK$)=0TTMLYA10^%fw$RAKG1hyPI_etG9ksQ63O zMg|PRv!@00#~Lc^S;!MS%)+h`tBnEML_Y-P2OBb6$e{I&uU3H><GuiqGN-~c`|K)1 z;17U_GxHF?QXlKt{Dcg{_42P@vP+3}IP6T>a7CJxZHIR5l$zU8S6}_56&2fA+8|H5 z^21rE48;GV8UuYrf)peWR4~K$_o2|a#eJ-0ptBYvdOL<CNqd&zjHU=&-Ca1u5EzBJ zb@Ek0%rYR~`#-$)y|_igvcmeg>dA80Le8Zy&g@9pKObuqc9b4GBag|n1heX3@Dh7_ z|CI@ygG^`mBW?FaQ(te-4tuMjXn7G(s-EwqUx#ZC8QJTo{`j0>=@`gn^H6bNuXo?1 z7O8!h=m}NV$MJW@{+<aZ+4?8ah(twHyr{#{-9cv9UEGECd|9l<u>A?FBn>az(~Zc< z|MRRkQqlJtk37LSE3#(z5Rw73w=59Q$>B84Sl=1jgw!Q2sPhiqcd_&C*>_qyc+*m~ z%9vMP=!S87^>S+n3)J6fGx|r+lMQmH6!CmaLxb$;hP--B$#eg#Gt+%lPg`-R%V9K4 zl$eBqiN=>-gb5bQt~)xaTjsIeTIvu`W@)^VRiqFM#{6O+^FVW+A@E9@0hvvoWv%sx zT+`fe#Eqal(y;F|wYRf2Q?Wynd?MkZTE@^|Duxg5ToL{AN7sm5U#28q@r32r#GyQQ zM9V@-fidgEWq51=Qh&A#?YneuW{jtmgftFEs5f)oZ4$iaVd**UGEcEH{vKdQ*g`j$ zcUWUM`Pk{x_EVXpUNlK+49~0*nKHrd5ryA3E<jmNTzXbpw=!1%HWCYMohc-pD&uxN z`bd56Z#=h{-!l8VOA|8Kq>F}8XTgR(e{K(+QDa-x)77L4eCWJ$xxY)<tfjhE6AN^a zI2KQr_MH9nZI;}R)WGgZJN5n1LO;w?)|ZbDeLpeyQM6cG$BsO0{c)C<*z1V=)rA^! zx3CGqVno3nq@IE-+udxG_LF-54NUO5a#opync;sGqfHo2v(GXMv1=>*$egc-_+%O+ z`GUa&owdr%QShz(ZDbMZ_fPhT;!0qeA$0zi(c&)ay@}&aeVF=^QgC=v%+_(Tl2i*1 z*T1kwHaF&$uxCuy94CL7g<kHlqnL3w@sVavBKeb@J$A%q%grr<gsT6MD&`C^Zi;Os z1wA!eo9J=gYHG^*tREvqO9~VL28fRaL>iSrc6Q1WveuX+PRtKJBvGe=#g!Poj&D+> z-BEiYOq%V4cM4%E&DO}{u)`#<^T?|G{m!FG7<z=%^y&O%LF!iC18S)T`u?D(82a&g zE^M&;?%-Sa6<&nn?;91TE>?2P`;x`$=VIp~Y084Lm$6qU&Fm)0+-(0LqYWsa4ZzCQ zSW3PLF+dzOqg3b!#;1Ls+ueRd`ag*Pv(xcEl2h8pzCY!M#tWx^Og(?~U}~hrluz{^ zJ#1$VNCNvqD3pJ$*(W;)j{t(g^q#GLG<!UmEhdmyh~d>m6K!X<#bmS?mlLvO<eB8Z z)hvnUe|*ztzQz!IfDm;nLnxAZX*vqW7FjiFH6f2HV#p_^x@=zwJmLSq;<$4+{5tn> z^U?mjnuuYnK85l*EQ<D;g^KSf30>{<(AMPhoqSD%bVyrq@x^Hv?&gSy#>3R7j_$)E zFkDwof9h3|^7U-t^BTFuFMq$fXHQs?3hyhZ@=k?g32f27{KVsUt-txm|1@0HtJ-4p zJQK1)gEhpn-c{v%r)a{SL?#}B>)I_bTr=O9dc}Hibl)=iv(%C}0I5i_YSeogavW-Z zpH#v+VnhuPg*BkfcIM1kQI}`<cy%UoX#}DZ$&0Dxq$Eu}=I1)>n2LpvRCwfw%)ga} zNfSWu+cQ)8FRl(|$u?g{TM@CF*bAYRFzrt0rutYc82e%=;yX_0y6o}d<xaCb4K+iv zS0k}eO?8t#;hXM=k@8?~Ko3D7dR=sf+NcsmOp(~T{A0P$dD4pNe1JS>;p*|}9~MtP z5<GyZ^I11M#1Uy$rHC-^;kOD?RvBlJDS_Y?CekU3x><ei*&l-eAtEPjjF|mgMRE4N z6eV{J2o}8bWLxD<z4BV4r&d(^EBB^v>D^7prg;kY>~I1}gY9PYBV8f$P)H=}cgX}A zJ@>~@mC;{O7&eO3&ja<JDLQ<{B+KQ-b5c8cE|Cy)JYXu*@+Z&t$zbRyjPv+$C2f8C zsH;X(YDch_*Xds&!RVPdlnZxk+u3nzAJhKbqS+_5%<kxtu2ftg%D$dPa|M5n%QAGL zaQ7IE<{)7W_INjDf3fWo*ZcljaYkFB8U;sRNVbAaxvOyo*d!*sYre)sEfbZ-<2-B4 ze7NGK@x0OI5`JpI1qp%6jo?qpDARANuHFBR&eqO?BU0Yy$Py~jY?H0Cczfjqn>(ni zOeB2V6MAgdY?M>Q^>!l*8HsXaN2Ucxdb4HRie+J^U9w|n_JzUa+=PZz%J4?Y<`*zr zbno~$2SuRA6DC@HohsQidHPiNb?S#8{W(T}>8)n9VF0CO;l;mc9D=SL@PQnkdA@bT zM%3@Hbnf-rD-%riATVInwV1UY{^OuT4M@jVis}KjmFApIZ8ufAgt6Jxs3-uIVr$84 zGVZT{nOMdT6+(a6lK7)U$R6^@fr%2z0j2D$nCdsd6}h)AJqri1otTHDRVuRlPWn7% zzg#}2OCIAl7T4>hO9}qjhh`4vN-}AeXGQ*AruWL^wr#Xu-F!8gStlBrCJY@gz*CRB zGwVL5>_!~MS@W3V9u&#!f#lgE1*G@E2k1YQ5uYl5kpGiZsBi4PFNqq-jMiAifz#{) z!9<hB`l(r!Nw}jwe<?J|8DpQ^bX|IBm+QO@_v_JVLZq7bZf?-SV!hRS)l=wP<uXc3 zT1%d6Q*wM75m(SX(#6=*-c5<b^`Zh!ml3x5AtRLp5nvXMtdek(5?K?*;i=^cGp{ea zR5AzP7%qGHYmXMf3_lCJN?sg6A;p*K0_MKHcJtqYaAzY9Hgp3%Ye<c}rA#+ZcuGfE zVcZ;o2jr(wAabz%k|y0ij0zDhobOkw{t7OJ;67Kh<ueYmw7W7waMnQ_s{GM>mfu67 zeA(wU9Y<@R8I$F(^ng$hm`%{s<scJ|Iw0Hmu&ahBAT>uysu&zAGx}vTTKO0G8D6G) z`>r8nZLBUldnS!Q`!K&wV}~pyPY`%Z=Fmq~b*+A^ZqOkX+GUE(-%<FHR`~A*YK^B0 z5a+u4lgX?~gSSP!9G}vmk&d8MrGX?Huwj;j@mLA!6-%DlxL|VRQb+!Dfp=7b>hP!C zaVWjx%TPPJE6vsy*4xYFeeD9NSC+;gPiO^6Oyul#TRI%~AUP(`v~x4Da^g|=U*=0s zQ0mfjz|f~Otku%=O?%7;cCEltV=uwf<;YDT{w6&?be65pLr1IN!LNxQky78S3uL%x zo7unM@^xr}04el;eK0n`JVY6Q&<t@QRDNolCC{}`_yMC(EZD{!{FwYd?2NA=y7sHG z>r+lNu*bU*&NI7%q#c#wsiy6)?n1<=od)a4^0uHA>q%T5!!84J{qNWd$uG~;zToT# zi#r}ej#&jxKc%0=E;02Ju*$c2w5SAeOmibrz3HB{)XLp!*fc&+!-DM)*kh1gsI%C{ zwWrSrc3%B%@T|(^iI>B6PA>e$^QhXWshT{|g3ZO<-c8#r(WaV)9jYzLX>$XzK@Aly z*<2IKMd*G1>ikj4nkm`$-U2^IMTUPa{#x#@pWjj6?{88fDXf2e&g)6OjA?PT7JOz7 zJ3sc+-BF=%baXcx-*>W{!`n}T@a{siScFrMPrwz<Mdin(N}mTq4dz+QwGj0eUx=z* z+>Zr&5a)rQ++#(AgG{18!ptZ3*}}x$C`opSxQj700^Zs3s^PG)4KQ?;DUU!oM<3oC zUnzw>wYp)LlC;!aS{97+Ju#nsMfry?l!*I5K9%r9WhVQlFV4oYo>VKFt?GlC)G>q` zHC~gP*2q@c!kXMpLum&v;5VzsurB~}{HMGKvj7EJzc(nDAjT&@b@QbrM_`}?Bdpqd zAD+)6)pbVX=0B<Z_qo(%Mz4rb%$ina%^Vmq_E;$4R?{@`gL6>nu@50Dk_=~-jl@Q8 zijDatD{?xg$?N8Y{`~y_UO+8kh`cGPatHqE19jD~%ZX84x6olU!OT0hdkhX<CuC45 z0onBmZ1BA6*N0}4Ajc?K&nczUAg;{G54p#WDOY%bGV*>KJi^~jg&m&yoF0!H|LiB) zy&cN&(8&&@kzgsxuITkJwnfF1fXM2*dlbrIzZuU9obZ;Sf*7_e$@j*N!wF9W7WgFV zGi@M8s;Lmy5VK^1g53Tf>Nk~uP4Wi(4S5%~*DINc7EXa8eb=0(eve2mr6)L=ua%hf zVAb9;2$sB`^LIH`>!kr?_zE>)QgYiIKb}Y+!@Q4l;>@APg=(n&ZevPnwjw3X0EMBr zUf39~^#%6VrdS1g%c1l5V(!S&2wvBoL2f0uJ%Lf@0LLn=-hWHVdg>OCUMD?ku;Pa{ zi-Q<tv_-~X5P+J3c`OP}4acjDnWk;}!$*)6IqhkV<{F2GJ$tEd*BFG60U!dpU-}RV z_F8(StR`u4b8pDHj31pwIzY#MO6B`&Jq<!_<HTxW*FRTd9W?*tS7hU*5~>B3O1;`v zVu8wQ#nMxgmd`m^hU7gm8n(a@@S4;E?^87DcPoGtj;1Kod6DgLPvBWrJ0Ha_?dWpz zNE{zZL&{&7eVC}-jmJS77zN=<)8{HYPv$MPWQ60zr(6a$y`WbHrgke|JL3o`oG7F7 z!Yxn;lw%d~T?dU8QLc5yNp9`xpl-TB(4<wQdt@Wb%v#M1%J`k^%pg-05Sht;V~18q zOb_@;sh;OFM3P30W&i$kQVWq|1flNy%M`N#?cq}tMSxr@$4$s9y@E;`M?b8l^Hdol z9+aU}1!nK8Mb1r_KwzyD&_;!FhV8X*h}huZ6u)nX0dZfnwIPq=4in1;&j7`hH<6n+ zC+naPMV#cVtMuEOSwXEiwP%lezY-)RmDV;nPM<YAuf*C7j12z45((I`MpdOrC-w&S z8XwSl_>v=R!Y@K0%H`K)MmFv_@)5Y<2a7m(4P+bOicI)2POn+UJzZ_5`{%dfb=J;1 zOmL<ypt;1>Xu`813(-soC;UJ>MtAVyRv4PuZ1;vfpiE5?KdIN$@jWXTmMn9v3IEE5 z2jf?yGc&FjfBARn_@^lOlS+d0n0Ie<Sq_8XUnzQ{Fykm5G$2RVl0O5?`6UtsNQUHW zga}KtLZyk?bw-x9krsD1e|O~2t+Nin8>4#$e;b^}!==|I+~>4a5tuDin|cs8@cRT2 zEgGHtL)%f_59bLC;?PcXhDsDjBHF+OkM<`;+70B(03XBaKrx(9SNPBX@|P9K_&Xpk zTHSc<8R@11$7Ty<8KrY>hLBxzsn(`G8Ib1MU9de+z!%VO&bH>^xW&c;Ra-!BK&BlG zF&7$H|6NRurWBeYZx3kIWL}@BKKXx^LB2By?B|9r2ukw+c#$u-Q8C3K;C(sE6TWp* zQ?WV~JykXfo=hN1U+@~;tgJ^xZR`5`L;L<M;8NQFGC^N@d5oN2?UoO{9Hvw^QVkN~ z(lsE<+*OMe_c;S!qO1z+seo6h43$jK<4;|<)wIIi-S`+lU;wn*iD29R-$Lr!n99N@ z)GmpVe9GMkxXt2qrLN(GXiD+(pm#ivE5<cQXCnr=IfX-&z<p=sRXJSUwYRxEJJ^aj zIzN&XMO1ArfzIe`gq6`-J4#fzGhd|QLH^|)#6+Hl<gbj5;&lVTaMH9sLmzzxW4sr^ zhGayC=H}~`)PNM$Rcnf!%hlvCN<vXWRO9J;FL2|au~8oudWUrDS*4n>a_xXwa+2=} z`0WFK*hu?KiXou0!;#cW4LC{yyZ5k}u~2_NV})cFn~#CH)vSg@z=_hkQc=|gN~i@H zyckM=HN0(ll<kCc%YuJ&E3WM{ol5J9ZSdRezDY#ik|@FjoKlH607o8p8F9G5kb@S& zGvm}IE3S)=iS1H>0he&ZOY8sJhLqe+LV-87Rlr&yy=hK9E%L4D2!dc|=V;V1AXj7? zInoAnYdS7o%R#>p%rX)g<YG!@U5}+1y#Yy{&KIw&Q{f3xMd}Ei$>|^~Ifwn`T#n}p zG6<o$ZC!;w|2{BRm)pP!CfpTQ$=?UJ$P1CM-kx=5BV-A~EkpwD#0dnv_zA$4`^_p% zXZqj@FbIFY1T2!(*RH-Z>f|eO{(U#)ZzaL-A*sKO7)u{J)>f*Bc-^mB*RpxPzi|2O zSYDCyznnp;L6Mu%Kgd4?@kM_Eo*DVXv6{c~tkc`|$AhfI&per*`Cl-`@FW2_YB;JO zJD{K>#q-PXvrO3Ufl<Xd`e{;74@nd%DD?kFhKKcEnI2W_0mI`5>RTO}Ny*7;(gS>U z3T)4A|HfZPzHpFOyd1icvXA)b5|rNk!*PfI$<XXMnY?MS{nWPl8^@P8q%fg#o5pN7 zC-qtFoQsq?vcO?+`?pU=CVV#!k(pf{K{UW5%Gx<SsT08TqN#}l7%c`pc2XcC8;yVR z4FQ|Tf6OuQUZ}fHEMP8DQ|4)of-fJle=Z9C1$(hBMdTBn90l=-r}s*m0}?4iB%&_# zU&N;id^Ir&$H2+d#+j^nUqsZCX_rVu$q{~_v!D^Q=D(=ljEs}HnyOW%2S#qM>MwFE zYZr=EDh*Py*^q9*GI8or^VoK1`=jTKE}%%VN`N6c{I<^*&O~C5OUN2Hi0Hf^<$^QN zJMw;x?u<nZk;S!p84H?)1%ot}_p0rV`jhFYVSvfTbUgcc|I2e~t(0{3#mfknh{dlU z($bU#^N?@NmBuV#{D9kNa@L7pH2#jGcq)yXV_qiQIepSm-5S=TB^2)hZvYlaF8un& zc)-r2X2M=k(C`*3){6HlV9b59^tB7B-pzC;nTcRp#}y_>q}Hr1`>r3*#^FUT_+1e= zL`<I_Jm~E>a_KRtaef>#GwvX4KPmJV?Ge5seoiLAiKOLy$P6flC~ayYz-7dGhsk{0 zw1W!i4tudy`YQ_s;aZA4<pQ^%gRHAhnzgrI{GN5d@jHzzFk7*$8DQUgyaOlLq=T;O zH&!SBpEG^^6>b=qgxj2YT!d;GY>iRrh}J<d>qa~UYyX!4h<sMPbTvz5@4gD9vF20& zURlDOpGO_*p#-XHT5b3^f=I`y``1wCLt`C8G9`~!eB>Sdz4}`5r*-*Hq6)ZlXIE70 zu@9o6YVGWJBE6HJzi^Joc0XRfDtdGA<#?m{_QL0OuoqpvLj7TZ{e6jNh!hNv>JnrQ zdHk}={=1mRMKiOi8s1b>j5)I-o$~8ZSAIKiv7O)l-&loy^4>~?unX&o9^V;*;T9dt z^GCzo3hGrB5oW;Cq_(faW-}=;S!Nd*{>~x38^YF=^ZGfRDci0$=}bu&VGOt%Ff_b$ zJh%3F<~P3t7A)u{KL`T_-dm?6S$YjH@0M1R8YU{8K8>XoROb=+&+1{B85JH2QebVw zW?kjzULHIy#0$YA?#Rdce?CGAjWtEka<t0vnGQ=2S}5jngxnlKe$fYB5txxQ*%2y; zPI_Hpg)C?`x|Z2~wAnRKh|y!Ar^L}d`+m2o|0{UL)byC7EI&FsVQS?5+;ZQ5p=RtX znr0bv$UO?C^?Yrb;2)EEwGNs7l!S#&HT4hwV-65e3LTfq(~m*Me>zS~{MA#CYmBKv z|Glfr12<rsm#%E9oagit7DH!WfN=-=`O8SoiQukrLJ6X!dlw_GEv3_0whxH7uKPa+ zL;|-C54E7R*J?b=((e#@)MF%Z@{;dIoF#Mffu>$ieipo!4(YShqJOMk9XYD^T2jTh zGJP5tYq6oo9uG^e$^VW(_>&$TewX=$EHHoi+SJ0q1c$g(GSTrl?yP1C|M0sFs*Q8X z(Fue#z@s}KBNXF1v!fC|H>6y2!ul3=)9X6Pfz9<mA>4#7uD;uth<fGg>eg>wdtl<5 zi!%JdY5(oy!Fe)3K`EhTxAInO%*QU{RA<@87S#=^R*Sd1tlg;{N(s*>P&dtG>Z)`m z`a0oGNvLUNrp1+r7Vj4Qj6~<W^CT&M#NH@=>7|}|1f9@LIAR?V<}XvVP=RS6zRL<t z2rt5j(2u#*8<cH=sxqeVu{Y2D<i^3TxF6NasS2lK7YhI;zTkM15)5z9&{CDvg}53L zM;MbzBbkqmdz~;^Nb&FkGq>wTPsrZS#usm|0vPy_?b0tkTvsfZN4^dG)fq_l89sl{ zwLfmpb~0FWgid7FHxMrme$Z(4f&%As{Lp@<%}ayR{tX^U#Gd|`u@*v){ur;3)ihfo z?a^0G^-sO*Fh0DqxL#)<WVb-AH!WoBk6?}Top%u>D+{TrE*(b`ZgF}V&r1q+AIPf~ z>2${WMJ(bo1fn07G7mkSzTJFp8rZYvCS;Kb?<-U-#m<ML5LAr4brdB+2`pQJdD?;! zsne=9j=5o|u?UB8+BB!FygeA;L9Cj0cx?0YO90tLgdO|hZLK9Ja40rx*Q#n694=dT zHW~NEZc-P6Gp7;|*PD$;owTo0{*~Xi65GcP52jU$Y@kV&p9s3-MA{7&D_S2fc#Npp z#LNIXJ*?(OulVqQeEwjbd12t>LIoVTO{p<#l*ge>5qLy7F~fksIFOWAxqH-a%eOu0 z`q(~o0T29Qpw7q&wcVHnXfDW3VG%S)bP@KuJI%?SE%2>a9d}}HU@$@urWu2!Gsa$q z#Y$XsF(EG3uv(soN6!r0`W!whrYXq=kpashQy|P$M;<6eTJ;RIoqE2RNLBaHf49xt zqm4$PX&*m`6|=Vsfa1nZJ=}DvIKWZ`hR`FjeM_*3xoEwxVH->3lbd?ODf+Ch?(Vbz z>tLNyYiD7AGq>U^C=x|gH@UENT-&o;o61@&z~FbiQ~wSkvf0@O5SkbQ>4MX*_l4dM zjY@Pm1?ldeslKfwATdqBj(=1at-Y*BMKG0Jt;q){VqcL#Jc@d(iNXsJtWrV=o>b~v z;E{#2OsfIr5@;qiRcAPE8L%IqSgt5(ozD3$?!;_a(20Jo|HM=27ioY26M~G<CXL=; zGri$gs?~>y*Hd!V`{C;lg946Y@Wm}*47VoGzp;ia-P-e-Q1b*js01Z4v|~)fl!LIy z-(cM2Y*dTd11U=&-SzD>j;HaX57b5I$beFCa=;I8g7s`*dLD_j=~*GW(Y<#7*T+`k z*CwDTTMnrQv^PnD+IVXfA{Df4c?&tT@h9cn%sA6be}AJEI(K^>Xs%MXTkJ1NA4M1W z01urX*%|I;#Ha9Gn^T)P)gNpMxJ(hB;(HGNoS|c`S5E;7m}?kSIgi<7i{X=vpFNCK zE}ya^^9Cn^5el4aUkO_>5D4h!m@r!9FrODI1RB0dxU(#{U|c+bUk?Go5zk&ah0{#E zTWrstJw(FHs?gu@G=LF*9x$zJQ-4d8NK>JJpDzFUR6ZB9(B%ZElQzjJn03xB3N|=Q zH<2`#-2P6;RQYo9XdxcxccXDA&$5;@Q<6q<ej06%3n{FT5e}pt&&vuTwI)>8l*|e3 z36=ddE784K3eecyy$G<f&4LK*^S*adJb6IS?<vLAh--uMU%+>X&%&~#KL6}2<cI`G z$-$@i{(e^NE`IeGI8EP0&kcQI76l`aX}nKas<>cB7@n3vrZ2nW8fBlT8+|Mt9P#2< z9W8#a`CNkjs=|{PInUn})a^oq2;EFOT`Sc>dlWR4yptRHzFUzD@hW(2h==^uv1>{V zVD-2tXUT#k+YN(W5oTFdVxo83(H8l}C)gnGy(nTUYgt-=)a>;~mSUt^tE9{s103!* z5H0qJo~Xp$>Vur+Z2eF4x9UF!DYtNQRs{IKy~X#Lw@+1KoW%9%Zl4<Cah$)*{`1)+ zmGS3_aYyzr7xM&~fa+VwKDn5F5VYnKG|kg1<n*6YZ44Y7BdR(&pt|-6G7|0QNEs_^ zZ<nEuFYnUK{|86MS951U=<v4^P{wAtV4&!U{$B)p9Ah6ev=F4InszG0yU?eq;}(h! z!6M?fEa-Se1anBv`b6y<LyR-O5{%j2uj9|mV_`oI9=Dk4Vt(K<FdbU#*(uxOSSkEL z=@z}6yK-u6Nk8qeGlG_o{X<`Cs6$r6%v1an`@54Q-oknK#1>7Pv5cc7hX5b%D`hk= zjzdD#F(^D@T>Ihu`R;l{;S2D4BNouUWF&Y*CJeZVvO=$Nh{J@^ML#+Ut;Im5Bm<8O zF$JnN0=9i&^ouw96Qj)OXn#pDxaDaSHtqx|MYIV~?T5DMKfYi#>FYO-#NrGMM6gvp zCd?6BzbJozKpL&M>~9*RCuRT6&2}vdo>qTnTxkiUFKsYK(H0^{5@tY?CZG4}^NlbT zd0Gm}F(vkWnHKeir&lb~yu(XPEkp_)^_qZy#mir-87S#8R4nSV$}7RfRMQJy6&|@C z^wh0`7kA2y8!nn8Wts3w89?SbC;k~gJds<)0{$?uc2&Sb%}yTt2HUpTa!zF`x=5yu z(RQ>@7P*<vV-X%Qz&HZV$og^QAyBrKK=cr`U9UGQCA2~PqYZEbrb%x9^}|@f3{-cI z%tutDU>8cxq1I>}kB2h{H&vA4ja{z!MF)^56=D<fofmKrN^jftHDcdK+=K83xpQ7m zyEgKxexyjE@aGXS8p^`}8^&>Zr>PRPnNC@pcd;j76r_)6EU6&_2h5cB!f*-J4F#F2 zCRA-64G*zTFwm;1<$;9>mz$t2Y0g*gvPi$3NrS*7&5t4~{+$!<90|(bJguTL%MvY- zXQeV{e#R^ZSV%=UxR$eh-1+bU28_bp<X%(FIBT$Oq{xRHX}S&(tS{R^f=!Zif5_jf zzv7>~teyCR_YyqcB!~CoGez33#$Kot@BP_qsH02wg}$EKJ27XwBcmT=&gop_F{6dh z{zr@e%A!@qqZBo^y(=UggwPF>{9B^DW<@Bg6HYzz7(%X|EyFIDf|3h9YFmny`54w1 zsrEhv_TB{QZAXXi?aB#&y1;0lAQ183;(zg)mA$<_nYk@yHW9Kj<9<c>z)q)OPGr6f z1Y5J1D)i$3e)`%7)*vu_%FC+^4<FM?;X3wv@y;*3QtfrTu|tW5CsCYYp+8L6K*Njm z<ke5>RZkvc+ECE%r!s721FSAumhK*hdaeBP#608<2T|f~WoPW-^o_lz*gvB<>6wR| z&qzZ+wxf4PV!>}|+a(_&qO$zRhOyX!ba`tJZx%b`aC!VK#>bTrA}kYfHiD?V<v#W; zpjQ>=Qt*=EGr_5mrrGLTe!zhwQViEe(t7creK~mb{kbq*Ap#eKpZXV#%kzy>omXc^ z%o<|~bYt8q;crg8Iyvqi`wDnLtV`?f%bp<G3CJ#7>xL&u$@W8Y;ax6#sz!vCGPV53 z3kwZMSlSs)_?CD4t-X_PlP@{oM2o;=<>M-l63f{bBEDzsm#KC0q30j(kWzQnZ2w(+ z#DeLbNOmt^?tC<~*48z!QDbe+$tthCSMk=werTAhdlPVh8nszQ=1&CsV+2#Pe>pMx z{R>(8Mc|$?cGvjnpEgmYv+Zw}&fL^Z{_Ohx*IpDG3}j{_cz4<#%hVk^in8G6ySBM0 zdvzCP#>2+c8)RfA1qqsCx$MB8hw4J%z3(hQ1`_`W1l=1?n6hYWHgh;FqhjuHCAn4v z`wB}bzQ$$TmlqIzBr2TUC-1bjzLrLIO@l`ZH^FnhY0K<EvxWsAzskgsL2ptUQHkJ$ zB)|fHjpfR2aZzYNnCB>HY?D;W6>j4^k|XSQZuu<;wzix8b|k&tW!CNAVl}Cf7q+7H z|NH%~7a?$1EDH7Z#14ZTq0I%w9ch(b`G(X|yk?JBaUoNiyx9{s?dniK4M)&!__|3w z+$#?pHoac(S$ZWnfM_R<1P1R#)p<MU+7>*f8T*(<H!_-AvEI_Gz-n*@dPe~ay7dvy z?lI#N33(qKm_dQ-y8bSx{lUgJEf}|XCaSKWW1`CGIro=$HFof;YSl^wzIVQiwikU^ zENmxBXy%9Dz>4v;Y3k6udaQ)H+KUq1tt|q@d0E6GA#%<C-Z`2;GZQpI-+*=m0^=0J z!rdZXa@!mbP?}<HV-IA-HGEewHl9kDMDofC-gda!Zp<2-S&24X4o9`B(y+hr_-Z$# zIwuY2hCZfbf5zJQn=gDYW_*I}Or0I)W2lhLBI>Q6aQCs=8*H<(D{A=q>}}UQM`f|# zbml=wRDjYaz!Jud=&d}w{r7_kHD_DXvD|ow?SRFzeQf1)yv=KDJG!l?f{i!IQdu12 zmvo7}C-$_f;tKu%c|W?4L%E`d*Pg?0_}n{QvN}rXhQ)u_ST7RAb6LK$+;7hjxoPW4 z?8?ZItlg01{`outQ3C0qv#xqn22{4~(HuIM{|@Kr7=aW;paNUULO-v|`|*Fd+bKWc z=c?~TkTc}_y36Sqaw6y>N?pYhMSgPebKRF2AL{h?{+>l%NUr&eV9Sc4tG`8FR4<y; zR@!nd2d(Mz`RMIl*r=4sb^Ek##^I*KZ#@E(emx>kQ0FZ*@Jx(XC}so}>s~U)w^>%| z_wgkP$pX3#U^`ie<aU2^9^r15!!fU^!ixH7GbEbU0i?`sW<9gG<jjk~T@-=B3N9zi zyF!~_KUAJlVtGKu@d~SpDb6erGa4nWWab_Eta{i3qMUzPy|Gjz|7AieHl#L#JPWR) za)TOcpHuvz4#8);V;F7hQg|Ac4)8#^cnUuAGXuS;)Z;df%5+2t)ZD{TtVB{Jqlt0; zA5s0~96QiYi)ZYrk>wj(Z>1-~&F$r~6Vv`UM^=6^G~o^l{1=&eW$^b!KF!r|0xKQo z)%*c%|86kbh30eZhwCM-4Q~XC#LoNc@S!a1M&YV9?H)C<v%|x$R?zBjkby^i4}4R~ zH$YAzE)4g*qn-D^h}IYxYI_I(JbXeqvFu7QaytHUn7UagBUv?e$5fJ;S~+&Mi)zB@ zK@baoFW|?kdyf-g@|VGd>PFe7b>_}u==Zf0UEuSS+=i5trGwbuLIN(`&==vql2;cM zwpkFQ9NBk?x;+m)x`vt(e4W_@+sXRn4(>$goBnPPgYFE)w1R#fA9@)+9lXCzFTR{` zAGJU+7Xpkg$^!MPcTANTAN@?%t5j_O)p&ga+*p0WjM&b=N2I{WXkh-;bu{WdtLwYD z8UTrDOgM6Rw*q-<;jRs{V5UBAvPrY^om1)Hs51qe-X?mSh}hdh-IyZJL?pz9yZt_m zecQ^4Rku07=+n8NdvEjvb`|E~(z_jY#R3t6gq`BZi{EFwBk)GXXZzsk0dfgjUvpL? z*{_#oDZ;;Uv7YEtI37z<Abi;MtFv_@Q_bBh&0YcPLyF&w+u{&2^AS6<uAZMBKW-I4 zI3Kgdg;CkW9GEOQu$>h7&Zoau8WNk~)$Bs4FfA*uwI+D76J~|yaK_Fz*-QaqRFc2V zs_NVK9_jI>`>t+y`2te#?h3L9l2O>sw1h&5o6#-BR={1i>aX~cDlF1sPuizDyF}D8 zYAx@Ui!g8vO3=dz!)Afa?&ny@*HR^&mV+VW^K^D$5?scqb!K>jsy4Xi_O%&DNkkE% zQHr+~+z(I%#ilxTN(hdb*WC-70CZJdEi`Viwuy9VWlm4#8{nnpk*86ft9tIA2(f|% zex1mF6jAqxU^O{w{iB7%pGVH&s4@GUA3tw;wSSldbkb+$&&W$WbN}(FFg1YELMuo3 z{I?o9CGG1h8)JOi3OQy^SQA2ELD8Fo;`;<Lm=uQUG4QE+Wdn7vn3e+2xfwHg)8IRI zRjSxdLHul6rR*vzlar46D^%UQ#1m+b!`XUokH7bv^gn#CZrzd1^t;Gl`kP93zTm4> z|M%UiOz)Q3`Ek$HfN(6G+2kvmp%;uqKm5g5`idL@)h0f_0Vp!@H?A~H$X|_*yc?ge z-(`aV&8k)(p4h=VOYFZB+(_CLHHgF9CD(QNmvDLn6e>wgKuKWSgiw9Y5cp9@I>c=J zi+c~`9!106Lv1~Eoi!l)mIV_Pb_h5e=wKX%B<uJnbf5DsDbj$NJuYfK`DV)kgOYb# z?%+mZ+Q8i=T}Du<&>*uwSIrf#u3Ya1jGCCNNZ9v3A-tQ0*(hX(2)E=2ZScDOr^iDR zmOq_8N_Je7919Sq{-fYShPm~Qy@lH;(>+{VAqls@x~@6@5V7GSaz2ZGZ$1h@S`biC zh3@Zc*vhkY!Js!B{V_$yqK%#l;<$!n_2qLX{XJ4tQVNFKt)N~dQG;S9OvHN;a+RmU ziuG@z>kaLP6~TvJzBSo2zm0s>n>RN>T(<=MdouzRMM(C#fAfzH{d|&`zqkM9Vy!Am zV>R89xQgaYEFBSdX{a2che{=XN6Bt~aHkpf&aPtIg0G?wva^9#7FfDBTnxqgBob>D zwh^E}Y$BO@bu>R7+{?BKVN<RHxzhg8P%L(8*(HDPuoO;;zLiN+ViOLl9l(+nQ$F46 zV+h_~Sa{1o*_vfBnwK%XIL0t;fvdj2g*gJWdSN?1e<lI8qJD4f%>Pj`1hUW{Yn1+R zGnQpsezDuSNvAx6VIe2XJB(Zw^){4RDbq+JxUM8{h?85Z&XV=nSBRZur~^M=Zt{9K zKsTo(Cp;AF@o+d24=DdkE25uJmv{I-r5UMCX^k{)e1P@TjM_3%l2$d`FWll8p(A~; zse%-`n@U0%RLv~V6T6F)B6`<`{?erXU;FniR1Km2&|7tFyh`41XyAeT$9r#&_gWc$ zs=SBq9vn83{@@#ve-u+l>lll%VLIKve>EF%CjUCO`T+|v+&lic=u8)OxXgTIe7L=K zb%9t_Dow(S46SO12UJS5y`#MkJoO2kBiI!~cAU_{!Ziz!VhGW5evL&)oYdB8PrnS; zSRpR=v)3)!j%=%bbw&k<j{tZ<ydr5$k(5{mK-GpO>R@C-&L0*hzGl~ixH;Z_V=8h4 zosG<;UV9fR`l)h7B(0tApxNjGi8WJ>BzYn>NG7%_#}}m^SW#uO{OV~Mpl?8IcuMY+ zP`qNABQSm&54dsnN4L$1(pM~tQL^H;WSV`J#(bkD9Kr9e<<4<eK(vvfg(R)7ns|R4 zO?~)$t+O~WwPCn)jx}jr3d>UAC#MB9yH^T<XV2Wh&*=lP`%FX}XD51yrR`P}!z<Wl z^jt@+t7IXQ3C^DGe<kuhzvze%p`rrD7?%1$)z!483!KMa)Kf;q=4hS_pI>pbe-nw} zihsm62-wU4ZX0cOgD*M8rSWG%8MBy_2+&w@c_53QznSas*cysN(7s28DbmdfC7xml z9NkkK(Brc0WvbNPZ}>dl%oPv+ju}FgyO}A4&Ks;T!Lp9R-b0X1tu6EI6>h4Qe_PFu zMLSPY-0d-pZ+;RsBt@roU@mf;PcH43_Y7|TJOE67UQ!5d==4^|pQjVZe_XUyiD#Dp zLTv*_$o`k3woFF8DN6N66@7c(R|H85I5D)ipxY_M3*{P1y);xqWsq@IOuAofgtij9 ztoNU~7Cx_AQ2%7>HI=(Z6}Yw_X2GpeMuCXq{6MVsaUh%E4-S~Xhi(fy+)uEM`CpQQ zT`+9L!Jm)m2nbW4k9U~X0?sv3Kr)p>@Vclm?gNX<H<~F?0%`%R3RZ@a$=NB62gbkX z0!h&o<&oAJJAQG;#-8YT==USq3i?^v6??sK+;ESG?>jRT>a%jveRAK*IXjoZD!yJ+ zqUS#NCR&l;uAt@2-EiIx&pasjUwb4T9<U5fw0A#mOVn8#ZH|OS-wr<ZnjxVJ3@r{3 zA``uSbHY`sR0z@I3{|5HNJ|r|@a&36!=Y;QLXb#bSH!?R_s4`(8?{u{C0&>?@^OEX zA{@Hp46smtCG;gkWt~?N=0g|w?k$nyRb`gsiyj-aQIvuU<tjooeRx2&^tFDz2IAW( z^mk&NJeoc5sN2+9_gmkjN$UYNo1nF+Jkynug()QMWO`vqlx%7=7pOSb;CToDTm1dP zTUZlZDgpFHn@QsViDYKK5YodTL3xQzu}>2H2j=!)M|-Y>6o*R0xWAiy@uGsuOlz>D z`?jRQiB($(F*Mm8W(EqRito$0Tq7xfNuF|er?L&NLfV-s6zy+ZSJO+q73Mg_X0_qd z7<F$~zXV`$VwMDbojYXsLb3S&>GdVAMxgGZ3w!O@o@o`y)la3@AMU20u>fD67v=4< zhI86Dfebe?_B&CaRQko*XFH<jW!NocjI%pTt;4#D6I!~f-?3(K_Ev2oWi3vso{6%@ z`MgBq+TQ=-6*;+o@Jd@V<+nG|#5_aSLT9yV#%gvuj=tf3Nm8Xz={uJ-_8N7;+S^fH zc{v{)Xf8*Fx$jr^LrOw7v!B~y@1DT0emSC(Us$Y%LwHN{YTjPN)oHbnre$(MDf(Vs z7qe~pZKZgXc^(pGTM;Dn-X94gUpx<us1>~8)xy6*^->X2@yUP<C5HC^VB<Q^<yd}T zQZLtHokf8?MUOmfae)p)pz!6HdrIYa*yRW~zqOy7bjz#it^V=%O}HzSa_{<Py?)P) zr5pW|&Il<-HY9bd%Nh&RGejsRV_AQ%D<baAi2sG@46bXBf#TVjc$9*6AV_(G$jk+8 z*6DL3YTq$$m4m3zbE25&9B3=UWu0Xk^^3J6gFw1H>5kq;m>h2K$li1W==_9<o)<+A zX&3QZzB-kVBlW1TtZeVt+@@kX(PElYk<e0@CI&8^v3prS|A7W#i!j_y^x!fM7-r@d zGXA@S&qkPrV{l8`_K@8eVVm>Xk`GSmDSdSpgk^PqPtAL0ULQ7dDHD6!pP6QW*?DMc zV#^6K+kKP<MV`Ba^aeY<F`D{~`ke$q<7)JRgkyJAZ^_xAf0~A@eR84RK%=!-{nc7> zb{!X*Js3(lurQNx(5ahSY2%vW@MRraBk~(tHbM4351`Ng@HND$+t=$%Y*y20##OkR zvN<`$vLX7?GgaB9&quDV=*ZhDwg{7jr(y*xy<YFdACCF=VHSZ2c|7mPV&1LwJP7wn zVkwx^;NBmc`f>hi%n0lbtUAf<=yY2ard=E6k--Z47u~rn7y7dLQ!$0?a~TEy5Sq~C z0b)#Nw0P`qOOFU#P|Wlq3Fr*3VL#h_NLJu`zye`Ku$PY58)t$!!;;W_+qE8ek6-%K z(=II+rBmHLpN#Q|Wn_@QpWiR(`^+hVPvI3HsVrp`0|50{>B`9jFdX7~-E*GUFJ&K+ zUm>Nl6oTed*PKv6Sjyte6233P1Xq|mpHvVmalgm5y#S&IZP|x^de6&01BzO#@v4K3 zFp{#DA-boE(g~il6+LsAEQ-SCo($L^eC!fbj{MMPZyf^5p9?(X>VJ%Tdo76Ab2H%e z>}*IfT?%vN2^T%>Vq3lajHzK<8G>QeH3D0w!_Dx%K365zWqd8=@Gym^6gwO;nl9bl z1dRaeK+TQQ#D}drY2+w`^>%ZHHmwwB+zXQ!)2$?{mSgvs{|0^kkdBW$e5RYbp9`p{ z%Q#1sQN|%|p8@Mk?2Hi*lz*LXsZIZZag!kN;;yX4edcTQB`|E}NB2e=3<W7!Al4!| zB;>WKA618=(C);?4Oo5p38ABeJ0e`jy}ABOf8;l{?=~3iu@v_7<GNZL+0+lB=MA_8 z9=KP8J8cn>_>1F!10M^t7PT=97`my6G1M-}OJK%S<S7Jwbd{l&Y=U^%1+Ji3@-yij zO-}xVf4v`VKY+Luo$e!;%$H?)_>dMK&2|-~j#1eE9gal8n80XopBc1M`iZOZ&%Mh~ zKjS<U;N;<7pSq-psrfYIBNCanSHtDYSgvg>_P~wk&0mZyuPP$*5Oc9{mRyc>%s^>K znh#!b9mLrt^IDibOzN#gb8V?gzt?TcGe$VzD^LIx`&i5_EYK90(jnC;;j_tGhP5uY zG#Ja96VR91F?ox!_WukiYiQaNkL>AhRX_bv)ovd|>zqIG(L{KEP#*9u&!|iV&IV$o zXhY>`=8!P-yG<D$C?nZVEoaiUouFlT5TS00uh2djg-7;g)W5#|cD4pL$_2@ZK|yb+ z{nSl9j0FqvM%1`Z?nc#CfC`)hzN?PQ(D5FBd<Tf1E}Bz;N}mN@3oJC*jV@GhdieUz z1o&IPVlLw|5sh#lW*-n($GzNS>QthqVtm}yRfNKct|>{)meAhh?yYm#o<9sC!U@E) zd!S4$8MHS$>(I|du_FFIlFl-&>F@31ForN{qth{3Iz?)9cPI@~3Iftf$LN&NC?T!V zBF#`zMyN2PLrPj=j+D6f``?dv#_Q~Ru5+Dp)%$~SUhPrnWZTl&q#WSSeXaeYd3=-y zTMbr*y{!9VuM1mSzb_&rM!MY(UHv^Z&kw0fRud}et*|!`M!F1=Rv7+`0%lU>iT><( z`kVa;%iTGlOg(8V=EcdBV|o&W33sQ5uPOKaHo6K&jJ_K`8sD0sQcO0jHcm347i&M{ zA9rg@(pUFa{*Bmed%ty@I;bO1%Q@F%^K|+-`)M8RSp|&sou!}vyl-@?%&+I&l4ghy z1@&NO-V#OMs61Wi!v{sn<o9m=^x@<4#_8$!*Rv+7rZ8XAPY-6)NuJ)E<p}xI@gg49 z118zH#bwr!d!|3PNpq{Ly-bVhZ8Una*ZcLeUx}Sq(R1Z4f&9X*OtnaXinTw{|AyU9 z#|s$eIH;uUtn4Jv)%4Yl*ZM`rT{?u5bY&cxr5EX|*TcbTHBYxT1oJX5U*axi_P~!n zzp)5uESD6Zu=p_aoC~f1Rea6(eP5z~yVT>N=!&Qe2@t9EejG-uxIBG)95M5s7-~KN z62?S~03t}OV9jq;q~u&XfTrFifn15@;~OwNimE&=tXYOi9%-x~zLeRmU~K?kzC}s# z{$u$A%wWlNL@wFQd4zg#;>SWB@WlwF=*sc7?$TO(*j=K$bJnkOrvv}L-7NzrlTgQ^ z5GFo@RURGJz>Y2<-RSLKfs1dUi>r^cOY5~RE+1V$6W?S*r{*<7Hk1d5S2N><ep7L? zV}W_GtILQ5_RmU2=#SJJql^nxNy~HefH`q_kR7z))3G%@%?w-k`G^|s3q-p%PYqV6 z@3&MWi%_hoDS{wk8A8~i!V6`dee6HW-Zd9}At;#ahI*u1Vprl6tswM?&?*&`4-7VG z)xBG#xjeN%>UWCjjboT@_x2mpPESL%$q{AT<&wsl7KG7+FQ{xO%^V~?c0DOwtW@VX zk;QW|s;#QQ_=nOh37epn|EV%XQ+ce$jGhTsguoi(J(?kTF(9XJGCtRcPq^!BDf_&8 z($gP4Ia*{56N|UBgCcw+KxWE#&AnyG(G>Xkn)y@8hZ2=8nOwt~wo9G#{TD$w1oXA) znwqrxz-OskOW(Lj@%d)v;1+x77*d->va~`s7W#@<fnQ=j-h7I9$|c&S#q_1vBf8Hq zP|5|19MFiywrSu2B{JjP%7trq>t#}B_2*J%j^mG|id&}({_tn6>v<Oq-uH+O3nhvr z9+AYoCPm<-N8K$`;_X%Q%krQXOdE3TuDLv#xyI3&%ejp5!Ue8=_huArtbVVGt*QnF zCrh_zDjIuIlG_D<9!dfIR%nAQyy-SPOjx;&;`%#$`uNhsEhyAzcMJPc{72+Ux6fd5 zd~IC4e|jWS{m#y9@^?di;tKaoLLk6|G#mlL?w7vj_MD|MgKR~wl=or;3hCx-%P6DM zOe5cRCn^Wx@1Y1*D)9rB8s(^29s%780M4=WspE^lvfKXUsXxu8aT9z#ot4gl&r6&A ztd*5xV^qk_X|of>gAkeq3K<*7pq;qDWpo@bpZEmd5px)!C~m~&7y7><OQ84?MQDWb z@t9n|{Ie~$>WcrbvSdPIBN{UpS9#4d18N6KQhs6agok7LusUxhhW+##oA?@5<jwcV z?2xJgjl(*(|AtQ|xC~$tpeAaUjYnra?A;ultZbQjbSmGDjE2z*C$!r0XmZaY#jHrq zSPdD@#WJ*OyQ)pMP;z}p{y`Z|H(l-xT*+2KKbW@RUm=O^0RPkd95Ucn<%or4cDEa( zj0OjUcCS9%QetvQ5HvTGqBal&17_wzNg62SuHjsis%a?S$ZHQlo%WVqMm!Nu{N0|t z0_j1128=Q++-;~8gvro>d~obdsH6=J1f-#K*Qpj@@S-}8IKqDc;(J3f)F4$x+oupx z{O~2@$=go8uy{c&p(n;+TyhGu^*c2fOu2|{POHOksZ5inCG#9_tcTD*b^JfvDjYXC z^?)&zT+c>4p^u}Wz;r;Ol<On0Eq){`h@BfzQ8_ed{VVsi)Eb1#+x4V7CN=~^!?l1; z8Pc8^RKAQs7z{MwPs?yGmT`&b_0vxB7>Y5mkVL#@s)pbuq?it9*qTFJ+_EL4LPNNk z(tZj3@iF58WX{`DGbF&1%)0~X+%M}(M$m2V-%vSZD-5qrGxJ<|C)ISjMbanvHlL5l zBbEU@`R6%K`4WT>N@6AluK6`?*w@~^(X72`7X|Dr=im~P08$KI;#k!XnRfKj=faBr zGSPsdlax<w%l3y~j-q-7P47W;0`L+A!vTjnlpYiJkP{BFMx3IN<K|>zF6V)&AdI5j zt9HO^v6Xq<bo%&yQ7r{b3`2BmSqPtKRfPKv;lnz`YMqUuH$HXKq}3L|@Q`+TvPWUq zvXvi?q$aeiqqNz9G%kYy6Dq9j_YI<;G&2jj>z_$CQo1ssY_AI@cmw|&5_wn1hglqC z6VY{y-XI-m@qL)OuX(i>=|E0W=n-92y!m0Pem3@{qH_M;k*@)2{h&JDMvZDN`)jOB zcPOa`s{Xy}vhhtbTX7WMfyP(-MjcO?8x*`O&xKBviSr<%WN}9)t-+rfS;88_{f|i7 zHvbwR!n!B{6ErSBVy8QpjG+RiMjtUfnAE^TO<5=x()&<9grMd$PM@pc0j7vYvo+(a zS4sgzU;D7Q+1>s9Gincw_zB02Z#n2t3!8}qHVz4KzPFhfdGw@h-*=)%n+arhG4;LW zllX^Tj;Z~Qxa~9E$SkXJTiOc!Y$qvvE9&XJ^gHB8-Fq9SmyfvCEu5z}(%umjz-)Wv zET;@`2pzN791Btxh2kO8fO+kEi;l(g0P4jo^1Y&DbCr*{6+J3InB`#x?w-p=xbc0# zTW$_;dE2AZ2_rpNXF3(AskQ)*6X<@-F8V;OnDTB>Bk*Fx_0xRSS2TaiTsO$VhBk+t z`e43@Cl^}&jjCnrBEBnhhW!(U=o;4<_UJ=Vn+XjP#L;0fR}@f1T}WLD1Ui;Rw{!{s zv1o!Tj&fL0NAPppmQ3I^Igb)=W3?=o3LPe-h8NPiUKUq#qQBD{IwabprBY%_g~4$B zM2CJn?YZdxma9R@#r(#EySjNw6*{d8Hb9mdY%GB!uvj{~xTs>89lKw&FNXP6lCx#^ z@^4ymgtC3;WA$z37Dry}h<h3R0dk`^=+bq?v=B0bZcnGx+RLA&S1)Y;KGCYKAv`e_ zo3itgb|z1V^0a4wSv1twf0kuR#cA@VDe79T58Asbwkj^al=R{QazgHy99R^dX_R`D zJsbpLd&%P(i-qB{R{zYe>>D%kR`GC5B;nsh-{ec!7e|_RZiOhf@<2JfgaY|P3jK{b z-qg0X@Gym)Z=^`a>N_uFXgvpE$vg8Ou<IOrw#0pA8Gm)tD}%eba&ZYw3D^?RY!%}_ z9k1&XB071~bthI7YNH+0^b9d>LElT@i{eY>KNw)qZIA78R8$RMRS{E+fQ;_#?U$B} z=4R{xpLK?GA!jW~AmD;R^Fo^wKvon*LM9XRZ}WtufiJ$gg@Eg@^OomJ#u?#U0MWws z3Rn$~al<`CPQx(7c=QRas}pE|Iauk-eNw%H>kQt70WvGEB`%zNJU1W4m;13V<!Dzj z!<(4%ggax$rqX3&e>;4wLso*_3k0>^KRWr*%RX441$-cS^JRw3^a)|g`*OCpBirC} z-hhbh5p(Liud3^GwC{d{<!dlRI-AOusvOx*oXqrrA73siM{YBgF>ecIrEN~p{5L-G z6u9Eq9l7^Nu+i`dYw&gG(`$TucG#s$2mlUgBh=qKpYj@fT0@tL3g^ZT@^dGl$`{Bj zGroW$-YX5f6^OqTNck%~#4oA2=z29)*#L^BVK`AZO;UM<m4>$?rw+WDaF+JFGJOG1 z099VUPOuapI_(M*6ADf1jCyo;Bn8|v#Vecf;NGw9Uabq~1GDuc$L(-0Vp2LZYr5te zxb%x#TQI_*GTUICI8wV1K?;cps?sdjmnYd%mlTssj00_?aN3jrXZQ1l+0BL6fK0*b zLRr)Kq7k!p;08cO`Q$g6XU@60Et%@e8uFkflqW_XfY(INs==<%Z7x9C=zG%AR&QKh zRve9d-p-&~7!#vy9JZh<vWZm&*5zmoKx4E7#b*&ru`Y?6!RDYu#l8wHN!1pKq~-TE zuvp!{L8CGAD-?w!U->mZT@lVsYoCg!_6Eu~eD1t{N>g=j&H3X4!<S`0+MKc*l{qX` zwn%}$vh$T2Cu~>na)AO)x*x)TrsHUNWeWvXu4I!%axtu*mB1wWUz9;tn`Q9h9t$W> z;vhO@u+<r!`bvtH1NopWa2hWFDC5#lxA@LxXKN)Eaw8+ByZNo_Mj<QD^uoe(M7M^< zaO1Ax_3;sIQipn1dB)lQq7&z4Mv63Dz7z7oEohDIQ)NQga=jy@M8xsY5)uDizY}G& zWZ`DMiYo{&!3vc)UN2{K?6sa0#{GG~$gn&PjHVOP@t^Ub7aAuqCq<~ZydM|o_f6aa z!ZK#Ne2neY5rT{eIw|ZyX?1qecf#iZEcl&xVnVliD<#Op^4_g9vo7`+#et;Ph6oXh z({STUU0(jjO$;VxQLOQbnlj-p{mxzT-)Hx)7n}AQ{kSel=4c%Ps7YhjtZ&-jT~!g^ zAMrPTov9p>F=rXexw<LU@iBjW3fahjzLJ+Q{CE)ckh~bcufmm4PTg>T*5GD)mpB=P z+1f5*q*R=no1hmm>toqrKx4}Gi6#IQ^1sBddi`N;eq+v%qVpIKkPdTNtB~$Y!HWm& zulSZST=v2y$%u&#t=z>Qx^aq%RYlL;8omsorGKZ_RbVN=b6==iE7GKG;$OG{EF{;s zRX2_)I0t`?7GE+GR#~H@D+Eu|ymzZ)YWuIVGam4Gi8L5Ru$7nOu+CwKR=#Z=T(8%f z0tk~_^uWp$S}d*CCW6Qj$Kj5ELQbQsA7WbTn^J*~DN|;s<AWMCb%-|R=I6iHEc_$) z-c5^5ci~v&q$6d}ZLyw?<I(0sIoG`i_m912&m+L4OZ4wMhx?nG9~t_9ixMP&+6vjr z;VL~rM*0AYO$_x6w_x<R<y$`xGG-1u^{?a<ckGSl$v6<y-pDC}AvEpdh|;20NIf4H z8A=pD-wh3j6_eJieyB_by(DYO$U7^k(b+|jM+?LT4RXN~6&Ar%r?y`7TUnRgQqOiK zUWNH4ADEvhS8stcVU?t@>sn+nW{byB-Ke&sp|>`wu*AMh6+B{PJ*R#L!PGt8Bw~-S zBE>vp_yA2jX!@lOv$P;TC%07<Zt@;5f~{)WGf?!*xo>TXXAqrP<D>k^7Ib?H?lza5 z<-^p?d&ib{6qp!5a0Pwhfa8+;hJl3-XHL=|z67;3u$RZV67DUOXLN{9k*lE)x?X$6 zpY~tBptQOq#`&fbH@n|_fk|XZ5RyGtsHVY{Dm!lq!JDu_#A);KkHj0vyM<;&HP&P2 zE_j&JnvP^NHq*UDUItP|x&bBt>LIWKLqxuqeM+l}+4_9m2OL|eW712uzkh940B;ll zzQiK<)NYAQPu$?nBj+!KDLfkO|1JL1K1eYtv(6cEq}4QI4lX~#(>U%3kRd!5@h~XP zcfigOFq5ySf&bbz4vRTRgm+)4-J1CsSJrjs<whzl&4>7fs6&NsMwgl}{fzGtAAEau zO83Ncih{!fDYny_|0Zr%<kGIhgg8MRHK^cy8`DrmDkMu@icAZ%2S&WvPbRQhdOR&g zHW2G@(peSD<9JY?;`LI8L-ogVu0oK6IB@MSGfQI>e^2>IkX9sSFh(O}T^in+-&_2P zH=bl%3H4wv`42*Tl{XlfZ6Bws|6ZOhag3%c<yChpxoQ8U*aEu7hag){5#AYWM0@$W zOroBGD`0}Gqfp$`mz9W-Xo;EY@a!m<P+h}igHkgz;#uq7YB|_-?)RBd4$6H>OJt|l z=k>>vdveCU<gwM3JfS;mBPm^tu|fx#6;_}Jn^`yp)s^(KI3?rW5VcLxI#3PCO@2x+ zN2w2q*8?GSi;=K5=b%`*ec>1W2t7aJD<IbDBP^@C&1(heo2-NnSQxYGUz|3!hGeS> z7@BY(+l0%vVaWP}vh)|lPMPSg20nZydXEoc+Vqw5B)s#9;vBE4%&#)esq|-nxlQo( zflkPc_g8eN?nxupB}qoc1B#EX)BWV*@z<+ohpRu61JJcNH<b{VzPS9KvdL3rWhMdW zJ940v<l24vT(-8@&h&s-`J=r{Ah79evoa+5{(%m;%jX!Qf3YeAki@%Do!>0_Azr@1 zFVhuEsdOfdV22y^jwdFiEDc4z#cRv=TJH$?{l*Uj1aqKoKkuyyIt~;4vzmEmkV@lJ z^D}7hXQL*kN-6-aC@=6^_d%6jDbrAbmZ4MtwJ27It07himp+NZ6p3StYgR3^ba-mE zXce}IDJ`P!*?sCmEC*g*Pm(|Ck*+qyaCzM^)(R00DHm~il!7sXy;9*UTubVUus4-d zuycweT{2pJjUBoavEKgI$8H{#%7`Co0lr?BMON`b2&WpN5daGbtF;L}U^;-`Wh2hP za)@C*B@fg9mRm`0O9VuxqM9Ka7fxWZ7c&X!(b^`oK+Nk&vWk?J*l=b|b_y5a)$e~a z?SB_)-(&p~qBz)bZ183c$xZxG^-^4t>|UHaXV&QGdZ`n>i6nMaplK)($~Vk&bJmbP zb#O6;??|XWHnC`|j(_yBQWi*pJ-+i|&})sU{&9yDL@Au$i-LU~S?*4$sF3IvM`@iT z61|Y^TqSF1kl^%{qq0bCA&{mGLUafU^Zrh)AX1CZMx422H%h{&CX60GIKqE?4*1Ql zmrD!tk<l9-El(h`jh+=<5OlOSHlpzP#%~!FdqMdP+Y``P%WGPZ$(VSXfD3+uILIwB zV`guXQVPpyJLBB$6h&3Y`wk`eAmsbu+or|Qeo=VeYMK77RPD$_<NT{9k3ZhI{25cA z_4<<Lf#e$9(wFD!G5q0I5l838|GK(78a@k{!Hi+y&EwzLLTKJ>mo=_QGpP@!Pj1SV zWOAAps=(aJf2qUXGD>3C`k`!CX%kY`p#C(}k9Rl+lCl)D)Q3$hcl%@eU`W`k08bLC z;SN*q2WHN<$4a=D4Te4BIR1krDR~#2jL%m!R;{ulh8s_gh@sZ`e?pq;DakP1cKN@x z`^0tT4UBo>=yIV_oWharfDYOq-FRY%$^9D7np6^{D+6Sjk;4-4_aD#(4??E|<vTjW z9%lL|IBtAvi7By&%hLvsR7)xNphv0r*O^R~a+DUnH@)UcU!m#LMtVP<HTbPFw*7Pd z_%O+{@_qmZnG5QDU<RcDrJhlA?Nip^4?!`J^R$!SH9rjh<&U5;S+&FV=J}^356!=Q z%8QkN1-+sYCF+C{N!yCcl*1`eUk~3_puY&hqZoJZ$9_6L#3{3|g~zdLLRI?8w-<}I zq_Ph3z9gUeoNpd>Q+{L5TDnUOTOfa#+~|EyL@)FW27wXW1Lm81)I|6BJ@hQcLeN_p z_zHgVL-wyikqzrBvMl@e2z34WAMC_$(B@~qd9~rlV^gV5yJ2A0hi4qI|5QFWnD6x+ zCrEcb|2MC|imqL8f5@kntR(wz3!n4+_D&ur!u5=6b!2TK$dK?R30ws+Wv3>mq%y0u z54jgcvk}jQlzY`?EfcCLd(=6cDl>>&+Gc_NM$mG>2VM@!MDDc&YDBqRb6g#70u)ec zld9}z`*f>UsHHm?{c|F0sg87Q@;DGt(({`G2~Ng4kx3zcG@)Qtb4Huy=>tB7Y+k2N zQ+?dp-nGvy^_p|V`q6uuJId@$3}ncL8?_%YU&V<nD<9qY1n~VaoHcB0)W~<I_VBS> z#~WKoY_;vSP+GlCy4M1I_2S*X3C^I9+C<6i>xED5l?g?VQBbnjhX=Z{SMTUZhhF;> zJBe2`g)haRb-`aR9^2TwQT8Mpeb~6n#A9;cEUeNAZyxVucUf!U5t<qhjVPBRE^7k0 zl;a;!fp@O_r4~)pqsOVF<jFX>$}|z%QnX_<x|AOB_(|by@DRI2R`IXb3q?D@$O@Qw zi3)`LYVf*rsEI!DG>8cX$K0t6upnyAV18$bRG*i`#ON+`^k~+~8B)J5RuV`y3rP2W z`RxLj@LEPA7pl+R@a6N#8xvR;1co8B%6-x*c3iKFaBv`^;Jk}_NKBq65Vy%|xcdZ< zw9N0iL8*0xz4c;zUg_rZzDt6FrtN+ty8h!UC`>mMm9EK)34h^=mnnHo;dIHU#jI)X z?i<S-oG=E{q6-+rRyN{}`mO4K`ebAz03%wAdmX3oaVl=*K3Ew9{lKIB`+ZgF;PKuw zdvt>edPV~i<9jnQIn&F|%9{RycyH=ax2}7nn6{~Y065$%)v_CUN+kzSq4J(YWYHZ` z>BD~IN@3&I>pDR+&5T8BbRT)Y(j<QCm&iD%@!a_KH7l!Ti9;v3AQfeoo-y--tpD(x zEKeBqXr2UyC{9o`PRw<Mjzrp;f0}cQ|92%xmq&7xg#K<EjGhP+^T&(Fq&|M|pAW0d zW#!O=Ev1NV9vt2T55BGsb;--i%Mp9@S~reKEbwGi-D7cqs==mXe>17i>EPtIz`V$G zU6$Z}-=|V~X`bxfQj{A808gpTByf!=5D$>%K*G2hYA)HDCPutBmar_r*Xwt)YWlOX zT;Juve-qx=byR45nfczHe;?>UwYBiVXl^g4tB#(Vr&8-OE4KUfYQACVj2%v%;D&tC z4s;%lO1sjuM{55Ngh$+-HoSWyCxt+@wzTkFeY^=W_)Frqm{%G1nR_;Sp~@>JV2O!? zj`Yd#h;Z`HYZ~naJQb6zyfZe3_#Z1fp)SqGhatH>X6}~W6uFfk8YEgT2C@tCpuh+F z0zK%0G-WRDu9+{qa0dA?dPQ~W8py47!rHf(gT$KsU&12rtNy_YP^>H6uFRnO2}vC} z-l&XA=&5i(Wjv$w7v@7j#n9Q~&uJr59-9v5&f!j`bc_tmH;^01?}<ZJ8Y^|mn&0O{ ziFK5t0>}S^95u8mQ&GL!tO<wy@@`P~^_F1Lkv}c>6_;P}B9{Ydeqtk(IYniy%rZIA z=oE{7D-ONSVsa_zUU^WH%duxvg{CLTJ)eaFlWN>^@F2pb6UGwCl2>N6Y?O;t&xR_g zsgu9*zw|~zmEht3PTJa}V&zV0ZXn>?Y4)0Yl{Rt9>(8k)Z)66G56XsG<B3Z!OYQ|! z=x{;g`-+SQz~kLLk{?sic(g$C_lt4!Khnu~Uh<#*OdSX}HY62g_3?mThuRIlxlF-o zK7Ii$Q=@!v&K$(O`+nbx?NqEEx7TbSJ3qJM2v|^_-=SE8GNKnqrxpj1)_&>AjH<*% z%9AuB#Z#U1!(!C)W|DJfBX<jYC^^kD0HlPNeUSjTeDWr<e9D0yDU|V`A)gN5ki*iS zBz1ZNIy|_%Bd^B>U8VrsCASF&1*E10XnA~>S|Jl21IchoL=*ghQuPypCl$qK@lSxX zzYNoF1XX7tnEBuX0>34a$sqay6~Py9_ba!lWhGP0KknAGP66nJN;ru*BcnWDuhu+W z8b3K-eJ3dlPlQYPyB*9DMDFK9?5Sa8N=PSszgI`|`%;oVhh7O;EuCZCw<De$3}qxP zuOI5c0-tTf;oe_xZC%kSvbG#r4~jDle04l&0jj*wvE&prP~Y#<%o#<8){|zHlBwn6 zj<~SJ@3`qdB=LVSE=|!=d!L-=Jf>jYW-fdlX(8i!v@S=v_v*ad<WV)~hEB)yVR8k@ z>Q$HM^7Jg{$;VQT#nMP_;HW-?EHdAqm5I<wO2~<{Vut6Mx`5lBr#udXkb=7xLM@D7 zoj&Fr_)2TR-%jL~!hryH8lzHcJpBjhryvd$hM`Uhcj<CbXW>;aho=2M;clA&bXT2U zSuJj5#~%ZZ(!FVy$9oWw?1;f^GdxP8MA7!a-5~&l=_jp|m50m8@hX1aEN0y)Z{e8r z0`Exb9mIT2{>%HP%k%*8pBx~Ryu4R5gqc_EleRncK0+*O+I9>86dWy8mU{X-;aMey zEw}|(RuGHFXa|3i^=VYB-r-`UtpD#0ej^~QQJag;JA8B;w(t8*h|yOB>2Exu{&t5! z8Vi`x18d5C;uc2F^`>Z{#6}{uMk)$%1XVA5+kSC;0rXng^;WahDvg+Gm&#~VzEr#% z6NOW}*k=D|hk&1+N(H;2Zf{&9tQMBUiSRi-*0OdNQ#u~B`mZrf8}aFZ!U0y+8-f^E zmz)8N3H}p&5UXrneIK9p7ZaKOD*E$0q1(eM4X=Lj*x}@3&A!A^QU1W9Lc?)zOwyqP zkbVM@OqLv7CgZm<mIR@rQ}N~IT;oghC;47@Nqm#Qbv9q~ec141$FQ<fU@6A>k)7QO z+GBg|rlwQ-&_C|x_J@jm2%mi8&ZqqoVp1y7%n9^*8%6Y~8eE5)EvYEcFB=rr*-&50 zGvQysU&Adf8>G&7_z?bob-*e1b3a0#2Z&qNmAFRUUH_*5RDEb26;X*Jh*g9}pB~|S zN7iy=0uNy~x-}MwE5f{_ErijXQ?C-iM?(kN({oQF$ciB0A2~~a%r3O@pdw@a$Ky1J z9`I?1q~>xvF36`m3wpm671Z$%Nr>kZXW%FA7p)(09Zp&>2iy66<r&oal!h`2|7kc= zF6VhxRyYiu?Gw5y6}GB0D3(&d0l&1+OAq4e7C=}oIYuwZ^O+a8dD3)S@Vq!$$>FyH z-vgtf%8q;2=;heo+kvDaEf(0Tm6{`8G2_%+9R6^Uf%8lr<KLqZIl}bl<V`_L!hP|i z;>*fSD|sNN+W?w14{8^*_QHq%yE@g0qa%YlpNeL!<AqEu?M_*wZ)L{Jv9KcRx%L3s z<}RgPI`^d(N|QT|(5mk=bcEmPsg|~oZJ=?3q9+l)`LTDmy_`pCvro5LKN|N`Fa6i! zut#wTJ!kOu@NE=!HwLSAGBo_P8mFXsy^Bms=R}9cHkb=4n?8coI`AVlXe+G`<l9(F zg$gwfD!rh9;Y~^GOH8@!(V5v}#~F$-PAYQ6+NC194~{0$J~SJ{HEAgO$cOi_=4zps ze$%8JW00}oYD>ZM@{F!m36zMfGn?l-j&}>5K6`dIz=Su;vQ>T1p1yzTrEQ49$<imF zaMx$QlM;$Bm_$Z>jWT<vDtn<)!mTb>BU7K?h}vvS*Ek~8fr^2ugGY<>(Z<(i!wply zvqTzgLoXdOi#+8`39O>zeuY*HV4$kAtAd1zdXVLG-j4?ODYj-t4BN?FoT;b#A>$FI z1eX}o?65WN46Rw27O1PgpB{z<|HW^qMYkq<?8`}!(FzUR<`z;g#lkD>@_J#if@Cm( z6l~Vs*HdD_E}D2b%ea?=9YTzgENp4jJ|@0oN^jTFRlX2!-;UhSD0rChE@RjNLz1Bt zGrz@$?9^Nif0FVkL4IfAs6pQo;lL29S6KmaVkqAeTCKip{M<2*ws}Jt_KR5|U=ICH zLi*dZX7~>EiG!8!canAQwww<~NvPbJ=%Dy#sv!e=t0#T>2fOZ;e@YpvR5$A!t$KHU z)!~9f1mLyUo;b`pU9p`TI61vUarSCfUe^5Dw*vRkY8z}vBtb{mM>91Dg%pnUWG;MG zC9^ifa}zHcGbOMp()oGHnE50W^Za%ZUX1e%vd$`jDu1#NK*;3M{HdP>&oQcD2@YqR z`+nzZ8j9~nx*er@<<L|7ZU(NcELU-U<;C=;<?u^ycEfiZtAHUhT6tBo5+Utl@Yv-V zE;y;dEKl$@O7>@h02s)d>}!FJiD6#>Q-S@iV*bYLB}g4q6HuQ`;oYkX_){X%r|)hb zp`2E}J|846JLB~o9hN`HjSmGHFl?Le3!31hB3HSc379U2f*}cr`F*=8hz6to%G^Sb zC0K_ez%EW&YyRO}GRAoc-w1tD>OoMMs}<CIN62ilNx><R_K<pKf+^%=!l1M*k(Ys% zhG$jQEad9=X3olShB#J1>Yhn^42Gz^?(ZhS4$+|CPSIOWeA`>SpeH=?{fz@5IR`4r z$k&x*U@{@C?v<469byDG?MkOLXOZ>F$kCodp)!{4#mAXlreMS>3I1DBRgrLtk|Cw0 znhhX{mcfH`(6z=_g3Q6s8yp5Go6{FBk3Kwz$vFG{Zb@PL&^8w;-%_Eq81o`np055_ znU>K&(Dy!t#feM>Z$^L>Z(Z4g23o-Z$|JaTI!TpI`X}&rV4)OV5y~^vIC#7{1(VaN z2&{%1t}JOBColQ0f-f7UUtTdR<b3wZFufI_&ea~~Ahp-%<whWtFbYPz;}3jvn9*}< zm;F*jsxaK0FD5_GqqPIBZ~s(i`P)I*>=C4XEspev<d+S?9+o7JF=(6M8anDl%XEd4 zP1<^CtO;IawehnpYXJS6KaGo)%U=ie5Gf;enb4E*=j!Q>&%P>?E?nm?pPZjtIlhuq z#;YfNRb!)nc-n5KozCawym3YK^!pij_HtJ6C&}#kb}qgume8v7)#pe6;e%G|<q!Dt zHuTiz!$qASCuj3FY7f7PaN@hR)Zv*=xRGH32;|4;jJAGG$Aa3+lQ#e>P1b2LjDCBr zPnY(_lKlH@G^@L1fn}N@>TtKzYKNNSw)HplD{O>yxe2M_rx|Dl^qJcJgdlus{gnuL z&HY*4OWUk%^H|(d9q_}t?{w{Ezk4zC%Ki12p}Q-lTk9Jc&edS=&rTO)gvt5rbb#aQ zzhVgJ<rX(2fop`_JT~!VN3wF03!qSi`-K4qM3IEcJ3*t2k2G(9kd(9012iL+`q^rX zCK>SI=>{dVDr-go5%zl*CIWAT!C7L81VsPTP?E4ydLP|?6cTInoNz|^_~k$4d36QD zj|@573RB}v*CRG&loo|j7N;vjLKdZe5XB_+>5kh(Rd&*f@8Pd3)b?V&`PV8Y{L^h5 zz3Dh2*|iA&0Zm-}%^9#j2zn9kB2c!N=_*-8p#xKw$Wm6s%OKokAZESgoiPqtD>TmC zxwq=ZSRRXny>~2%QW3yEi3?#;=z@msE9|I|(n)DeTJMt`Uk}$67IjpnJo7syr%=$4 zN9|t5LR!4A8`Aopa<*KjLM_9DIyrpj5fUoH4u~Nb)BUO9KNhk$U7r9+Km~XnffCc< zggY@Uf=29Tgc!K%k;p|1kW-rF(~vZAIPe<5+V=xu4jcq6Y{ROaUAn-ulnM-BhxD4u zR4H0+E3$})j40JRf`Vnrvp_3X)^0ye(N&wN^>3Hd78gF@drdgBowK&jtm^{T&>%wt zerPuf(?1s(8B^x$b%D^^T7OO-hc57jz?V;Clx}yNF~s|w`KLWGKf1{Jp`Nb~e|2!p z$9%Ut{U$CM)TDdD@pXx-GQBJ~!g73w^xFS<)V<&p0+^CmlozqK(_A?NLY>?;_}98F z0FSSwN{MIYp_3T{RqDddomjZC{~9MuJP=E@hi5!^zxbvEH|wSv^03W8RxKPMBou7< z)~|VQH8n-{8A)xxPdtx{V-=WNlTfUm0gb!?UJ>?kycDe3i&nToU#!>Kf&x)Ku8*k@ zJ_*XuSf%axsZteLt4;vwQu$i<!kJV#@?JRlz6C%B52kt2zjo4F_s$nEd<l)213LY; z%b-gt;Yge^2a7oY00H($$T-llnb(MHPR^Jyd^V#zis3TkL@=VmslmA&{?t2;OICi9 zL4-A~&r$bzv>D^4cu^Lm44FH2=?S-{fD4O`m{g7-HDIlU(@Y!|GOU7u{Gj&&lFV9! zQtXtz<_WMzDEDw+<Pxr6k@;6Nzo`n@U;{jZJ9en$WSJq0VB2D6xrsn+tkwT7j=V;B zV>erI9Ju4bDH?9M=T=T0Q)tQMt<lbssGa_j8Xc3*{4QuJzoW8rQwP`}M;5!i&GkxS zh@aQ23(8*h@Z`Hu@)moxm#pt))Ijz*y$RT-dxciYmXIWUt(#O>mimAo6y005Rjnj* z>#KbVp=kNXq4mq6kxt*|OO*e!qjV{eCNposueU)Ahycyy%3h7&m}!;krgkwbXJ+6x zU1W@|roG4J?-~ib##8ugyZR_m65<ocB33(HyU-~VT3h^Onw4w+UPbI6<43$#&QlVl zu!z3RR*n#SiBZH4_w}r&_cxE)2bapA?9P<EWzIf!5_@_-+lu)r$N^dOTyAUqx_JRf zsK~n)?h<}QKuXBl8ukR9(k^8P!#NJ$ioDi^;ivPG#);bLxW`0(8}{qp8HZKlA++!D znvokT4qx#7B}ap$?(M-l8R~o>gQua-rh*52=<^4Y8R0g2hyb(g(K}y+nYQlFaf!eq zt}Y+l$!^p?>7YR$Lf9PA%3N=vs+#@B3;j3ofB(k&v$JXe+`%|J`gx-}pMB#LEcL@8 zo`6I-KZ?F*?NJGG^b0euL7(h%ByQ3Qh+z)SBbx@4u~Z}|3q4e}xU7oju?v7`531X9 zYA=ylB5^R9NhT@puhpzp+69$WjgN|*+ny{l0JVi#%^zsZO7xv-p)5Gkj|JaqRSd!3 z-U@F}zuD+vT}l6Y8w>aBp*Qq;r_r$+h4YQhz4)jLW*h2b@4HJJ?z2S#iiHYsK%|xO zAD7`c8Y14Vv;Ty46z@lJ>pZ*l|LYUY{J+JK!+UV!8rtrZ<XL#Y%Ug6P`7_?3Ui3fP z9Ffj`6T%0=aG{al1BE(DkCEDhQk_t53*8QeP37G~b-tJYkIMP}lZv59@txz}35*ko z6k2pkzISe9Zg=SSPhjEaL3TV~vj&=*p4ye;<6$noGDROS*1=`Cli=&pKcHNc$eHyQ z%pVhiVJ=p(OF>&Ar~R%hZEKA}WqgOZ1jhjXnz0WPd`3i$$tCbi3@G5GO<9B2J&`VP zb#}yX@xzaVh7L6=wU`9y)MX~67Hw3*$#%BOHD-qwSuip9)94$efE>FixvZ;r9C0bf zwDImSdx;Gr*QQaF0)Zws!@e(PG7)6C<V@FkOUMo+=3lSpQAy6(bG_R6@&|FRVu22M z`1|dD{C&+m>Z6TM20#^(SP@#GNXUoLlor!6WxO)ybfW-kupk7jTAA=1u|lvfED~&< z3H^XCjh;8%-uJc^aP$q<d(Q6tfE>f%sds#dSwCq|0t6~Nq^obo5XqN932tN=Z_amK zG$s_X9TNnKaZDJIse1cN+lE<?9ovZ?=>DDWg+>>>2;Z1QS~>!|unAI=Ic9e@z~H~| zb@(1Ro>G<(_+k8$;&Rt4p`i)E-NqCufR()ZoRlY?lb#V65AqPl^mD#u;|_Q!{M<Sh z8Vq4x1<bw#LD-wDU0@Bbx%OM<TN8>S3%q8+MS0;jS65vYRxPG<<fT%1*W$9o4ao%5 z3fv=H16-!TZeMfU(`gMuNo71gr&&zw5lmCf5X@Pn@VRHSd~75R-6E2`KcHQU0%EIq zrK7gh))x00u+sngY}6rNhgi8uyCGJZc=;u-d>$Y|n^G?o)zfau$bHaf9X8`^UC6oY zgi%Y|$)h-${%mt&i76g9<T)v8yqYkeZ6#!VhYnoKt{7tV9;_H*JX8r`x`dSHFw`@> z3bHxgl071tjlr$PB{0+*niH4FG5Hf8%%Xk^TKt5nGWhM+rv*Bss5~~K;z2sT#c}YE zTsFkt5qd1E2Me~}r}ccRxc2{tVN(w-12gW!$OyGKCgEY=H13w^40t4%1r=h2o*I^t z0UfTThC~9WcQP`aJi|v(sC(i@l`?}*wxj4IVT)uK5OoP9yXY@Y%=%<I4p}T~?2}OV zPWuU19xqL9y>zk8W{33dx$Ad11tnnlT~n=a4-RCa|5+g@dOx{`=6(9dFg30<!}JO5 z?Q$ghRqhXo>4xM|)s`c_h(@<i^jo@bnNkMUn*Tc=rYghzTosnj$|566^eXXl;k@^S zJT+%{(Y+RrQc)%s8B9AWLZ%@|u<oPUr1}K^$vZ$b?S>0vTC8`9%0{8+Xhjx>aH;Eb zvmHPD^A+hQC;}ceDYoS}OVqT!@OGT|0x!bgK57fw|7Z<tb~ZMKJSEm)PpGvO_imd# z7iZYMwD!FF2#X|lr|KxYaM<P;Q$2+tASFx=NRj`oFSDoqr_iY#>^?2mOg|p|UG*A< z2|vk5*0e7hg9+wU41K-47dT3IZK34~Ct&3NK1Y*F&$;Reg+p5$*6F$sxZIxI99u!1 zbXRh`#5>e2#BHIUdvAH#t7GN($9IHxil-fJ?15nkyfth!d84#Ex)?s)1LX!!LGzi} zYIevD*OxNfDDGZs27vg1Wa=swqG%#l<@qyoQ-J2cqm=*m%+k@F=O@#ZfzMp38XQYg z4nP~T+*l~L<Z7QKFyqkEJ{KAu=&$W$#NfNLS~bKU@>$H&<g@q0*MgrbRJur!aeO2k zw7WpDgQ!m!XbQz5@efej-PIu=v+-KO*jq)C&%i*^SF1niPmgkH{@7$gGm(j(6EdJ( z9$ojW>2cy4U%?OGDN}nEWyzCm2-%S{iP>=?$9U_t`n6$Cu|GSeN&j;>thx*NX7A+r z{k0*}jXn69;Gk62ZW1b%$egOJ4kv?pwv*BRI)6XJ_UbBqfIkyDvhM`dYpK)7Yd}Lc z(!Zxo$=!o5r|G4CQ5ulD*8?VtH&(X;oiN1%e~T@+O^8SCumy!220iM8?&q6@F#Yiz z^(Ps2cD1-<vkyVSWyG0ssr)>$A73FDV;-KEZN$8Bbdr{|)qsf@%sG+#ZPxhD0}-NI z&rZ+I4o2&pkWO!(uE~&<^~YwzI&&N2GZ@SNWMQ0Tkw?${ru!}41zB5@l8D}%YOd3j zDsK+=?@BMU-XTL)knB*uJqemleJwbSGj0=!^2y`_2KFIW>?cGc&ux7ZvZ5VcaS>pg zvv3^mc0%?E`Z%29$iQs-Y5hT!`v}@PFnGzeXgDEGCDtSxZu)OYLJXM6_r!tzF5Fs} zM%#6x`<ctXw~IC_p3c~Q9`=SKtv4manH~rG+Mo>|%4fV%Sl#KZEd0q)*9lo{ld=PI z&Yv{asEnW>(Hjae1M74tXVPLuw=pO5s25!z*4QckVYg)5In_mC1WC4cXd&loyOyEn zc27mR+$K&THS{a;(CvJDmsk;o#HXTDO|m|9Rd+b1&za=a67>K{2hlt0dZZ=bK-s~4 zoc&qVXzlN0ZiTQ+1>5li3)nS*39}CKxhTEQ#aCVGH0s3r*y5$BQVk0BFEeYenc}kX zOx4h6<vWY1c&ut*bR)>mco0qQa%Pta^-#-ekK^!tqW%=F58?c-%pp=tJ)Dr4KBMV; zKed>xecF`0owQRXE8Z~`WabKYXwQ^vhBtmAim+R6!_;>)*!*FK3`+Pj)1YqI&e_(~ z@X>zE2Hv_~)3F_Lmfyt??Td2;GP%;1F8Q0+lYV)SyvidoSfFS3jKOl0CR>ymK*$rk zF#*VX#oO8OpYbl=J1s`F#V(kE1|Hh0e}2jh`NDknel7B;=>)ofWk-D4F}YI3Wo%J) zlv?^{GM_ixMxAL;S}$l)D6F8`g1qXQFyKXPm7s-LCCOjvYYA%sFg<iX7zsyu6Yo%e zRk)}4iigp}2Ku9r=<W08zNQfQZ&UvCn`7Op$^VGw&WtGtrN6_2gTAlqc$1eLa)?4> z&)OwFbj@C5tCMa3o~0_QB1Z44!VW*izpzM{ZZyIKVPh8l{rjQVpJ4H+hAvST$)=k7 z99QHdT*|K5fG-3;(oWAA;L%fOr^N?Obb@U5-bQVX$C5rteNFoPc;1oDA31Z2&+gFf zWuYBJe*oN2g+0AUk+-V^rkFqc`HQ#prY=nX=}`6xL$!H&A3F5xLiCN7Mt_bE$qxQI zw|1QEnTA4k+gaSLst+U2_xkSqlKFv~8Km3ozr(jycLlHEuZel)3_B-a7SM#j-hL$= zz(Y_EcE@SZ?ChSdVT-{EeXvS=Lu^2x;ph6W2hTUsP}#5{RT$o|d*0}RZwl>bZt}CC zRAMjQm9YDmWM4f(wH)3+jh?nSlCxBNCJ@(2#*RPFb0?Lo82Z(qSZnZiWtuqH=iQLT z?_E%r5z;^Ujkm^cLQnoz5qR&WHN-Zqy_C|jiN&-Id8t61v+IJ^M!SunG7{PK$}FFK z1`|}nRstAl21cI&0^jTFb3ts_Q?_Y;aU{_s*8KNwKih09-R-Brh5s0+wmcn5ttak% zx#rN%!tpKEE?~Nm>hu(!xB8Tmk_2f3a=J9_ttN8w5Ag$X<;HYmpIHA!wOw+f+6bGp z|Hus1hfKBN9Qtx#6l8!m-$WWeLHq8igb-*n*6U2e<y0rtj=sts`EQ4?)f0X8y1$IL zDmi6(mF75OmQcuS?+1wZ<KVlxsq!a0N}iW7idz8`W}Zr<P5qF07-;!#Ex`_7onqm( z_@5^cr+7;kxu1Kh-*~t9IgpJ<+pX-=<M_dCXQkALiu*!y?N={eaEVgC{@vwRF*jg- zk4W;&@iAbMqwS}}PPZS*!`CAqea4z)AfEr_C}<%Y`ZoL~9y~KR%32Qv1|t<`PuiVH zh}D|vy<+=565k6R_k8is*0(H9P+EB!tO6B)Uo|I0!T(0ER|-lVA?&t@<i)k`mW?6E z1Hm*@qA+d0UV3SPm%}<VR;kLCzc|Z)eP8&rD+Ca9Imqwm1*&F;7S<;@o+F$sVtS;{ z3MSC<n5*yo|D-Y)7rqPdVdwkOzf3C^;4@bY0+SkFY(J7E7@(Rm4hZY+V51dxL6EGO zp9VBHKbEKV)lD@g`0{tb)fk>7>3h0F!eSC-gjake%#^)xEJf;BI#T+!9X?xM2eza0 z-NFdUy&V?2e1A_rz!rz@{<}22exXCZq+V(G$il*C{rrK?<znbT$4oB%Fsp`SA0OnU zs|4k@Km+zN;e8VGVtX7Bg41=|ZGhxQ&@zR1ypyWpx*@!=lnGaz2^Mp=AO+fiPsiw0 zp`Q8VxzS5xdG+x;A#UqxA}-(&FmZ~7OgAS<J<T!|p!81C^m~j(j0->(R6!2#eFVg? z1bdUgnHn_%M=XOqv3Y7q{kJ;WrUsJC;BxOopb5V8L2~w0b2+`fUP*Q79o41?yjEkv zEap04a4#tf%=(V0G;L1w`QD0nip*f^t?%<4Uq2-Qc!bP?a2nYG5jPmoG?en*HZ9<8 z-C@WgQ8*jH$X#Q0Zt&X?s;T4OGd<p>O*A_y|LD(So`WR?+AH|E-CheCcbM8r{}}<1 z9ee!nuTdcFD!6cORSmokNMdXcyM<qq5dUx4Mo#<XL!l|cx=8*c%g;Vpp_73PU_MdC z^8SP;w82VUnO8@YJFFVEA#PHkY|cvcuAP}-Z&D3@o^g&=BnNIukYMN(H-G$i)%tha z9|`5K$=mP+?)U~Yzni6rl3RwfiDV}{232D4v|%c;oznS!WJ2IBbQ0ag1uSzQabe4_ z^pwtPO~8G-Zj}90e?%I!B~ZD2<jfwgi1D>S8U_8dYy>d_sHxvdaB~7PUmDz2WGY*8 z9U3@VBswWczczeg+WL_;sc&flKi3st!H$Q7PsI<i;1R1+w7~`ibA&BV&<Yh=Ya?Qk zvGr`mYh}L4l@W=N)CZfnE*Kd@UzAa`u){aY5HZ`la;QwciR#YB!2rAV7xd0w9({1V zkqX^p!&%~i9(farACgeyeDmoPaGc`muv)T(pJ+vy8N1!{0-L3bz3y>MWA-4Xqx47; z#^w0Y`x$-|u}`Xp0}Wy--u!R9gbE*{3-W=oN&2)b#AR>QSEdLM4m2CSUYd_-0nBWk z@#@Qe<S5pBI`~(N_NFRG9OYI&>I*Vjj`JQHPFH)b42NOp;4io-1uZLHnIp#Z@g<$R zLt}x@M+?<9HAb%}$3VLR{-*c>z@OLb$)}K0QXGeKG(y3$0~1B_rY_=&C1~&XF1rn< z<(XM@`+G+VLk`GARUA=@oxdu741oKrjH?Z|+DFRaz~sW)G8?eSF+4fKJdmg;{y*a; zopS~(4s^k~K{v*%<_Stya?Mk{QigX{pW^Nh2QY%7Ss2n#hdlQooK>5Y6e_uYscRgE z@D4=!;SALWR>HnOJ+s}v>1GufZAo`HUNmbi^J1Lk@dn;~3qr?42sUbIKh2x$dO^%# z`@k(dG+M3KGUWZLdwX)RY<Q>OVCssYxI;ue5X+@FDvr}#4pT^dU2{pWK^%^9++39Y z{@XFkq8%tBOH&D^CEjws((zh!;zKl2(oFJoa3H7Ap<FNn6ieiu{_=d`to}9;y(|d8 z&VV2KA!~XiB9|NO!*u;xPSc(hYeM@s4@z8~6OMY7m)O}uB<9Ur@cNrgA&=aqbV=Jo zKJ>s>{?^y1`xQg;J0uNSl?kc&w2H68AHz02lAJf?u+#%W8{LU_#K$}7=eYK1H$>)r zWjHM+B;IZ?^E(W8+yPL(C(;YJ)20-s(+eFUeUuT~8vH7T(YZ7FaGLoNg7$a%!UL52 z$32jJcuwJD{u-0d40x7?l2nsk40&d(0|WcgHaPyty-<rBIp<8$vn}4#E6<wA?Sk*~ zsI%q1R7qAIWYM($Wz{NtvgsxQuRbgLyQFiI2s+2EbeP<|`5iV+coggJdUjQ#)xxc< z{4UL`mIJPss+%r(I7NI_n;?)5gRe~Aov7an-7HpWq;Xg7r=Onio9*Z3QgtCfyUY;& z{mh01V^8|}h^28z%Zi6B+NZ|v9ouGRfDaWeM_?{gnF(IcjGe?k*EF6goWK0DG2|(p zme#IrGk(qYzn=mK#^=+NzgK-ZF-64=LhIPhQ~kn1LP9?FJK`u!#*nbiN4t$x88e*( zTuNvUF<mu$Y$7m=8&D3Eo~mfRUR=yw3p~zuCGU2YjxJO>`Dv!~v*oDOH(3%16}@H7 zCRsTP>8baS&>d?e*)z8fr5Kk4f7tJN^Gh?OIAOl#We@A+y;IOBainmVaF7*Ud@>CZ zFP;)Bx#^b(pvD~|`$HN??W{)+5{(RmE&^!_*IAzPb%1<cK`1h}ItmI^r2ab&uEbd7 z7#fBJE~|j-@v5_i&$pk&&~|D4A*dtAXSC|H!T2HSjJAC{_eBG5{4O~14+JO*tkD_N z07<<qOX=NQzsiK226d<j%!TVVKD3Aqm{&o1=%zP*Lp9U8v!;~xHR6*L4wx7(yR0!0 zkOk9e(3|mk5_HU*`Sz=F=}P4}UBj%@*~sUs9<mV`jI69B^a1cIulM@hoqk6ivL>@r z@v=s%<X=RSfosgMQk;zc>|~+HZsu5ymvrp{po;t0?@O*4xLNgdz~uJcDWg7(d0PsA zK~wFJA5kb=4aneRc<LaYdV?dd!%c?ZbF+ajVk7IdhusC>yZz)4E(KE8;#&OZLT1{` zF<WTs(?wF*JI~kx=tkRr)jdf5uD7@TeEFouJbj7t^<8jwolkz$K-rTUw*D8w!D#7u zq)%K<bT%}Kr5;!eS9e+|ppt}Il2*EUpPV$949pLb$T>oIb6r@>Oe?a{c3-qsm<Luf zb}P>fRk*#qVo5T#$@hRADvilgbt<rFbXVXzjZZr1)O3Scdl`W{EpO&E*mG@Q%1!Mj zvoSN5hIOc#!x)v~Lk=o(U|*dnMuWX1#eN9wu`o$c?CxNXf27o@s*z0Fzp!#SuPLQ; zol3dbb4^_~>j87q20lJ8+T%w`8y?HqrO%+D72sb|TTWnOlHq=q`h4HtS#z>azZc^r zM-fGI8=CLa%62}gU{?|o6dZn3K06T=VaO&jjaJ)KAWV&+vozfyTwO)@9v!LFxP|9~ z{o^Jc4C?*V^=9*(Sg$1)^x6nNG)%di9Z((`*#=&8`sU_ioRxZQOjxIvV@SYI`RO89 z@a5Nk?+%rAMNb1h3crEL;kA4Gygz-;c!1OjI<hAEix+`xaWt?@7cR)APfQ7F4tfw; z3$MKQGFl;Xp`m`6h{G36*eqT92D5Ieo>bVlcaS9?)dLm1^T$N}(`0=p!56QLSLo-> z%f1?`)NeMoy~L19`lKTtCb%O-NIyp~UQPT)lI-+HmD>=ol0{fU-Z@N&X}`(+Lb#D~ z^sjnK`r>Sb27!0&bFV@mqEmYx-x?#-rO<;!C5J!Tit4+?d){gt@NAeOeJS_0@Lr15 zVN^1j>Ft<K2)FnROgB!*IaYL#A0Qn!BlaD2x!o<=%l>~HT?Iqa-@hiMgwf3yjPB+~ z4C#_qLK^Ar7~S2Cbax0!qtYX#I|b<+o!<TLOE}y4o=-frkM)5Yqt1GM4ixGY-z2rT z^GO}}Wz5)RxK$IF#~+kv<UZ-U)gC3%i+rN<>%z7i&k~SX?^Ups2g21|!uUSj)*HR@ z^_Lvay)Uv)=yPwYLb&9|uTyr~vC9z>+ug;#%3J*nIjH9{M}uMzHQM=uq%Z#Ecr9JD zr7yr@@Kvo}EhI}eSlnkym6{Lw!AFP>;k<a}Zgkb8Q!JTm1z*b%hA)KnYnG-8Iv=L| z$M0xwuIqr-`0hP}IXUmzWNoNik!xU3jvB|zNU45lIA_3|py6R1M(&<fBgT4XI#ACN z?{SOI-2;;Cf)2-gU#!vES6v$Fw$u=12WYrj(zpdZM?+!X2|Gc(`Br^+D|~G*SClO( z!e~1H93v$Jg7h4jR#?_2-+OH$2P$Vtt4g_>7vnsN`c4E8UMzi-^*hmZF{6RpB8VM> zNm&H<JA$t#C%e@0iz;_NOy0K-)ob0^Q9!Zm0Ui?-GdnXoojlEbi8bkVA4siG){Ce& z#r!zVPdP6eb`rWhrz6egQ-Q_%1oRF5d|i3wmu8jYy);oX0<=vIgHrD23nav&J6L!* z$Fhj6+)ixCY3~r?`Tay78NKs_zD1=CEKg>aK&T~JR_cgtktBR5HXC!ucLf{q#x3m{ z-`knJqDh0#)xGrv^n`7)LB>_0)ffL(HV;A;K?VSz_zC0Dzl8$IS(R@Xp-eEgHf39S zXHLX?q%0}eyl%}1A$+3dHdA#H^X8>(<hNxK+UOAo%^n9(qZg;N6};LkmMroZ_UtjE zBZm6v6JuXVKP0P4P+Lx#MEgQNz^@LOy;enGE}oEDPoCY9U4%r+x9POF50ynl=V2Xv zi;QT(>94}5*_8k@i@4il_Lw$S@HXM7BGaGrrkF@qlxc51@<3-|MAQ-ZJU$t*RZb!J z8*|_Fl*KgNmM$qzHw&Tq=Maw88%63hy{H{pcgQ2kB-NeL1`J#3#fh6a`@1(&YU{^1 zx4`s=_|&C{5l5Ym=m}%JJ3l#3t}>;KGzgzF<hf-VyRZK}Ab7hoa1Pby$1nF-X}@3z zydfN0*X#<BrLa<<85w6;RN?JG!kCWyTk^PhI5*C(^>KRH^zdAP@67F}x(j7E@>-nR za>BnyWo5XicdPCb$l5vn_rVV7Ew4aCmi4i?`8ALex@Qe&m_IPd76=$~;bR(mN6XUM z4Y=i4(IO&ED4|lIR2UU6e1VEB&#GUUzAYVyoDAd-chpDw%rDrcNSV1!^v|Ke{|mRM zQUI9SwUS1rF%`&=G<G8OxJ30k=UCLesLCKBnVl<wFKmwikn1v7(IEhdrMvn}OWeCG zsZ-xR5q2%b1Gx8Nmvp0lKl~hmie#yWz<<!uF@KbZE81f*WVUZi@Odr$Gx}dCZVY!o z`;MG<twMv-SX*nDtBL&CS8ci0Cm+hJBkghVVYN}-q%Riv9TuMjQCV@yVtbYf8p-4# z%lo9|=BT(j!xkdobdwjmNW8_@y3kc<k+APK6)GKEFgJPs+8W&K+ID7VxN$Pni0tAr zIt0?%y&szvT4(6U7C>xSi?79p_MF}E4WdJ!_1S9tQ!88Rv|AQPO=x^s00Tzw`lT@S zuZpyi6+L0S*&<rTz3y{bVn~l%N45>-7A+C3dkdU3>5$0U$1?DLC!s3#zSSFdBU#yY z%^Qf-%l(_*+QWRF*xa;4`aMOX#OyxA#9@pHrZL*7ZbycQOs8VS{{X9zgtE_hT0_`O zmx}Yc{{)R_yg5I866Wu%&A&3*SQLV9Z0~rbDO3hM%E|h6zo3^z#U`0{h!UPHW!22L z{>8KPw^7E@c$;JYpO`!Z#V<TRls){7;a9KkYL{kYIW4wow|X;%gs`M>q`Kgp2=u|` z<~KmJO-A>vg%k;`4WBa}MSr)Lm!^JM89rSHONF~a9K%nUBKuC6k_CvqRU1~YW>TpP zVj(L5hg^O?;Km($CIF032FY?_GqC!CM7&f}B^QLHaqV4@un6P3Cu())ZB}k<`Z!YL zI|zvPGTgNvN_wq?8YLb9qF8-e;Dqi8f4#P5+?hj%%^*fLhy-h^G^EzF_3U=tu_>zB zz)bBzOM+e!esLnT&1+bG>qB35OqvFy8vEg7iLLvd?xT0i+;oKcqSe=03bH6+xYdJC z<-^~JP^qA;5)2+q>cj&_21>6=Cdxm!Ndlc`{oaaB@sfG&^(lAQvwOKK2NG1ce(X<0 zX#74BH7dJ|26`PS+upIVdH1BES;`SdxThgU>`^GlAw|&<igy!k^v(goq)x$#ciqL; zHVqQWxy4LkR64%o@-Y_17+CyS2_P1OfQ|thZ%U}W@U(L!ZmqH}=Fswq*+LlN0CZEI zlJ={`pUXgz;}|H#cp^R9HF_tP18mf~%D{AB2?R}<HomP-G--<e{LjFZr8~(I_(Dbv zd`@N@P}Z&2$n_)k8^K5Uqtv;~g!h*-k9Z`}Jiorl_Mf%?AfdzGEI79kRseDR=6|O7 z>5Ta5zm^yQrU`N*sx&xL<)}L}<5@lxoRB#B{4H#^I`koqYa@EW?;l}MK{$DJ18~Ho z&II}3guVa8?JH(~E<5JcO`lomw_PCgmE}`^dz${<s0Cw8M@b>c`tozf2eLM9HP<iK zK6k79<#^&S8joW>eX=cM05?S3yXyA8sREHoNIGQbu(Q}f4u0`rk4nE2-U+TN{$5c# z$O~;3ct1w`RUO>eXn;IqZ^`AOlO8wdPtw@dStBch&Tg2J5jrYf_A^=nc~2U2|NBnK zemDQu<6bNUM!M7eP<iv*fpSc@1^%D%w6vD2*j1kicH$A+eq}>xsk%ZAfpJ;44M|XR zKczTp#^xJ&<GvbzF$%%~&)Z#=kV`0HT`p=8>YIpZGG6<#vV0k}N^yD$X|s|`&a7uq zI--Co(X>rP2+H|BzYcm^2j+-uc}o|cN;U1%!DW`i%=eJWFphNM73R#6%(96;5@YF# z?UZZG0l(BAV-2`rd{){e)Zg2B!z0Bzxoy6f=J^^&P4c~lhwXrBZ~Hy6xtcIf9Q25R zvRSH+Pn!?<VeklrOo1xjy@ejX2KX%OUm^(4<ngyP%ob(UEtWqqBY!`y^Y<4WL)_r9 z{BxIz8fcr<CBj|&H~#Z-zwzn~4H_F>l-+L6ouLf4v7R(1oCEaR2@&`~H_FhgJ9QDp zK9=P6@%*GssiXgc8P3+LF`-NBA~m84-F4sET^r0H5gcA_U?8yi`AQFi5xTXn=Q{-G za*I2-mPt)SM>#3Nh9nU8W{iWd7NAfLO&WqW=X0wEK<rgK)uzN6Y!(K=!82hDy>aXg zA0Na7;HjTRw-%9o*udde0wGuIVx7>;!D}q!MAzv6&F4jx55oK?SPQSh2H^8+&C3b5 zS^6D&^La?EkV}ZUxE^*~DJmLaF@KU!U2<jn4=^Eu##<nsPPkCjn$ot0f`frjI5O}% zN2T8oI2(QPzR=&ebJ{E*Si8MbPjKx-8!`oEn&u!x6kf8V_5?7_(Y~YWcaIJT5$r{i zWi42hmDe5;{*Eba`8+36MA$D_%*90wpB<gzgEVnJFu>PSRdM8g|CI5k_7Qlg7ynHN zVb!BaP7z>ViRstMUV@?%S}Z1^Vm#{qZwWtTrm<XoB2;VxC2thgr+E9uYpZL^Ea!DW z(ZP+EhY}no2Gla~q3`s4%!p)#$9cxl#NLowe@3vIaKPsnN<>TFt!K*=_^tw>gp0IZ z5uAxGtirM!YxjRdEWGTey{ACJ{{h@V90t6am%;KIoguMpl3^belNP;H$NWv$brn|o zfMs}p<QS7mTy9k8#DisAkDHHsS>301%n!G5bj3=<1VAaA?$n_r$J0a~u>Ge06S2c% zafgLn6U2Y?4}YlcgFS^V%NdAox0h8zd#HEZ>s4u1Sbx`GF~pS@H3>HgZHhlCH4}tv z4HHgo#MP(hW*3bUfce#5o7NWoi<welT+r27sP$oD$T=`Kv>A>4bj`TbwD2_(|GkuK z$XlNHK&{^}D!@~F$+cp`)M%9)yAlKTSfCa^Z(OE?3NCx{<gR3KP#dck_Jix|!F_gH zS5`tdKEroHXpcLY`oBA=WVXXz4<j$gtzgMOczUuJxtrW!NMA;^0ga?L%hHYBe4+@j zK;oOr_ugbe86eUQLCD(|JO+lDI)m)`_*%AXR~jxQv;ILNvt3+b)IS%MEl*R?Ia5(` zb+nVJ^#7HJ#8;mt50I63^W%SjpcFsjbF6!Tom-o45c$vA>A!2(*pod!mhio2?&5!J z<yYfS3;nO&wEE-8!+#tn-)U+PEC9Fy5x8*zGe$9~O16pnOMffTDJSjUZ>fYO)v+lL zGOzS5Mu?QRb~3HC?R655?vzCa_(r4V&%VF^R6(=l!^8S*f6BIu9LgYlMIu%GOP*oZ zJYGh0fChfr`*3#TrLf);l(~8&PJK=sXw@x(p_0TnqtG~9laU%VsTU%#n=;CnU4K#L z)^{y2lwyBJ7A(AMzP~z{MnJvSn<Sbqawgn{&h@-1d!yv33?|80n*${iUl&Up4E}WL zNLjoVS6OF^>$c6;y*;JqWyhcBo6(fcsuT&(>tW1coRb_BB!>#7+=);^gOrcx7}zFf zTr%b|K%|-PeENx^G^rv*IEI(VDtNqc4G+#%EL$)bM1u-EY<BCldmi7p!#oZzu`0)_ z#bX`TyH*wa=*o8G)=%ijT`P-DeW^dwoz9K|4|1L&zOgIQI(&IoyxZFYq$)n{l|eeY zI06^FKMYAT^(E1GRU;1)5GhIV78wh@Xex~02*4DT7yC_6&75472vf?Pja+J3s}xuO z<G&cP+az?aT<LM|gYf?NL8_Em|9H$$FN}%3vZ~`YFGT=q8wq!@Xyh?MsFlBryjMja zx)Ikbt9bhuwT|M3Yl1pwn-{-qH`}zzM7-vF=W!a>?}~9|5V2;1-D;@dM(TfK-w!^N z4`(F<i>(u7+NPBcV=dXgA0K_g;PD-bN=HfthV|novTWsb%r(SjJ|xl-4ahy99uU#x z1dN0qqcDxJb<Ob#x9q5t^|#=@_sK(p3Y&+#Pae4TXfm3hX_X>mPUg`2_6NOzN170f zzh6P1hyWE3<7-_?Z@{-!y3ag$Jn(|?#CO3{Xi7#XQWKok0UlBw<VIZwVSaZ5uqP-# z_<SH+r2OvtM7!$aN!r!!kR!=&kzU)t^^E;vd&hLQs4g<Hq+731lwA<T4*AdEhbz-v zl2@eENBNC^<v8{=*Y{UM{8oWkRJKWIL(b(H?2Qm4HUMeEK^vb@5?z+`VY*2FvJ$Y9 zgslmqay)E1b{%<>_cujowpC|Cm}An{tk@*iAC)+5*t!gGuNIHbwH=~C4}-6b9hx?* zoG}U27_Z}{tO@hz4QB!<#emw}{WeHS79`0>bL<C&FdVzpcX?ET<>1k@q=fsg_l#lO z_Z)o1^GnZqv-%o9oM4^lt|J!&F3=%O<i8O*kcv!OamJCP_$Py=`X`699Sq-l{1ZS8 zgD^3`EsWrYY0_jZUPAYUzOVrN_4gm*+OlE$-_ikS@Lx>|(83OmG8%}<3Tu@;1Wyi% zWaInxuij3R0*_%tbB1#+`(sZN33lf?*X<PNUI#6yO1`k+HtY4cE1{J+ML~B`uKWf7 zye&cgbn}Gvu=paD`~^>mp*&@!jIEqk8PR%mm}(x}Ukgz{b>+K~fDqB;qd`BQE7+No zjN@4=IRD1Je<;W1oYRxy-~Qcy2@Pm`13ZsXFR~koi{R{hmBUuvFITG2tSEkY4ufxe zYz(dN1+F2_sNwxC-Q!H6cN|c^k%xzu#uJkjvB4*@ycfkxz19-6>I~S^JC&XK1K)TY zUGM%P5x+gZ;KFNDzAo#el4IUvUUykTiY_j&@-FdxJ&;;pU(~%zlZT;Y44q`lsY>tC z&g;!ew~Wvvx3;#JPrGdIzn6aWL8-GkXWf*2Gt1$h5#oK+X5tocXoShb&qk4wpELM* z>34sx1HtFm3S%!;fY~c@9SSIhYj0m{=CI8h)oZbWclRz!A4=c$Ny@R{Z=y+2FW7Iu zR%Ly|3tQbDpRgGg+07X<?lMJu!rVKPn~2SS{7O@CK1Uh-^BnsumB*xc?e(B-a;czb zwtK1(!toWX)e`giPY;vN$QM=@6^#&<{HfdW+HOnzu(SjH;u#Vu1_MS#eKY8FiJ0Y% zfG5^oO0QUI(wOB!O{8vlaBOd`bf<Z(`(+$;3#8Zn3mNG8Irf~gbgtM@nsWC$&%|-g zZ)2j$^VJe9)W2jjeTXZ`)?P95ZHTN(E+LeE29ZE>E6$eC{iF%z=JoevLX&=FVP>oN zG;~Y8#_)&x)4r9*Pi;E{tp2?V=tU8tL|excErOl8<aDKYURw6i-zSrVv04$phjP+N z(7vJe`>RO9Iy^4!&oSULO{%UGfq$0<4dA=OAejJsqt7v1m)~&Ob<h>ilB8p>SE|J) z)(O;8#Q7T%=Dug9(X?cp*xxozYyEr89RrW|O+<-y#Y{hgVZ?oZawpJA1jWHet+HR? z-fJ!^B1M=-!KXPUvO%Y0`?(jlk|Eg#&pc1Ext0L-vWoa+dq(wVm-|~Tz&{Z+A@R%4 z$0Hesh)y9r5bZyxD!N9@QTFkja1+sPjP@HgO7OY$_wp!rFVf#Tg}Z$Yhm5>rsUcq* z1|Xfcl<h;xEXqm2-!Z`lWd1+9RQ%2&nup*K6vAyLh8l5v6JH7ahJP0_`wA%S_FU0= zU+O3Uh>~o+08wZg-gj{whS6N{*d+4y_6AR%^pA<5>waqcQx|n(;JVO%enZ~KU%5P* zg#8D(H|62&z#Lvum<;BX2>JmzL7#$KWs55Ke8-A6cY`6Y^#w74|5JrC)X_;5?WUtF zz9WL&o+7L@g2WAb9g{>lauJ%QN#unH?eLs3yDTEmMA<nJbP>_7nC|v${p(<VpX8)} zMv<P16H>-2CSYE46j`e3pBEka%}Pn(aQkvzMDeqo?8u!xJ_sPASkf$=C-FnnSd{ta z#c(vI!B?<b`5%%?6BA~{=-`ic$jfE;)iQ9PFN1=g>=60%a!oODiVr|#8`9TUdqTj3 zzRbt{WzVhV_F&a>ug)+c5;`rgUpGvCXi0v1QL@N~p?(qh67*@#zV#o|`H|O`>XHK@ z9>`2ZhGvyEs}^#7NpW;Zg-tZwMwKR!s)~UBw844z<tWbQ65h*&d(0ofcM_S_r-IhM z&s=;RD&LVB<*QW^O9V+Ad_L{DUD?acRq6Xe;Wu+B+mFlPlEIqrO0U1AOr*#o{Es%i zyN{xa$ZeOt(RtSh`CFjeR}PknX#(2EGBmbGO45qy!gu+IhxN-Rf!Y?JS9GrTPNsH7 z59ztKPJsR=cOaHmTWN%N#$C;Id!WGRxpo7aY7#Hy&M1e+XNv0#2{%DFyz#FZA(RSD zjGli-%CD*Jy6JwaOFhM<+{*}QY}~U^Atmu%KPO4?u(xwwq-1%SFY5<JxPr;vIK=&4 zrq8n@f%M6yBbjtSbE%#oMQKqwLLN<WnClIy6fM`ciDll!2{rj>`*Q50NEyY)fwm;% zMW!-Yj33$|14l?SUt+`%s;EgKSnKe$Aj2Uc>17ZPe2-0J+%BmWJ)xT&gkQn>XUo8* zHkx0G4B{Z4Wp+Is06uTDJtR1nB@%V)azcBo;fXL406rrn!fsd1<b2!x@-K4Fha7zM z$Yb1av{PBvnoQ~Ua!zJpV{hv|1hR7N3&5QqTi7}~F}254*Y`Oszyh&IyY@cOt6B5l zu+UeHTl~Xf3dSz*k|(O4%0j&&jeubYBwTz{sn;#%0dEskhMKsj7P54y@vyC;h6U|! zmbA%Alk8Lax3{}pIvnh*y!lxMD|`wHiStU3?e|1B&Sz=t@Di(*B>o2hJJ$yNM}B>! zZ2lbQM`hhb(8wi1@3`A@kh4Fg%GWEyWD~8~@L|^sIx@+G*`^E;qlD7xq`<^#udAja zTGVe!oIceAMzA;OGA>}l&OXS4@PMHy%^2khBuQmxo^RXET!Ng@a6^vk23$fl*0KwE zn&ZmO!dFz6?GV*rK}P6Oh%!o8^YHRzM-LmFIFLQ~GFp@s5j);!EAfZ!And~)u!nEk zu5h=Q(|tsK;2Va^1;e3?-=5e>w*9tp<hX0eS@27E-L@jAkAl<-X4um?-%L{AQ2m-5 z#Y{_d&CUc6V6T?6W2SV{@nk1%x1vja4H}2lI<4Q0-96mR*V<2X>VD|%Osb6U?kRP$ zw?Az1gySD3(iJf=MB^()_ru?!poa=|3L@@vG7t;5)_P;djA@zB_h9*(dcuoDh3EGp z9qA|TdXKdCFGpVOg>q7%BS8xl!yD@J4Nxc4MoB^VM^~!&ZlCuZ^UWDvvR26JU9Y#l z1Qexx6<fKM!-`Dq98Yt?#4U#MiawEvp(}8o{+Of6iTD-?DUkkar=GejMT11<7oN-x z2wLHiI?C3=l8fH`wY-TO7-rwyFcWz@c4>NGP9IvRAU_|}&+S4K6S;aQE2Gmv7!#?b zxI(SC|4t4RtN!|4egpM*p=UIqBD##F^^fuTFc{%mEX}`OEr}^K9U+x`sD_1t0!0v) z3nT?nvQBteA+4;C8Ia@0(@6U~MP}_KJdy43@}qL)#1bza=jF2OH#v*sUn(A=u?Hmg zf6s5(FCSz|hY?yhjOhq(ZvJQ&=Jyr=E{I;s?>r#%!7m>g#f{Sg_R@jYhB%(oI@oSn z7Y8K2?mbNi59uzW8KFF-Ws2>6qbT|O%t6_~>_cEuk*2pSm)6%~t~1bH9+v2|2;bKW zq+oP5kSlSfq9vZADLVLk_==H|3FF6f$?`{(91YMv9I*5GAJ@1s(oc-d;`oK_R98oT zp!2Y<Hv%VZ_S2}gnXY;r|5&lnW)LZ$<WNYEK<!NbMC(RtstgOQ!BEwMc#xv!6Vx=4 zZMYgqvt}EeT_ena&1reMN*Oz1?;FnJjK%(Uvvl4-k$ME`<h2*CwdTv>8k@kJSUR(l zbj&?pk0a@IpPM}Fx|ImF1Avk-W(hhL!_pAza0H@G-axJyTG4Upi<k%a*p{qj^TI+W zGK=CDGQjPgFQ}8#�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 literal 0 HcmV?d00001 diff --git a/packages/twenty-website/public/images/releases/0.30/0.30-new-settings.png b/packages/twenty-website/public/images/releases/0.30/0.30-new-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..264a182a4ddc0f464715aaee5293510668f1d731 GIT binary patch literal 321910 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⩔zJ}b&VNhy;q*s&D>{#7U%pWv6tI2rbWYsWM)wy&3l2zg2 zva1L^wy-WOVwk(0yLGh`;SebK_8Q<@OZ4LpaOa)Nej)9`)p_vXzoi<5FGBD&BBG!d zOLWG*m2EdNYH4*My5$BoNciXAk^%cB%usW$q1ai__-K5NO@8uo{^T#<oqsZnJ)Q%; z_YY{N6~UC_*r1_<+o>p7ixfnyE<9Aay<^Q0xIWanFTmLg66J)J)=(j3i52Y9Dpow~ zMU2LiS1lMwtll659RrRYfCum+<2(oyfSX&|(zba8^r$yccNu`FPv=@FO(?QZ&Rzb8 zrqGBbt{xLp8-;>;jk%0vQV%|VmddMnd}z%00A+`&iE&6U4ja0xsf~!AmI5}~l<Oyl zPaZ_;h&E{hFYEr6M3`UC^t78c!=pgHXLT<m^U4oxC|&zle$%!|>Z3cMR~8#@2v8Tk z0gjKTb(I4bp4Z8vr6S>|ne3WbA#Z75qroGoOD`CR{6F#(X%j0a642HQI4%KsB&%O2 zdXxuc8qLrRj=pXIo&H-9DDdT?CR>Siy-nF?UVSL}RELJ_wlTV-m;-v40Le{Z+w_b6 z*EW%e|0@MlRb=<XOT?l)7e^I5+R36v-I)D52@m?Y72tN{1A<JS265A8W-kdbU7x?7 z^cv2Pqy#5t-1iUD9@x83^1TkddXG8Q)@s{-B3#J60JnBL^~xmxq=(uMY&<OabxI3@ z38V@?YPFy=6>~?c&ytW*aL2(PwL_z7d&8sS5?9)o*_nF3WR?`Wv6-i3c&}+xxo?rk zL7?dEj3xSXkEht@I`z?gY9Bsjk}%cz4p?c8zMG}zz<f;ow;~jNF()S<N?OtP5=GmM zEUNG{RlLf9f@zld>lu_nU9JI?2+WgbuO8=#$Dff{+308glc?vD$tNnG;|bx6&q6Sx zB6asKWSgUYTpNP0BFg0^HPR}BjSoU;4FjGv_)+sfdwjWUL{`~es0_OKla9Z0c|TDV z5|`!cw*Bv)8CMV}s*G2)=0i?k+r%gyNZzrWhClhU2<NYl<I-#>5M*b&VO5`M?0Z~e zfNEcQu=1#CzFS~6fh*Yu-li8oSdGeJ+7|%l-M+^?hCi8)ivzSpO%@g~TwVxJ8MTGj zH8YDRxaYnE@-div6Fzf8Tf4pj4+!$NS|m^3YIer=@G++RVNnev!5jPO)>&^7vCscf z8S8yDt*D#VwGA4OAId_wr47Q6a^_lASmBwvf6R!hqGckN02|Vuwi@51lMeuXJr$qi zxuBd-C|KXB()MY4cb=s?A`;`Chh?7Fw{oia)cyuW+s*>Owa;f}69T9iW`F{}4!q8? zo0Gxt-7#I1#L18<5Jkt6A>8`ZkfH2jM@>%80|f_znkrM*m@rR=whk*}-%k-oFmPoU z8Qfnn%D7;JF~dl#%#pI#1xeMsP`4P`Buo4aw;51+bIJkruFGS?0ec@@|6Wx&RT|Eu zQ#f*_pJiP1Cjb(6YY7tNWhAsXRt$T~?g##$1Uy-6^(Un3Ua+FT<HUhvxBf_Y6yi~) z>Z7J-D}bg3D?!$!{lpVc`ZaO<<FC5(X+5k8DZ9d*G^o(Czj$7Lc^uFd9wM0XJ#m#V zzch2F{BeNCDVIocs3?mJFXO}mixseML;>JFa%>^@wMHrWz~RyNP!K#+pH+T8oofVB z=6*+W7Nc+Mk;E1cMc1M}F}d|8p1USAiZdSp{9XXrRLrDam)Hx-Q_j70vtqJ!S;&5b zx~L4~JD$sV>P2vB=d=<N4(q*(m*qmjaq7;+W`D{*p1!75_*ibTyxPaVmsfSQo{7kx zfxW%`@cNHL6ln#X6W18z56!MYI{h*#C-^>oJegMk6i*_Ql$su4#5k3ZaNr~YQ5pOW z@CDB^hS4dNr?sNGb<EfjD9eqJfCYOXgQBlZDf?Dvisq3%SMQGC@NxcQz9@P&XpV{4 z*GrKUxPUTMoyXFiCZp|J2V|$#xf^I!M$mvGjU>zwz3-?Sx>@$Plc&*gBP0d>%An?` z+lXnbrun2v0SjG;>!|B<XGB~uG2DdwV)c@PlJHc$yH|F9y{?Esd{2LY7Xme`blJ~O z1;kXs!VB6nJA-nE{G~EgJN37&A6F_qDv}1GT!F=;0|K0k`u<d%%9ypy`YLz)lZJ0j zPDBkDv?ZG|yvYQRQRktSjoA09Q42(1^@=VZMKZ$x3TT(McYP7DTn1G9<;97)J@^Wq z6ia?!gS}=_GG8O<YewWmm5d{(B;s|1^^jiEL3CA5e!?F9$4{?=E;(Zcm9N4<@b1&c z(}|nW(B=enUPhZ}UO{rW1$&jbof4<|?)xjfJz!BVkS_&+E-B`QO8otGN@Pm|d};2q zBORF(7Bfw-oe(=k2gkhfS%3ASjI!$iihiZZgAY;=d_10l<Ov;61o$S^c|3m2RhBvw zR4)EokIHRL8x*fur_-=r?(*KL<tfU^T)u;vO!8x>%cq%x^Azu;OGUpHq>$?C!QiHE zEAzEMFSm$vc&xB`{|*_LO0wU%&=Wz^MIERbg0<+C(wDwvT1u_A<*aJ!gHUJ>lL|=8 z)kh~M&L}87cKbuaQ<0TwJ>_h0s9(=5J!(HZo^4vZ!COR7Q<#c_Kz(R_)r;|G9s~d; zOHZ|k!x4{|LfzGG0F^;NR7|-^c`$G4xCO%lqj?yZ609%Q9U{IuKU1-y^*dplg1p>i zpCbPhayXCX82i>{d^1#>IO@;G7@mStB#Q>t`&<8@E-zFfU##NK(@T?|&5v#I`Kov@ zTxT19=0O8J*ZdZp;nM+mXWgV4JR=(Lx4L#83olwMa~74@UmDRX0T~_&<&X%RUE(cz zdc7fpeyiZT=J%@?>F`pD<<k9MF6=SeGN{o!(Odg(mYNKL>9KP)neY_p!AGQYH7O}# zXC6q2g;H&PP{4ZQEBxBYoZoPS8CJO6hl%&g|4>sIJkNdcEh}vJXY^C>>G*TMWd7v4 z=4l=tXzQoHY`jXx@pepfVMc=)4UVq2AS|K7@GJ2m_+a}JeX|XDEP{mMmfz$CzFKxs z_C+|PEA5U00QWxp>PD!*AJm}{OLITZKtuMsryo>q@=~cPg#;3#UYAv`IDoT(qTC)l zgh|M~H$+A0`2rsDZ{NW>rB&T>YPM$~9@^#?Z5KZi9*?NSGbG$bB!-W10M1N1_D1YT zD$4Gi+~osY<NVvU;i&N}fEc(Ll2fASD|oS!V~kX+d3(w<y(oHqL~E9fPmP*+Gq$O$ zMjc6gTll$D27}-x(94+;H<+OEiG@b4R;?&5Woa1l9IJ`y!tbRL8Bi9^K2`JcA^ABX zU&>74Kn8o~RFy91l)C2t-~E}*yzwj%;H5yD-Y`@w)X?LTzSI#Uk~w5B`B8ocM}A4M z-(MQa`q|(@vwrGEUO+qtT8^5;O8WVIQPFxFWJq864FawE`km6Q@Bm)fTL6@okunIS zF4rg=g`6{2aipog&?*<{&%Yi>&8K8v!^BzQBehZt1Q=O(F{Bxk3`Kgm-`}i8^YOQK zQc@&qQ}ng;RcIecq)_iXThE_kiFE0hGAppgsjA-Eb%QEs^s5_?rYvE~MSdr&O1|e3 zxcJifFSjdCQjJ(jl+h~yr5ZF$5EndeXqx|A3!^@fs4FSJlNP2lTy0VbzWhsGtKA-p z>j+x;NesEQ=CPdpXyQAsl5t2fRH4ltx0Ml28ZS!#C3tr7EW?ED;1#q+T8=@Lc+1Yc z^|ea5N%mIp*O;%>xviohn+dTW%3g^F;_ZN&7O#qNe8B0sR4gYfC``apWEjl(PO*$Y zWxsC4p*kUU&HTfsfF>+IUvhf8C4f>DbKZ}H-_=eKqQFAoR#eD?9{1JJy(Y+NNQ^o3 zM;a$i=d{bSezj46lJ9o){A~_SL>-&rMRxGcwTv;jG(_9ksrUfZSSDg}GQwx}{p`LR zr)I4w2X||=0L!V;u0ahF-Yt%IXsLB8RGHM|MT*#RlT3Sl>7F-FW7t5y_4VF2VDCAo zBw!#o=WHZ){*;+D_A@n^eQ8NCZ$N^br@;9zPnsqF8^o44bXV4j3H?N9ny1-^l>(-m zES#84qkaDV1+dXNQ`JqT3rC|?)uan#s!muT;R3)kKuK}ZXg$?!CgLe-XZq$*Z31gP z0=Pwwb7im7*MKmQZfQnH*@)N;miYMlVJ!jW^%4*Y`zsf9_KL2j5=S0H&i+w<l+=NX zghHZ+QWUq0)g+vm3Og>D&dat2%|I0;YzDOoG@za3eMG^6B?OeR0-DYD{>g#<<ROI* z2BK#`17{Umezj*mAAvOz@4V|v@OaeW!>t&!c`PI1E0qKo&N1Q!Jn2*a{(wF9t+Bag zot(+coIy>?UDkK&*h>O|y8%g+L8JDHf{)vfDBgF2wdd6?QiUldX?+erzv0A5;RhKQ zgfr<VPGbkkK=l*^4zp#|>2^gpb&u%*nokLV3X*Kn0%c$e{EqJOnFm&EAPCP3GT{#{ zWM%#m%bB!mhCY^PP3E0^@=+l_n^B%=Vq#8W!~nFyiy$H+gI(?MJxkUTjzd{`^rLc< zB7yx)o(ayLWE#qkqiyP+7kH{UFs==%%&CiG!In&J`PXU^Bi|YIKf@QUky=+qTi~Xp zgvUj|<XA5`i`^k&Qy<f>2KM~Pqn;~G!Q&}p1i=)jT15p^3>A{^To+IH1qi#iXX2F^ zA=cl2$=SgTt7C5<D)Hho9HX;a7F0d8P$GRy6<Q*|Sus*@gk&85uL${I9=GFJn)zHF z=phxlzFXFK#*f#R;S$=Y_M&QbU->7Y${;-QJ>V}MXu$rKxyDtAz|<<P#NO<|6TLcG z@PL(CgA0;I2|DL}AsowDI>K0wf`ZIh``jyEQK0sPYZ<PqZMUELQ>cp+5C8#`icp^q zQ!5Bskb^alp$Aq<R2yKhv&rl00z6rB$f_Y}$|Ob<>bgC1`ei?aD?Zm&b6J0ysm;r% zDAA2O0?fV6yiJ~CpRFBRzkrh|guX0yrqHTAXQopd6pr-fp(bNM!BH3M&UG%lgg=NJ z=E3ZSbjBKr^P~5=sw#t@3HK((1ry+sZRwwVhVEHWNkox|gk>YiZ#25WLoi%01nVYr zYml41HCC_^zv7Do*J7exioFl9S#zyZDPugKROj2&wxt~VQy!Q}5qFVa!p4SKY{8jG z^&3iQb#9hU2t1@z&3(6onlt_+QScJC0~tfMBYbf8aaW$RkysL6y<^J+J_u%COXFR| zR`I4;?Z40gs9}(I{RwyTis(@D5IrODF*h*HmPvohDhn}l{E(U~`hQ{2Yd_H(1~zYc zNU-a&Mnn(5EO~03xZ7sxlG0E*hNfSqMfKLmS&yGxI<q#iS5lI*K_5@fJ_7;Ott^)R zT%}k7n%4G<KQ8jBD4Du4P$Iu`^)R*_0!RG-(zI7kT|DfS*H4MGg-o@wOE$Tq_NA%` zRAO*+=p1>k0_MjM8DR+Di%eCZI=_xAHG&HLJ>t%Wju86$S)Z+ldysxeoCQ`7e@r6k zI6447ek~4{4@=t`xNCy|nhmPZZ~mVLar~_MUJnx9F(b%T{kt&`Uv^zeR0Rs*G-peV ze-r@)G8i%954$kn7`EeWE$mE0MqTGL?ZU=+LTsrlNtBdl4fz58%S2b1H3uWHRTU@$ z5{j@}n4X-xA=XVE9p2eHG60@b#*Y_WKQpz#H~)P}X>&tw6KL-NPeRO)dxk!tqU{rl ze2RdE=d}A^5beA(2?#;1bm0J-*g9CuNLM<{$=Ek1;D4?A;@9Oj1K<){a8RMEcbA8W zx9NA`rfqm0vCU=r&^J72^3*l>RNr@CFfde>Hw<_}C)yUYRpCO<3T>u<$1VK;0j4FL z!c(hC*kI&c)MShF-Kv=Vu~L1h$$5k?w+O0ZW=ALc)~5;xV%MfZt6BGcV8(}rkE$?Y zuR#u9lR-_(ja5)(mdYYy;M;fRNO0Nt;WrM9BZY#Lb8XC|$Y_GJW)UtNi+N4BKDSA_ znDA_<4pvdpg=hKomb&B^obV<0LF-s$zQ8~f+^TTCK9|={@436*w+kAIx&H+q+8OJE zc$sL(#w((Rfs2q$;rM<=g&{1q^NR>S<JDnUVUGp}6CM6u2rFuamn$;#DFG&0D6xt= z@GGJ$+bT1%Q>&d$IeWUSWD|pM!DCqq17N{T7N3$$kvQ-O;<S;WC@q?No|eZH_V=)} z6TVI-?M$|=O4pv!XsXomvjN~lrSO&JD3Mvm@-$>=OTRWm+`UJ|v-0*iA>4P9mg5OO z_VF<0l?Y$#Oym0?JeGR$BLlI}g5}9JAu|4Cf3=->(5W1-_?HrJ>;#NxKkJkWLBcJ5 zV~k6uOkS^efM5X8E57It)F&@d0w*GzId?sY@I!HSYqnx4!ukxIUIY14h=|g8LBTvV zb5KxLJ-1@A3VFTD(nB1Q!*Hz&T=~h$f$ojc!9qQG89(;rEO9gTddL#H*4#daz(XZW z*Z&hWBrP^FrXd?GLpsj(KgEaIe8Kg*Mb6TBK6^5_k}tcb0C9%!r`$6HU}q06O!)&! z&Xw()YJOfrW9~|<Do26YSeBuH!61vFGDk3}dd#Jc>l%;ZIz|&%^g(qiHLC6Wm7!u3 zz<1S>!w<yni%`59>m_t(Rg8Mrc;a*Q1s2l=^oI<=kn5fbKM2nI&u~CLXu0PvtH>i& z{pXoyeKzfC0z8!H#41xUK^4!^S?mzr(31m}R7J4Un@0<iyX#k^eTR-fEI!sX=NeG* zM}~svQi+ez7uZqd(w++c@t?~lQ7qc#Lri84X*vzHt^`ckDmWg_@!>?(zcWaP4TUK) zdlUrGf<W-bLJqmc?`JH^&+<CC1lveRLen)n9?twB1Z`$h2{|3x8U^$Q4@$l*ePQIO zZOF^`W8-ER{3CionN&pyMzu+0#4c(q#_Yj_xcFTxeYrIzfbBx#V8r{#ftNBLUuwVu z8Hk`uh5+fWrWT}+%cgyEb3054gLkdF65&_>2`(Na??n2zz-4{P=$a#_6c$#BLv^8# zEh)hTzPr?9L{Q%0zj(?x9zV6#hBL3ko`r_&Nv0}bLix5K9POnFea&H0%}jvGS68$7 z<t*1>GpCR1KM*Z8wF}e_*bAo`HTbTna4C@k!^WL);tm8?=InX~z8AANfmKpvS&=#E zx!x>-V^XPivbSK7wTC4NDoX!3?_b753n_k6fws2%!k<Zq4YoU_d~%^oVj#WKiGqLi z&+6k7B1x-bK<)f+Q=Naik~a9986UH|p!xA#$5^)YYt9Y=%~76kc*uD<TZJSX`EQ$b zr~u`=EkUZ>_vtaa{l(qA?n*|AwP=?O@yRpdAQ@NKa!D;T1l0KMzRam|B7HDLhhV)q z+f97p>QUfTz^UwC(Mu8aTwBsAmFFr-@^A_`i)fiH#~96|lC1f^4l)P~X)|DNs&|uw zSV$%nR)>Qh1^`YP7v&%sIE2QsB_EzC+TI%vFSJS~?)v#U4W=hntGQJ;dbQG{m$pCA z^H)sG16d}>x22Y?K~NXuP|qKEQI{P`#aLxLojw=1RF1ax+c~h{UfFKoKwEyuu%ryu zq_k1QdgBN_o@-A=Q1){|mY*i9Zyrv29{Fl%>XkK{Q<Ke;r|9CvtW)<EoH-NvN7KGA zv=665fmBzO{@G6z!J+Lb{E@+5kEtGX1b2_6XM;frv8-_P`rm5Z)#|%<ei>`PRqk!7 zgvl2?Z*m{HiOdq~1Ov>u$g~Bj*NUSCGzfS)p{O@_LtZ^QJ;1;h(5Q0;{EL!WyqMR6 zA*Knj5f2nrv+zn6zx|hj7|AK4W4>&4RSIyPS<l{lsk`E!g+*d#TG-g^NDRbk0chuS zrne=(MC%6Z)j^^)Vjs`V1ijDi>UaJTqGl$Q+>VOy#`K{l{{^|Q;Ke{V@w2$`<ipnk z1##d<(D8MyCI{M8Bb-MmJ(s0DvHShw6<Wl_F=@fL8yMbCu^@vNA=p+Ce^0A0X@g3~ z@KGU^ixQWlotjEE^HX<NI9U{ayuQ^zPoUkC`2#ySb+E?@39*vTV=cqBi5;dZB0>+1 zI8O_8;U91{3S;D_NoSTgIAP~ZEa#R2=rpw70ET4ZPo@E?=e&Js^83UCc=B|!bu@X` zQ4JnW;;mu7IAq*+S?wkH$F21$R?-8HgR^KO%(79vq~X99Fc8O-m<ETiW4M$QTLs@Q zYTk=^w%IUVzCC59F9gPk<pfX8CB(k?uZ@D{5*TGvHXQh5&1$_5d{_7#z|KToEx{S? z+<qNaw@2gJ%J~ZkZkOQne+$FH5WV<tX6k?CT2CKaWU8`bzL(6Rqtm*S0DRD~ZF>kv z71SiORP!0Iuu^vL8k_+%zliCTF;z6kc{lkW?3F-lMba3wmvGy;;^MUzJNUj09~wb( ztO$r#OL(doCxS`>%=TNg;otNSZqAF{oEVpj40CMxnMFv*C2L}#&{MvsqZvcBkd=R_ z?<V;eA5GGPIGp}Vd2!hDpg|2&%nR3f@qnsa0LPtDzyoUU!;|OCvJb|bra(>AVzc6e ze&ft99^olxp?HDg4^W?izNGYByx3d7Vf?)By+NXjZlQUI7RP4LZ_Oqs!l`|lQ1h;A zGHv2fu29%4z(4^C!ce<SNk2!@<9f*Ys-=ci@3pny-Q-U%^u7*b!SJ$nos5TUXp6t^ zD;k#?h$=X5D@8hfw4RgUd|O(iyx8<w&o8z87dY-@r9~Z!QGjgjo|mP@m9W*eB==&r z9vcK{!5PT#V#s?ZBEt*%;6W6B7lkz8zA2iz@SSVR1_zDT5Rk|_BpkB1u8OgjoCr#$ zc65{F&j}_s3nk$9FV|&6xPg5wl0@qKwwVzNB4Ng9sT*I$h1|yeyGb?`Q~?RtIXfL} zRUu=9ynlm*wcxqSOahDxrY7sGzsyxCUe}fszsyowc&<EWsmmOmBHUP3R+n0<`@4YB zzz^{9#PvD1(N5bsc=-ep^{J6G%-A&vD$Z$o*6!|Orv-*roCm)~INN@c`%XRBYl4NU zez|Lw{I;d?K;bOuVO=i^ECpdAr(dyEUQ|gMxvGkp?^nz#oj(4Yqxup8B#mpI%%LG8 z0RSJ{)+<1%LPw^ZOvISKoEie`fzpO$dTBzH;VtVotZ`pH7-PMC(zaxBYv<d|{l@l| zBc436{V%GRN6f&cVBOtV>}(y)xS<9vxzFLw95GCdO`U>04Oh=yUvq%KuVTW;V?NsU zyN0}t(EWJ$zRc)`we1-ujuT44hPwwl*q!2VU;`T+rLpY`K8ep7lJ&@I)pz8Tbbnkf zJg4vYjVvKn0Hqv9_V3yvxs(uo=d-y9jrl`7cqb0RNGhs*7y(f-fZ>wRGCiiwFcZm| z5uDpMq9p_Lld=C%BT@!>Bdcdz8@m>n5wsLlVzYS<6Jqa}PS}c5;1^^jEc5{)rhwun ze{|0-hU<*$MQ#tBfSd90MclHeU_y~zUA!UU58q70%Et8)+&6cbN(MDDcvn6yXh^Lv zaPRmb%zz4b-4KhFWRbv;Q$W@EBF>E2LJozeQTb}q39;gU6G{lJ0!v;PH5eX>;=bEI z$wXk-@KC{^WzzOC&F?h>ID!F0S+ViTL@WvX$Mr`#9l8VzH;X6^gq20j?tk<BJ7Mkm zaL(;CGzBi>aX>x=28DFII?m>ReoOIA#w$dSbG0ToCISpz{=921C}E>QYE`6YL3nmY zLIOb2Poof6O!Gqz(dH|fyZEnOQ`t%<jdP3JEX^fs9ya-!NEvI5<8hZ;Ga&SS=f~Uu zi^4k>UWjt_JFD<I_C9{_T;V%KkN0X&-MmMi_KH~6N;a;4Hs5s4e{36j0@$i*1jC&f zHqB_r4idh9J+1m|ocp4EMex-F1!0}Q)1&EU@b5s=Lp+{~9VK8I0X!BFD;W+(*saKW zR=SvRVK!ZJ%{egJh9GlUuhkAN3=u=O0hd`e-h>-iS9p!D$k{F*AM(cXm`L1WgI$Eu zM9c^rpbJ|cvV6jXgYCj<(TM-vut7TA-p{v>ThUm{1W=`0J~2@l6ym-Fv8pA+vLGe_ z6M!hD{Ly3pB}1rFEe_UF$3hbW&#piU!b(g<)cgH8JHPt<v{Zn_RF5dpUodu^*L(nJ zPinsE-JD7Kk+=~j-|AwJy1lJ>d0JtE{!Yk@#L)*vK7SdsFyE*qUU~JunmbK7kvd&- z&DfZG8;dv?O0O;!t0W9Cz>V5E%aY@9J~p@SmA8L`UyQR}3#K0(F{3-Lh=24(2*z?J zE;T|KZZGqT7CtLh-aY%=s<rqV=W4Q)39*8IJ}1N$aiE`moq_z~<zkl5uq>PON<&=m z6!wTk3KzMg%l~{17~%kb^ROaJH)s^)Za(L+VW~@j?}%hH+8H~IC*p7sN`$-8rGt_T zomy~6xmzOhs}|9WqQEPsP+1Nj-q1GTy3sR`h~PNb7Z2%tdYlHwD?*3#>@6hyc78$( zY|@b;&9!_O-$e+$>c;8qt$0B3+!vX_6YYe+ql-fBdocWKYz#HoddrV#%BZD4?ehvE zzM{j@a|+y;S%Oyusgo{T>Ms$XEE0bI_L1^G&_L0HXd4MzoOvwy@wSoQ>4|-fGRold zf?xldspFU3Flm~knrl?P5+L-Z{*iI=ChA6=Gqt})UrtULN_BaH8$3^&9qv2X4(JV; z<5$nEkoYQ-w9`UIZmFw02~@)B33PoZ+1ypL#)nfjd;!Fq6hPKp|GryQd=_S+qV(<2 z-uYH1eJXrsna7|<t<B^T0`xJ+%Y7vmKgkNf5J%ObD8cM>>2p-b`~`N=fP{@}@BoYN z90-XL3BolV@Z-jM@tDC?;g(#h&cdw4%2jQ@VK4~NnLotymC+G7c1`N@K;iF|OU2@F z72pXF95(CqW#-8aQD;m^F#+`F2{5h~v>G;B?K1ZJ<1qw=uA0AqBE+Khf9EKTm$;0H z_6g;%L+f1jVMBOGY2w@k{)kjWuwWsgMN%g^`|#utV4wyq+#H8!#$cQ*`btL6g)Vnh zox^P;T~s8WCb(z~$_akq@y%lUSe0ICZeb7Vk3hfZe+GZpPH;HEqXm~1<t#Qzms5c@ z%(#bGTRC=8lV!;7zho%frL&|V3&V^5R(k}C8TF7KKf8UBY|Qw*h6?s4=ca}no&=ZK zo9ovTEBoW1GB}@9Qk-`q8~L>q^Yr6CRyfAGzmNxmPJ;jD$F~Av_@jg`+^n8WjFEOY zij=epppn3r98Jc|jH&&@N>^zfZ%{k0<PPe@wc*BT4|zBaU`~*v>PODw>5`n%q$si8 zJdP5M$cyE^6nL*%(qVvz8`P5fW^76a7NeV~{PCkWQR^)6=wLXR<g3cw2o0XXhOgBw z`*r`5Q5BWWCSg%oOTovu<&o22L2b8&kDH~CZIO(KL>!lD`?|=*qu&XW8ISvT6Ci$o z2gKtgjN+y-2!dT=xVj`?PE8Vgc3V2R(NPm#)m=r`Ua@etzj*Qx(2x8J2Ch4whv|zs z9VE*oQIqL6ERH%Ia)i++{Bn+8n~x+@QKBS&H6T;;gT`VSq&`C(eG{{||BxMw4$lM6 zO+2e9*}Rgg*$T;CcBxe|!5ezScXh5VM1n&b7J7;Nth2T@j-G$66e<-37$`$;cnj_+ zP&wgI#bA)<#gG4;I!kje9uz;Orr=(gQ#<Cq^$0D<f&Tl!a&%BO>fNJ}YOzzk)`gRn zyZEazHE0ESz{Ai{`krygeb3mE%?&DgZLMdZjy$f}jqTTigpvNi{!HoHY%7?Sy{;H) z7|77F!_5&lvaY>C7%NhQZV}2k{AK0lxby7+B|V_4@e>W~=2ye`Md)M0k8C0U10~G2 zg)~+!jO26NGjp|euE1PhvSZIYzwiWji13c2K_tEc)PCW3b_S+VKqh-K@Do~=^_;g^ z=dLX#Q_xCQoGdAb=vw88gz5DWbm+eE6K2PyhX{t8##3GpM>y5Qz`2mkO`im<laiVQ zd%o}uuDPa|yNPRo8`#nC5sl4j`Z>)OHtEr`5C&kpNX3}om~#jHOTW~QU3}(P3`sBB zpU(sK#m~aYBELdGeVdRWAb6DAitJ9jFK+FRy0RN?G#fV=uiaL}F{bnL_%LA4(UE>C zS`%O|Gwfu!<X`zMT()gQW-MyV`W<HIJURHBXaTmf3Ei2-M@^@1w-wX-CL|Hbb19Ed z@h5+;iG&j%nwtop78$Jf8H<2mWsgy33pN~)IZzuVsP-AnK^;ygo;ShfxwgEFv|!~p zd<r<ZLNE)<fITi;X>76cPCHxF@OIpaMztRa!Nyn+7v%5ivEhTEvPx0*Wjs*iR(J~h z+$e_7$Wy5V;sk<}WUB#mJ{lP8nVcLO@jwf>`nvG|u6zN1x@eaju9+2xXV-Cc21T2> zZ-R;*5_@bjI?fn*+^7YAir{55*!+w{-MmmZk`Z9!2Uc-_zmO9E?CtOLK$Ja7&6pG% zjQv~tInt=C#}e7u!}}jeszifJj$f>@&RZp^qY=aMGb6|l{#bFuEMN<^!^?ZlBC4c# zL`fZni_iDuV)Wq@AZQ1M*$-f!wy-&^@rv;0-@}ewt=Rz29|nSW%3Er51nbwUKO|vg z)x^crWURF=QY(142Po3j@yfNSb3fC}(js`#7E|>}k;KF>q}4#=V#{z*5szQ%7-iH9 zm>A&jmlZR%peJVa(~~K^u;U@<7~lYlu{zFK>sP{JXcq0Qb>5mP@;;8pM?8%rrIL3A zhyYx8URa}h388XkadeFO3<@bBiFjeJvcWNQ?M~+JA94N#_|hrZwZ4{h&*sXt-J+_x zp3N)F{sDGq^0p~0^n;tGJAyFh*73R<YITH)duo*0goq`_Cvs^en+hIC)dT+xGuxU? z*ifi-s}9Ob&T}d~@ys$$d_Le7(j+IxYzE+CL(?+Gc;E(|x<3tPI42?imp(v|QMw;q zH|kX{O}?leeWJ`->lfDwmvYb~P|(QEUmLVdFW2FWipF|<5q{ZaL&O~+mq+$p!h4~O zc4rKur{^CkN*Hz(#kd$jq;O%dnp=4J(YAR<8Sb%5#f@1gT9UiTRnEYJo(4}vb7|^; zW{FVwp#u~ASTz7299={6Q0%dYEND+qnxX35Co}9!96kx01|<DA)mI5CJk-+$f=;72 zHIQqy*Z11M#$50VM#NG6u0&@uYb8yZhP;~Q)`0B1n-O$KRqO9(3sOIIDD^Ivhan&h z6a@g<s+VFTAJ=~DV8BymS<M0rxYj1k(d-d+CBsMCVj6cFa6rZy<J<qE=(+=;{Qvkl zCug6{S&zMEWX2hnvv)RGWh5ga`^07Moyf`_$^0T&AtW+Fwjz6P`aQpY{o`}b^L*Z) z_xrUzk>FcAUz;H7Eu04*=@}$KS(BU<#D}(%Qd$U)25D`PdpC7QF7B#A@;4Gfa^{03 zF}U;P*(8NPtx4RPxKbz*e6a9&qOa|R>|Yw>#NYqOp^H~GpRnZuXGRK0FGrN1@pnl0 zV~)dtEYf_PAj6UHcByl}(Baz@RLK|uPKfq@VrtF3pjo{js5A9Sh19It92&h$22GL+ zH`dg-UcLL6M+0~c=?WCfZ}`%0Z}0uUcndG$#wNlBfob?O(ZsL#GTN%A(AlhfP*Bq6 zto*J^l{4Q(Z!`PLc<Wywf@%cHKAqm34W;xg0ekJfjn#M&(>M6TC*oNB{v!&!Ud{oB zk3XzEjNgHWs_I~VY9_pw&MiALdAsUVZ8YtJq>2mOCak?b{3hTT8A{<_fVd>Mw^}PH zR*#s$##VV-D{GbRZRf-4GF&0MNZe8?FR$_~AM#mx&m%h2=6{6)nffXCF}VH=y?qX} zs-Ge)<bX+jWJMsoNlmSsj3{0sh>!rrFPi;kld(+lvBWP0+d6$FJ0y}lL>tf*J9}K+ zd78QQiaV_8n>DR`Fih0bz<K35>Ysw>*MN`g%ON$R%8cbij#=%Q(R$kf&xlYyj2vy+ zEP)Nh(p+fOcKz*Xq~<T-@Vfb&yx;}w0i(G$A5u<nS!Lx%r1-_%TD++IpT=mhFI;{+ zZfI2oe&nTkDl|;SS$rDS^muSEuZc`!D_HovW)19*XbgRt0^XldqMT>1cb48^s!g1= zWoD?bo{(gEr}KLdXeIr(N?(;T&w_N_h84L*$I3#xf`*Y16;{-#HwPhfAjRNLUbiF` zXnHyxDB}E!u`_?IVIV_9ZLjW2DP=PKe^t$o?M#jC*KEiXmJ|1lX#-2tRQEnv*`1kZ z;6?QR$z<1n6U5+xQrD<Z3r)@6VTH>FAyj%w_&d^n!6N<yqyNfzF6o$#=_DFNb?{)* zaSu(|v;jer3mt-bG%u^Q5-(y>^ea9F9LgV>rRRo>0um?rcv`o2rb!2H#_!>;v!Wio z=sbECH$l+a^O@I&YpD8YNVSCxMBNZHg9()x6aswq*jRMaMsIxZ-J0_&>PNK3%sLVl zJfVj?E^4FTm~-BEgsoWXSrK4<PeVrUfL68XRr9M72wO^W9hFJwsMHfgu8c(MVTS%Z zz3}<(6mCd}=-e&fWHes0wf=ft<Bsw7ZCn*!QpAEs&bb13boMGOv)o1w+ylBPF^Bi> z<hvx;q^EF)HfB&%n$`d0%z)INPhD$tR}QP5OTXd!iEkIK`!2jYvq5T~h#K>lL+KD7 zQW%3iJAUa-jKu5RURrr_VZbn*>1hc=Y^CzKOuz543Z)^-f6EzRy<|a422QW86Bql# z*Win9*muV`R&P*~SOvn$@uO_d^c7uIRXqOXXipK{%(!HlvnL(HQp7$MuGhx?TVX`y zzKo-RcZUYpo~u1usnQ&@fV7&2c9{F2!np=`X{Q?t*%iF`rkKOeZKvRbeJ5WwCn{Iu zLX98ish<vC<3YRvDip*&Xs(t!WBOIR=4sT=oW}ZgW|uP0G}3%h#h;`_Dpvh44i$>Q zp&@ohMCPNzV&XiDILDjsCS&{e!YA-xgcnQ{|I$Ng2qvbA8p(*H2N=8U41lB|QtX<e zH^Q^4BKURZBDpp7jS6D}N$ff7K_l{aDRBC+=V_RjyaA{fEu^;==<}_1hG*h|{c{%Q z;zyQ@a*4jX%06Zae5!PerCGZ#l|x{t1QwgGl4r%^1O0cp`#%o-If4V{$0Nr!q9b#Y zUEf(!syjzgUK^0gf?eNp1=>JJIcL<+>(=8TeaUM>Z(b99+$;JW3zF&bb&>uI&RA+K z`9TGA`?y2+*@fE)D_5W!eiXCvE*z%#+-|@wwT0jZCK1B1ti(gT{<dt=^N$C?ss!4D zXD1$_lCL5xPq+6-gn-u<>>{FOekA1SmFpH`m5{$dY{LcoqaV(*bLf`zDGMjMr&fSZ zAatBl2>bIu*0v)qmzK;f>CP+rD6^&TLiSL(h#ulU_O0btkJ*^$x{^-{0_{vBxn32r zlM6vG?k=(S#rW$>`hC{6h=EQqp7RgR(@cbj-Y^O5XOjnr%*0z}Wdte<WiJuXji2wh zEdRLKkEM}_qMd%Mc+FIjVcv2nHEF)CGam3sAV+CW#P|15!oNf?IhrJAs;JvRwbD~| z_WqN915zO|Klus9<%K<2Y)PU&><Wxr?Vd36Ta$3fI;PtVlUQvP6g!`j!44#kS~S3E zigWA7+`Gk4e|h}1DR+jbJmCLa#NxmA?!QMxF8n%Z1lll9X741^Sj2o*N5sk!9I9O} z-Qy~D_Md$XiEvmwnHqFfm3YrvHST{0!Gnk+!gG}EqXluN?<*bSS=WkT6IX{`<h@h_ zD<&DOyol9uJ%y?)h777Xu}_EtqK>XPy4I$cDHF(Yvv{++E2nC=9>xbjJYR+$tDCqy z_!``9JenX*rn&;UDbH2uD9rXhzKtdjIb){H`v48wKa<sB4Z+63dna7Y+U@`k8~5v& zN}dl~$KWnwfyvZooZtx6G6(av6L=C5V(8)+8h4JTn0=GDFe-lEfjcSqhmJZRn{6D+ zu22pE%UW?P+>xA$c>>ClDg7IoNtkpwT=eTMXfYexkQ2=R{M%J(b6#K*vT|k!ggM@! z#%zh9fwIXm=)moRfZOoQZVqUa_OD~YIB(#U&7VtZ_k|~)9;J_V^CMX+?cs0tOPu|w zFtp025c{){tu}Sg-Z1E)vHkkDI7^lDhQ;x`P0)!bbA4Qbc(UedZRl;6O0nUWPzh{{ zI*i1sVkuAyNCWusz-68u>bPYnygdKFiLhAm4h=9-5uO$Jb(}c3)iC&&p4b(_J5|;F z#Tp`eJ|YRl+<xbJ*V8My5U@oHEq}Mx7w{r3ni#X7(;`pB_0}73Hau)93X#IA?zgxR zDlTM~FgMm`r*C216hSVF5dt=IX}ejpEQVw!|BNNA;%UgdnE8=Y&&DUqnXAOm191ho zQ_^#TUPY*OIx36}4Nd0eI)fDd%+$+}2dNCPjEj=ku0VX0VjM6evY3?b^(L-WI*DEU z(Dn4Hbe;eaGOaR}L<Cz_^?l>!DSesLA3LZV*_uvY8tpLrU@R%W2FLLtpskTyMWazz zDh;I>d}(+iw7t2-r{j-dtiJ0AT0EP#8D{)GdOK_l3y2~a-kP3#NI7Oo<uK6?&!8bo zH|f!owNE-@{*gWFg13-=5rH4YiwMFOfA;_&`q3f&6=JwOR5}!0_OnO@z#D>MgIJWw zcY5x+!5x>Wo#d3d^@emH;x8X$aQnx*z!3F{=3iGf3~oc5V92~iuPl>i47|_YIkzZw z?BG$GNli-qnq4;fCuBvrTjAV-6hu~7#FrYl97F7TUP;FLNS>m{lC}@jyQGKa<I!!K z_LCt3rWLbK(!bpO<8(L{yge#_fVcJ)kLiDDL{b^)=s!TLdJp}yx)Y8l0H@re{G`OA zmsYp=aFsco4FQa|nwChSduldrqm|_w3*=zO+>C(?kBe63WU#l&zk0HThs+R)U|!42 zX&Ckx)ef1w&r_7>Y9M({6~?@_<`QlyS^PsdhCPLIkv3=#FQN(xC@A`aC3m%)O1jut zCg00-#%|9@yiu{ru(6i$#oy7EJAJmD-%hF}u;;pnp5uot49^D7R5%G9swZiFz{M^& zU<FSc+YOkgrtrSdeo6$am@xF&AJ_6w6GrKrO>2K#I!S=X9Zwi(;V^S=9UyT*esb%> zz*OH$TNYGYT5{7<_qVw#aeVfn1nA^2X_)uRqLt8Vp(TkJ+=B;0mH$AL;m7J=XZRK< zw5A8`LYOf`e{v!F4en#1U9h)##cVBeE~Ueqc{b|lk%iHndIJ}$ASp<>pUIzmvGJhy zq!A`a-&@$?tz5WgZhvTfA-g)0q4IL3FeUtGG#GNAQmT;5xHp&7Auq4JhPsUxcIe1_ zL6Ku_a`LTyjtwNXzhO}&$u(<IhVPus@DPc>Lw>b3WAXEBHcA0LxTyb(_YKiKuhjf% zV&L|Jv1xh?Zo<Nep)b0?nJ=<u;Onmy>V(JjSajP48#m(VL?b_<<CP$o^q`2f8op<& zxD{lI&+!}(ijK9Y1^Ltj7TrKr-PtvH>a(xBMSDU__B+9l<#;o1<Etm!MFp4$qvllM zO6{`A&z@du{g7U^n_Z{O3u5-SDPLdd<*h4eM)^LJtiq3?0C8|D;Zt#bWX1K|^Asyy z-Y*jpqAyBo@CQPMq-Tnq8LoZq^R8-D3B;e_MW{EjWnRk0@$XW@Z9nP)^_(>A81GP0 z<+vyREM9SrC{|_GO6^C>WMOv{!#x?qkqMslh_B3lyLefGBwAa@26Z5I9BX(f>OKAm zaw<0DfMS7CmK9Ussx+vdx+>b)_JbipZ0j{wHzNw|O10I<P~_@#vsO7NSGRw|V@io* zMA51+^x+~Q!u__fCk8j<b<x}-GJ8TuLpB64ET3HrRrsaPhPP$}Te+eJ4S+BNc5C2W z5UH}rDyvlusoMNv5G4lXWsN^vN*TfC{3*;GhTZ5AeSgQO_kPId4*63E2W9WaMnY4^ z!SqYp*HU?$O>~Krs0H1IPB_rt7Lo}94%Pmjk-3P>oli?wA$OPVhYwtVDmn>6Nh?xe z`9gHT^8xz*bIIp_k#9||3t6@d$q{^e^8)x$gpt=W*sOiB>vs;6N?h1A8kFKIKpju{ z7kd<54(eTtt^`=Gs>aP~ze<thR)7U{JKO$;zNFbFJ@roRB#y8R_p8gXd(>Y+(7drR z>i$N`$HL`6=mk~SzOQH7MxUgmHkzX#!ffofCcfokM&*#N@Rck2&)`EM3z^|L0Q`8| zKb$Lu$-K9rB}3Q57$eg?e;!RN3stnw6C#54{_!F%=G1{OJ`1)5JtyV3QiWFkKEh0B z^ipTJS~ypA-HS1iZ*K<r#FpX3T3^Eo3qF}-yW}9xJ@vDuQZII>86PDT%i71~=`qvy z+w^-;bb_^_O?uB#*ZUaMm9ZPI<$od@TrG*QN_P+d2JEk%DE33AL636~^h}OtHsewU za&YGTOjUv(S(DOI_YF!YOG8#P-nB#*R(Ey<<9M)21S3q6HWY0q!Mg|uWobf=Yu_RI z>8}UCMa!E#A2_n82vC>a{4xt#q=}A5?L}V`<quiL?=j4LGG4&2>1iZ5zg>@VcXee| zcrzTA%zjahkFlH5^ssmnYDG&%Q8fPZ{J$z^Gh6#=&Vh#y+(%NL>#IQwM%M8iF7Je; zd85xq!NM%`o>XJK?LLU+G?L$G#_Oeqi#V=6VL=`9n<|KdcmRixNk?93>J_|xktvUp z&yX|Z54A2IN7DpeaRLzAn#Z*_gaRou9PEVm&_a>b`2EQpR4<dmND4JpvNuuWKRfjX zLbWDhm>~qgNPa`}$V76DgA##>icIaYiY_|`DK4wEu^3!zqf6|=Bqp$WtX`ZW!Y2GG z$%ekqv=-^$6;oohhbJf7XW_5Gm&${n0DL}4gl%l7p|=D2S9Gc9XU^OPJcF2($rp!` zbn9S<=q<0y`WT?3{D)$vnSh!H97xgo22qvh?9o=>!-Lzt^m?QCkoQIc3xrj5Limxp zY-Ms`b?gD#31NlHu9d`J3)T;xv;iCl`0HQ><)Ae?um*lRAte6PdcsNE%|r>0=y?Xg zwA$d>9rY#GA_q)L3`Es#SC@j;tRV+5Z*yoJF%Sr|BcrKkHVawOQyknfNBne$eL!YK zFAh<{ZIKIAP_Uh8f5!0Cl>Q?O(a%e{_g_{S`vgR-HryPB701>UvL|pU8hC_B4f?X7 zK1UK%n^=$%k4L|5M0>scCN-PXTZ)KaKd{H9nl<#im8nVidw&1@Iv3JN<W%8V8NE>1 zNOsl#S;_G{u~u3R)`rg~I#7NA$Q0h1XMTzM@BApB{ukRbflr70gNf`>(;DM$qzNdF zZW6-|!Gzc8h++|b9tF<$1r(5=XU1*jxcE0=QmgHPv7tGOuH0eZ`o))ff2hIF+Tz78 z!lZF=p``&vC#jd_Twcn6Vab65-0=KrV%cRR<%juYstMBTcbv0xgxRwH>D0*&ne0)5 z#q8_z<MKq4{SO^}1J}1~utMptzX%a#CO41zsPTY(vQ*yn!<0nuG-&0i39l@^Tzp8? zY=@0i*H=f>Yib29l%!`*U%+A=N(K80531Xt{~}uZ)BvLlg^Sd`pi1orWFjA2*sSvT z?maDXPPA&m;ZE+)JiN7g;m(+e$4sLXXw~BzOKT%Cju8osu{uq_chbK0KA92?*@f(` z9xL@HXmC|dPHJ#03X`-c5@rT#ZFqTy|Hb|Fgh5C9@XZs&c;H0^UVl?&!80V^SrNqA zAL0ueD>BseOWJd4VNZ%eoxZ)JKP-rWv_=4gzl@&um(WgH^pc}hXK)dQGrs>H?1F_b zWBR7G9fh#`s*xC+%*B0JxuEuvl7@^nC1z{mLTz-a!ny2We_^B+hW_$>8lrb`JPt67 z7~!xKe4HSDqsj|{_=qWFD+Qo<y3@S(N}?&;ID7ES#3eomsk}{HNPdU$@7w>Je=gIv zaA7ChlwHwRSN~=Ga>A&Q!xqv9>U4K*6>mNzLc@jjSS#YZWD)Z?n9Y2Vv<|_bFigC( zNDR|$2a+1CGROzQ^8S_XqFfl_3crxS@Oz<rv@iLP-;{<N3L`Pj#oK=jPbtcAfajp@ zmD!T(TcyogHBf-SC=l;4*Ovy5z#qtjta*O7dw*(X^)aO-n`4a5^UcTuKSXcsi?2gZ zm1dYJ)tcGy-bDljaMp(d>MY8e_6|vsR-s$`?WCzHt{p?d1Z|aDPxcFU%RCrf*=#*Y zFQCB-scgAL{`hNXSlLY3n`x0FFDr<wuivR?(Oth6gCkeogmlC0sm9^J{kym4f$jHr z3Y?>!(?E*Df&G1d)ATQE4tOS`yz8jKK772jBUt!HB)Uf~tfh6-repGVPFWPomRenq ztx8HWqF1>hx{pVQ?5lpK6n{+*h{?~Y)fF>6ydO1$lIUY+naV<i2pSALm=hEIuuQ2| zR17W>0tQ+V(Wst#B@X|XL=#5L!R_@ncn<%|WY3+bchGs*>~BA|iv+=kUd||1<2WJN zADV>`YH`stWNt8(JZLx{qzlxg8PgOPBfUN}HpYbfw+Sn>9M8dRI6-8G*S;fiErroA z17FbYZqQ%&a8(e#(k%Qk{lPcB=R@Q<R;V$t8jb-2^(49ftApO;M)dxg$Xz6Mcf?!| zP2oqWBW$^EMdse@z!1W0Z7{?F`UlhI$p(n)_wM=P{>{f*yyD1}?Mr+i=L1#bsNu$J zLh98Kzro&Th<OyOy4w5WysgBqTkj2n<g-Kg(MUn6r`fvJD2HXaU+783ff48b5gw&| zTJYz=<&F84RE=?KVz9z}d=AS+6hcW@5+VT|;OVKk*YVg5<7BIX_{jo0kY;O{HrzRM zg9E}B<3>ap(WuAGst5`1mgYvf7#k=CfvpPaZXVOB{v>`H2pdz9V`~2L7wls;CP?!4 zeG8o7U^}f4KET#U=1TZndF*?f#wNq{&L+$A@5IzLsU~CBPTXtWWdqVDKGtrkhflNf zIT7a-kV55Gw{zbMZld}ltZ{F%hS&9M7CZn<2e(|zGhuA5!-`>?Y$%5aJLRD&T%u|P zw<1^h?oqFYB{3^_&bzfp!II&IH7ehN4h9DVQe&>=l?5gs$5XBvr?GF|zCEM~)fU2l z5mTyyxZEQfFhnEQ1Tw=Jb!C2C`&5;xykC+_wK!$==)=U;MJIbA5GjXesY#f<SThy$ zoCt6f4mU<t!n!%vGQtB}9)I-ydD<AP;d+9Y9LYdEI<9};>cpbF|F+^zrbiZzlqg>i z8MjWMFWFn}!HIcU#!-<V8K8C-9HC19S1Ah~J<(1autxbPsK(<yM|o0~<qJ=JHC%Dw z^ZHIH*rw&O*jw)PyM)4LGU%Rw=Uo3t>A1$H=FX5mj&`!ZiNhA$UUYD9_gwc-HJWMH zDt&{fnC9U}xq++}?29juhkA7Ai)U&VzLjDS2VBO188^}(2%&W}_|&cX3z*0@NF2`_ zJjH7P4iqoCaHb{oongRqB<kV~XV{wFp-W+p3}H%bKu5_up<<f{d(@S|t`pzFdn2QS zcWzHSZhX9^`WK~spJ`PDE{g?x&bVLgae96y*J3Q`U#}aaTm9T~#r7*>^^o`oUh#n% z+rl@kfFhya<l$w27n+;A+fJhCk+zD?^B7UhA)XK9<<J389=*KCfY+Na=oi%FE<7AD z&c9jAj~_kg$?P_~h)PQN#QI4g3{dSp8F82RglYPGT1~+j#aNd9Q{}&kGm%<(ZcL8Z zu6qxYHn6CQIK>Q2O{^U|W3W;07>tOBsNpu+C&x62&VtO3ZM3)6y(@ly5-c;b?ehud zL*}f5z+b)lvKtMVI8Vd2OkANIrE)uj=GHp@?H|Mpaz+;9N2UwM;s4yU9nR>X14vj5 z4C>)h;V4FmOZ3Wom_1*~v-_LlbjBy#v2teh!<$dVUH?v#NXf!=5K+3Hud3O7VdAR| zRF+rMHWB*DT|-Uc`Aa>o3YUXn<s@4c;tdNL4`Kyq3R=EJdJXBeRgRWiCeV`~v3(0f z_w)!N$$2O99dnS0dYn<i*?-3~mZk(M3k%u@&6X;FDASQC0?}!$BBKWOF$b!WV#*&` z4O#YYQEAhoQ&Qd@C+EQl8k3IlLz1xWpl-2J#n8?i{l!F$$JhN9yxk0H%fIzr#RSnR z4~yOZp^q?N5(|BTvACiXwPYY+VZWdMl1Vwpv2K_^TGR3yUovHoe&A;=Y{Q4oPGQ%Z z{_UPw|2)$Q3%>Cgb)9)%pvS&L2A)tx$f9)O4Qkah&1lH}a)^UpDP?czzu?M|V5D3i z8(u`h7H{Zvz-^8R@};STE&c!j&4AstY6wZ4J=0=lA%{}j-X%p|q7z!R`Ey^gkV@Cc zZztAM(<Vxne>A8NzLMdfZgs-?Jrfv~_J@G(5y5!h0MGXjGlq4P_e05RhH!?QDOMeT zWoG*1T>@;7vqa+d@6(`d){Efz5K85VDW|x>O39iu*<Zp&_yf`iwL5AhUl$__*}1&@ zVqZ{97XARDrh5*PUfzH2c<o7fHE?-t|6Ai55heB~!9p>h4<HyVC2{6qjW;r<cga(^ zn_=B;tP<!KPPGX0g+%`0b5pRn32>LleGv6DowAqII}soSe*N-7!7i>Gj}NeV97ZG6 zByhv&k@XKr_VMH~MmTFYi*k4+y3ur4tf!3t<`sie0(FPFnxD_o+Quy&hai<3m}h^N zH3%TT>JaoCtE^>5VqO70eHQAR_g;K*R~;`HhkFF(EjtO#P7<m86QDwc3~U7s*7+p@ z&vfjYCAH_O$ea89WRjI;C<h{C@hm?yL@|FXEZ_zy$<MJ3iSD{KgoymK1-~fGuGRS1 zpZ#7-sYW$1M6lpAEqML>Rq<}ESH=3F-#t9bP)rG>FhOHsL8<3R8yfZ@wEX`owO9&x zUlHp<k;W55tb81B=}K-1LUc6l7~DZH2fAlRGRs3f7@M2B*Pq6CO@Hp+U9SdI;Yx_q zOrpC)G?<RE&d?|09|N=J<WrwR3SgF>4Q<RS@l4JfTwg7|w$;5>-7qbI@uoIMQ*jYM zJ|tEXBJ@hL*?m?DS`y&hMq9(M{IrjE>g2*cSF+A0+wavo-8x7xqg`xE<n9gc@9My? zvGhBCY_|5tq4d_Vn|iyP7;CG1mdZl*ns>HMA3^WB1C{bGH~x>4cxu+{ATzzT8QGuB z_Hw>Vh1}7%f^C)(L%J7G@b^)^%znMi)p4qaOyOP}ds3RzF0&oj)I{3|zS_uaUDgLD zrFwk26qJpkFmvd~Pr-Wmvx%e{Lp1%qSwK>jo0JGAJh6fl@I30`JW^T^whDq!`#$O* zm`!3}g!i@OgEAuL7Ul*4-1ic2Pd(TNsjs%cE)WQ{J(P|6(jaD<C<a@B6n{e1ytSZE zxJ!Ul5G%_^V*M#mYKd~#&rhfbuihq`z+{a%;cvNlp&ELC>|{O-UPQsyAwbTH>=4i* z?@Yb0CI~<JJ@?Id3vOT8cPh_*N6k}HLcYqt=k{+0dzcm2&kKZ^NtGS!H-h8J?@`gf z&3jy>Za!6!ty2k}p;XFo|CdAVl^)B$${)q91nfz2@gaA6h_)5OTBh#{B2z#dtnmDi z$hXUvP>^b3&A}0ffd#XaNUf=dAe7IYwnaJ`|Eywml=!SdDd;!<9T}*`jC&orVL&d7 zq3qCJ=C$ScW3;MbXx;Fh*#4mG4|<q4g|diAtV`!ZNi_}WhjrmZYqq?N54&Dz6&<f$ z#WsIbPI-&N?h`e+K1KK3co3&oxxCqRQFq+@i$}nxw3YpIZM5DZaweQ>q+`PM!Mow4 z&<zKPTUroWz)R|fuiRH?!xk14R;24ieGo<WR2H)}30sGf0xPukVEHP|rs5)`9ME^^ zRdHlgCcX~sWQTuAqg-T1`~;t{I`DH;GOAqvpzY1lh0nzO<euvp%Bb Ss!^R4E!G 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�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�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 R<JbTI002ovPDHLkV1it*EJgqT literal 0 HcmV?d00001 diff --git a/packages/twenty-website/src/app/_components/playground/rest-api-wrapper.tsx b/packages/twenty-website/src/app/_components/playground/rest-api-wrapper.tsx index cd2da8ea8e6d..390fd0cf633a 100644 --- a/packages/twenty-website/src/app/_components/playground/rest-api-wrapper.tsx +++ b/packages/twenty-website/src/app/_components/playground/rest-api-wrapper.tsx @@ -23,7 +23,11 @@ export const RestApiWrapper = ({ openApiJson }: { openApiJson: any }) => { overflow: 'auto', }} > - <API apiDescriptionDocument={JSON.stringify(openApiJson)} router="hash" /> + <API + apiDescriptionDocument={JSON.stringify(openApiJson)} + hideSchemas={true} + router="hash" + /> </div> ); }; diff --git a/packages/twenty-website/src/content/developers/self-hosting/docker-compose.mdx b/packages/twenty-website/src/content/developers/self-hosting/docker-compose.mdx index b7fa656c6ba9..833fffbcc43e 100644 --- a/packages/twenty-website/src/content/developers/self-hosting/docker-compose.mdx +++ b/packages/twenty-website/src/content/developers/self-hosting/docker-compose.mdx @@ -1,58 +1,231 @@ --- -title: 1-Click Docker Compose +title: 1-Click Docker Compose icon: TbBrandDocker image: /images/user-guide/objects/objects.png --- +## Overview + +This guide provides step-by-step instructions to install and configure the Twenty application using Docker Compose. The aim is to make the process straightforward and prevent common pitfalls that could break your setup. + +**Important:** Only modify settings explicitly mentioned in this guide. Altering other configurations may lead to issues. + +See docs [Setup Environment Variables](https://twenty.com/developers/section/self-hosting/self-hosting-var) for advanced configuration. + + +## System Requirements + +- RAM: Ensure your environment has at least 2GB of RAM. Insufficient memory can cause processes to crash. +- Docker & Docker Compose: Make sure both are installed and up-to-date. + ## Option 1: One-line script -Install the project with the command below. -It will install the latest stable version. +Install the latest stable version of Twenty with a single command: ```bash bash <(curl -sL https://git.new/20) ``` -If you want to install a specific version, you can do so by adding the version number. `VERSION=x.y.z BRANCH=branch-name bash <(curl -sL https://git.new/20)` +To install a specific version or branch: +```bash +VERSION=x.y.z BRANCH=branch-name bash <(curl -sL https://git.new/20) +``` +- Replace x.y.z with the desired version number. +- Replace branch-name with the name of the branch you want to install. ## Option 2: Manual steps +Follow these steps for a manual setup. + +### Step 1: Set Up the Environment File + +1. **Create the .env File** + + Copy the example environment file to a new .env file in your working directory: + ```bash + curl -o .env https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/.env.example + ``` + +2. **Generate Secret Tokens** + + Run the following command four times to generate four unique random strings: + ```bash + openssl rand -base64 32 + ``` + **Important:** Keep these tokens secure and do not share them. + +3. **Update the `.env`** + + Replace the placeholder values in your .env file with the generated tokens: + + ```ini + ACCESS_TOKEN_SECRET=first_random_string + LOGIN_TOKEN_SECRET=second_random_string + REFRESH_TOKEN_SECRET=third_random_string + FILE_TOKEN_SECRET=fourth_random_string + ``` + **Note:** Only modify these lines unless instructed otherwise. -1. Copy the [.env.example](https://github.com/twentyhq/twenty/blob/main/packages/twenty-docker/.env.example) into a `.env` in the same directory where your `docker-compose.yml` file will be -2. Run the command `openssl rand -base64 32` four times, make note of the string for each -3. In your .env file, replace the three "replace_me_with_a_random_string_access" with the four random strings you just generated. +4. **Set the Postgres Password** + Update the `POSTGRES_ADMIN_PASSWORD` value in the .env file with a strong password. + + ```ini + POSTGRES_ADMIN_PASSWORD=my_strong_password + ``` + +### Step 2: Obtain the Docker Compose File + +Download the `docker-compose.yml` file to your working directory: + +```bash +curl -O https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml ``` -ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access -LOGIN_TOKEN_SECRET=replace_me_with_a_random_string_login -REFRESH_TOKEN_SECRET=replace_me_with_a_random_string_refresh -FILE_TOKEN_SECRET=replace_me_with_a_random_string_refresh + +### Step 3: Launch the Application + +Start the Docker containers: +```bash +docker-compose up -d ``` -4. Copy the [docker-compose.yml](https://github.com/twentyhq/twenty/blob/main/packages/twenty-docker/docker-compose.yml) in the same directory as your `.env` file. -5. Run the command `docker-compose up -d` -6. Go to http://localhost:3000 and see your docker instance. +### Step 4: Access the Application + +Open your browser and navigate to [http://localhost:3000](http://localhost:3000). + +## Configuration + +### Expose Twenty to External Access + +By default, Twenty runs on `localhost` at port `3000`. To access it via an external domain or IP address, you need to configure the `SERVER_URL` in your `.env` file. + +#### Understanding `SERVER_URL` + +- **Protocol:** Use `http` or `https` depending on your setup. + - Use `http` if you haven't set up SSL. + - Use `https` if you have SSL configured. +- **Domain/IP:** This is the domain name or IP address where your application is accessible. +- **Port:** Include the port number if you're not using the default ports (`80` for `http`, `443` for `https`). + +#### Configuring `SERVER_URL` + +1. **Determine Your Access URL** + - **Without Reverse Proxy (Direct Access):** -## System requirements + If you're accessing the application directly without a reverse proxy: + ```ini + SERVER_URL=http://your-domain-or-ip:3000 + ``` -Please use an environment with at least 2GB or RAM or one of the processes could crash due to memory issues. + - **With Reverse Proxy (Standard Ports):** + + If you're using a reverse proxy like Nginx or Traefik and have SSL configured: + ```ini + SERVER_URL=https://your-domain-or-ip + ``` + + - **With Reverse Proxy (Custom Ports):** + + If you're using non-standard ports: + ```ini + SERVER_URL=https://your-domain-or-ip:custom-port + ```` + +2. **Update the `.env` File** + + Open your `.env` file and update the `SERVER_URL`: + + ```ini + SERVER_URL=http(s)://your-domain-or-ip:your-port + ``` + + **Examples:** + - Direct access without SSL: + ```ini + SERVER_URL=http://123.45.67.89:3000 + ``` + - Access via domain with SSL: + ```ini + SERVER_URL=https://mytwentyapp.com + ``` + +3. **Restart the Application** + + For changes to take effect, restart the Docker containers: + ```bash + docker-compose down + docker-compose up -d + ``` + +#### Considerations + +- **Reverse Proxy Configuration:** + + Ensure your reverse proxy forwards requests to the correct internal port (`3000` by default). Configure SSL termination and any necessary headers. + +- **Firewall Settings:** + + Open necessary ports in your firewall to allow external access. + +- **Consistency:** + + The `SERVER_URL` must match how users access your application in their browsers. ## Troubleshooting -#### Not able to login +### Unable to Log In -If you encounter errors, (not able to log into the application after inputting an email) after the inital setup, try running the following commands and see if that solves your issue. -``` -docker exec -it twenty-server-1 yarn -docker exec -it twenty-server-1 npx nx database:reset -``` +If you can't log in after setup: +1. Run the following commands: + ```bash + docker exec -it twenty-server-1 yarn + docker exec -it twenty-server-1 npx nx database:reset + ``` +2. Restart the Docker containers: + ```bash + docker-compose down + docker-compose up -d + ``` + + +### Connection Issues Behind a Reverse Proxy + +If you're running Twenty behind a reverse proxy and experiencing connection issues: + +1. **Verify SERVER_URL:** + + Ensure `SERVER_URL` in your `.env` file matches your external access URL, including `https` if SSL is enabled. + +2. **Check Reverse Proxy Settings:** + + - Confirm that your reverse proxy is correctly forwarding requests to the Twenty server. + - Ensure headers like `X-Forwarded-For` and `X-Forwarded-Proto` are properly set. + +3. **Restart Services:** + + After making changes, restart both the reverse proxy and Twenty containers. + +## Persistence + +- **Data Volumes:** + + The Docker Compose configuration uses volumes to persist data for the database and server storage. + +- **Stateless Environments:** + + If deploying to a stateless environment (e.g., certain cloud services), configure external storage to persist data. + +## Getting Help -#### Cannot connect to server, running behind a reverse proxy +If you encounter issues not covered in this guide: -Complete step three and four with: +- Check Logs: -3. Update `SERVER_URL=https://<your-api-url.com>` in your `.env` + View container logs for error messages: + ```bash + docker-compose logs + ``` -#### Persistence +- Community Support: -By default the docker-compose will create volumes for the Database and local storage of the Server. Note that the containers will not persist data if your server is not configured to be stateful (for example Heroku). You probably want to configure a special stateful resource for this purpose. + Reach out to the Twenty community or support channels for assistance. -<ArticleEditContent></ArticleEditContent> \ No newline at end of file +<ArticleEditContent></ArticleEditContent> diff --git a/packages/twenty-website/src/content/developers/self-hosting/self-hosting-var.mdx b/packages/twenty-website/src/content/developers/self-hosting/self-hosting-var.mdx index abd7de752432..6eb28b045504 100644 --- a/packages/twenty-website/src/content/developers/self-hosting/self-hosting-var.mdx +++ b/packages/twenty-website/src/content/developers/self-hosting/self-hosting-var.mdx @@ -36,10 +36,12 @@ yarn command:prod cron:calendar:calendar-event-list-fetch ['PG_SSL_ALLOW_SELF_SIGNED', 'false', 'Allow self signed certificates'], ['REDIS_HOST', '127.0.0.1', 'Redis connection host'], ['REDIS_PORT', '6379', 'Redis connection port'], + ['REDIS_USERNAME', 'redis_username', 'Redis connection username'], + ['REDIS_PASSWORD', 'redis_pwd', 'Redis connection password'], ['FRONT_BASE_URL', 'http://localhost:3001', 'Url to the hosted frontend'], ['SERVER_URL', 'http://localhost:3000', 'Url to the hosted server'], ['PORT', '3000', 'Port'], - ['CACHE_STORAGE_TYPE', 'memory', 'Cache type (memory, redis...)'], + ['CACHE_STORAGE_TYPE', 'redis', 'Cache type (memory, redis...)'], ['CACHE_STORAGE_TTL', '3600 * 24 * 7', 'Cache TTL in seconds'] ]}></ArticleTable> @@ -160,7 +162,7 @@ yarn command:prod cron:calendar:calendar-event-list-fetch ### Message Queue <ArticleTable options={[ - ['MESSAGE_QUEUE_TYPE', 'pg-boss', "Queue driver: 'pg-boss' or 'bull-mq'"], + ['MESSAGE_QUEUE_TYPE', 'bull-mq', "Queue driver: 'pg-boss' or 'bull-mq'"], ]}></ArticleTable> ### Logging diff --git a/packages/twenty-website/src/content/developers/self-hosting/upgrade-guide.mdx b/packages/twenty-website/src/content/developers/self-hosting/upgrade-guide.mdx index cd121f7357f9..8a71df02a433 100644 --- a/packages/twenty-website/src/content/developers/self-hosting/upgrade-guide.mdx +++ b/packages/twenty-website/src/content/developers/self-hosting/upgrade-guide.mdx @@ -40,11 +40,44 @@ Run the following commands: ``` yarn database:migrate:prod -yarn command:prod workspace:sync-metadata -f yarn command:prod upgrade-0.23 ``` The `yarn database:migrate:prod` command will apply the migrations to the Database. The `yarn command:prod upgrade-0.23` takes care of the data migration, including transferring activities to tasks/notes. +## v0.23.0 to v0.24.0 + +Run the following commands: + +``` +yarn database:migrate:prod +yarn command:prod upgrade-0.24 +``` + +The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas) +The `yarn command:prod upgrade-0.24` takes care of the data migration of all workspaces. + +# v0.24.0 to v0.30.0 + +Upgrade your Twenty instance to use v0.30.0 image + +**Breaking change**: +To enhance performances, Twenty now requires redis cache to be configured. We have updated our [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) to reflect this. +Make sure to update your configuration and to update your environment variables accordingly: +``` +REDIS_HOST={your-redis-host} +REDIS_PORT={your-redis-port} +CACHE_STORAGE_TYPE=redis +``` + +**Schema and data migration**: +``` +yarn database:migrate:prod +yarn command:prod upgrade-0.30 +``` + +The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas) +The `yarn command:prod upgrade-30` takes care of the data migration of all workspaces. + <ArticleEditContent></ArticleEditContent> diff --git a/packages/twenty-website/src/content/releases/0.30.0.mdx b/packages/twenty-website/src/content/releases/0.30.0.mdx new file mode 100644 index 000000000000..2600d6d59d16 --- /dev/null +++ b/packages/twenty-website/src/content/releases/0.30.0.mdx @@ -0,0 +1,22 @@ +--- +release: 0.30.0 +Date: September 18th 2024 +--- + +# New Settings layout + +Experience a more compact and intuitive settings layout, now featuring a breadcrumb navigation for easier access and better organization. + +![](/images/releases/0.30/0.30-new-settings.png) + +# Add Several emails for one contact + +Enhance your contact management by adding many email addresses for a single contact. All emails sent to these addresses will be automatically synced with the contact, ensuring you never miss an important communication. + +![](/images/releases/0.30/0.30-emails.png) + +# New Array field type + +Developers can now take advantage of the new array field type to store non-predefined values. + +![](/images/releases/0.30/0.30-array-field.png) \ No newline at end of file diff --git a/packages/twenty-website/src/content/user-guide/getting-started/what-is-twenty.mdx b/packages/twenty-website/src/content/user-guide/getting-started/what-is-twenty.mdx index a13746ffe694..92b5e2d90d19 100644 --- a/packages/twenty-website/src/content/user-guide/getting-started/what-is-twenty.mdx +++ b/packages/twenty-website/src/content/user-guide/getting-started/what-is-twenty.mdx @@ -49,7 +49,7 @@ Internet connection (Offline mode isn't yet supported). If you wish to try Twenty before creating your own account, go to demo.twenty.com and login with the following credentials: -`email: noah@demo.dev`\ +`email: tim@apple.dev`\ `password: Applecar2025` ## Vision diff --git a/packages/twenty-website/src/github/contributors/save-issues-to-db.tsx b/packages/twenty-website/src/github/contributors/save-issues-to-db.tsx index f7cb48e68214..0b8e70e28788 100644 --- a/packages/twenty-website/src/github/contributors/save-issues-to-db.tsx +++ b/packages/twenty-website/src/github/contributors/save-issues-to-db.tsx @@ -25,7 +25,14 @@ export async function saveIssuesToDB( isEmployee: assignableUsers.has(issue.author.login) ? '1' : '0', }, ], - { onConflictKey: 'id' }, + { + onConflictKey: 'id', + onConflictUpdateObject: { + avatarUrl: issue.author.avatarUrl, + url: issue.author.url, + isEmployee: assignableUsers.has(issue.author.login) ? '1' : '0', + }, + }, ); await insertMany( @@ -44,7 +51,14 @@ export async function saveIssuesToDB( ], { onConflictKey: 'id', - onConflictUpdateObject: { updatedAt: issue.updatedAt }, + onConflictUpdateObject: { + title: issue.title, + body: issue.body, + url: issue.url, + updatedAt: issue.updatedAt, + closedAt: issue.closedAt, + authorId: issue.author.login, + }, }, ); @@ -59,7 +73,14 @@ export async function saveIssuesToDB( description: label.description, }, ], - { onConflictKey: 'id' }, + { + onConflictKey: 'id', + onConflictUpdateObject: { + name: label.name, + color: label.color, + description: label.description, + }, + }, ); await insertMany(issueLabelModel, [ { diff --git a/packages/twenty-website/src/github/contributors/save-prs-to-db.tsx b/packages/twenty-website/src/github/contributors/save-prs-to-db.tsx index 892b5565fcfc..abc5f7088e65 100644 --- a/packages/twenty-website/src/github/contributors/save-prs-to-db.tsx +++ b/packages/twenty-website/src/github/contributors/save-prs-to-db.tsx @@ -26,7 +26,14 @@ export async function savePRsToDB( isEmployee: assignableUsers.has(pr.author.login) ? '1' : '0', }, ], - { onConflictKey: 'id' }, + { + onConflictKey: 'id', + onConflictUpdateObject: { + avatarUrl: pr.author.avatarUrl, + url: pr.author.url, + isEmployee: assignableUsers.has(pr.author.login) ? '1' : '0', + }, + }, ); await insertMany( @@ -46,7 +53,15 @@ export async function savePRsToDB( ], { onConflictKey: 'id', - onConflictUpdateObject: { title: pr.title, updatedAt: pr.updatedAt }, + onConflictUpdateObject: { + title: pr.title, + body: pr.body, + url: pr.url, + updatedAt: pr.updatedAt, + closedAt: pr.closedAt, + mergedAt: pr.mergedAt, + authorId: pr.author.login, + }, }, ); @@ -61,7 +76,14 @@ export async function savePRsToDB( description: label.description, }, ], - { onConflictKey: 'id' }, + { + onConflictKey: 'id', + onConflictUpdateObject: { + name: label.name, + color: label.color, + description: label.description, + }, + }, ); await insertMany(pullRequestLabelModel, [ { diff --git a/yarn.lock b/yarn.lock index 123d0d0a6747..26889c43c79c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3369,231 +3369,6 @@ __metadata: languageName: node linkType: hard -"@chakra-ui/accordion@npm:^2.3.0": - version: 2.3.1 - resolution: "@chakra-ui/accordion@npm:2.3.1" - dependencies: - "@chakra-ui/descendant": "npm:3.1.0" - "@chakra-ui/icon": "npm:3.2.0" - "@chakra-ui/react-context": "npm:2.1.0" - "@chakra-ui/react-use-controllable-state": "npm:2.1.0" - "@chakra-ui/react-use-merge-refs": "npm:2.1.0" - "@chakra-ui/shared-utils": "npm:2.0.5" - "@chakra-ui/transition": "npm:2.1.0" - peerDependencies: - "@chakra-ui/system": ">=2.0.0" - framer-motion: ">=4.0.0" - react: ">=18" - checksum: 10c0/72d8c89e8d9b886b6387f4b1877263cecacc50897b38328bceb84e62c13e95759e081abe805465ee690dbbeede48e8638e5cfe3851b38613d8c26e6cbd7bc7ef - languageName: node - linkType: hard - -"@chakra-ui/anatomy@npm:2.2.2": - version: 2.2.2 - resolution: "@chakra-ui/anatomy@npm:2.2.2" - checksum: 10c0/06088161541e63bcc240487c0916d536c4b807e53da8ec4821b6dad737c84683a5936e3e44b99b6a6435a9cf896a3236d5f87226add27378c939804daed77305 - languageName: node - linkType: hard - -"@chakra-ui/color-mode@npm:2.2.0": - version: 2.2.0 - resolution: "@chakra-ui/color-mode@npm:2.2.0" - dependencies: - "@chakra-ui/react-use-safe-layout-effect": "npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/9df4a9f0bddff97c06e95c2863d0064d48cf2b0e7d149d322e33c2daebc40d980ddf3367c62db006ee0b20c470a7feed3ca76ad37a29c5e51f01f71f332447ab - languageName: node - linkType: hard - -"@chakra-ui/descendant@npm:3.1.0": - version: 3.1.0 - resolution: "@chakra-ui/descendant@npm:3.1.0" - dependencies: - "@chakra-ui/react-context": "npm:2.1.0" - "@chakra-ui/react-use-merge-refs": "npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/979af5026f261be91023619290f7edfcb49113eefd5094a9f5ccbf98e8b3a49688c05b894b11c47764e689ced1a9eb52af8fc99541c9a3fcbbef4575666e707a - languageName: node - linkType: hard - -"@chakra-ui/icon@npm:3.2.0": - version: 3.2.0 - resolution: "@chakra-ui/icon@npm:3.2.0" - dependencies: - "@chakra-ui/shared-utils": "npm:2.0.5" - peerDependencies: - "@chakra-ui/system": ">=2.0.0" - react: ">=18" - checksum: 10c0/0bd5c4b2dafc0adef1c5ffe9a137556a81b7f6f724c406d49740bea34153ba8ce6d8c9eaffa697a3d564d7df7b226cd59a8f0c103853f874543466c2816643b1 - languageName: node - linkType: hard - -"@chakra-ui/object-utils@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/object-utils@npm:2.1.0" - checksum: 10c0/581350502ae80b5fbb9ed7443002168c5cc685dc291fc0ace0946443041e5ac8835141c265da4e2c547e3795b7eea6b362d1dd03447187665791de8cdf2c746f - languageName: node - linkType: hard - -"@chakra-ui/react-context@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/react-context@npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/a2e7b5ccf3ea2316ee2537641c5bff5ef0a48a3717f3daaa749eccdc96751423db184747c489c876ca1ce8e0a31881c4690214d913c638f3d0fc89cd2b87612b - languageName: node - linkType: hard - -"@chakra-ui/react-use-callback-ref@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/react-use-callback-ref@npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/77e4cb8e71e75c178071cba80a18d114225116fadc5c325ae036144cde76ea491d11f5def721ea1d390d7ae3974371d41d0fe79beec308353866f43275b834c4 - languageName: node - linkType: hard - -"@chakra-ui/react-use-controllable-state@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/react-use-controllable-state@npm:2.1.0" - dependencies: - "@chakra-ui/react-use-callback-ref": "npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/b62ce7e5e8b9c20f67dea77e63e28feb5f9846b53c7d3d8a4d404b5aee30677be9f024f0d9e43c85f468e0c559486f49d2eaf8b6ab0656260847101d2723d4ca - languageName: node - linkType: hard - -"@chakra-ui/react-use-merge-refs@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/react-use-merge-refs@npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/2da9b877145c0bd426fd0cef3b46051f8f1f4d1e0f2d0feb1dd68ac40ac6a3899e71abf04440d3a7067fb64d637c17241c98fafd0bd78b22f0d8850cad08c567 - languageName: node - linkType: hard - -"@chakra-ui/react-use-safe-layout-effect@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/react-use-safe-layout-effect@npm:2.1.0" - peerDependencies: - react: ">=18" - checksum: 10c0/f2d760068dd6c90680076ccccd68c0e6dbc12015e819bfe128a1be4010ff86487812b5d2ec23b385cd11aa83614f418909abe503c78512b5dc076735a6e5265f - languageName: node - linkType: hard - -"@chakra-ui/react-utils@npm:2.0.12": - version: 2.0.12 - resolution: "@chakra-ui/react-utils@npm:2.0.12" - dependencies: - "@chakra-ui/utils": "npm:2.0.15" - peerDependencies: - react: ">=18" - checksum: 10c0/2bfa8626b6da77a666896da3be80a85f90808db27f8fbbcbdce89ad0ce1ffe688c352d0ef7e07f3c048c9d73f345fd05dfa803f9d1f75d7876f3568f4e81a0c5 - languageName: node - linkType: hard - -"@chakra-ui/shared-utils@npm:2.0.5": - version: 2.0.5 - resolution: "@chakra-ui/shared-utils@npm:2.0.5" - checksum: 10c0/d9095a4abb678e382f8fdf882a2e50fde5789267b9bf7165bd06babcbd0afcb0c8c319b78922b7ea9fdbf22659623fa8604cd76bcfec8750304fa4614c73a3f0 - languageName: node - linkType: hard - -"@chakra-ui/styled-system@npm:2.9.2": - version: 2.9.2 - resolution: "@chakra-ui/styled-system@npm:2.9.2" - dependencies: - "@chakra-ui/shared-utils": "npm:2.0.5" - csstype: "npm:^3.1.2" - lodash.mergewith: "npm:4.6.2" - checksum: 10c0/0dfe83262cf74b62ecdf8150401ae28b32079c53bda5c6ba32c230c1ad6db63148a3bfbe2bf118526a4cecf60f5df3f7f1aba0d43311453ac551fb2bf917574e - languageName: node - linkType: hard - -"@chakra-ui/system@npm:^2.6.0": - version: 2.6.2 - resolution: "@chakra-ui/system@npm:2.6.2" - dependencies: - "@chakra-ui/color-mode": "npm:2.2.0" - "@chakra-ui/object-utils": "npm:2.1.0" - "@chakra-ui/react-utils": "npm:2.0.12" - "@chakra-ui/styled-system": "npm:2.9.2" - "@chakra-ui/theme-utils": "npm:2.0.21" - "@chakra-ui/utils": "npm:2.0.15" - react-fast-compare: "npm:3.2.2" - peerDependencies: - "@emotion/react": ^11.0.0 - "@emotion/styled": ^11.0.0 - react: ">=18" - checksum: 10c0/026c7df02ae997c331f9f4af2ab07c9352e81e091882edb20186cddb5a8fe2964d09afad2ce674ccf925a0f1161d27c1a250679098f3c0b7d960b94f62451f8a - languageName: node - linkType: hard - -"@chakra-ui/theme-tools@npm:2.1.2": - version: 2.1.2 - resolution: "@chakra-ui/theme-tools@npm:2.1.2" - dependencies: - "@chakra-ui/anatomy": "npm:2.2.2" - "@chakra-ui/shared-utils": "npm:2.0.5" - color2k: "npm:^2.0.2" - peerDependencies: - "@chakra-ui/styled-system": ">=2.0.0" - checksum: 10c0/b7015d34cf19b1b0d6c0b415c4f489158d0cc65d8066050deff782b62705db68e8dbdcde0d7dd3b920be4b34c0a98e22568ea1e27ccc8ee133e78476e746f262 - languageName: node - linkType: hard - -"@chakra-ui/theme-utils@npm:2.0.21": - version: 2.0.21 - resolution: "@chakra-ui/theme-utils@npm:2.0.21" - dependencies: - "@chakra-ui/shared-utils": "npm:2.0.5" - "@chakra-ui/styled-system": "npm:2.9.2" - "@chakra-ui/theme": "npm:3.3.1" - lodash.mergewith: "npm:4.6.2" - checksum: 10c0/9fab70021a46d4a4b04d01d54270218a9e06817a26dfa03473e68529ea2aef54ffed0b0c451a4a64160bd62a23fd798ef202965af1211fddea66aaf36fe51db2 - languageName: node - linkType: hard - -"@chakra-ui/theme@npm:3.3.1": - version: 3.3.1 - resolution: "@chakra-ui/theme@npm:3.3.1" - dependencies: - "@chakra-ui/anatomy": "npm:2.2.2" - "@chakra-ui/shared-utils": "npm:2.0.5" - "@chakra-ui/theme-tools": "npm:2.1.2" - peerDependencies: - "@chakra-ui/styled-system": ">=2.8.0" - checksum: 10c0/ff1f479636965c1d8a345a8ea37ae67f772bf67ac83a82141c7e80a7e25e7cefcf5f89a16eafe469fa3b21f53c18040e0dc49cde6f484d702e705633c5385e55 - languageName: node - linkType: hard - -"@chakra-ui/transition@npm:2.1.0": - version: 2.1.0 - resolution: "@chakra-ui/transition@npm:2.1.0" - dependencies: - "@chakra-ui/shared-utils": "npm:2.0.5" - peerDependencies: - framer-motion: ">=4.0.0" - react: ">=18" - checksum: 10c0/08256dcdb2ed5e83ab7deedd1a76ef83ae3f2b1cab07492db1022fe7889437ac38fa2db7d32034faa1da5a73ea875e6b2f89e42de7943a60a12ad7c939421ec3 - languageName: node - linkType: hard - -"@chakra-ui/utils@npm:2.0.15": - version: 2.0.15 - resolution: "@chakra-ui/utils@npm:2.0.15" - dependencies: - "@types/lodash.mergewith": "npm:4.6.7" - css-box-model: "npm:1.2.1" - framesync: "npm:6.1.2" - lodash.mergewith: "npm:4.6.2" - checksum: 10c0/5dea8094bddfeb0e6809c1110c04dc8e975c741e0ba71bef4b640fab69218436fa16509706716af2c5d326fd33c2a32f6f30870397f8eaff0a5757fe0e18a6df - languageName: node - linkType: hard - "@codemirror/autocomplete@npm:^6.0.0, @codemirror/autocomplete@npm:^6.4.0": version: 6.18.0 resolution: "@codemirror/autocomplete@npm:6.18.0" @@ -4609,6 +4384,18 @@ __metadata: languageName: node linkType: hard +"@esbuild-plugins/node-modules-polyfill@npm:^0.2.2": + version: 0.2.2 + resolution: "@esbuild-plugins/node-modules-polyfill@npm:0.2.2" + dependencies: + escape-string-regexp: "npm:^4.0.0" + rollup-plugin-node-polyfills: "npm:^0.2.1" + peerDependencies: + esbuild: "*" + checksum: 10c0/8573eb409d19769ea6a2f621d8d7e344d84a9f19d03f37f4ace053e23dab8eeea08feea871c1704a2d39c0859adadfba808b59a50de4d227cb3879dbd90e7f52 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.19.12": version: 0.19.12 resolution: "@esbuild/aix-ppc64@npm:0.19.12" @@ -6504,16 +6291,16 @@ __metadata: languageName: node linkType: hard -"@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch::locator=twenty-server%40workspace%3Apackages%2Ftwenty-server": +"@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch::locator=twenty-server%40workspace%3Apackages%2Ftwenty-server": version: 2.1.0 - resolution: "@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@npm%3A2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch::version=2.1.0&hash=96a960&locator=twenty-server%40workspace%3Apackages%2Ftwenty-server" + resolution: "@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@npm%3A2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch::version=2.1.0&hash=ba139d&locator=twenty-server%40workspace%3Apackages%2Ftwenty-server" peerDependencies: "@nestjs/common": ^10.0.0 "@nestjs/core": ^10.0.0 "@nestjs/graphql": ^12.0.0 graphql: ^15.0.0 || ^16.0.0 graphql-yoga: ^4.0.4 - checksum: 10c0/d7a9f1ff65642cf64e942ef1caf2596b0b2866118bd95200fc2112902e71d4aeb00fe436d5d253f2415f51cf79c48417f3859fae8ed4beaf2ac7e52d49eef3a1 + checksum: 10c0/9ab6b702399658c120a2250d1b69df1c9094deadea0df8da2c610114ce1089a4e373586f8e967179025a567d8343731aaf971d3278e32778bdd5a840db7e45bd languageName: node linkType: hard @@ -9569,6 +9356,388 @@ __metadata: languageName: node linkType: hard +"@opentelemetry/api-logs@npm:0.52.1": + version: 0.52.1 + resolution: "@opentelemetry/api-logs@npm:0.52.1" + dependencies: + "@opentelemetry/api": "npm:^1.0.0" + checksum: 10c0/fddecb2211f987bf1a7f104594e58227655c887a6a22b41e9ead5ed925a4594b56186b38fca8e24db33058a924d8b54ddd6b315eca915c469f9653ce7813c31a + languageName: node + linkType: hard + +"@opentelemetry/api-logs@npm:0.53.0": + version: 0.53.0 + resolution: "@opentelemetry/api-logs@npm:0.53.0" + dependencies: + "@opentelemetry/api": "npm:^1.0.0" + checksum: 10c0/969ad3bbb74e3de6fdfe8eb9b3ab86d3dc284ca7bffd0ca67eef64efd08c97a4305696afe0b7b03e5d356f15d0a1a67ac517e5fa7d1ddee6fdc249eef2209fcb + languageName: node + linkType: hard + +"@opentelemetry/api@npm:^1.0.0, @opentelemetry/api@npm:^1.8, @opentelemetry/api@npm:^1.9.0": + version: 1.9.0 + resolution: "@opentelemetry/api@npm:1.9.0" + checksum: 10c0/9aae2fe6e8a3a3eeb6c1fdef78e1939cf05a0f37f8a4fae4d6bf2e09eb1e06f966ece85805626e01ba5fab48072b94f19b835449e58b6d26720ee19a58298add + languageName: node + linkType: hard + +"@opentelemetry/context-async-hooks@npm:^1.25.1": + version: 1.26.0 + resolution: "@opentelemetry/context-async-hooks@npm:1.26.0" + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 10c0/76ed53be50a472cbfe26a62620cb2a34f031474d08d302d31eb95d71cac2ed1567c6fa302c7ac5498e9d467d7d8e64f8d0e58c5c8b7bd987a352baafe5d9b213 + languageName: node + linkType: hard + +"@opentelemetry/core@npm:1.26.0, @opentelemetry/core@npm:^1.1.0, @opentelemetry/core@npm:^1.25.1, @opentelemetry/core@npm:^1.8.0": + version: 1.26.0 + resolution: "@opentelemetry/core@npm:1.26.0" + dependencies: + "@opentelemetry/semantic-conventions": "npm:1.27.0" + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 10c0/8038a3b9124a0b3b48dceb3949f88726c6853eac33b79fc049856f78dcf4b7ee453db1e6f4d5205a79b315caba809cb7d2f853946cf14773e50ce6a87fd5260e + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-connect@npm:0.39.0": + version: 0.39.0 + resolution: "@opentelemetry/instrumentation-connect@npm:0.39.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + "@types/connect": "npm:3.4.36" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/c137f64b32d2bf916c0e928428ece7313682c9e845052d1f3884e807dcc0417c7751577e04451200c8d49448789c197f459dbbaad3ccb3748342cdfd242b3b51 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-express@npm:0.42.0": + version: 0.42.0 + resolution: "@opentelemetry/instrumentation-express@npm:0.42.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/ba0749ba7e74898a1cb361fdef65661eb84218d827d3e53ab5b4fa46a2e5a35b944e64bb5f5391ead0e0578f94a7624d953b06b66de0467a64d43bcf24d20f3c + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-fastify@npm:0.39.0": + version: 0.39.0 + resolution: "@opentelemetry/instrumentation-fastify@npm:0.39.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/2363868111029b2c874f64c31fe41232b21922dfba62892e422cab8af19f0d2995807afba7112c570d93a2a8634e3ad79ea4171f010ecd869439cf863967f939 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-fs@npm:0.15.0": + version: 0.15.0 + resolution: "@opentelemetry/instrumentation-fs@npm:0.15.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/d06508e7c36fe9ed8db920f2481bcaafb5cc22d6f3d0c95dd97b098ca326a8b6089e2bf3b77c106f275ed3e019576e49c5b16036943e76675b1ce80a4d427a2b + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-generic-pool@npm:0.39.0": + version: 0.39.0 + resolution: "@opentelemetry/instrumentation-generic-pool@npm:0.39.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/962b19814aa06d5dca42a94f6c94d29ab7ab81a64e951f18d712055343aed11f6ed40df95f39f71ba92ab34c47b21eec514ab93dc8323bbd7567caeebe3a2752 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-graphql@npm:0.43.0": + version: 0.43.0 + resolution: "@opentelemetry/instrumentation-graphql@npm:0.43.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/d1db48ea4af5f9352da5c644a04253908c4df1d386176ee2d2679a7f22769411a2ce10a53fd9910c11ea2d80307d0bd613ba64193b77329648e2e2da08edabf5 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-hapi@npm:0.41.0": + version: 0.41.0 + resolution: "@opentelemetry/instrumentation-hapi@npm:0.41.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/cbfecb84de7b79d9c54d2d60d881a6bbfa8cca6e2b54d4eaa3ea093b99b3fa990a03c4641bc76b36367af1c793e4f639ce0c09e3b5aed9f20f04c08076c5e31e + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-http@npm:0.53.0": + version: 0.53.0 + resolution: "@opentelemetry/instrumentation-http@npm:0.53.0" + dependencies: + "@opentelemetry/core": "npm:1.26.0" + "@opentelemetry/instrumentation": "npm:0.53.0" + "@opentelemetry/semantic-conventions": "npm:1.27.0" + semver: "npm:^7.5.2" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/421d5d9d0725dab6d2e77bf1464e0a76c22a88415854ce703d9cce7f795e4b11653d1705e7e060c61f6dba8019dd365f527b0d6332e4a8ef473f5101b5637a9c + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-ioredis@npm:0.43.0": + version: 0.43.0 + resolution: "@opentelemetry/instrumentation-ioredis@npm:0.43.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/redis-common": "npm:^0.36.2" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/81f3988baa1cd78819951eab2e2a889d0f758a8cf3ecdacb8581ee362a339050cfd3e2bf1d56cae2fdfd055ded6975b74a1a1bea793ef2ca4c1953537e63f12c + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-kafkajs@npm:0.3.0": + version: 0.3.0 + resolution: "@opentelemetry/instrumentation-kafkajs@npm:0.3.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/e29b0a0010a004418ada1277018aca316eb38de304afe7c5f5e56c60bbfd714fc7e8f0ddcd53c9a87233d1d31c57761292a0b1292496a08ccbfd954df0635a5b + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-koa@npm:0.43.0": + version: 0.43.0 + resolution: "@opentelemetry/instrumentation-koa@npm:0.43.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/d9596de9915ced84d8db2f244376420700dbb2731e044cd2091f8b32938a732e41525e50f9fa32cb95dc2f4fd560bb9a327061a44a993db034dd89a7d2e0495b + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-mongodb@npm:0.47.0": + version: 0.47.0 + resolution: "@opentelemetry/instrumentation-mongodb@npm:0.47.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/sdk-metrics": "npm:^1.9.1" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/aa3238c3fd4d8f58bb22255051b4203ca6fb2d6e45ef16fc6c3e34bd79230e9faa3f4753b5c1dbc154d50f4be832107623781ab070c63c5ae46713d0e1a65e45 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-mongoose@npm:0.42.0": + version: 0.42.0 + resolution: "@opentelemetry/instrumentation-mongoose@npm:0.42.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/993fe0a0c8eda24bf2e650a78131fcc80227b850b0c70e0a4242ed0110e0b24c2ea23125bc9bd071b5f9ac9f3c46df84e8988e7edd5f27f79b0a8a8567f2f5ad + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-mysql2@npm:0.41.0": + version: 0.41.0 + resolution: "@opentelemetry/instrumentation-mysql2@npm:0.41.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + "@opentelemetry/sql-common": "npm:^0.40.1" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/a51217ff9da3ee9aca9ff956755b67068813fdd6f266b605bff5c9fe8f8b67d40ec0293c01d1817c69abc41c19e7589f7bcb24535f259cc539d42d7d32fd2232 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-mysql@npm:0.41.0": + version: 0.41.0 + resolution: "@opentelemetry/instrumentation-mysql@npm:0.41.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + "@types/mysql": "npm:2.15.26" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/f472b0a8f5ea240da3c616d2eb2ed14d6a6d50e98e3c40eb773894d38eff3b5f1bc2d2426240c9228eb8b3eb3717e605822a7506025dea4549055b13807680f2 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-nestjs-core@npm:0.40.0": + version: 0.40.0 + resolution: "@opentelemetry/instrumentation-nestjs-core@npm:0.40.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/d362daf6eb77fc716159f0bfbbf5685699ed7e85c14a8f241c316daa5ebc2c80a9e20dda8245e7acfbc7bcc7c95ab2d01c2c637b8d428352673fc77f862c87c6 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-pg@npm:0.44.0": + version: 0.44.0 + resolution: "@opentelemetry/instrumentation-pg@npm:0.44.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + "@opentelemetry/sql-common": "npm:^0.40.1" + "@types/pg": "npm:8.6.1" + "@types/pg-pool": "npm:2.0.6" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/d20db7b7791d40cf65751dc9d79feae8694b2eb156985ef1dc1ee3ff9a230424305b24534192d9f234b87465b47d6b622e8f9e001e4665ea17d9017825835b80 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-redis-4@npm:0.42.0": + version: 0.42.0 + resolution: "@opentelemetry/instrumentation-redis-4@npm:0.42.0" + dependencies: + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/redis-common": "npm:^0.36.2" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/4bb5408daeefc10395443fd10bd2b933c88f18658f181bd80c240f49e896c14bb520b71f2eca31fa27a4f1d82448ffceb88c2ee419eec1041f997f8a1d9a6818 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation-undici@npm:0.6.0": + version: 0.6.0 + resolution: "@opentelemetry/instrumentation-undici@npm:0.6.0" + dependencies: + "@opentelemetry/core": "npm:^1.8.0" + "@opentelemetry/instrumentation": "npm:^0.53.0" + peerDependencies: + "@opentelemetry/api": ^1.7.0 + checksum: 10c0/eafaf213f6da1ad479ee56c8cf884cf27871a40749444784ca03d77fd0c4418164f3fffaec42ad07b81a4613cdf076594e305917698663424a081b50d0c6b481 + languageName: node + linkType: hard + +"@opentelemetry/instrumentation@npm:0.53.0, @opentelemetry/instrumentation@npm:^0.53.0": + version: 0.53.0 + resolution: "@opentelemetry/instrumentation@npm:0.53.0" + dependencies: + "@opentelemetry/api-logs": "npm:0.53.0" + "@types/shimmer": "npm:^1.2.0" + import-in-the-middle: "npm:^1.8.1" + require-in-the-middle: "npm:^7.1.1" + semver: "npm:^7.5.2" + shimmer: "npm:^1.2.1" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/943e289926812272cb77cda5e0a6b662bc6a92812b66420ceeca1c764f2e3a13364f6bbed7c9e84a17ad677474101ea3c598ef6a6cca982c35bfd24be6f6a25e + languageName: node + linkType: hard + +"@opentelemetry/instrumentation@npm:^0.49 || ^0.50 || ^0.51 || ^0.52.0": + version: 0.52.1 + resolution: "@opentelemetry/instrumentation@npm:0.52.1" + dependencies: + "@opentelemetry/api-logs": "npm:0.52.1" + "@types/shimmer": "npm:^1.0.2" + import-in-the-middle: "npm:^1.8.1" + require-in-the-middle: "npm:^7.1.1" + semver: "npm:^7.5.2" + shimmer: "npm:^1.2.1" + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 10c0/1d4946b470ac31358ba8d81a9f9653a1d705db96ffb8958fef873340c3d3c9699cfd8ff617c313ea8c6a8ece51aa7cf8af37d87a60813c31ed2207e5c14a33ba + languageName: node + linkType: hard + +"@opentelemetry/redis-common@npm:^0.36.2": + version: 0.36.2 + resolution: "@opentelemetry/redis-common@npm:0.36.2" + checksum: 10c0/4cb831628551b9f13dca8d65897e300ff7be0e256b77f455a26fb053bbdfc7997b27d066ab1402ca929e7ac77598e0d593f91762d8af9f798c19ba1524e9d078 + languageName: node + linkType: hard + +"@opentelemetry/resources@npm:1.26.0, @opentelemetry/resources@npm:^1.26.0": + version: 1.26.0 + resolution: "@opentelemetry/resources@npm:1.26.0" + dependencies: + "@opentelemetry/core": "npm:1.26.0" + "@opentelemetry/semantic-conventions": "npm:1.27.0" + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 10c0/62ffbf7edee8676055661cf608b32a52bfa46fedb1a88830b4d4d0faf6664edbcbf7922034d3690d11fe9ebef9d9f5ffcb05645e8c7b27c707bf57d5289617e9 + languageName: node + linkType: hard + +"@opentelemetry/sdk-metrics@npm:^1.9.1": + version: 1.26.0 + resolution: "@opentelemetry/sdk-metrics@npm:1.26.0" + dependencies: + "@opentelemetry/core": "npm:1.26.0" + "@opentelemetry/resources": "npm:1.26.0" + peerDependencies: + "@opentelemetry/api": ">=1.3.0 <1.10.0" + checksum: 10c0/640a0dcfa4af73a029ef57b51f8ecc1d08dfb0c3a5242552876fab36c7f9ae7c410fa52dbc5202a2d8675fcfe61df3c49205079963f1c11acfe42981d1d01a76 + languageName: node + linkType: hard + +"@opentelemetry/sdk-trace-base@npm:^1.22, @opentelemetry/sdk-trace-base@npm:^1.26.0": + version: 1.26.0 + resolution: "@opentelemetry/sdk-trace-base@npm:1.26.0" + dependencies: + "@opentelemetry/core": "npm:1.26.0" + "@opentelemetry/resources": "npm:1.26.0" + "@opentelemetry/semantic-conventions": "npm:1.27.0" + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 10c0/0d5fc19179375f1599edae91b7232f432faf8631746835a10d0cd0c4907d0ca3ed156cc8087d4e78efdfbd9ba5ba414cc9e1399172c2aa68d7e0cd5190394d87 + languageName: node + linkType: hard + +"@opentelemetry/semantic-conventions@npm:1.27.0, @opentelemetry/semantic-conventions@npm:^1.27.0": + version: 1.27.0 + resolution: "@opentelemetry/semantic-conventions@npm:1.27.0" + checksum: 10c0/b859773ba06b7e53dd9c6b45a171bf3000e405733adbf462ae91004ed011bc80edb5beecb817fb344a085adfd06045ab5b729c9bd0f1479650ad377134fb798c + languageName: node + linkType: hard + +"@opentelemetry/sql-common@npm:^0.40.1": + version: 0.40.1 + resolution: "@opentelemetry/sql-common@npm:0.40.1" + dependencies: + "@opentelemetry/core": "npm:^1.1.0" + peerDependencies: + "@opentelemetry/api": ^1.1.0 + checksum: 10c0/60a70358f0c94f610e2995333e96b406626d67d03d38ed03b15a3461ad0f8d64afbf6275cca7cb58fe955ecdce832f3ffc9b73f9d88503bba5d2a620bbd6d351 + languageName: node + linkType: hard + "@parcel/watcher-android-arm64@npm:2.4.1": version: 2.4.1 resolution: "@parcel/watcher-android-arm64@npm:2.4.1" @@ -9813,6 +9982,17 @@ __metadata: languageName: node linkType: hard +"@prisma/instrumentation@npm:5.19.1": + version: 5.19.1 + resolution: "@prisma/instrumentation@npm:5.19.1" + dependencies: + "@opentelemetry/api": "npm:^1.8" + "@opentelemetry/instrumentation": "npm:^0.49 || ^0.50 || ^0.51 || ^0.52.0" + "@opentelemetry/sdk-trace-base": "npm:^1.22" + checksum: 10c0/437ca8b61815642cb511bfbe9d5ba64a94accbd4902a037ab12b68e9ca77a9bf74c9269b6b3fd02a4bfd7474209e151accc24f051dd99828568c9df5f57d4a0d + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -11898,37 +12078,49 @@ __metadata: languageName: node linkType: hard -"@sentry-internal/feedback@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry-internal/feedback@npm:7.118.0" +"@sentry-internal/browser-utils@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry-internal/browser-utils@npm:8.30.0" dependencies: - "@sentry/core": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/b6d9dc372771b2ae4895dda14ad6e0925d52377af2f6ae815c373f67a9d3667062bb86328ec64d8437a8d935b59084b8f3e01164454cc0f5b4403aee46cae8b0 + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + checksum: 10c0/f7ca0a528b4d30cfbdc54d117068cdf1647f0c2b88d39f17e79cf2be2122819592814c07226628d52b817bf6744d33b2bcb0e25b389784cf7425f5d096ff1270 languageName: node linkType: hard -"@sentry-internal/replay-canvas@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry-internal/replay-canvas@npm:7.118.0" +"@sentry-internal/feedback@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry-internal/feedback@npm:8.30.0" dependencies: - "@sentry/core": "npm:7.118.0" - "@sentry/replay": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/6b9c1e9e72687454c4d80ff95038bc36695885a06069845831946e3710b69a9f3e625cf03010afa0af311e4fd1b20e51d7c4a66f82be9e5c80184cfec8930926 + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + checksum: 10c0/c6061721ef7d9faee3e54477a7554b3221c90e7eda473ce2215dd438939efeada0c9dab3b745402553b7cc5f37c79f3994a9123356596dddea0c6e5f9c4d6ebc languageName: node linkType: hard -"@sentry-internal/tracing@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry-internal/tracing@npm:7.118.0" +"@sentry-internal/replay-canvas@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry-internal/replay-canvas@npm:8.30.0" + dependencies: + "@sentry-internal/replay": "npm:8.30.0" + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + checksum: 10c0/918d85ae873fcbb4592ea8672e3cf17f7300388e4b2dbb6c1c0d190fb62b18ed4d23c2a5090253e1d4290883bc895873c8b47877e5b9dbb0ca7c96da050b5632 + languageName: node + linkType: hard + +"@sentry-internal/replay@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry-internal/replay@npm:8.30.0" dependencies: - "@sentry/core": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/335c5918a34ecfafb1c56f90ca83be94489a2fb1d71b3ed5f74c3349c00b93dcd2c0775b612cc190a2dfce5baac061224761143ffe33895b93ddf34a3ff76389 + "@sentry-internal/browser-utils": "npm:8.30.0" + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + checksum: 10c0/68045de057dda34e3693b855586d2f3d52fb01947173937aebac07b23cf64d51b4ccb188d4a60f71d891e29d5fd9e6a452999f6aa384ffa981daf4affa2b42a1 languageName: node linkType: hard @@ -11944,19 +12136,18 @@ __metadata: languageName: node linkType: hard -"@sentry/browser@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry/browser@npm:7.118.0" +"@sentry/browser@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry/browser@npm:8.30.0" dependencies: - "@sentry-internal/feedback": "npm:7.118.0" - "@sentry-internal/replay-canvas": "npm:7.118.0" - "@sentry-internal/tracing": "npm:7.118.0" - "@sentry/core": "npm:7.118.0" - "@sentry/integrations": "npm:7.118.0" - "@sentry/replay": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/eeff411162c5b64abfbdb1477a026cd327f3219dbb64954b0b4a19068e603633c440087f65c0d4e1c7e0a4a6aec334eb539401075ef00e2d5925d3100e1b3857 + "@sentry-internal/browser-utils": "npm:8.30.0" + "@sentry-internal/feedback": "npm:8.30.0" + "@sentry-internal/replay": "npm:8.30.0" + "@sentry-internal/replay-canvas": "npm:8.30.0" + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + checksum: 10c0/34c89d1db837ab2b73cea1c58d6bba090edf3c88875e1d0aa9ab9f6d662183b78b9d3fcf8b5351f932b6f3f8b7e60a5edb99943c8f03682f886563bedb750e60 languageName: node linkType: hard @@ -11973,13 +12164,13 @@ __metadata: languageName: node linkType: hard -"@sentry/core@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry/core@npm:7.118.0" +"@sentry/core@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry/core@npm:8.30.0" dependencies: - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/560114a6ee97f054f2bb461656e57447c5f0d0f79820ee263a191365119ac236d20cc9ddde1b33768d30d481e3e20796c038c8a4e3f7f9cde52ec96755ebadc8 + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + checksum: 10c0/5a0b9abbd30543417aa6a3e1fe7583084ec15d5cf52c271893032951e40ec04b620d68b67696e85496831dac942eb2a47fb01c6d97f63017a426a3b13fe7c5f5 languageName: node linkType: hard @@ -11994,18 +12185,6 @@ __metadata: languageName: node linkType: hard -"@sentry/integrations@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry/integrations@npm:7.118.0" - dependencies: - "@sentry/core": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - localforage: "npm:^1.8.1" - checksum: 10c0/4256662bc7b28474eda1d284c5aa87091f588c0bcf6ea05cdf45b99fae9ab401e486ee8518b6911e9412331668ec5b74f192bcd45b7e627d3320d3931a88324d - languageName: node - linkType: hard - "@sentry/minimal@npm:6.19.7": version: 6.19.7 resolution: "@sentry/minimal@npm:6.19.7" @@ -12017,31 +12196,92 @@ __metadata: languageName: node linkType: hard -"@sentry/node@npm:^7.99.0": - version: 7.118.0 - resolution: "@sentry/node@npm:7.118.0" - dependencies: - "@sentry-internal/tracing": "npm:7.118.0" - "@sentry/core": "npm:7.118.0" - "@sentry/integrations": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/41d67d67201526038eac03dc81e8ee6341908ce1f4a6d64c0f745f63272e6ea9fdd8ed651f30b173ef73ab39c4234360e2ec6416de5abdf6ba3f43f587fbc0df - languageName: node - linkType: hard - -"@sentry/profiling-node@npm:^1.3.4": - version: 1.3.5 - resolution: "@sentry/profiling-node@npm:1.3.5" +"@sentry/nestjs@npm:^8.30.0": + version: 8.30.0 + resolution: "@sentry/nestjs@npm:8.30.0" dependencies: + "@sentry/core": "npm:8.30.0" + "@sentry/node": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + peerDependencies: + "@nestjs/common": ^8.0.0 || ^9.0.0 || ^10.0.0 + "@nestjs/core": ^8.0.0 || ^9.0.0 || ^10.0.0 + checksum: 10c0/f0412787f5fac68743ed6e4f4b58fd06a198d3f0b5777dd072784d9c943fbb3725ee82b00838a7f274f4eb51d7776f5a72f80f8cba253f5c30a7649a292f20c0 + languageName: node + linkType: hard + +"@sentry/node@npm:8.30.0, @sentry/node@npm:^8": + version: 8.30.0 + resolution: "@sentry/node@npm:8.30.0" + dependencies: + "@opentelemetry/api": "npm:^1.9.0" + "@opentelemetry/context-async-hooks": "npm:^1.25.1" + "@opentelemetry/core": "npm:^1.25.1" + "@opentelemetry/instrumentation": "npm:^0.53.0" + "@opentelemetry/instrumentation-connect": "npm:0.39.0" + "@opentelemetry/instrumentation-express": "npm:0.42.0" + "@opentelemetry/instrumentation-fastify": "npm:0.39.0" + "@opentelemetry/instrumentation-fs": "npm:0.15.0" + "@opentelemetry/instrumentation-generic-pool": "npm:0.39.0" + "@opentelemetry/instrumentation-graphql": "npm:0.43.0" + "@opentelemetry/instrumentation-hapi": "npm:0.41.0" + "@opentelemetry/instrumentation-http": "npm:0.53.0" + "@opentelemetry/instrumentation-ioredis": "npm:0.43.0" + "@opentelemetry/instrumentation-kafkajs": "npm:0.3.0" + "@opentelemetry/instrumentation-koa": "npm:0.43.0" + "@opentelemetry/instrumentation-mongodb": "npm:0.47.0" + "@opentelemetry/instrumentation-mongoose": "npm:0.42.0" + "@opentelemetry/instrumentation-mysql": "npm:0.41.0" + "@opentelemetry/instrumentation-mysql2": "npm:0.41.0" + "@opentelemetry/instrumentation-nestjs-core": "npm:0.40.0" + "@opentelemetry/instrumentation-pg": "npm:0.44.0" + "@opentelemetry/instrumentation-redis-4": "npm:0.42.0" + "@opentelemetry/instrumentation-undici": "npm:0.6.0" + "@opentelemetry/resources": "npm:^1.26.0" + "@opentelemetry/sdk-trace-base": "npm:^1.26.0" + "@opentelemetry/semantic-conventions": "npm:^1.27.0" + "@prisma/instrumentation": "npm:5.19.1" + "@sentry/core": "npm:8.30.0" + "@sentry/opentelemetry": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + import-in-the-middle: "npm:^1.11.0" + checksum: 10c0/54ec05c004424eb03ed7d5ad352d0e0a0c929085f9ff07b47de0046014f1293499f746ccbf68910fc62fd0bfe2f53c3deda27feeb773f94b8a3ced090b0471b1 + languageName: node + linkType: hard + +"@sentry/opentelemetry@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry/opentelemetry@npm:8.30.0" + dependencies: + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" + peerDependencies: + "@opentelemetry/api": ^1.9.0 + "@opentelemetry/core": ^1.25.1 + "@opentelemetry/instrumentation": ^0.53.0 + "@opentelemetry/sdk-trace-base": ^1.26.0 + "@opentelemetry/semantic-conventions": ^1.27.0 + checksum: 10c0/71bebf23a6334d1d4655536bb0c7be1208b0b8b84446baec32e336b946d4e4f20f848d648ac7d9624002b6cb5ba335a1bd546f04f082e49e31406aa5f1095786 + languageName: node + linkType: hard + +"@sentry/profiling-node@npm:^8": + version: 8.30.0 + resolution: "@sentry/profiling-node@npm:8.30.0" + dependencies: + "@sentry/core": "npm:8.30.0" + "@sentry/node": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" detect-libc: "npm:^2.0.2" - node-abi: "npm:^3.52.0" + node-abi: "npm:^3.61.0" node-gyp: "npm:latest" - peerDependencies: - "@sentry/node": ^7.44.1 bin: - sentry-prune-profiler-binaries: scripts/prune-profiler-binaries.mjs - checksum: 10c0/7d4613ea702a1ed455e63ce063aa91a2f84666311c1d0139479810e84061cf5b7d49f790316efbc4d70f4b0e8424481d0e57bf082de073fb89b3139646cf7057 + sentry-prune-profiler-binaries: scripts/prune-profiler-binaries.js + checksum: 10c0/2e6153e45682529f3aa6c51e3475c0e1a124bb57b268e024b376f23b31ae5a51e5bdf2e9b215ec54e992057d8f0d5c06593e773774b88f7fa114e50208c3ffec languageName: node linkType: hard @@ -12061,39 +12301,18 @@ __metadata: languageName: node linkType: hard -"@sentry/react@npm:^7.88.0": - version: 7.118.0 - resolution: "@sentry/react@npm:7.118.0" +"@sentry/react@npm:^8": + version: 8.30.0 + resolution: "@sentry/react@npm:8.30.0" dependencies: - "@sentry/browser": "npm:7.118.0" - "@sentry/core": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" + "@sentry/browser": "npm:8.30.0" + "@sentry/core": "npm:8.30.0" + "@sentry/types": "npm:8.30.0" + "@sentry/utils": "npm:8.30.0" hoist-non-react-statics: "npm:^3.3.2" peerDependencies: - react: 15.x || 16.x || 17.x || 18.x - checksum: 10c0/e3e61469ee6e38033b84db47d01ce622c81cd6fd42059937241f4f228b3b15371f82f41b7601d447cdfedd064507039d2fb02e6ff729c6edd4715a7ea42b3e09 - languageName: node - linkType: hard - -"@sentry/replay@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry/replay@npm:7.118.0" - dependencies: - "@sentry-internal/tracing": "npm:7.118.0" - "@sentry/core": "npm:7.118.0" - "@sentry/types": "npm:7.118.0" - "@sentry/utils": "npm:7.118.0" - checksum: 10c0/e1af72a4fce1a970b6bc5fb4010405b3b405bf55661bab1a3c0d3f55f2063925192785f4ad454c4190cc8a08b6706906562f2b1b1dae8288aed15ac438770b24 - languageName: node - linkType: hard - -"@sentry/tracing@npm:^7.99.0": - version: 7.118.0 - resolution: "@sentry/tracing@npm:7.118.0" - dependencies: - "@sentry-internal/tracing": "npm:7.118.0" - checksum: 10c0/68a93f3eb5d6d4890bde1bf3393ce53290d3b001297f26bc19ce8e32414ea6b9e35adf4dbd1661560be4f9baba1ea21ea0da8a39c475c17877e685746e924305 + react: ^16.14.0 || 17.x || 18.x || 19.x + checksum: 10c0/089f0bc47efba9f4c912b46e143ad3de97da09c40e046395b6847ff81e850ac722a04c6deec98d5b4fcc687aa89eeaf51dc5b4287b0f5ad8be37be7ce13e018c languageName: node linkType: hard @@ -12104,7 +12323,14 @@ __metadata: languageName: node linkType: hard -"@sentry/types@npm:7.118.0, @sentry/types@npm:^7.109.0": +"@sentry/types@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry/types@npm:8.30.0" + checksum: 10c0/9cc57d19ebcb7b06f922373f832a268fa0023c20493370a0145def3bb0d1aa6ace7340a09e2abd28ef622eb17b4e7722d054a2a140b0a5f077c3a58614a42b0e + languageName: node + linkType: hard + +"@sentry/types@npm:^7.109.0": version: 7.118.0 resolution: "@sentry/types@npm:7.118.0" checksum: 10c0/3c9f1c301cd0a2b51fadd6105ee80e7cb39d47631c75bf5ecef3a1251b8eabc237533654e8afeaf77b44f7074c195c01e70e7b6e73f93277c63ada1f2b2c4a30 @@ -12121,12 +12347,12 @@ __metadata: languageName: node linkType: hard -"@sentry/utils@npm:7.118.0": - version: 7.118.0 - resolution: "@sentry/utils@npm:7.118.0" +"@sentry/utils@npm:8.30.0": + version: 8.30.0 + resolution: "@sentry/utils@npm:8.30.0" dependencies: - "@sentry/types": "npm:7.118.0" - checksum: 10c0/64d5581344bc4435fc09b518a5a2b06605cf0df2aaf60b0f3c5f3b2b7f64bbc86bb1f967a5a52b40f3fbfe2898ed37e436b4aa51d018ff403d945a1232b1713d + "@sentry/types": "npm:8.30.0" + checksum: 10c0/f65fac0f8d7ab64697b536e9399a43727056f18c4699514ef4bca2a0ef0e52eb679967b875ae42a7cd96e429baf23ee97aa84ab41bc416541d3a60c4c526e258 languageName: node linkType: hard @@ -15663,6 +15889,15 @@ __metadata: languageName: node linkType: hard +"@types/connect@npm:3.4.36": + version: 3.4.36 + resolution: "@types/connect@npm:3.4.36" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/0dd8fcf576e178e69cbc00d47be69d3198dca4d86734a00fc55de0df147982e0a5f34592117571c5979e92ce8f3e0596e31aa454496db8a43ab90c5ab1068f40 + languageName: node + linkType: hard + "@types/content-disposition@npm:*": version: 0.5.8 resolution: "@types/content-disposition@npm:0.5.8" @@ -16683,15 +16918,6 @@ __metadata: languageName: node linkType: hard -"@types/lodash.mergewith@npm:4.6.7": - version: 4.6.7 - resolution: "@types/lodash.mergewith@npm:4.6.7" - dependencies: - "@types/lodash": "npm:*" - checksum: 10c0/d3945227d2e08034eaec1eb15abb204af841215f55b9deb8173ac3bcb24e40c98181033652ad4bc46951afc04fe0de1021677d4036f0e5cff4c05e238e76abee - languageName: node - linkType: hard - "@types/lodash.omit@npm:^4.5.9": version: 4.5.9 resolution: "@types/lodash.omit@npm:4.5.9" @@ -16868,6 +17094,15 @@ __metadata: languageName: node linkType: hard +"@types/mysql@npm:2.15.26": + version: 2.15.26 + resolution: "@types/mysql@npm:2.15.26" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/3cf279e7db05d56c0544532a4380b9079f579092379a04c8138bd5cf88dda5b31208ac2d23ce7dbf4e3a3f43aaeed44e72f9f19f726518f308efe95a7435619a + languageName: node + linkType: hard + "@types/node-fetch@npm:^2.6.1, @types/node-fetch@npm:^2.6.4": version: 2.6.11 resolution: "@types/node-fetch@npm:2.6.11" @@ -17044,6 +17279,44 @@ __metadata: languageName: node linkType: hard +"@types/pg-pool@npm:2.0.6": + version: 2.0.6 + resolution: "@types/pg-pool@npm:2.0.6" + dependencies: + "@types/pg": "npm:*" + checksum: 10c0/41965d4d0b677c54ce45d36add760e496d356b78019cb062d124af40287cf6b0fd4d86e3b0085f443856c185983a60c8b0795ff76d15683e2a93c62f5ac0125f + languageName: node + linkType: hard + +"@types/pg@npm:*": + version: 8.11.10 + resolution: "@types/pg@npm:8.11.10" + dependencies: + "@types/node": "npm:*" + pg-protocol: "npm:*" + pg-types: "npm:^4.0.1" + checksum: 10c0/c8800d0ab2c6424308e6c6b40c73f19583ee1aed758462bd07694844b0a551b5841442205a4ee05207b80109ba502f33f20241b1bd9b4902e713611fb9e08f6c + languageName: node + linkType: hard + +"@types/pg@npm:8.6.1": + version: 8.6.1 + resolution: "@types/pg@npm:8.6.1" + dependencies: + "@types/node": "npm:*" + pg-protocol: "npm:*" + pg-types: "npm:^2.2.0" + checksum: 10c0/8d16660c9a4f050d6d5e391c59f9a62e9d377a2a6a7eb5865f8828082dbdfeab700fd707e585f42d67b29e796b32863aea5bd6d5cbb8ceda2d598da5d0c61693 + languageName: node + linkType: hard + +"@types/pluralize@npm:^0.0.33": + version: 0.0.33 + resolution: "@types/pluralize@npm:0.0.33" + checksum: 10c0/24899caf85b79dd291a6b6e9b9f3b67b452b18d578d0ac0d531a705bf5ee0361d9386ea1f8532c64de9e22c6e9606c5497787bb5e31bd299c487980436c59785 + languageName: node + linkType: hard + "@types/pretty-hrtime@npm:^1.0.0": version: 1.0.3 resolution: "@types/pretty-hrtime@npm:1.0.3" @@ -17253,6 +17526,13 @@ __metadata: languageName: node linkType: hard +"@types/shimmer@npm:^1.0.2, @types/shimmer@npm:^1.2.0": + version: 1.2.0 + resolution: "@types/shimmer@npm:1.2.0" + checksum: 10c0/6f7bfe1b55601cfc3ae713fc74a03341f3834253b8b91cb2add926d5949e4a63f7e666f59c2a6e40a883a5f9e2f3e3af10f9d3aed9b60fced0bda87659e58d8d + languageName: node + linkType: hard + "@types/sockjs@npm:^0.3.33": version: 0.3.36 resolution: "@types/sockjs@npm:0.3.36" @@ -17350,6 +17630,15 @@ __metadata: languageName: node linkType: hard +"@types/unzipper@npm:^0": + version: 0.10.10 + resolution: "@types/unzipper@npm:0.10.10" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/10e9da33791be1087adb25adc2fe4d5ab267dae51fbcf7b1f10d0aca3130a13ef5fed994d7be45af8c465ff3946bc360a53eff6e5aab4eb9ac9489477535342f + languageName: node + linkType: hard + "@types/use-sync-external-store@npm:^0.0.3": version: 0.0.3 resolution: "@types/use-sync-external-store@npm:0.0.3" @@ -20977,7 +21266,7 @@ __metadata: languageName: node linkType: hard -"bluebird@npm:*, bluebird@npm:3.7.2": +"bluebird@npm:*, bluebird@npm:3.7.2, bluebird@npm:~3.7.2": version: 3.7.2 resolution: "bluebird@npm:3.7.2" checksum: 10c0/680de03adc54ff925eaa6c7bb9a47a0690e8b5de60f4792604aae8ed618c65e6b63a7893b57ca924beaf53eee69c5af4f8314148c08124c550fe1df1add897d2 @@ -22217,6 +22506,13 @@ __metadata: languageName: node linkType: hard +"cjs-module-lexer@npm:^1.2.2": + version: 1.4.1 + resolution: "cjs-module-lexer@npm:1.4.1" + checksum: 10c0/5a7d8279629c9ba8ccf38078c2fed75b7737973ced22b9b5a54180efa57fb2fe2bb7bec6aec55e3b8f3f5044f5d7b240347ad9bd285e7c3d0ee5b0a1d0504dfc + languageName: node + linkType: hard + "class-transformer@npm:^0.5.1": version: 0.5.1 resolution: "class-transformer@npm:0.5.1" @@ -22727,13 +23023,6 @@ __metadata: languageName: node linkType: hard -"color2k@npm:^2.0.2": - version: 2.0.3 - resolution: "color2k@npm:2.0.3" - checksum: 10c0/e7c13d212c9d1abb1690e378bbc0a6fb1751e4b02e9a73ba3b2ade9d54da673834597d342791d577d1ce400ec486c7f92c5098f9fa85cd113bcfde57420a2bb9 - languageName: node - linkType: hard - "color@npm:^4.2.3": version: 4.2.3 resolution: "color@npm:4.2.3" @@ -23640,7 +23929,7 @@ __metadata: languageName: node linkType: hard -"css-box-model@npm:1.2.1, css-box-model@npm:^1.2.1": +"css-box-model@npm:^1.2.1": version: 1.2.1 resolution: "css-box-model@npm:1.2.1" dependencies: @@ -25379,7 +25668,7 @@ __metadata: languageName: node linkType: hard -"duplexer2@npm:^0.1.2, duplexer2@npm:~0.1.0, duplexer2@npm:~0.1.2": +"duplexer2@npm:^0.1.2, duplexer2@npm:~0.1.0, duplexer2@npm:~0.1.2, duplexer2@npm:~0.1.4": version: 0.1.4 resolution: "duplexer2@npm:0.1.4" dependencies: @@ -26852,6 +27141,13 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^0.6.1": + version: 0.6.1 + resolution: "estree-walker@npm:0.6.1" + checksum: 10c0/6dabc855faa04a1ffb17b6a9121b6008ba75ab5a163ad9dc3d7fca05cfda374c5f5e91418d783496620ca75e99a73c40874d8b75f23b4117508cc8bde78e7b41 + languageName: node + linkType: hard + "estree-walker@npm:^2.0.1, estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" @@ -28169,15 +28465,6 @@ __metadata: languageName: node linkType: hard -"framesync@npm:6.1.2": - version: 6.1.2 - resolution: "framesync@npm:6.1.2" - dependencies: - tslib: "npm:2.4.0" - checksum: 10c0/9e7d240ddf0bbe062bc9b71ffffd889b9923ee5d9c638ed84f2fe31aaa42e25e624eaf0b28ccca1d08f5ae170b8d083a6dabe5983f5dabea6bbbe6d4a9f8d27a - languageName: node - linkType: hard - "fresh@npm:0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" @@ -28398,8 +28685,6 @@ __metadata: "@babel/preset-typescript": "npm:^7.24.6" "@blocknote/mantine": "npm:^0.15.3" "@blocknote/react": "npm:^0.15.3" - "@chakra-ui/accordion": "npm:^2.3.0" - "@chakra-ui/system": "npm:^2.6.0" "@codesandbox/sandpack-react": "npm:^2.13.5" "@crxjs/vite-plugin": "npm:^1.0.14" "@dagrejs/dagre": "npm:^1.1.2" @@ -28457,10 +28742,9 @@ __metadata: "@ptc-org/nestjs-query-typeorm": "npm:4.2.1-alpha.2" "@react-email/components": "npm:0.0.12" "@react-email/render": "npm:0.0.10" - "@sentry/node": "npm:^7.99.0" - "@sentry/profiling-node": "npm:^1.3.4" - "@sentry/react": "npm:^7.88.0" - "@sentry/tracing": "npm:^7.99.0" + "@sentry/node": "npm:^8" + "@sentry/profiling-node": "npm:^8" + "@sentry/react": "npm:^8" "@sentry/types": "npm:^7.109.0" "@sniptt/guards": "npm:^0.2.0" "@stoplight/elements": "npm:^8.0.5" @@ -28527,6 +28811,7 @@ __metadata: "@types/passport-google-oauth20": "npm:^2.0.11" "@types/passport-jwt": "npm:^3.0.8" "@types/passport-microsoft": "npm:^1.0.3" + "@types/pluralize": "npm:^0.0.33" "@types/react": "npm:^18.2.39" "@types/react-datepicker": "npm:^6.2.0" "@types/react-dom": "npm:^18.2.15" @@ -28589,7 +28874,6 @@ __metadata: facepaint: "npm:^1.2.1" file-type: "npm:16.5.4" framer-motion: "npm:^10.12.17" - fs-extra: "npm:^11.2.0" googleapis: "npm:105" graphiql: "npm:^3.1.1" graphql: "npm:16.8.0" @@ -29372,7 +29656,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.3, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.3, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -29712,7 +29996,7 @@ __metadata: languageName: node linkType: hard -"handlebars@npm:^4.7.7": +"handlebars@npm:^4.7.7, handlebars@npm:^4.7.8": version: 4.7.8 resolution: "handlebars@npm:4.7.8" dependencies: @@ -31135,13 +31419,6 @@ __metadata: languageName: node linkType: hard -"immediate@npm:~3.0.5": - version: 3.0.6 - resolution: "immediate@npm:3.0.6" - checksum: 10c0/f8ba7ede69bee9260241ad078d2d535848745ff5f6995c7c7cb41cfdc9ccc213f66e10fa5afb881f90298b24a3f7344b637b592beb4f54e582770cdce3f1f039 - languageName: node - linkType: hard - "immer@npm:^10.0.2": version: 10.1.1 resolution: "immer@npm:10.1.1" @@ -31180,6 +31457,18 @@ __metadata: languageName: node linkType: hard +"import-in-the-middle@npm:^1.11.0, import-in-the-middle@npm:^1.8.1": + version: 1.11.0 + resolution: "import-in-the-middle@npm:1.11.0" + dependencies: + acorn: "npm:^8.8.2" + acorn-import-attributes: "npm:^1.9.5" + cjs-module-lexer: "npm:^1.2.2" + module-details-from-path: "npm:^1.0.3" + checksum: 10c0/b5b52b635450f69640289b9b597fef796ef9aa6c231ae22583a1c2e97bd1b61aa0048d7fc143b4af3ec5bffb7d64131302ed0882f62e0e2d60f0a4f009daff3f + languageName: node + linkType: hard + "import-lazy@npm:^2.1.0": version: 2.1.0 resolution: "import-lazy@npm:2.1.0" @@ -34412,15 +34701,6 @@ __metadata: languageName: node linkType: hard -"lie@npm:3.1.1": - version: 3.1.1 - resolution: "lie@npm:3.1.1" - dependencies: - immediate: "npm:~3.0.5" - checksum: 10c0/d62685786590351b8e407814acdd89efe1cb136f05cb9236c5a97b2efdca1f631d2997310ad2d565c753db7596799870140e4777c9c9b8c44a0f6bf42d1804a1 - languageName: node - linkType: hard - "lilconfig@npm:^3.1.1": version: 3.1.2 resolution: "lilconfig@npm:3.1.2" @@ -34540,15 +34820,6 @@ __metadata: languageName: node linkType: hard -"localforage@npm:^1.8.1": - version: 1.10.0 - resolution: "localforage@npm:1.10.0" - dependencies: - lie: "npm:3.1.1" - checksum: 10c0/00f19f1f97002e6721587ed5017f502d58faf80dae567d5065d4d1ee0caf0762f40d2e2dba7f0ef7d3f14ee6203242daae9ecad97359bfc10ecff36df11d85a3 - languageName: node - linkType: hard - "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -34817,13 +35088,6 @@ __metadata: languageName: node linkType: hard -"lodash.mergewith@npm:4.6.2": - version: 4.6.2 - resolution: "lodash.mergewith@npm:4.6.2" - checksum: 10c0/4adbed65ff96fd65b0b3861f6899f98304f90fd71e7f1eb36c1270e05d500ee7f5ec44c02ef979b5ddbf75c0a0b9b99c35f0ad58f4011934c4d4e99e5200b3b5 - languageName: node - linkType: hard - "lodash.omit@npm:4.5.0, lodash.omit@npm:^4.5.0": version: 4.5.0 resolution: "lodash.omit@npm:4.5.0" @@ -35139,6 +35403,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.25.3": + version: 0.25.9 + resolution: "magic-string@npm:0.25.9" + dependencies: + sourcemap-codec: "npm:^1.4.8" + checksum: 10c0/37f5e01a7e8b19a072091f0b45ff127cda676232d373ce2c551a162dd4053c575ec048b9cbb4587a1f03adb6c5d0fd0dd49e8ab070cd2c83a4992b2182d9cb56 + languageName: node + linkType: hard + "magic-string@npm:^0.26.0": version: 0.26.7 resolution: "magic-string@npm:0.26.7" @@ -37698,6 +37971,13 @@ __metadata: languageName: node linkType: hard +"module-details-from-path@npm:^1.0.3": + version: 1.0.3 + resolution: "module-details-from-path@npm:1.0.3" + checksum: 10c0/3d881f3410c142e4c2b1307835a2862ba04e5b3ec6e90655614a0ee2c4b299b4c1d117fb525d2435bf436990026f18d338a197b54ad6bd36252f465c336ff423 + languageName: node + linkType: hard + "moize@npm:^6.1.6": version: 6.1.6 resolution: "moize@npm:6.1.6" @@ -37715,10 +37995,19 @@ __metadata: languageName: node linkType: hard -"monaco-editor@npm:^0.50.0": - version: 0.50.0 - resolution: "monaco-editor@npm:0.50.0" - checksum: 10c0/79189c926c2fc1e3a3b9118e80911599bf18108018fe176c7b47a27b4856b544129f9a59c9a5c321d154d6a30a8d9c231684246e9382f4f18329a548d11cb4d6 +"monaco-editor-auto-typings@npm:^0.4.5": + version: 0.4.5 + resolution: "monaco-editor-auto-typings@npm:0.4.5" + peerDependencies: + monaco-editor: "*" + checksum: 10c0/1127183865f3ed486eb3bad407da3d8d8ca47ba3bd382a146a692741f9de4eb4f2335dc616b612cdaadfb3844e9b948060d407ea8a585c6710043b8bba29ed77 + languageName: node + linkType: hard + +"monaco-editor@npm:^0.51.0": + version: 0.51.0 + resolution: "monaco-editor@npm:0.51.0" + checksum: 10c0/7fde310c747e46cd7293e1a0f5e1fa85c389df9a1f8db03b9ccd58fd45356ab021a591b46198d19345566ad54556158f6489e2da4ad428a7a6ca3ea7b504afcb languageName: node linkType: hard @@ -38197,7 +38486,7 @@ __metadata: languageName: node linkType: hard -"node-abi@npm:^3.3.0, node-abi@npm:^3.52.0": +"node-abi@npm:^3.3.0": version: 3.65.0 resolution: "node-abi@npm:3.65.0" dependencies: @@ -38206,6 +38495,15 @@ __metadata: languageName: node linkType: hard +"node-abi@npm:^3.61.0": + version: 3.67.0 + resolution: "node-abi@npm:3.67.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/72ce2edbdfb84745bc201a4e48aa7146fd88a0d2c80046b6b17f28439c9a7683eab846f40f1e819349c31f7d9331ed5c50d1e741208d938dd5f38b29cab2275e + languageName: node + linkType: hard + "node-abort-controller@npm:3.1.1, node-abort-controller@npm:^3.0.1, node-abort-controller@npm:^3.1.1": version: 3.1.1 resolution: "node-abort-controller@npm:3.1.1" @@ -39129,7 +39427,7 @@ __metadata: languageName: node linkType: hard -"obuf@npm:^1.0.0, obuf@npm:^1.1.2": +"obuf@npm:^1.0.0, obuf@npm:^1.1.2, obuf@npm:~1.1.2": version: 1.1.2 resolution: "obuf@npm:1.1.2" checksum: 10c0/520aaac7ea701618eacf000fc96ae458e20e13b0569845800fc582f81b386731ab22d55354b4915d58171db00e79cfcd09c1638c02f89577ef092b38c65b7d81 @@ -40312,6 +40610,13 @@ __metadata: languageName: node linkType: hard +"pg-numeric@npm:1.0.2": + version: 1.0.2 + resolution: "pg-numeric@npm:1.0.2" + checksum: 10c0/43dd9884e7b52c79ddc28d2d282d7475fce8bba13452d33c04ceb2e0a65f561edf6699694e8e1c832ff9093770496363183c950dd29608e1bdd98f344b25bca9 + languageName: node + linkType: hard + "pg-pool@npm:^3.6.2": version: 3.6.2 resolution: "pg-pool@npm:3.6.2" @@ -40321,6 +40626,13 @@ __metadata: languageName: node linkType: hard +"pg-protocol@npm:*": + version: 1.7.0 + resolution: "pg-protocol@npm:1.7.0" + checksum: 10c0/c4af854d9b843c808231c0040fed89f2b9101006157df8da2bb2f62a7dde702de748d852228dc22df41cc7ffddfb526af3bcb34b278b581e9f76a060789186c1 + languageName: node + linkType: hard + "pg-protocol@npm:^1.6.1": version: 1.6.1 resolution: "pg-protocol@npm:1.6.1" @@ -40328,7 +40640,7 @@ __metadata: languageName: node linkType: hard -"pg-types@npm:^2.1.0": +"pg-types@npm:^2.1.0, pg-types@npm:^2.2.0": version: 2.2.0 resolution: "pg-types@npm:2.2.0" dependencies: @@ -40341,6 +40653,21 @@ __metadata: languageName: node linkType: hard +"pg-types@npm:^4.0.1": + version: 4.0.2 + resolution: "pg-types@npm:4.0.2" + dependencies: + pg-int8: "npm:1.0.1" + pg-numeric: "npm:1.0.2" + postgres-array: "npm:~3.0.1" + postgres-bytea: "npm:~3.0.0" + postgres-date: "npm:~2.1.0" + postgres-interval: "npm:^3.0.0" + postgres-range: "npm:^1.1.1" + checksum: 10c0/780fccda2f3fa2a34e85a72e8e7dadb7d88fbe71ce88f126cb3313f333ad836d02488ec4ff3d94d0c1e5846f735d6e6c6281f8059e6b8919d2180429acaec3e2 + languageName: node + linkType: hard + "pg@npm:^8.11.3, pg@npm:^8.5.1": version: 8.12.0 resolution: "pg@npm:8.12.0" @@ -41077,6 +41404,13 @@ __metadata: languageName: node linkType: hard +"postgres-array@npm:~3.0.1": + version: 3.0.2 + resolution: "postgres-array@npm:3.0.2" + checksum: 10c0/644aa071f67a66a59f641f8e623887d2b915bc102a32643e2aa8b54c11acd343c5ad97831ea444dd37bd4b921ba35add4aa2cb0c6b76700a8252c2324aeba5b4 + languageName: node + linkType: hard + "postgres-bytea@npm:~1.0.0": version: 1.0.0 resolution: "postgres-bytea@npm:1.0.0" @@ -41084,6 +41418,15 @@ __metadata: languageName: node linkType: hard +"postgres-bytea@npm:~3.0.0": + version: 3.0.0 + resolution: "postgres-bytea@npm:3.0.0" + dependencies: + obuf: "npm:~1.1.2" + checksum: 10c0/41c79cc48aa730c5ba3eda6ab989a940034f07a1f57b8f2777dce56f1b8cca16c5870582932b5b10cc605048aef9b6157e06253c871b4717cafc6d00f55376aa + languageName: node + linkType: hard + "postgres-date@npm:~1.0.4": version: 1.0.7 resolution: "postgres-date@npm:1.0.7" @@ -41091,6 +41434,13 @@ __metadata: languageName: node linkType: hard +"postgres-date@npm:~2.1.0": + version: 2.1.0 + resolution: "postgres-date@npm:2.1.0" + checksum: 10c0/00a7472c10788f6b0d08d24108bf1eb80858de1bd6317740198a564918ea4a69b80c98148167b92ae688abd606483020d0de0dd3a36f3ea9a3e26bbeef3464f4 + languageName: node + linkType: hard + "postgres-interval@npm:^1.1.0": version: 1.2.0 resolution: "postgres-interval@npm:1.2.0" @@ -41100,6 +41450,20 @@ __metadata: languageName: node linkType: hard +"postgres-interval@npm:^3.0.0": + version: 3.0.0 + resolution: "postgres-interval@npm:3.0.0" + checksum: 10c0/8b570b30ea37c685e26d136d34460f246f98935a1533defc4b53bb05ee23ae3dc7475b718ec7ea607a57894d8c6b4f1adf67ca9cc83a75bdacffd427d5c68de8 + languageName: node + linkType: hard + +"postgres-range@npm:^1.1.1": + version: 1.1.4 + resolution: "postgres-range@npm:1.1.4" + checksum: 10c0/254494ef81df208e0adeae6b66ce394aba37914ea14c7ece55a45fb6691b7db04bee74c825380a47c887a9f87158fd3d86f758f9cc60b76d3a38ce5aca7912e8 + languageName: node + linkType: hard + "postgres@npm:^3.4.3": version: 3.4.4 resolution: "postgres@npm:3.4.4" @@ -42207,7 +42571,7 @@ __metadata: languageName: node linkType: hard -"react-fast-compare@npm:3.2.2, react-fast-compare@npm:^3.2.0, react-fast-compare@npm:^3.2.2": +"react-fast-compare@npm:^3.2.0, react-fast-compare@npm:^3.2.2": version: 3.2.2 resolution: "react-fast-compare@npm:3.2.2" checksum: 10c0/0bbd2f3eb41ab2ff7380daaa55105db698d965c396df73e6874831dbafec8c4b5b08ba36ff09df01526caa3c61595247e3269558c284e37646241cba2b90a367 @@ -43764,6 +44128,17 @@ __metadata: languageName: node linkType: hard +"require-in-the-middle@npm:^7.1.1": + version: 7.4.0 + resolution: "require-in-the-middle@npm:7.4.0" + dependencies: + debug: "npm:^4.3.5" + module-details-from-path: "npm:^1.0.3" + resolve: "npm:^1.22.8" + checksum: 10c0/67c2242ea5b059c2a10c01d4f409233c67278051b47b9bf83198ab7e3ea591ffe3fa1d97912180d7d3d9a5e44490c00c55882b702849d61ac4db87d2c3823cb0 + languageName: node + linkType: hard + "require-like@npm:>= 0.1.1": version: 0.1.2 resolution: "require-like@npm:0.1.2" @@ -44076,6 +44451,35 @@ __metadata: languageName: node linkType: hard +"rollup-plugin-inject@npm:^3.0.0": + version: 3.0.2 + resolution: "rollup-plugin-inject@npm:3.0.2" + dependencies: + estree-walker: "npm:^0.6.1" + magic-string: "npm:^0.25.3" + rollup-pluginutils: "npm:^2.8.1" + checksum: 10c0/35b9d955039b56b43750a9e458bb51b7956b048b6d3ca57b1f03462aa5a0cb176d1b677d95e909b64eee4e9adf73c02f569ad8c0ab5aafdec818ff51700c114c + languageName: node + linkType: hard + +"rollup-plugin-node-polyfills@npm:^0.2.1": + version: 0.2.1 + resolution: "rollup-plugin-node-polyfills@npm:0.2.1" + dependencies: + rollup-plugin-inject: "npm:^3.0.0" + checksum: 10c0/30f9e09cbbf979b1212e0c455d74c3a061994fc19ddf160da4634b11377222cea5903a5ba05db66be849f550cde9ffc80ecbfcfb48544045d08bfc408501417d + languageName: node + linkType: hard + +"rollup-pluginutils@npm:^2.8.1": + version: 2.8.2 + resolution: "rollup-pluginutils@npm:2.8.2" + dependencies: + estree-walker: "npm:^0.6.1" + checksum: 10c0/20947bec5a5dd68b5c5c8423911e6e7c0ad834c451f1a929b1f4e2bc08836ad3f1a722ef2bfcbeca921870a0a283f13f064a317dc7a6768496e98c9a641ba290 + languageName: node + linkType: hard + "rollup@npm:^2.25.0 || ^3.3.0": version: 3.29.4 resolution: "rollup@npm:3.29.4" @@ -44498,7 +44902,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.6.3, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.0, semver@npm:^7.5.1, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": +"semver@npm:7.6.3, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.0, semver@npm:^7.5.1, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -44811,6 +45215,13 @@ __metadata: languageName: node linkType: hard +"shimmer@npm:^1.2.1": + version: 1.2.1 + resolution: "shimmer@npm:1.2.1" + checksum: 10c0/ae8b27c389db2a00acfc8da90240f11577685a8f3e40008f826a3bea8b4f3b3ecd305c26be024b4a0fd3b123d132c1569d6e238097960a9a543b6c60760fb46a + languageName: node + linkType: hard + "side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": version: 1.0.6 resolution: "side-channel@npm:1.0.6" @@ -47200,13 +47611,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.4.0": - version: 2.4.0 - resolution: "tslib@npm:2.4.0" - checksum: 10c0/eb19bda3ae545b03caea6a244b34593468e23d53b26bf8649fbc20fce43e9b21a71127fd6d2b9662c0fe48ee6ff668ead48fd00d3b88b2b716b1c12edae25b5d - languageName: node - linkType: hard - "tslib@npm:2.5.2": version: 2.5.2 resolution: "tslib@npm:2.5.2" @@ -47405,7 +47809,8 @@ __metadata: version: 0.0.0-use.local resolution: "twenty-server@workspace:packages/twenty-server" dependencies: - "@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch" + "@esbuild-plugins/node-modules-polyfill": "npm:^0.2.2" + "@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch" "@langchain/mistralai": "npm:^0.0.24" "@langchain/openai": "npm:^0.1.3" "@monaco-editor/react": "npm:^4.6.0" @@ -47416,6 +47821,7 @@ __metadata: "@nx/js": "npm:18.3.3" "@ptc-org/nestjs-query-graphql": "patch:@ptc-org/nestjs-query-graphql@4.2.0#./patches/@ptc-org+nestjs-query-graphql+4.2.0.patch" "@revertdotdev/revert-react": "npm:^0.0.21" + "@sentry/nestjs": "npm:^8.30.0" "@types/lodash.differencewith": "npm:^4.5.9" "@types/lodash.isempty": "npm:^4.4.7" "@types/lodash.isequal": "npm:^4.5.8" @@ -47428,10 +47834,12 @@ __metadata: "@types/lodash.uniqby": "npm:^4.7.9" "@types/lodash.upperfirst": "npm:^4.3.7" "@types/react": "npm:^18.2.39" + "@types/unzipper": "npm:^0" cache-manager: "npm:^5.4.0" cache-manager-redis-yet: "npm:^4.1.2" class-validator: "patch:class-validator@0.14.0#./patches/class-validator+0.14.0.patch" graphql-middleware: "npm:^6.1.35" + handlebars: "npm:^4.7.8" jsdom: "npm:~22.1.0" jwt-decode: "npm:^4.0.0" langchain: "npm:^0.2.6" @@ -47441,13 +47849,15 @@ __metadata: lodash.omitby: "npm:^4.6.0" lodash.uniq: "npm:^4.5.0" lodash.uniqby: "npm:^4.7.0" - monaco-editor: "npm:^0.50.0" + monaco-editor: "npm:^0.51.0" + monaco-editor-auto-typings: "npm:^0.4.5" passport: "npm:^0.7.0" psl: "npm:^1.9.0" rimraf: "npm:^5.0.5" tsconfig-paths: "npm:^4.2.0" typeorm: "patch:typeorm@0.3.20#./patches/typeorm+0.3.20.patch" typescript: "npm:5.3.3" + unzipper: "npm:^0.12.3" zod-to-json-schema: "npm:^3.23.1" languageName: unknown linkType: soft @@ -48395,6 +48805,19 @@ __metadata: languageName: node linkType: hard +"unzipper@npm:^0.12.3": + version: 0.12.3 + resolution: "unzipper@npm:0.12.3" + dependencies: + bluebird: "npm:~3.7.2" + duplexer2: "npm:~0.1.4" + fs-extra: "npm:^11.2.0" + graceful-fs: "npm:^4.2.2" + node-int64: "npm:^0.4.0" + checksum: 10c0/4cae2ad23bfd47011d5f8a6d61fb1dc0e4b5008bc3896e6f3d5ab946a64e9482714992a988128bce541440aa646e16e5e5c9bf35e49097edbaf833e7f814d36d + languageName: node + linkType: hard + "update-browserslist-db@npm:^1.1.0": version: 1.1.0 resolution: "update-browserslist-db@npm:1.1.0"